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