template-saas/docs/01-modulos/SAAS-002-tenants.md
rckrdmrd 50a821a415
Some checks failed
CI / Backend CI (push) Has been cancelled
CI / Frontend CI (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / CI Summary (push) Has been cancelled
[SIMCO-V38] feat: Actualizar a SIMCO v3.8.0
- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8
- Actualizaciones de configuracion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 08:53:08 -06:00

201 lines
4.3 KiB
Markdown

---
id: "SAAS-002"
title: "Multi-Tenancy"
type: "Module"
status: "Published"
priority: "P0"
module: "tenants"
version: "1.0.0"
created_date: "2026-01-07"
updated_date: "2026-01-10"
---
# 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 (incluye settings) |
| PATCH | /tenants/current | Actualizar tenant (incluye settings) |
| GET | /tenants/:id | Obtener tenant por ID |
| POST | /tenants | Crear tenant |
### Configuraciones de Tenant
Las configuraciones se almacenan en el campo `settings` (JSONB) de la tabla tenants.
**Acceso via API:**
- GET `/tenants/current` - Retorna tenant con settings incluidos
- PATCH `/tenants/current` - Permite actualizar settings junto con otros campos
**Estructura del Campo Settings:**
```json
{
"branding": {
"logo_url": "https://...",
"primary_color": "#3B82F6"
},
"notifications": {
"email_enabled": true,
"push_enabled": false
},
"features": {
"ai_enabled": true,
"whatsapp_enabled": false
}
}
```
**Nota:** Los endpoints dedicados `/tenants/current/settings` y `/tenants/current/logo` estan planificados pero no implementados actualmente
## 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-10