+27
−0
+48
−0
+47
−19
Loading
Étape 1 du socle multi-organisations. Un compte devient une identité GLOBALE ;
c'est `Membership` qui le rattache à une organisation et qui porte son rôle. Une
consultante peut désormais animer chez un client et concevoir chez un autre avec
une seule identité — impossible avant, l'email étant unique et le tenant porté
par le compte.
La refonte reste contenue parce que `AuthUser.tenantId` continue de désigner
l'organisation ACTIVE : les 106 sites qui lisent `me.tenantId` ne bougent pas
d'une ligne. Seuls l'authentification, la signature du jeton et l'administration
des membres changent.
Sécurité — trois pièges traités, dont un que la refonte ouvrait :
- `INSTANCE_ADMIN` entre dans l'enum des rôles. Tel quel, un admin d'organisation
pouvait se l'attribuer via `POST /users` et prendre la main sur l'instance.
Deux verrous : les routes d'organisation n'acceptent que `TENANT_ROLES`, et
`isInstanceAdmin` exige le rôle ET l'organisation système (module pur, testé).
- Réinitialiser le mot de passe de quelqu'un présent dans plusieurs organisations
donnerait à un admin d'organisation la main sur ses accès ailleurs. Refusé,
comme le changement d'email. Le rôle reste modifiable : sa portée est locale.
- Retirer un membre supprime son APPARTENANCE. Le compte ne disparaît que s'il ne
sert plus nulle part.
Le garde de session applique la lecture seule en un point unique, sur le modèle
du garde joueur : un jeton marqué `ro` refuse toute méthode autre que GET/HEAD.
C'est le socle de la bascule d'administrateur d'instance (étape 2).
Un compte existant ne peut pas être rattaché à une organisation depuis la console
d'organisation : ce serait y ajouter quelqu'un sans son accord. Le rattachement
reste une action d'instance jusqu'à ce que les invitations existent (étape 4).
La migration est conservatrice : chaque compte existant devient une appartenance
unique, avec exactement l'organisation et le rôle qu'il avait. `ALTER TYPE ...
ADD VALUE` tient dans la transaction (PostgreSQL 16, et la valeur ajoutée n'est
pas utilisée par le report).
Non vérifié : aucune chaîne Node dans cet environnement, donc rien n'a été
compilé ni testé. Contrôles manuels : équilibre des délimiteurs, absence de
doublon de clé i18n (393 clés), aucune référence orpheline à `User.tenantId` ou
`User.role`, `User` retiré des modèles cloisonnés au profit de `Membership`.
Co-Authored-By:
Claude (RCA) <noreply@anthropic.com>