---
titre: Rôles et permissions
statut: Draft v3 — partiellement implémenté
date: 2026-05-13
---

# 03 — Rôles et permissions

> **État d'implémentation au 2026-05-29** :
> - ✅ Auth Symfony Security configurée, `ROLE_USER` et `ROLE_SUPERADMIN` actifs
> - ✅ ADMIN ⇒ `access_mode = all_accounts` appliqué serveur (PrePersist/PreUpdate + Validator)
> - ✅ **Administration d'organisation par le profil ADMIN** : voter `ORG_ADMIN` + `OrganizationAdminChecker` — accès à `/admin/organizations/{id}/edit` (org courante), membres, comptes, biens, activation plateformes org
> - ✅ Un ADMIN actif reçoit automatiquement les droits délégués imports / transactions / tags (sans passage par la matrice « Droits par profil »)
> - ✅ Routes déléguées (`/admin/imports`, `/admin/transactions`, `/admin/tags-categories`) accessibles aux autres profils si cochés dans `membership_role_delegatable_permission`
> - ✅ Routes globales réservées au `ROLE_SUPERADMIN` : liste/création/suppression d'organisations, référentiel plateformes, matrice « Droits par profil », suppression définitive d'un compte utilisateur
> - ⏳ **Voters** Symfony supplémentaires (objet par objet, `access_mode` restreint) à compléter selon la matrice métier
> - ⏳ Rôles Symfony `ROLE_ORG_*` dans `User::getRoles()` — en pratique le droit org passe par le voter `ORG_ADMIN` + membership actif
> - ⏳ Audit log non implémenté (entité spec mais pas de table en BDD)
>
> Cf. [`docs/existant/etat-courant.md`](../existant/etat-courant.md) pour le suivi à jour.

> **Changelog v2 (2026-05-10)** :
> - ADMIN explicitement non-restrictible (toujours `access_mode = all_accounts`).
> - MANAGER peut désormais être en mode restreint (cas cabinet multi-clients).
> - Ajout d'une section « Tags » dans la matrice.

## Définitions

| Rôle | Portée | Description |
|---|---|---|
| **SUPERADMIN** | Globale (cross-tenant) | Opérateur de la plateforme. Gère les organisations, le support, le monitoring. Aucune action métier dans les organisations sauf intervention support tracée. |
| **ADMIN** | Organisation | Propriétaire fonctionnel d'une organisation. Tous droits sur le contenu de son org : comptes, transactions, utilisateurs, catégories, paramètres. **Voit toujours tous les comptes de l'org** (jamais en mode restreint). |
| **MANAGER** | Organisation | Gestionnaire opérationnel (typiquement comptable). Tous droits sur le **contenu financier** (comptes, transactions, imports, catégories, tags) mais **ne gère pas** les utilisateurs/membres. Peut être en mode `all_accounts` ou `restricted`. |
| **USER** | Organisation | Collaborateur opérationnel sur un périmètre limité. Peut consulter, importer et catégoriser sur les comptes auxquels il a accès. Pas de suppression. Souvent en mode `restricted`. |
| **PARTENAIRE** | Organisation | Lecture seule sur des indicateurs agrégés. **Ne voit pas** le détail des transactions. Adapté à un investisseur, un partenaire externe. |

> **Note** : un même `User` peut avoir des rôles différents dans plusieurs organisations via la table `membership`. Le rôle effectif est résolu au moment de la résolution du contexte d'organisation (`OrganizationContext`).

## Mode d'accès aux comptes (`membership.access_mode`)

Indépendamment du rôle, chaque membre a un `access_mode` :

- **`all_accounts`** : voit tous les comptes bancaires de l'organisation.
- **`restricted`** : voit uniquement les comptes listés dans `membership_bank_account`.

| Rôle | `all_accounts` | `restricted` |
|---|:---:|:---:|
| ADMIN | ✅ (forcé) | ❌ interdit |
| MANAGER | ✅ | ✅ |
| USER | ✅ | ✅ (cas typique) |
| PARTENAIRE | ✅ | ✅ |

**Cas d'usage** :
- Famille : parents = ADMIN (`all_accounts`), enfants = USER (`restricted` sur leur seul compte).
- Cabinet : ADMIN du cabinet = `all_accounts`, MANAGER assigné à un client précis = `restricted`.

## Matrice des permissions

Légende : ✅ autorisé · 👁 lecture seule · ⚠️ scope limité · ❌ refusé

### Organisation

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Créer une organisation | ✅ | ❌ | ❌ | ❌ | ❌ |
| Voir la liste de toutes les orgs | ✅ | ❌ | ❌ | ❌ | ❌ |
| Suspendre / archiver une org | ✅ | ❌ | ❌ | ❌ | ❌ |
| Modifier les paramètres de son org | ❌ | ✅ | ❌ | ❌ | ❌ |
| Voir les paramètres de son org | ❌ | ✅ | ✅ | 👁 | ❌ |

