Apparence
A4 — Gestion utilisateur
🆕 Évolution proposée — n'existe ni en v1 ni dans la v2 spécifiée
Statut : 🟢 prêt à spécifier, deux points de détail à confirmer (Q18).
En une phrase
Un compte utilisateur n'est aujourd'hui ni corrigeable ni désactivable : on ne peut que changer son rôle ou le supprimer — et le supprimer efface la trace de ce qu'il a testé.
Constat
Trois manques précis :
- La fonction saisie à l'inscription est perdue. Le consultant renseigne « Consultant MOA Finance » au moment de créer son compte ; l'information n'est jamais enregistrée et n'apparaît nulle part dans l'application.
- Aucune donnée d'identité n'est modifiable. L'écran d'administration ne permet que deux choses : changer le rôle et supprimer le compte. Ni le nom, ni le prénom, ni l'e-mail, ni l'entité de rattachement.
- Il n'existe pas d'écran « Mon profil » : personne ne peut corriger sa propre fiche. Et le rattachement à une organisation reste impossible depuis l'interface (D1) — il faut passer par la base.
Conséquence : une faute de frappe dans un nom, un changement d'e-mail ou un départ se règlent aujourd'hui par une intervention technique, ou par une suppression de compte qui emporte l'historique d'exécution.
Références au code v1. La table profiles porte id, login (= e-mail), nom, prenom, entite, role, organization_id (migrations 009 / 010).
- La migration 010 le dit explicitement : « Le trigger NE LIT PAS user_metadata.fonction → profiles ne stocke pas la fonction ». La valeur reste dans
raw_user_meta_data, inexploitée. app/admin/AdminContainer.jsx→PATCH /api/admin/users, qui n'accepte que{ userId, role }.
Modèle proposé (v2)
Identité portée par le composant d'authentification, champs applicatifs sur le document utilisateur :
| Champ | Type | Éditable par | Remarque |
|---|---|---|---|
prenom | string | l'utilisateur + admin | |
nom | string | l'utilisateur + admin | |
email | string (unique) | l'utilisateur (avec re-vérification) + admin | sert d'identifiant de connexion → changement à sécuriser |
fonction | string libre (ex. « Consultant MOA Finance ») | l'utilisateur + admin | texte métier, à ne surtout pas confondre avec role (sécurité) — distinction déjà documentée en migration 010, à conserver |
entite | string ou référence entities | admin uniquement | donnée structurante de reporting (filtre du dashboard A1) |
role | admin / consultant / testeur / viewer | admin uniquement | |
organizationId | référence | admin uniquement | corrige D1 / Q3 |
isActive | boolean | admin uniquement | désactivation ≠ suppression : conserve l'historique d'exécution |
Écrans
- « Mon profil » — self-service, champs personnels.
- « Administration ▸ Utilisateurs » étendu — édition complète, invitation, affectation d'organisation, désactivation.
Garde-fous existants conservés (RG-19) : impossible de supprimer son propre compte ou le dernier administrateur.
Journalisation des changements de rôle, d'e-mail et d'organisation — rejoint Q8.
Point d'architecture — ne pas passer par le plugin organization de Better Auth
Better Auth expose un plugin organization (rôles owner / admin / member, invitations, limites de membres). Notre modèle multi-tenant ne doit pas s'appuyer dessus, pour trois raisons documentées côté éditeur :
- Pas d'accès administrateur transverse — les API d'organisation sont strictement fondées sur l'appartenance (
listOrganizations()ne renvoie que les organisations dont on est membre), contrainte imposée au niveau API et base. Un « super-admin » qui voit tous les tenants devrait être reconstruit à la main. - Les clés d'API ne sont rattachables qu'à un
userId, pas à un tenant. - La configuration par tenant n'est native que pour les fournisseurs SSO ; e-mail/mot de passe et magic-link restent globaux.
➡️ Le modèle retenu reste celui du CLAUDE.md §D : un champ organizationId porté par l'utilisateur et par chaque ressource, vérifié dans canInContext (couche ABAC). Il évite les trois limites ci-dessus. Cette décision doit rester écrite — sinon quelqu'un adoptera le plugin plus tard et rencontrera le mur du super-admin en production.
Aligné marché
Rôles et permissions configurables par projet et par groupe (TestRail), permissions par type d'objet (Zephyr Scale) — au-delà de notre besoin immédiat, mais utile si le multi-projet est confirmé (Q11).
À trancher — Q18
entiteen texte libre ou en référentiel d'entités ? (le référentiel est nécessaire pour filtrer proprement le reporting d'A1)- Qui peut modifier un e-mail ?
- Faut-il une désactivation de compte en plus de la suppression ? Recommandation : oui — supprimer un compte ayant exécuté des tests abîme l'historique.