Organizaciones, equipos y tenancy
Configura espacios personales, roles, invitaciones, límites de plazas, aislamiento de tenant, créditos compartidos y facturación por organización.
Sincronizado con el commit
7d452a6del starter.
Cada cuenta tiene una organización
El registro crea una organización personal y una membresía de propietario. No existe una ruta paralela de recursos del usuario: archivos, tareas, pedidos, suscripciones, créditos, claves API y reservas usan org_uuid.
Better Auth aporta las membresías e invitaciones. Sushi añade aislamiento de tenant, permisos, límites de plazas, saldos compartidos y controles de concurrencia.
Roles
La jerarquía es owner ⊃ admin ⊃ member.
| Acción | Member | Admin | Owner |
|---|---|---|---|
| Leer datos, crear/eliminar archivos y gastar créditos | ✓ | ✓ | ✓ |
| Invitar, eliminar miembros y cambiar roles | ✓ | ✓ | |
| Actualizar la organización | ✓ | ✓ | |
| Gestionar facturación o eliminar la organización | ✓ |
Usa getOrgContext(request, optionalSlug) para resolver usuario, organización y rol, y can(ctx, action, resource) para autorizar. Nunca aceptes org_uuid desde el cuerpo de una petición.
Aislamiento y plazas
Todas las consultas de tablas tenant usan scopedToOrg(column, ctx.orgUuid) dentro de los modelos. Las pruebas de arquitectura detectan consultas o inserciones sin organización.
Las invitaciones caducan en 72 horas, están ligadas al email y reservan plaza mientras siguen activas.
| Plan | Plazas totales |
|---|---|
| Free | 1 |
| Plus | 5 |
| Max | 20 |
La capacidad se comprueba al enviar y al aceptar bajo el mismo bloqueo advisory de PostgreSQL. Soporte puede aplicar una excepción temporal o permanente con auditoría.
Invariantes
- Nunca se elimina el último owner.
- Nadie puede abandonar su única organización.
- Un miembro no puede conceder un rol superior al propio.
- Un downgrade conserva miembros y datos; bloquea nuevas altas hasta volver al límite.
- Créditos y cliente Stripe pertenecen a la organización.
La interfaz vive en /{locale}/account/team y la API en /api/account/team/*. El starter no incluye todavía selector de organización, rutas por slug, roles personalizados ni cobro Stripe por asiento.