template-saas/docs/01-modulos/SAAS-002-tenants.md
rckrdmrd 4dafffa386 feat: Add superadmin metrics, onboarding and module documentation
- Add MetricsPage and useOnboarding hook
- Update superadmin controller and service
- Add module documentation (docs/01-modulos/)
- Add CONTEXT-MAP.yml and Sprint 5 execution report
- Update project status and task traces

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 05:40:26 -06:00

162 lines
3.4 KiB
Markdown

# SAAS-002: Multi-Tenancy
## Metadata
- **Codigo:** SAAS-002
- **Modulo:** Tenants
- **Prioridad:** P0
- **Estado:** Completado
- **Fase:** 1 - Foundation
## Descripcion
Sistema de multi-tenancy con aislamiento completo de datos via Row-Level Security (RLS): creacion de tenants, configuracion por tenant, y contexto automatico en todas las operaciones.
## Objetivos
1. Aislamiento de datos por tenant
2. RLS en todas las tablas
3. Tenant context automatico
4. Configuracion por tenant
5. Subdominios/custom domains
## Alcance
### Incluido
- Creacion de tenant al registrar owner
- RLS policies en todas las tablas
- Tenant context via middleware
- tenant_id en JWT claims
- Configuraciones por tenant (JSONB)
- Slug unico por tenant
### Excluido
- Custom domains - fase posterior
- White-labeling completo
- Tenant isolation fisica (DB separadas)
## Modelo de Datos
### Tablas (schema: tenants)
**tenants**
- id, name, slug (unique)
- domain, logo_url, favicon_url
- settings (JSONB), status
- trial_ends_at, created_at
**tenant_settings**
- id, tenant_id, key, value
- created_at, updated_at
## Estrategia RLS
### Implementacion
```sql
-- Funcion de contexto
CREATE FUNCTION current_tenant_id() RETURNS UUID AS $$
SELECT current_setting('app.tenant_id', TRUE)::UUID;
$$ LANGUAGE SQL STABLE;
-- Policy generica
CREATE POLICY tenant_isolation ON table_name
USING (tenant_id = current_tenant_id());
```
### Middleware Backend
```typescript
// Set tenant context antes de queries
await db.query(`SELECT set_config('app.tenant_id', $1, true)`, [tenantId]);
```
## Endpoints API
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /tenants/current | Tenant actual |
| PUT | /tenants/current | Actualizar tenant |
| GET | /tenants/current/settings | Configuraciones |
| PUT | /tenants/current/settings | Actualizar config |
| POST | /tenants/current/logo | Subir logo |
## Flujos
### Creacion de Tenant
```
1. Usuario se registra como owner
2. Se crea usuario
3. Se crea tenant con slug unico
4. Se asocia usuario a tenant
5. Se aplican settings default
6. Se inicia trial
```
### Resolucion de Tenant
```
Request llega a API
├─► JWT contiene tenant_id?
│ └─► Si: usar ese tenant_id
├─► Header X-Tenant-ID?
│ └─► Si: validar y usar
└─► Subdominio?
└─► Si: buscar tenant por slug
```
## Configuraciones Default
```typescript
const DEFAULT_SETTINGS = {
timezone: 'America/Mexico_City',
locale: 'es-MX',
currency: 'MXN',
date_format: 'DD/MM/YYYY',
features: {
ai_enabled: false,
webhooks_enabled: false
},
limits: {
users: 5,
storage_mb: 1000
}
};
```
## Entregables
| Entregable | Estado | Archivo |
|------------|--------|---------|
| tenants.module.ts | Completado | `modules/tenants/` |
| tenant.middleware.ts | Completado | `middleware/` |
| DDL tenants schema | Completado | `ddl/schemas/tenants/` |
| RLS policies | Completado | En cada schema |
## Dependencias
### Depende de
- SAAS-001 (Auth)
### Bloquea a
- SAAS-003 (Users)
- Todos los modulos multi-tenant
## Criterios de Aceptacion
- [x] Tenant se crea automaticamente
- [x] RLS aisla datos correctamente
- [x] Contexto se setea automaticamente
- [x] Settings se guardan y recuperan
- [x] Slug es unico
## Seguridad
- RLS activo en todas las tablas (excepto plans)
- Tenant ID no modificable por usuario
- Validacion de pertenencia a tenant
- Logs de cambios en configuracion
---
**Ultima actualizacion:** 2026-01-07