Apparence
7. Rôles & Permissions
👔 En clair
Qui peut faire quoi, par rôle (Administrateur, Consultant, Testeur, Lecteur). La grande matrice ci-dessous se lit de gauche à droite ; la dernière colonne Enforcement est technique (où le droit est vérifié) et peut être ignorée côté métier.
Enforcement v2. Le masquage UI (héritier de
utils/roleGuard.js) reste cosmétique. L'autorité réelle est la couche autorisation Convex : chaque fonction part des wrapperszQuery/zMutationet vérifiecan(role, action)+canInContext(rôle etorganizationId), plus la RLS applicative. Défini danspackages/backend/convex/lib/authz.ts.🔁 Rôles : le tableau ci-dessous utilise les 4 rôles fonctionnels v1. En v2,
lib/authz.tstypeadmin/consultant/testeur(⇐metier). Le rôleviewer(lecture seule) reste à trancher — voir Stack v2.
Matrice des permissions (actions × rôles)
Colonne Enforcement = où la règle est appliquée en v2.
| Action / Ressource | admin | consultant | metier / testeur | viewer | Enforcement (v2) |
|---|---|---|---|---|---|
| Écrire le référentiel (flux, étapes, renommages) | ✅ | ✅ | ❌ | ❌ | UI + mutation Convex (tests/etapes) |
| Créer un module | ✅ | ✅¹ | ❌ | ❌ | modules.setup (admin+consultant) |
| Éditer style / renommer un module | ✅ | ❌² | ❌ | ❌ | modules.update (admin) |
| Supprimer un module | ✅ | ❌ | ❌ | ❌ | UI (CAN_DELETE_MODULE) + modules.remove |
| Créer / éditer un flux (test), une étape | ✅ | ✅ | ❌ | ❌ | tests.*, etapes.* (admin+consultant) |
| Exécuter un test (saisir résultat d'étape) | ✅ | ✅ | ✅ | ❌ | etapes.updateResult (+ testeur) + garde campagne active |
| Déclarer / éditer une anomalie | ✅ | ✅ | ✅ | ❌ | anomalies.* (admin+consultant+testeur) |
| Gérer les CRIMs (créer/éditer/importer) | ✅ | ✅ | ❌ | ❌ | UI (CAN_MANAGE_CRIMS) + crims.* |
| Supprimer un CRIM | ✅ | ❌ | ❌ | ❌ | UI (CAN_DELETE_CRIM) + crims.remove³ |
| Créer / éditer une campagne | ✅ | ✅ | ❌ | ❌ | campaigns.create/update (admin+consultant) |
| Activer une campagne (snapshot) | ✅ | ❌ | ❌ | ❌ | campaigns.activate (admin only) |
| Désactiver une campagne | ✅ | ✅⁴ | ❌ | ❌ | campaigns.deactivate (admin+consultant) |
| Supprimer une campagne | ✅ | ❌ | ❌ | ❌ | campaigns.remove (admin) |
| Éditer / créer le projet | ✅ | ❌ | ❌ | ❌ | projects.* (admin) |
| Gérer les utilisateurs (rôles, suppression) | ✅ | ❌ | ❌ | ❌ | domaine admin + Better Auth (admin) |
| Upload d'une preuve (evidence) | ✅ | ❔⁵ | ✅ | ❌ | authz evidence + Convex File Storage |
| Consulter (tous les écrans) | ✅ | ✅ | ✅ | ✅ | queries Convex réactives, org-scopées (RLS applicative) |
Notes de nuance :
- ¹ Création de module via
modules.setup(admin+consultant) ; le bouton « Nouveau module » est masqué pour les non-CAN_WRITE_REFERENTIEL— cohérent. - ² L'incohérence UI/serveur de v1 (bouton d'édition visible consultant, mutation réservée admin → refus) doit être arbitrée en v2 : aligner UI et
can(). Voir Dette technique. - ³ Idem : en v1 l'UI restreignait à admin mais l'API autorisait consultant → à unifier dans
can('crim:delete'). - ⁴ Désactivation : admin+consultant ; activation strictement admin (double contrôle UI + fonction).
- ⁵ En v1, la RLS réservait l'écriture des preuves à admin + metier (un consultant ne pouvait pas uploader alors qu'il peut déclarer une anomalie). Incohérence à trancher en v2. Voir Q6.
⚠️ Règle de sécurité fondamentale : le masquage UI n'est pas une sécurité. L'enforcement réel repose sur les fonctions Convex (
can/canInContext) et la RLS applicative org-scopée — voir Sécurité & enforcement.