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

3.4 KiB

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

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

// 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

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

  • Tenant se crea automaticamente
  • RLS aisla datos correctamente
  • Contexto se setea automaticamente
  • Settings se guardan y recuperan
  • 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