# US-MGN004-003: Aislamiento de Datos Multi-Tenant ## Identificacion | Campo | Valor | |-------|-------| | **ID** | US-MGN004-003 | | **Modulo** | MGN-004 Tenants | | **RF Relacionado** | RF-TENANT-003 | | **Prioridad** | P0 - Critica | | **Story Points** | 13 | | **Sprint** | TBD | --- ## Historia de Usuario **Como** Usuario del sistema **Quiero** que mis datos esten completamente aislados de otros tenants **Para** garantizar la seguridad y privacidad de la informacion de mi organizacion --- ## Criterios de Aceptacion ### AC-001: Usuario solo ve datos de su tenant ```gherkin Given usuario de Tenant A autenticado And 100 productos en Tenant A And 50 productos en Tenant B When consulta GET /api/v1/products Then solo ve los 100 productos de Tenant A And no ve ningun producto de Tenant B ``` ### AC-002: No acceso a recurso de otro tenant ```gherkin Given usuario de Tenant A autenticado And producto "P-001" pertenece a Tenant B When intenta GET /api/v1/products/P-001 Then el sistema responde con status 404 And el mensaje es "Recurso no encontrado" And NO revela que el recurso existe en otro tenant ``` ### AC-003: Asignacion automatica de tenant_id ```gherkin Given usuario de Tenant A autenticado When crea un producto sin especificar tenant_id Then el sistema asigna automaticamente tenant_id de Tenant A And el producto queda en Tenant A ``` ### AC-004: No permitir modificar tenant_id ```gherkin Given usuario de Tenant A autenticado And producto existente en Tenant A When intenta actualizar tenant_id a Tenant B Then el sistema responde con status 400 And el mensaje es "No se puede cambiar el tenant de un recurso" ``` ### AC-005: RLS previene acceso sin contexto ```gherkin Given conexion a base de datos sin app.current_tenant_id When se ejecuta SELECT * FROM core_users.users Then el resultado es vacio And no se produce error And RLS previene acceso a datos ``` ### AC-006: TenantGuard valida tenant activo ```gherkin Given usuario con token JWT valido And tenant en estado "suspended" When intenta acceder a cualquier endpoint Then el sistema responde con status 403 And el mensaje indica "Tenant suspendido" ``` ### AC-007: TenantGuard detecta trial expirado ```gherkin Given usuario de tenant en estado "trial" And trial_ends_at fue hace 2 dias When intenta acceder a cualquier endpoint Then el sistema responde con status 403 And el mensaje indica "Periodo de prueba expirado" ``` ### AC-008: Platform Admin switch explicito ```gherkin Given Platform Admin autenticado And tiene acceso a todos los tenants When NO ha hecho switch a ningun tenant Then no puede ver datos de ningun tenant And debe hacer POST /api/v1/platform/switch-tenant/:id primero ``` ### AC-009: Middleware setea contexto PostgreSQL ```gherkin Given request autenticado con tenant_id en JWT When pasa por TenantContextMiddleware Then se ejecuta SET app.current_tenant_id = :tenantId And todas las queries posteriores filtran por ese tenant ``` ### AC-010: Indices optimizados por tenant ```gherkin Given tabla users con 1M registros distribuidos en 100 tenants When usuario de Tenant A busca por email Then la query usa indice compuesto (tenant_id, email) And tiempo de respuesta < 50ms ``` --- ## Tareas Tecnicas | ID | Tarea | Estimacion | |----|-------|------------| | T-001 | Crear migracion RLS policies | 3 SP | | T-002 | Implementar TenantGuard | 2 SP | | T-003 | Implementar TenantContextMiddleware | 2 SP | | T-004 | Crear TenantBaseEntity | 1 SP | | T-005 | Crear TenantAwareService base | 2 SP | | T-006 | Tests de aislamiento | 3 SP | | **Total** | | **13 SP** | --- ## Notas de Implementacion ### Migracion RLS ```sql -- Habilitar RLS en tablas ALTER TABLE core_users.users ENABLE ROW LEVEL SECURITY; -- Funcion para obtener tenant actual CREATE OR REPLACE FUNCTION current_tenant_id() RETURNS UUID AS $$ BEGIN RETURN NULLIF(current_setting('app.current_tenant_id', true), '')::UUID; END; $$ LANGUAGE plpgsql STABLE; -- Politica de SELECT CREATE POLICY tenant_isolation_select ON core_users.users FOR SELECT USING (tenant_id = current_tenant_id()); -- Politica de INSERT CREATE POLICY tenant_isolation_insert ON core_users.users FOR INSERT WITH CHECK (tenant_id = current_tenant_id()); ``` ### TenantBaseEntity ```typescript export abstract class TenantBaseEntity { @Column({ name: 'tenant_id' }) tenantId: string; @ManyToOne(() => Tenant) @JoinColumn({ name: 'tenant_id' }) tenant: Tenant; } ``` --- ## Mockup de Referencia Ver RF-TENANT-003.md diagramas de arquitectura. --- ## Dependencias | Tipo | Descripcion | |------|-------------| | Database | PostgreSQL 12+ con RLS | | Auth | JWT con tenant_id claim | | Backend | Schema core_tenants creado | --- ## Definition of Done - [ ] RLS habilitado en TODAS las tablas de negocio - [ ] TenantGuard implementado y aplicado globalmente - [ ] TenantContextMiddleware seteando variable de sesion - [ ] Tests de aislamiento pasando (cross-tenant access blocked) - [ ] Performance test con queries filtradas por tenant - [ ] Security review aprobado - [ ] Documentacion de patrones para nuevas tablas