Organisations, équipes et isolation tenant
Décidez comment vos clients collaborent, puis adaptez les rôles, invitations, sièges et frontières tenant livrés.
Vérifié avec le commit
2a1a04adu starter.
Répondez d’abord à une question produit : votre SaaS vend-il à une personne, un espace partagé ou une personne qui gère plusieurs espaces ? Sushi SaaS livre le modèle courant de « l’équipe d’une personne qui peut grandir ». Chaque client commence dans une organisation personnelle et toutes les ressources facturables lui appartiennent.
Modèle de collaboration livré
| Comportement | Par défaut | Option future |
|---|---|---|
| Propriété des ressources | Partagée dans l’organisation | Ajouter propriété du créateur ou partage par ressource dans can() |
| Rôles | owner, admin, member | Ajouter des rôles métier ou l’accès dynamique Better Auth |
| Facturation | Prix fixe par organisation | Ajouter quantité par siège et prorata testé |
| Navigation | Sélecteur d’espace avec ?org=<slug> | Ajouter des segments de chemin par organisation si l’URL doit exprimer une hiérarchie plus forte |
| Équipes | Adhésions et invitations d’organisation | Activer des équipes imbriquées uniquement si vous avez besoin de sous-groupes |
Chaque compte possède une organisation
L’inscription crée une organisation personnelle et une adhésion owner. Il n’existe pas de seconde voie de ressources « utilisateur » : fichiers, tâches, commandes, abonnements, crédits et réservations utilisent org_uuid.
Better Auth fournit les adhésions et invitations. Sushi ajoute le périmètre tenant, les permissions, les limites de sièges, les soldes mutualisés et les gardes de concurrence.
Rôles
La hiérarchie est owner ⊃ admin ⊃ member.
| Action | Member | Admin | Owner |
|---|---|---|---|
| Lire, créer/supprimer des fichiers, dépenser des crédits | ✓ | ✓ | ✓ |
| Inviter, retirer et changer les rôles | ✓ | ✓ | |
| Modifier l’organisation | ✓ | ✓ | |
| Gérer la facturation ou supprimer l’organisation | ✓ |
Utilisez getOrgContext(request, optionalSlug) puis can(ctx, action, resource). N’acceptez jamais org_uuid dans le corps d’une requête.
Isolation et limites de sièges
Toutes les requêtes sur des tables tenant utilisent scopedToOrg(column, ctx.orgUuid) dans les modèles. Les tests d’architecture détectent une lecture ou insertion non limitée.
Les invitations expirent après 72 heures, sont liées à l’adresse invitée et réservent un siège tant qu’elles sont actives.
| Plan | Sièges totaux |
|---|---|
| Free | 1 |
| Plus | 5 |
| Max | 20 |
La capacité est vérifiée à l’envoi et à l’acceptation sous le même verrou advisory PostgreSQL. Le support peut définir une exception auditée, temporaire ou permanente.
Invariants
- Le dernier owner ne peut pas être retiré.
- Un utilisateur ne peut pas quitter sa seule organisation.
- Un membre ne peut pas attribuer un rôle supérieur au sien.
- Un downgrade conserve membres et données, mais bloque les nouvelles entrées.
- Les crédits et le client Stripe appartiennent à l’organisation.
L’interface est sous /{locale}/account/team, l’API sous /api/account/team/*. Le starter fournit un sélecteur fondé sur un paramètre de requête ; il ne fournit pas encore de routes avec slug d’organisation, rôles personnalisés, équipes imbriquées ou quantité Stripe par siège.
Avant de changer ce modèle, écrivez qui possède les données, qui invite ou retire des personnes, si un membre peut supprimer du contenu partagé et qui paie. Il est validé lorsque deux organisations ne lisent jamais leurs données mutuelles, que le dernier owner reste protégé, que deux invitations simultanées ne prennent pas le dernier siège et qu’un downgrade conserve membres et données.
Étape suivante : reliez sièges et capacités aux Plans, limites et droits, puis mesurez leur impact transversal dans Comment Sushi SaaS est structuré.