- Update vision, architecture and technical documentation - Update module definitions (PMC-001 to PMC-008) - Update requirements documentation - Add CONTEXT-MAP.yml and ENVIRONMENT-INVENTORY.yml - Add orchestration guidelines and references 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
307 lines
7.6 KiB
Markdown
307 lines
7.6 KiB
Markdown
---
|
|
id: "PMC-001-TENANTS"
|
|
title: "PMC-001: Módulo de Tenants"
|
|
type: "Module Definition"
|
|
epic: "PMC-001"
|
|
status: "Draft"
|
|
project: "platform_marketing_content"
|
|
version: "1.0.0"
|
|
created_date: "2026-01-04"
|
|
updated_date: "2026-01-04"
|
|
---
|
|
# PMC-001: Módulo de Tenants
|
|
|
|
**Versión:** 1.0.0
|
|
**Fecha:** 2025-12-08
|
|
**Estado:** Definición
|
|
**Prioridad:** Alta
|
|
|
|
---
|
|
|
|
## Descripción General
|
|
|
|
El módulo de Tenants proporciona la arquitectura multi-tenant que permite aislar datos y configuraciones entre diferentes organizaciones (agencias) que utilicen la plataforma.
|
|
|
|
---
|
|
|
|
## Objetivos
|
|
|
|
1. Aislar completamente los datos entre tenants
|
|
2. Permitir configuración personalizada por tenant
|
|
3. Soportar branding personalizado (logo, colores)
|
|
4. Gestionar límites y cuotas por tenant
|
|
5. Preparar arquitectura para comercialización SaaS futura
|
|
|
|
---
|
|
|
|
## Entidades del Dominio
|
|
|
|
### Tenant
|
|
|
|
```yaml
|
|
Entidad: Tenant
|
|
Descripción: Organización/agencia que utiliza la plataforma
|
|
Atributos:
|
|
- id: UUID (PK)
|
|
- name: string (nombre de la organización)
|
|
- slug: string (identificador URL-friendly, único)
|
|
- status: enum [active, suspended, trial, cancelled]
|
|
- plan_id: UUID (FK a Plan)
|
|
- settings: JSONB (configuración personalizada)
|
|
- branding: JSONB (logo_url, primary_color, secondary_color)
|
|
- limits: JSONB (cuotas y límites)
|
|
- created_at: timestamp
|
|
- updated_at: timestamp
|
|
- deleted_at: timestamp (soft delete)
|
|
|
|
Relaciones:
|
|
- 1:N con User
|
|
- 1:N con Client (CRM)
|
|
- 1:N con Project
|
|
- 1:N con Asset
|
|
- N:1 con Plan
|
|
```
|
|
|
|
### Plan
|
|
|
|
```yaml
|
|
Entidad: Plan
|
|
Descripción: Plan de suscripción con límites definidos
|
|
Atributos:
|
|
- id: UUID (PK)
|
|
- name: string (Free, Pro, Enterprise, Internal)
|
|
- code: string (identificador único)
|
|
- features: JSONB (funcionalidades habilitadas)
|
|
- limits: JSONB
|
|
- generations_per_month: number
|
|
- trainings_per_month: number
|
|
- storage_gb: number
|
|
- users_max: number
|
|
- projects_max: number
|
|
- price_monthly: decimal
|
|
- price_yearly: decimal
|
|
- is_active: boolean
|
|
- created_at: timestamp
|
|
- updated_at: timestamp
|
|
|
|
Relaciones:
|
|
- 1:N con Tenant
|
|
```
|
|
|
|
### TenantSettings
|
|
|
|
```yaml
|
|
Estructura JSONB: settings
|
|
Campos:
|
|
- default_language: string (es, en)
|
|
- timezone: string
|
|
- date_format: string
|
|
- currency: string
|
|
- notifications:
|
|
email_enabled: boolean
|
|
slack_webhook: string
|
|
- integrations:
|
|
crm_external_url: string
|
|
n8n_webhook_base: string
|
|
- generation:
|
|
default_model: string
|
|
default_quality: string
|
|
watermark_enabled: boolean
|
|
```
|
|
|
|
---
|
|
|
|
## Funcionalidades
|
|
|
|
### F-001.1: Gestión de Tenants
|
|
|
|
| ID | Funcionalidad | Descripción | Prioridad |
|
|
|----|---------------|-------------|-----------|
|
|
| F-001.1.1 | Crear tenant | Registro de nueva organización | Alta |
|
|
| F-001.1.2 | Editar tenant | Modificar datos y configuración | Alta |
|
|
| F-001.1.3 | Suspender tenant | Desactivar acceso temporalmente | Media |
|
|
| F-001.1.4 | Eliminar tenant | Soft delete con retención de datos | Baja |
|
|
|
|
### F-001.2: Configuración por Tenant
|
|
|
|
| ID | Funcionalidad | Descripción | Prioridad |
|
|
|----|---------------|-------------|-----------|
|
|
| F-001.2.1 | Branding | Personalizar logo y colores | Media |
|
|
| F-001.2.2 | Límites | Configurar cuotas de uso | Alta |
|
|
| F-001.2.3 | Integraciones | URLs de webhooks y APIs externas | Media |
|
|
| F-001.2.4 | Preferencias | Idioma, zona horaria, formatos | Baja |
|
|
|
|
### F-001.3: Aislamiento de Datos
|
|
|
|
| ID | Funcionalidad | Descripción | Prioridad |
|
|
|----|---------------|-------------|-----------|
|
|
| F-001.3.1 | RLS PostgreSQL | Row-Level Security por tenant_id | Alta |
|
|
| F-001.3.2 | Middleware | Inyección automática de tenant_id | Alta |
|
|
| F-001.3.3 | Storage isolation | Prefijos S3 por tenant | Alta |
|
|
|
|
---
|
|
|
|
## Reglas de Negocio
|
|
|
|
```yaml
|
|
RN-001.1:
|
|
Descripción: Todo tenant debe tener un plan asignado
|
|
Validación: plan_id NOT NULL
|
|
Default: Plan "Free" o "Internal"
|
|
|
|
RN-001.2:
|
|
Descripción: El slug del tenant debe ser único y URL-safe
|
|
Validación: Regex ^[a-z0-9-]+$, único en BD
|
|
|
|
RN-001.3:
|
|
Descripción: Tenant suspendido no permite login de usuarios
|
|
Acción: Validar status en middleware de autenticación
|
|
|
|
RN-001.4:
|
|
Descripción: Límites del plan se heredan al tenant
|
|
Override: Tenant puede tener límites personalizados que sobreescriban el plan
|
|
|
|
RN-001.5:
|
|
Descripción: Soft delete conserva datos 90 días
|
|
Acción: deleted_at marca fecha, cron job limpia después
|
|
```
|
|
|
|
---
|
|
|
|
## API Endpoints
|
|
|
|
```yaml
|
|
Base: /api/v1/tenants
|
|
|
|
Endpoints:
|
|
POST /tenants:
|
|
Descripción: Crear nuevo tenant (Super Admin)
|
|
Body: { name, slug, plan_id, settings? }
|
|
Response: 201 Created
|
|
|
|
GET /tenants:
|
|
Descripción: Listar tenants (Super Admin)
|
|
Query: ?status=active&page=1&limit=20
|
|
Response: 200 OK (paginado)
|
|
|
|
GET /tenants/:id:
|
|
Descripción: Obtener tenant por ID
|
|
Response: 200 OK
|
|
|
|
PUT /tenants/:id:
|
|
Descripción: Actualizar tenant
|
|
Body: { name?, settings?, branding?, limits? }
|
|
Response: 200 OK
|
|
|
|
PATCH /tenants/:id/status:
|
|
Descripción: Cambiar estado del tenant
|
|
Body: { status: "suspended" | "active" }
|
|
Response: 200 OK
|
|
|
|
DELETE /tenants/:id:
|
|
Descripción: Soft delete tenant
|
|
Response: 204 No Content
|
|
|
|
GET /tenants/current:
|
|
Descripción: Obtener tenant del usuario actual
|
|
Response: 200 OK
|
|
```
|
|
|
|
---
|
|
|
|
## Dependencias
|
|
|
|
```yaml
|
|
Dependencias del Catálogo:
|
|
- @CATALOG_TENANT:
|
|
path: shared/catalog/multi-tenancy/
|
|
uso: Patron base multi-tenancy con RLS
|
|
adaptar:
|
|
- Extender modelo Tenant con campos branding
|
|
- Agregar sistema de quotas por plan
|
|
- Integrar con limites de generacion
|
|
docs: shared/catalog/multi-tenancy/README.md
|
|
|
|
- @CATALOG_PAYMENTS:
|
|
path: shared/catalog/payments/
|
|
uso: Suscripciones y billing (Fase 4)
|
|
adaptar:
|
|
- Crear productos/precios en Stripe
|
|
- Definir planes PMC (Starter, Pro, Business, Enterprise)
|
|
- Integrar creditos de generacion
|
|
docs: shared/catalog/payments/README.md
|
|
|
|
Dependencias de Módulos:
|
|
- PMC-007 Admin: Gestión de planes y configuración global
|
|
|
|
Servicios Externos:
|
|
- Stripe (Fase 4 - SaaS comercial)
|
|
|
|
Referencia de Implementacion:
|
|
- Proyecto origen: projects/gamilit/apps/backend/src/modules/auth/entities/tenant.entity.ts
|
|
- RLS policies: projects/gamilit/apps/database/ddl/policies/
|
|
```
|
|
|
|
---
|
|
|
|
## Consideraciones Técnicas
|
|
|
|
### Estrategia Multi-Tenant
|
|
|
|
```yaml
|
|
Tipo: Single Database, Shared Schema
|
|
Aislamiento: Row-Level Security (RLS) en PostgreSQL
|
|
|
|
Implementación:
|
|
1. Columna tenant_id en todas las tablas principales
|
|
2. Políticas RLS que filtran por tenant_id
|
|
3. Middleware que extrae tenant del JWT/sesión
|
|
4. SET app.current_tenant antes de cada query
|
|
```
|
|
|
|
### Ejemplo RLS PostgreSQL
|
|
|
|
```sql
|
|
-- Política para tabla clients
|
|
CREATE POLICY tenant_isolation_policy ON clients
|
|
USING (tenant_id = current_setting('app.current_tenant')::uuid);
|
|
|
|
-- Habilitar RLS
|
|
ALTER TABLE clients ENABLE ROW LEVEL SECURITY;
|
|
```
|
|
|
|
### Storage Isolation
|
|
|
|
```yaml
|
|
Estructura S3:
|
|
bucket/
|
|
├── {tenant_slug}/
|
|
│ ├── assets/
|
|
│ ├── generated/
|
|
│ ├── models/
|
|
│ └── temp/
|
|
```
|
|
|
|
---
|
|
|
|
## Criterios de Aceptación
|
|
|
|
- [ ] Tenant puede ser creado con datos mínimos (name, slug, plan)
|
|
- [ ] RLS impide acceso a datos de otros tenants
|
|
- [ ] Branding se refleja en UI del tenant
|
|
- [ ] Límites del plan se validan antes de operaciones
|
|
- [ ] Soft delete funciona correctamente
|
|
- [ ] API responde correctamente a todos los endpoints
|
|
|
|
---
|
|
|
|
## Referencias
|
|
|
|
- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md)
|
|
- [@CATALOG_TENANT](../../../shared/catalog/modules/multi-tenancy/)
|
|
|
|
---
|
|
|
|
**Documento generado por:** Requirements-Analyst
|
|
**Fecha:** 2025-12-08
|