erp-core/docs/04-modelado/requerimientos-funcionales/mgn-001/RF-MGN-001-008-record-rules-rls.md

5.5 KiB

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:
    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"
    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

Notas Técnicas

  • Patrón Odoo: Similar a ir.rule (record rules de Odoo)
  • PostgreSQL RLS:
    -- 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:
    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:
    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)