### Utilisateurs et membres

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Créer un utilisateur (compte global) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Inviter un membre dans son org | ❌ | ✅ | ❌ | ❌ | ❌ |
| Modifier le rôle d'un membre | ❌ | ✅ | ❌ | ❌ | ❌ |
| Révoquer un membre | ❌ | ✅ | ❌ | ❌ | ❌ |
| Voir la liste des membres de son org | ❌ | ✅ | 👁 | 👁 | ❌ |
| Modifier son propre profil | ✅ | ✅ | ✅ | ✅ | ✅ |

### Comptes bancaires

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Créer un compte | ❌ | ✅ | ⚠️ assignés | ❌ | ❌ |
| Modifier un compte | ❌ | ✅ | ⚠️ assignés | ❌ | ❌ |
| Supprimer un compte | ❌ | ✅ | ❌ | ❌ | ❌ |
| Voir la liste des comptes | 👁 | ✅ | ⚠️ assignés | ⚠️ assignés | 👁 agrégé |
| Voir le solde d'un compte | 👁 | ✅ | ⚠️ assignés | ⚠️ assignés | 👁 agrégé |
| Définir le mode d'accès d'un membre (all/restricted) | ❌ | ✅ | ❌ | ❌ | ❌ |
| Assigner des comptes spécifiques à un membre | ❌ | ✅ | ❌ | ❌ | ❌ |

### Transactions

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Voir les transactions | 👁 sur incident | ✅ | ⚠️ assignés | ⚠️ assignés | ❌ |
| Créer une transaction manuelle | ❌ | ✅ | ⚠️ assignés | ⚠️ assignés | ❌ |
| Modifier une transaction | ❌ | ✅ | ⚠️ assignés | ⚠️ ses imports | ❌ |
| Supprimer une transaction | ❌ | ✅ | ⚠️ assignés | ❌ | ❌ |
| Catégoriser une transaction | ❌ | ✅ | ⚠️ assignés | ⚠️ assignés | ❌ |
| Tagger / détagger une transaction | ❌ | ✅ | ⚠️ assignés | ⚠️ assignés | ❌ |
| Annoter (notes) une transaction | ❌ | ✅ | ⚠️ assignés | ⚠️ assignés | ❌ |
| Exporter les transactions (CSV/Excel) | ❌ | ✅ | ⚠️ assignés | ❌ | ❌ |

### Tags

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Créer un tag personnalisé | ❌ | ✅ | ✅ | ✅ | ❌ |
| Modifier un tag (nom, couleur) | ❌ | ✅ | ✅ | ❌ | ❌ |
| Supprimer un tag personnalisé | ❌ | ✅ | ✅ | ❌ | ❌ |
| Supprimer un tag par défaut | ❌ | ✅ | ❌ | ❌ | ❌ |
| Voir la liste des tags | ❌ | ✅ | ✅ | ✅ | ❌ |
| Filtrer les transactions par tag | ❌ | ✅ | ⚠️ assignés | ⚠️ assignés | ❌ |

### Imports

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Lancer un import (PDF/CSV) | ❌ | ✅ | ⚠️ assignés | ⚠️ assignés | ❌ |
| Voir l'historique des imports | ❌ | ✅ | ⚠️ assignés | ⚠️ ses imports | ❌ |
| Annuler un import en échec | ❌ | ✅ | ⚠️ assignés | ❌ | ❌ |
| Configurer un mapping CSV par défaut | ❌ | ✅ | ⚠️ assignés | ❌ | ❌ |

### Catégories

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Créer / modifier / supprimer | ❌ | ✅ | ✅ | ❌ | ❌ |
| Voir la liste | ❌ | ✅ | ✅ | ✅ | ❌ |

### Biens immobiliers (Property)

Entité tenant-scoped, gérée par l'organisation.

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Créer un bien | ❌ | ✅ | ✅ | ❌ | ❌ |
| Modifier un bien | ❌ | ✅ | ✅ | ❌ | ❌ |
| Archiver / désarchiver un bien | ❌ | ✅ | ✅ | ❌ | ❌ |
| Supprimer un bien | ❌ | ✅ | ❌ | ❌ | ❌ |
| Voir la liste des biens | ❌ | ✅ | ✅ | ✅ | 👁 agrégé |
| Associer un bien à une transaction | ❌ | ✅ | ⚠️ assignés | ⚠️ assignés | ❌ |

### Plateformes de location (RentalPlatform — référentiel global)

Référentiel **cross-tenant**, géré exclusivement par le SUPERADMIN. Les autres rôles n'y accèdent qu'en lecture indirecte via l'activation côté organisation.

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Créer une plateforme | ✅ | ❌ | ❌ | ❌ | ❌ |
| Modifier une plateforme | ✅ | ❌ | ❌ | ❌ | ❌ |
| Archiver une plateforme | ✅ | ❌ | ❌ | ❌ | ❌ |
| Voir la liste globale | ✅ | ❌ | ❌ | ❌ | ❌ |

