# RF-MGN-001-008: Record Rules (Row Level Security) **Módulo:** MGN-001 - Fundamentos **Prioridad:** P1 (Post-MVP) **Story Points:** 13 **Estado:** Definido **Fecha:** 2025-11-23 ## Descripción El sistema debe implementar Record Rules (RLS - Row Level Security) para filtrar automáticamente registros según reglas definidas por rol. Un usuario solo ve/edita registros que cumplen las reglas de sus roles. ## Actores - **Actor Principal:** Administrador de Sistema (define reglas) - **Actores Secundarios:** Usuario (consume reglas automáticamente) ## Precondiciones 1. Sistema RBAC debe estar implementado (RF-MGN-001-002) 2. PostgreSQL RLS debe estar habilitado en tablas 3. Usuario debe estar autenticado ## Flujo Principal 1. Administrador accede a módulo de Record Rules 2. Administrador selecciona modelo (ej: sale.order) 3. Administrador selecciona rol (ej: Vendedor) 4. Administrador define regla SQL (ej: "assigned_to_id = get_current_user_id()") 5. Administrador define operaciones: read, create, update, delete 6. Sistema crea registro en auth.record_rules 7. Sistema genera RLS policy en PostgreSQL: ```sql CREATE POLICY vendedor_ve_sus_ordenes ON sales.orders FOR SELECT TO vendedor_role USING (assigned_to_id = get_current_user_id()); ``` 8. Usuario con rol Vendedor consulta sale.orders 9. PostgreSQL aplica RLS policy automáticamente 10. Usuario solo ve sus propias órdenes (filtrado a nivel DB) ## Flujos Alternativos ### FA-1: Múltiples Roles con Reglas Diferentes 1. Usuario tiene roles: Vendedor + Supervisor 2. Vendedor: ve solo sus órdenes (assigned_to_id = user_id) 3. Supervisor: ve órdenes de su equipo (team_id IN user.teams) 4. Sistema aplica OR entre reglas (usuario ve unión de ambas) ### FA-2: Regla Compleja con JOINs 1. Administrador define regla que requiere JOIN 2. Ejemplo: "Ver proyectos de empresas donde usuario tiene acceso" ```sql project_id IN ( SELECT p.id FROM projects p JOIN user_companies uc ON uc.company_id = p.company_id WHERE uc.user_id = get_current_user_id() ) ``` 3. Sistema valida sintaxis SQL 4. Sistema crea RLS policy con subquery ### FA-3: Bypass de RLS para Administrador 1. Usuario con rol Administrator 2. Sistema NO aplica RLS (administrador ve todo) 3. RLS policy tiene cláusula: `OR has_role('administrator')` ### FA-4: Regla Inválida 1. Administrador define regla con SQL inválido 2. Sistema valida sintaxis SQL antes de guardar 3. Sistema retorna error 400: "Sintaxis SQL inválida" ### FA-5: Desactivación Temporal de Regla 1. Administrador desactiva regla (status='inactive') 2. Sistema elimina RLS policy de PostgreSQL 3. Rol afectado pasa a no tener restricciones (o aplica otras reglas activas) ## Reglas de Negocio - **RN-1:** Cada rol puede tener múltiples record rules por modelo - **RN-2:** Record rules se aplican con OR (unión): usuario ve registros que cumplen alguna regla - **RN-3:** Administrador bypasea RLS (ve todos los registros) - **RN-4:** Reglas pueden definirse para: read, create, update, delete (independientes) - **RN-5:** Funciones SQL permitidas: get_current_user_id(), get_current_tenant_id(), has_role() - **RN-6:** RLS se aplica a nivel PostgreSQL (no bypasseable desde código) - **RN-7:** Reglas heredadas: hijo hereda reglas del padre (rol herencia) ## Criterios de Aceptación - [ ] Administrador puede definir record rules con expresiones SQL - [ ] Sistema valida sintaxis SQL antes de guardar regla - [ ] PostgreSQL RLS se aplica automáticamente en queries - [ ] Usuario solo ve registros que cumplen reglas de sus roles - [ ] Múltiples reglas se combinan con OR (unión) - [ ] Administrador bypasea RLS (ve todos los registros) - [ ] Reglas pueden aplicarse a read, create, update, delete - [ ] Funciones SQL get_current_user_id() y get_current_tenant_id() funcionan - [ ] Herencia de roles incluye herencia de record rules - [ ] Desactivación de regla elimina RLS policy ## Entidades Involucradas - **Principales:** - auth.record_rules (role_id, model_id, rule_sql, operations, status) - auth.roles (roles con reglas) - auth.models (modelos con RLS) - **Relacionadas:** - PostgreSQL RLS Policies (nivel DB) ## Referencias - [ALCANCE-POR-MODULO.md - MGN-001](../../01-definicion-modulos/ALCANCE-POR-MODULO.md#mgn-001-fundamentos) - [Auth Domain Model](../domain-models/auth-domain.md) - [Auth Schema DDL](../database-design/schemas/auth-schema-ddl.sql) - [Gap Analysis MGN-001](../../01-definicion-modulos/gaps/GAP-ANALYSIS-MGN-001.md) ## Notas Técnicas - **Patrón Odoo:** Similar a ir.rule (record rules de Odoo) - **PostgreSQL RLS:** ```sql -- Habilitar RLS en tabla ALTER TABLE sales.orders ENABLE ROW LEVEL SECURITY; -- Crear policy CREATE POLICY vendedor_ve_sus_ordenes ON sales.orders FOR SELECT TO vendedor_role USING (assigned_to_id = current_setting('app.current_user_id')::INTEGER); ``` - **Funciones Contextuales:** ```sql CREATE OR REPLACE FUNCTION get_current_user_id() RETURNS INTEGER AS $$ BEGIN RETURN current_setting('app.current_user_id')::INTEGER; END; $$ LANGUAGE plpgsql; ``` - **Set Context en Request:** ```typescript await this.db.query( `SELECT set_config('app.current_user_id', $1, false)`, [req.user.id] ); ``` - **Performance:** Índices en columnas usadas en reglas (assigned_to_id, team_id, etc.) - **Testing:** Casos de prueba por rol para validar RLS ## Dependencias - **RF Dependientes:** - RF-MGN-001-001 (Autenticación) - RF-MGN-001-002 (Roles) - **Bloqueante para:** Módulos que requieren filtrado por usuario (CRM, Ventas, Proyectos)