Construire le produit

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 2a1a04a du 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é

ComportementPar défautOption future
Propriété des ressourcesPartagée dans l’organisationAjouter propriété du créateur ou partage par ressource dans can()
Rôlesowner, admin, memberAjouter des rôles métier ou l’accès dynamique Better Auth
FacturationPrix fixe par organisationAjouter quantité par siège et prorata testé
NavigationSélecteur d’espace avec ?org=<slug>Ajouter des segments de chemin par organisation si l’URL doit exprimer une hiérarchie plus forte
ÉquipesAdhésions et invitations d’organisationActiver 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 owneradminmember.

ActionMemberAdminOwner
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.

PlanSièges totaux
Free1
Plus5
Max20

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é.

Organisations, équipes et isolation tenant · Sushi SaaS