### Activation des plateformes par organisation

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Activer/désactiver une plateforme pour son org | ❌ | ✅ | ❌ | ❌ | ❌ |
| Voir les plateformes actives de son org | ❌ | ✅ | ✅ | ✅ | 👁 |
| Renseigner des notes sur l'activation (commission…) | ❌ | ✅ | ❌ | ❌ | ❌ |

### Tableau de bord et indicateurs

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Voir le dashboard org consolidé | ❌ | ✅ | ⚠️ assignés | ⚠️ assignés | ✅ agrégé |
| Voir les graphiques détaillés | ❌ | ✅ | ⚠️ assignés | ⚠️ assignés | ⚠️ agrégés sans détail transac |
| Voir les KPI globaux plateforme | ✅ | ❌ | ❌ | ❌ | ❌ |

### Audit

| Action | SUPERADMIN | ADMIN | MANAGER | USER | PARTENAIRE |
|---|:---:|:---:|:---:|:---:|:---:|
| Consulter le journal d'audit de son org | ❌ | ✅ | 👁 | ❌ | ❌ |
| Consulter le journal global plateforme | ✅ | ❌ | ❌ | ❌ | ❌ |

## Règles transverses

1. **SUPERADMIN n'agit jamais sur le contenu métier** d'une organisation sans tracé d'audit explicite (`SuperadminInterventionLog`).
2. **PARTENAIRE ne voit jamais une transaction individuelle** — uniquement des agrégats (totaux, graphiques).
3. **Membre avec accès restreint** : la restriction passe par `membership.access_mode = restricted` + table de jointure `membership_bank_account`. Cf. `02-modele-donnees.md`.
4. **ADMIN ne peut JAMAIS être restreint** : `role = ADMIN` force `access_mode = all_accounts` au niveau base + voter applicatif.
5. **Toute action d'écriture déclenche une entrée d'audit** sur les entités sensibles (BankAccount, Transaction, Membership).

## Implémentation Symfony

- Symfony Security `roles` :
  - `ROLE_SUPERADMIN` (mappé sur `User.is_superadmin`)
  - `ROLE_ORG_ADMIN`, `ROLE_ORG_MANAGER`, `ROLE_ORG_USER`, `ROLE_ORG_PARTENAIRE` (dérivés du `Membership` actif)
- Voters dédiés pour les permissions fines :
  - `OrganizationAdminVoter` (`ORG_ADMIN`) — administration de l'organisation courante (profil `MembershipRole::Admin` actif) : paramètres org, membres, comptes, biens, plateformes org
  - `DelegatableAdminFeatureVoter` — imports / transactions / tags selon matrice déléguée (ADMIN actif : accès automatique)
  - `BankAccountVoter` (view, edit, delete) — vérifie role **et** accès au compte spécifique via `membership_bank_account` si `access_mode = restricted` — ⏳ à faire
  - `TransactionVoter` (view, edit, delete, export) — délègue à `BankAccountVoter` sur le compte de la transaction.
  - `ImportVoter` (create, view, cancel) — idem.
  - `TagVoter` (create, edit, delete, use).
  - `MembershipVoter` (invite, revoke, change-role, change-access-mode).
- Service `AccountAccessResolver` : retourne la liste des `bank_account_id` accessibles pour un membership donné (utilisé partout pour scoper les requêtes).
- Le rôle est résolu à chaque requête depuis `User.current_organization_id` + lookup `membership`.

## Changements de rôle et de mode d'accès

- Promouvoir un USER en MANAGER : ✅ par ADMIN, audité.
- Rétrograder un ADMIN : ✅ par un autre ADMIN. Une org doit toujours avoir au moins **1 ADMIN actif**.
- Auto-rétrogradation : ❌ refusé (pour éviter qu'un ADMIN se sorte de l'org sans transfert).
- Promouvoir un USER/MANAGER restreint en ADMIN : ✅ — l'`access_mode` est automatiquement basculé à `all_accounts` (avec confirmation explicite à l'écran).
- Modifier les comptes assignés à un membre restreint : ✅ par ADMIN à tout moment.

## Changelog

- **v3.1 — 2026-05-29** : administration org par le profil ADMIN (`ORG_ADMIN`), droits délégués automatiques pour ADMIN, sidebar « Mon organisation » / « Membres ».
- **v3 — 2026-05-13** : ajout des matrices Biens immobiliers, Plateformes de location (référentiel SUPERADMIN), Activation des plateformes par organisation. Mise à jour de la liste des voters à implémenter.
- **v2 — 2026-05-10** : ADMIN forcé en `all_accounts`, MANAGER éligible au mode `restricted`, ajout section Tags, ajout `AccountAccessResolver` dans l'implémentation, légende « ⚠️ assignés » harmonisée.
- **v1 — 2026-05-08** : création initiale.
