🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
219 lines
4.5 KiB
Markdown
219 lines
4.5 KiB
Markdown
---
|
|
id: "BA-007-TENANTS"
|
|
title: "BA-007: Modulo de Tenants"
|
|
type: "Module Definition"
|
|
epic: "BA-007"
|
|
status: "Draft"
|
|
project: "betting-analytics"
|
|
version: "1.0.0"
|
|
created_date: "2026-01-04"
|
|
updated_date: "2026-01-04"
|
|
---
|
|
|
|
# BA-007: Modulo de Tenants
|
|
|
|
**Version:** 1.0.0
|
|
**Fecha:** 2026-01-04
|
|
**Estado:** Definicion
|
|
**Prioridad:** Alta
|
|
|
|
---
|
|
|
|
## Descripcion General
|
|
|
|
El modulo de Tenants proporciona la arquitectura multi-tenant que permite aislar datos y configuraciones entre diferentes organizaciones que utilicen la plataforma de Betting Analytics como SaaS.
|
|
|
|
---
|
|
|
|
## Objetivos
|
|
|
|
1. Aislar completamente los datos entre tenants
|
|
2. Permitir configuracion personalizada por tenant
|
|
3. Gestionar limites y cuotas segun plan
|
|
4. Preparar arquitectura para comercializacion SaaS
|
|
|
|
---
|
|
|
|
## Entidades del Dominio
|
|
|
|
### Tenant
|
|
|
|
```yaml
|
|
Entidad: Tenant
|
|
Descripcion: Organizacion que utiliza la plataforma
|
|
Atributos:
|
|
- id: UUID (PK)
|
|
- name: string
|
|
- slug: string (unico, URL-friendly)
|
|
- status: enum [active, suspended, trial, cancelled]
|
|
- plan_id: UUID (FK a Plan)
|
|
- settings: JSONB
|
|
- limits: JSONB
|
|
- created_at: timestamp
|
|
- updated_at: timestamp
|
|
- deleted_at: timestamp (soft delete)
|
|
|
|
Relaciones:
|
|
- 1:N con User
|
|
- 1:N con Prediction
|
|
- 1:N con Model
|
|
- N:1 con Plan
|
|
```
|
|
|
|
### Plan
|
|
|
|
```yaml
|
|
Entidad: Plan
|
|
Descripcion: Plan de suscripcion con limites
|
|
Atributos:
|
|
- id: UUID (PK)
|
|
- name: string (Free, Pro, Enterprise)
|
|
- code: string
|
|
- features: JSONB
|
|
- limits: JSONB
|
|
- predictions_per_month: number
|
|
- models_max: number
|
|
- history_days: number
|
|
- users_max: number
|
|
- price_monthly: decimal
|
|
- price_yearly: decimal
|
|
- is_active: boolean
|
|
- created_at: timestamp
|
|
- updated_at: timestamp
|
|
|
|
Relaciones:
|
|
- 1:N con Tenant
|
|
```
|
|
|
|
---
|
|
|
|
## Funcionalidades
|
|
|
|
### F-007.1: Gestion de Tenants
|
|
|
|
| ID | Funcionalidad | Descripcion | Prioridad |
|
|
|----|---------------|-------------|-----------|
|
|
| F-007.1.1 | Crear tenant | Registro de nueva organizacion | Alta |
|
|
| F-007.1.2 | Editar tenant | Modificar datos y configuracion | Alta |
|
|
| F-007.1.3 | Suspender tenant | Desactivar acceso temporalmente | Media |
|
|
| F-007.1.4 | Eliminar tenant | Soft delete con retencion | Baja |
|
|
|
|
### F-007.2: Aislamiento de Datos
|
|
|
|
| ID | Funcionalidad | Descripcion | Prioridad |
|
|
|----|---------------|-------------|-----------|
|
|
| F-007.2.1 | RLS PostgreSQL | Row-Level Security por tenant_id | Alta |
|
|
| F-007.2.2 | Middleware | Inyeccion automatica de tenant_id | Alta |
|
|
| F-007.2.3 | Query scoping | Filtrado automatico en queries | Alta |
|
|
|
|
---
|
|
|
|
## Reglas de Negocio
|
|
|
|
```yaml
|
|
RN-007.1:
|
|
Descripcion: Todo tenant debe tener un plan asignado
|
|
Default: Plan "Free"
|
|
|
|
RN-007.2:
|
|
Descripcion: El slug del tenant debe ser unico
|
|
Validacion: Regex ^[a-z0-9-]+$
|
|
|
|
RN-007.3:
|
|
Descripcion: Tenant suspendido no permite login
|
|
Accion: Validar status en middleware
|
|
|
|
RN-007.4:
|
|
Descripcion: Soft delete conserva datos 90 dias
|
|
```
|
|
|
|
---
|
|
|
|
## API Endpoints
|
|
|
|
```yaml
|
|
Base: /api/v1/tenants
|
|
|
|
Endpoints:
|
|
POST /tenants:
|
|
Descripcion: Crear tenant (Super Admin)
|
|
Body: { name, slug, plan_id }
|
|
Response: 201 Created
|
|
|
|
GET /tenants:
|
|
Descripcion: Listar tenants (Super Admin)
|
|
Response: 200 OK (paginado)
|
|
|
|
GET /tenants/:id:
|
|
Descripcion: Obtener tenant por ID
|
|
Response: 200 OK
|
|
|
|
PUT /tenants/:id:
|
|
Descripcion: Actualizar tenant
|
|
Response: 200 OK
|
|
|
|
PATCH /tenants/:id/status:
|
|
Descripcion: Cambiar estado
|
|
Body: { status }
|
|
Response: 200 OK
|
|
|
|
GET /tenants/current:
|
|
Descripcion: Tenant del usuario actual
|
|
Response: 200 OK
|
|
```
|
|
|
|
---
|
|
|
|
## Consideraciones Tecnicas
|
|
|
|
### Estrategia Multi-Tenant
|
|
|
|
```yaml
|
|
Tipo: Single Database, Shared Schema
|
|
Aislamiento: Row-Level Security (RLS) PostgreSQL
|
|
|
|
Implementacion:
|
|
1. Columna tenant_id en tablas principales
|
|
2. Politicas RLS que filtran por tenant_id
|
|
3. Middleware que extrae tenant del JWT
|
|
4. SET app.current_tenant antes de queries
|
|
```
|
|
|
|
### Ejemplo RLS
|
|
|
|
```sql
|
|
CREATE POLICY tenant_isolation ON predictions
|
|
USING (tenant_id = current_setting('app.current_tenant')::uuid);
|
|
|
|
ALTER TABLE predictions ENABLE ROW LEVEL SECURITY;
|
|
```
|
|
|
|
---
|
|
|
|
## Dependencias
|
|
|
|
```yaml
|
|
Dependencias:
|
|
- BA-001 (auth): Autenticacion de usuarios
|
|
- BA-008 (payments): Gestion de planes/suscripciones
|
|
|
|
Catalogos:
|
|
- shared/catalog/multi-tenancy/
|
|
```
|
|
|
|
---
|
|
|
|
## Criterios de Aceptacion
|
|
|
|
- [ ] Tenant puede ser creado con datos minimos
|
|
- [ ] RLS impide acceso a datos de otros tenants
|
|
- [ ] Limites del plan se validan antes de operaciones
|
|
- [ ] Soft delete funciona correctamente
|
|
- [ ] API responde correctamente
|
|
|
|
---
|
|
|
|
**Documento generado por:** NEXUS Orchestration
|
|
**Fecha:** 2026-01-04
|
|
|