erp-construccion/docs/02-definicion-modulos/MAI-013-administracion-seguridad/requerimientos/RF-ADM-004-auditoria.md

24 KiB

RF-ADM-004: Auditoría Completa y Trazabilidad de Cambios

ID: RF-ADM-004 Módulo: MAI-013 - Administración & Seguridad Tipo: Requerimiento Funcional Prioridad: P0 (Crítica) Fecha de creación: 2025-11-20 Versión: 1.0


📋 Descripción

El sistema debe proporcionar auditoría completa y automática de todas las operaciones críticas, permitiendo:

  • Registro automático de eventos de seguridad, cambios de datos y operaciones financieras
  • Trazabilidad completa: Quién, qué, cuándo, dónde, por qué, cómo
  • Consultas avanzadas con filtros múltiples (usuario, módulo, fecha, acción)
  • Retención diferenciada: Logs operativos (90 días) vs críticos (5 años)
  • Reportes de cumplimiento para auditorías internas/externas
  • Alertas automáticas ante eventos sospechosos o críticos

La auditoría es fundamental para cumplimiento normativo (ISO 27001, SOC 2, LFPDPPP) y para investigación de incidentes de seguridad o errores operativos.


🎯 Objetivos

Objetivos de Negocio

  1. Cumplimiento normativo: ISO 27001, SOC 2, LFPDPPP, auditorías fiscales
  2. Investigación de incidentes: Rastrear errores, fraudes o accesos no autorizados
  3. Análisis forense: Reconstruir secuencia de eventos ante problemas
  4. Responsabilidad: Identificar quién realizó cada acción crítica
  5. Mejora de procesos: Analizar patrones de uso del sistema

Objetivos Técnicos

  1. Performance: Logging asíncrono (no bloquea operaciones)
  2. Integridad: Logs inmutables (append-only, no se pueden editar/borrar)
  3. Búsqueda rápida: Índices optimizados, queries < 500ms
  4. Almacenamiento eficiente: Compresión de logs antiguos, particionamiento
  5. Disponibilidad: Logs disponibles 24/7 para consulta

🔍 Categorías de Eventos Auditables

1. Autenticación y Autorización (Security Events)

Evento Severidad Retención Ejemplo
Login exitoso Low 1 año Usuario juan@empresa.com login exitoso desde IP 192.168.1.10
Login fallido Medium 1 año Intento fallido para admin@empresa.com desde IP 203.0.113.5
Bloqueo de cuenta High 5 años Cuenta pedro@empresa.com bloqueada por 5 intentos fallidos
Cambio de contraseña Medium 5 años Usuario maria@empresa.com cambió su contraseña
Cambio de rol High 5 años Usuario carlos@empresa.com cambió de engineer a director
Acceso denegado Medium 90 días Usuario jorge@empresa.com intentó acceder a /admin (403)
Logout Low 90 días Usuario ana@empresa.com cerró sesión
Cambio de empresa Low 90 días Usuario luis@empresa.com cambió de Empresa A a Empresa B

2. Gestión de Usuarios (User Management Events)

Evento Severidad Retención Ejemplo
Creación de usuario Medium 5 años Director creó usuario nuevo@empresa.com con rol engineer
Invitación enviada Low 1 año Invitación enviada a invitado@empresa.com
Suspensión de usuario High 5 años Director suspendió a empleado@empresa.com por 30 días
Reactivación Medium 5 años Usuario empleado@empresa.com reactivado
Eliminación de usuario Critical 10 años Super admin eliminó usuario antiguo@empresa.com
Modificación de permisos High 5 años Director otorgó permiso budgets:approve a ingeniero@empresa.com

3. Operaciones Críticas (Business Critical Events)

Evento Severidad Retención Condición Ejemplo
Aprobación de estimación Critical 10 años Monto > $50K Director aprobó Estimación #125 por $2.5M
Aprobación de orden de compra High 5 años Monto > $20K Finanzas aprobó OC #452 por $150K
Modificación de presupuesto Critical 10 años Cualquier cambio Ingeniero modificó Presupuesto Obra A: $10M → $10.5M
Cierre de etapa Critical 10 años Irreversible Ingeniero cerró Etapa 1 de Obra Los Pinos
Eliminación de registro High 5 años Soft delete Admin eliminó Proyecto #45
Cambio de estado de proyecto Medium 5 años - Director cambió Proyecto A de "Ejecución" a "Entregado"
Pago de estimación Critical 10 años Monto > $10K Finanzas registró pago de $1.2M para Estimación #130
Modificación de contrato High 10 años - Ingeniero modificó monto de Contrato #22: $5M → $5.2M

4. Administración del Sistema (System Administration Events)

Evento Severidad Retención Ejemplo
Cambio de configuración High 5 años Admin cambió maxLoginAttempts de 5 a 3
Creación de backup Medium 1 año Sistema creó backup full backup-2025-11-20.tar.gz
Restauración de backup Critical 10 años Admin restauró sistema desde backup del 2025-11-15
Modificación de centro de costo High 5 años Director creó centro 301 - Etapa 3
Activación/desactivación de módulo High 5 años Admin activó módulo INFONAVIT para Empresa A
Cambio de política de seguridad Critical 10 años Admin cambió expiración de contraseñas: 90 → 60 días
Actualización de sistema High 5 años Admin desplegó versión v2.1.5 → v2.2.0

📝 Modelo de Datos de Auditoría

Estructura Completa de AuditLog

interface AuditLog {
  // Identificación
  id: string; // UUID
  timestamp: Date; // ISO 8601 con timezone

  // Usuario (quien hizo la acción)
  userId: string; // UUID
  userName: string; // "Juan Pérez"
  userEmail: string; // "juan@empresa.com"
  userRole: ConstructionRole; // director, engineer, etc.

  // Contexto empresarial
  constructoraId: string; // UUID (multi-tenancy)
  constructoraName: string; // "Constructora ABC"
  projectId?: string; // Si la acción es sobre un proyecto específico
  projectName?: string;

  // Acción
  action: AuditAction; // create, update, delete, approve, login, etc.
  actionDescription: string; // "Aprobó estimación #125 por $2.5M"
  module: string; // projects, budgets, estimations, auth, etc.

  // Entidad afectada
  entityType: string; // project, budget, estimation, user, etc.
  entityId?: string; // UUID del registro afectado
  entityName?: string; // "Proyecto Los Pinos"

  // Cambios detallados (para updates)
  changes?: AuditChange[];

  // Contexto técnico
  ipAddress: string; // "192.168.1.100"
  userAgent: string; // "Mozilla/5.0 (Windows NT 10.0; Win64; x64)..."
  sessionId: string; // UUID
  requestId: string; // Para correlacionar requests relacionados

  // Geolocalización (si disponible)
  geolocation?: {
    latitude: number;
    longitude: number;
    city?: string;
    country?: string;
  };

  // Metadata adicional
  severity: AuditSeverity; // low, medium, high, critical
  category: AuditCategory; // authentication, user_management, business_critical, system_admin
  success: boolean; // true = exitoso, false = fallido
  errorMessage?: string; // Si success = false
  duration?: number; // Milisegundos (para operaciones largas)

  // Datos adicionales (JSON flexible)
  metadata?: Record<string, any>;

  // Control de retención
  retentionPeriod: number; // Días (90, 365, 1825, 3650)
  expiresAt: Date; // Fecha de eliminación automática
}

ENUMs

enum AuditAction {
  // Autenticación
  LOGIN = 'login',
  LOGOUT = 'logout',
  LOGIN_FAILED = 'login_failed',
  PASSWORD_CHANGED = 'password_changed',
  ACCOUNT_LOCKED = 'account_locked',
  ACCOUNT_UNLOCKED = 'account_unlocked',

  // CRUD
  CREATE = 'create',
  READ = 'read', // Solo para lecturas de datos sensibles
  UPDATE = 'update',
  DELETE = 'delete',
  RESTORE = 'restore', // Restaurar soft delete

  // Aprobaciones
  APPROVE = 'approve',
  REJECT = 'reject',

  // Cambios de estado
  STATUS_CHANGE = 'status_change',

  // Administración
  ROLE_CHANGE = 'role_change',
  PERMISSION_GRANT = 'permission_grant',
  PERMISSION_REVOKE = 'permission_revoke',
  CONFIG_CHANGE = 'config_change',
  BACKUP_CREATED = 'backup_created',
  BACKUP_RESTORED = 'backup_restored',

  // Accesos denegados
  ACCESS_DENIED = 'access_denied',
}

enum AuditSeverity {
  LOW = 'low',         // Informativo (login exitoso, logout)
  MEDIUM = 'medium',   // Operaciones normales (crear proyecto, actualizar datos)
  HIGH = 'high',       // Operaciones críticas (aprobaciones >$20K, cambios de rol)
  CRITICAL = 'critical' // Máxima criticidad (aprobaciones >$100K, eliminaciones, backups)
}

enum AuditCategory {
  AUTHENTICATION = 'authentication',
  USER_MANAGEMENT = 'user_management',
  BUSINESS_CRITICAL = 'business_critical',
  SYSTEM_ADMIN = 'system_admin'
}

Cambios Detallados

interface AuditChange {
  field: string; // "totalAmount", "status", "role"
  oldValue: any; // Valor anterior
  newValue: any; // Valor nuevo
  dataType: 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array';
}

Ejemplo:

{
  "id": "uuid-audit-123",
  "timestamp": "2025-11-20T14:30:25.123Z",
  "userId": "uuid-user-456",
  "userName": "Juan Pérez",
  "userEmail": "juan@empresa.com",
  "userRole": "engineer",
  "constructoraId": "uuid-empresa-a",
  "constructoraName": "Constructora ABC",
  "projectId": "uuid-proyecto-1",
  "projectName": "Fraccionamiento Los Pinos",
  "action": "update",
  "actionDescription": "Modificó presupuesto maestro de Etapa 1",
  "module": "budgets",
  "entityType": "budget",
  "entityId": "uuid-budget-789",
  "entityName": "Presupuesto Etapa 1",
  "changes": [
    {
      "field": "totalAmount",
      "oldValue": 10000000,
      "newValue": 10500000,
      "dataType": "number"
    },
    {
      "field": "notes",
      "oldValue": "Presupuesto inicial",
      "newValue": "Presupuesto ajustado por cambio de alcance",
      "dataType": "string"
    }
  ],
  "ipAddress": "192.168.1.50",
  "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
  "sessionId": "uuid-session-abc",
  "requestId": "uuid-request-xyz",
  "severity": "critical",
  "category": "business_critical",
  "success": true,
  "retentionPeriod": 3650,
  "expiresAt": "2035-11-20T14:30:25.123Z"
}

🔍 Consultas y Filtros de Auditoría

Filtros Disponibles

interface AuditLogFilters {
  // Rango de fechas
  startDate?: Date;
  endDate?: Date;

  // Usuario
  userId?: string;
  userEmail?: string;
  userRole?: ConstructionRole;

  // Acción
  action?: AuditAction | AuditAction[];
  module?: string | string[];
  entityType?: string;
  entityId?: string;

  // Severidad y categoría
  severity?: AuditSeverity | AuditSeverity[];
  category?: AuditCategory | AuditCategory[];

  // Éxito
  success?: boolean; // true = solo exitosos, false = solo fallidos

  // Búsqueda de texto libre
  search?: string; // Busca en actionDescription, entityName, userName

  // Proyecto/Empresa
  constructoraId?: string;
  projectId?: string;

  // IP Address
  ipAddress?: string;

  // Paginación
  page?: number;
  limit?: number; // Max 100
  sortBy?: 'timestamp' | 'severity';
  sortOrder?: 'asc' | 'desc';
}

Queries Comunes

1. Todos los cambios a un proyecto específico

const logs = await getAuditLogs({
  projectId: 'uuid-proyecto-1',
  startDate: new Date('2025-11-01'),
  endDate: new Date('2025-11-30'),
  sortBy: 'timestamp',
  sortOrder: 'desc'
});

2. Todas las aprobaciones financieras >$100K

const logs = await getAuditLogs({
  action: 'approve',
  module: ['estimations', 'purchases'],
  severity: 'critical',
  success: true
});

3. Intentos de login fallidos (últimas 24 horas)

const logs = await getAuditLogs({
  action: 'login_failed',
  startDate: subHours(new Date(), 24),
  sortBy: 'timestamp',
  sortOrder: 'desc'
});

4. Todas las acciones de un usuario específico

const logs = await getAuditLogs({
  userEmail: 'juan@empresa.com',
  startDate: new Date('2025-11-01'),
  endDate: new Date('2025-11-30')
});

5. Eventos críticos (alertas de seguridad)

const logs = await getAuditLogs({
  severity: 'critical',
  category: ['authentication', 'user_management'],
  success: false // Solo eventos fallidos
});

🔔 Alertas Automáticas

Reglas de Alertas

Evento Condición Destinatarios Canal
5 logins fallidos en 10 min Mismo usuario o IP Admin de TI Email + SMS
Acceso denegado repetido >10 intentos en 1 hora Admin de TI Email
Aprobación >$100K Cualquier estimación/OC Director + CFO Email
Cambio de rol a Director Cualquier cambio Super Admin Email
Eliminación de registro Cualquier entidad crítica Admin Email
Cambio de configuración Sistema o seguridad Admin de TI Email
Backup fallido Cualquier fallo Admin de TI + Director Email + SMS
Acceso fuera de horario Login 22:00-06:00 Admin de TI Email (diario consolidado)

Ejemplo de Alerta

Asunto: 🚨 Alerta de Seguridad: 5 Intentos de Login Fallidos

Estimado Administrador,

Se han detectado 5 intentos fallidos de login en los últimos 10 minutos:

Usuario: admin@empresa.com
IP: 203.0.113.45
Última intento: 2025-11-20 14:35:12
Ubicación: Culiacán, Sinaloa, México

Acciones tomadas:
- Cuenta bloqueada temporalmente (30 minutos)
- IP agregada a lista de vigilancia

Detalles completos:
https://app.ejemplo.com/admin/audit-logs?userId=uuid-123&action=login_failed

---
Sistema de Auditoría Automática
Constructora ABC

📊 Reportes de Auditoría

1. Reporte de Actividad de Usuario

Reporte de Actividad: juan@empresa.com
Periodo: 01-30 Noviembre 2025

┌─────────────────────────┬───────┬────────────────────────────┐
│ Acción                  │ Count │ Último evento              │
├─────────────────────────┼───────┼────────────────────────────┤
│ Login                   │   42  │ 2025-11-30 17:45           │
│ Logout                  │   40  │ 2025-11-30 18:30           │
│ Crear proyecto          │    3  │ 2025-11-25 10:15           │
│ Actualizar presupuesto  │   18  │ 2025-11-29 14:20           │
│ Aprobar estimación      │    5  │ 2025-11-28 16:00           │
│ Modificar contrato      │    2  │ 2025-11-22 11:30           │
└─────────────────────────┴───────┴────────────────────────────┘

Eventos críticos: 5 aprobaciones de estimaciones (total $8.5M)
Eventos fallidos: 2 (acceso denegado a módulo Finanzas)

Proyectos modificados:
- Fraccionamiento Los Pinos (15 acciones)
- Torre Residencial Aura (8 acciones)

2. Reporte de Cumplimiento (Compliance)

Reporte de Auditoría para Cumplimiento ISO 27001
Constructora ABC S.A. de C.V.
Periodo: Q4 2025 (Oct-Nov-Dic)

1. AUTENTICACIÓN Y CONTROL DE ACCESO
   - Total logins: 2,450 ✅
   - Logins fallidos: 45 (1.8%) ✅
   - Cuentas bloqueadas: 3 ✅
   - Cambios de contraseña: 120 ✅
   - Sesiones concurrentes promedio: 35 ✅

2. GESTIÓN DE USUARIOS
   - Usuarios creados: 12 ✅
   - Usuarios suspendidos: 2 ✅
   - Usuarios eliminados: 0 ✅
   - Cambios de rol: 5 (todos auditados) ✅
   - Permisos modificados: 8 (todos auditados) ✅

3. OPERACIONES CRÍTICAS
   - Aprobaciones financieras >$100K: 25 (todas auditadas) ✅
   - Modificaciones de presupuestos: 45 (todas auditadas) ✅
   - Eliminaciones de registros: 3 (todas auditadas) ✅
   - Cambios de configuración: 2 (ambos auditados) ✅

4. RESPALDO Y RECUPERACIÓN
   - Backups exitosos: 90/90 (100%) ✅
   - Backups fallidos: 0 ✅
   - Restauraciones: 0 ✅

5. INCIDENTES DE SEGURIDAD
   - Accesos no autorizados: 0 ✅
   - Brechas de datos: 0 ✅
   - Alertas de seguridad: 15 (todas investigadas) ✅

CONCLUSIÓN: Sistema cumple 100% con requisitos ISO 27001

3. Timeline de Proyecto (Forense)

Timeline: Proyecto Fraccionamiento Los Pinos
Periodo: 01-30 Noviembre 2025

2025-11-01 09:00 | Director        | Creó proyecto "Fraccionamiento Los Pinos"
2025-11-01 09:15 | Director        | Asignó Ingeniero: Juan Pérez
2025-11-02 10:30 | Ingeniero       | Creó presupuesto maestro: $50M
2025-11-05 14:20 | Ingeniero       | Modificó presupuesto: $50M → $52M
2025-11-08 16:45 | Finanzas        | Aprobó presupuesto ajustado
2025-11-10 11:00 | Compras         | Creó orden de compra #1: $1.2M
2025-11-10 15:30 | Finanzas        | Aprobó OC #1
2025-11-15 09:45 | Residente       | Capturó avance Etapa 1: 15%
2025-11-20 10:00 | Ingeniero       | Aprobó avance 15%
2025-11-25 14:00 | Finanzas        | Creó estimación #1: $7.5M
2025-11-26 16:30 | Director        | Aprobó estimación #1
2025-11-28 11:00 | Finanzas        | Registró pago: $7.5M
2025-11-30 17:00 | Ingeniero       | Cambió estado: "Ejecución" → "Entregado"

Total eventos: 145
Usuarios involucrados: 5 (Director, Ingeniero, Finanzas, Compras, Residente)

📋 Casos de Uso

Caso 1: Investigación de Error en Presupuesto

Contexto: Director detecta que presupuesto de Obra A cambió de $10M a $15M sin autorización.

Flujo:

  1. Director va a "Auditoría" → "Consultar Logs"
  2. Filtra:
    • Entidad: Presupuesto Obra A
    • Acción: Update
    • Fecha: Últimos 30 días
  3. Sistema muestra:
    2025-11-15 14:30 | Ingeniero Juan | UPDATE budget
    Campo: totalAmount
    Cambio: $10,000,000 → $15,000,000
    IP: 192.168.1.50
    Sesión: uuid-session-abc
    
  4. Director click en evento → Ve detalles completos:
    • Usuario: juan@empresa.com
    • Razón: "Ajuste por cambio de alcance aprobado en minuta 25/10/2025"
    • Archivos adjuntos: minuta-2025-10-25.pdf
  5. Director valida que cambio es legítimo (hay minuta)
  6. Cierra investigación

Resultado: Trazabilidad completa del cambio, investigación en 5 minutos.

Caso 2: Detección de Fraude (Intento)

Contexto: Alerta automática: "Usuario compras@empresa.com aprobó OC #455 de $500K fuera de horario (23:45)"

Flujo:

  1. Admin de TI recibe alerta por email a las 23:46
  2. Admin accede a sistema → "Auditoría" → Busca evento
  3. Ve detalles:
    2025-11-20 23:45 | Comprador Pedro | APPROVE purchase_order
    OC #455: $500,000 (Proveedor: ABC Materiales S.A.)
    IP: 203.0.113.99 (externa, no es IP de oficina)
    Ubicación: Guadalajara, Jalisco (oficina está en Culiacán)
    
  4. Admin llama a Pedro (Comprador):
    • Pedro: "No estoy trabajando, estoy en casa"
    • Admin: "¿Aprobaste OC #455?"
    • Pedro: "No, yo no aprobé nada"
  5. Admin identifica: Sesión comprometida
  6. Acciones inmediatas:
    • Bloquea cuenta de Pedro
    • Revierte aprobación de OC #455
    • Fuerza logout de todas las sesiones activas
    • Cambia contraseña de Pedro
    • Bloquea IP 203.0.113.99
  7. Contacta a Pedro para reactivar cuenta con nueva contraseña

Resultado: Fraude detectado y bloqueado en 15 minutos. Pérdida evitada: $500K.

Caso 3: Auditoría Externa (ISO 27001)

Contexto: Auditor externo solicita evidencia de controles de acceso.

Flujo:

  1. Auditor solicita: "Todos los cambios de rol en 2025"
  2. Admin va a "Reportes" → "Reporte de Auditoría de Cumplimiento"
  3. Selecciona:
    • Tipo: Cambios de Rol
    • Periodo: 2025-01-01 a 2025-12-31
  4. Sistema genera reporte PDF:
    Reporte de Cambios de Rol - 2025
    Constructora ABC S.A. de C.V.
    
    Total cambios: 12
    
    #  Fecha         Usuario           Rol Anterior  Rol Nuevo    Autorizado Por
    1  2025-02-15    juan@empresa.com  engineer      director     Super Admin
    2  2025-03-20    maria@empresa.com resident      engineer     Director
    ...
    
    Conclusión: Todos los cambios fueron autorizados por Director o Super Admin.
    Cumplimiento: 100%
    
  5. Admin exporta reporte y entrega a auditor
  6. Auditor valida que todos los cambios tienen autorización

Resultado: Auditoría externa aprobada en 1 día (vs 1 semana manual).


Criterios de Aceptación

AC1: Registro Automático de Eventos

DADO un usuario que aprueba una estimación de $100K CUANDO completa la aprobación ENTONCES

  • Sistema registra evento automáticamente (sin intervención del usuario)
  • Log contiene: usuario, timestamp, acción, entidad, monto, IP, sesión
  • Severidad = critical (por monto >$100K)
  • Retención = 10 años
  • Log es inmutable (no se puede editar ni borrar)

AC2: Consulta con Filtros Múltiples

DADO un admin que busca "aprobaciones financieras de Juan en noviembre" CUANDO aplica filtros:

{
  userEmail: 'juan@empresa.com',
  action: 'approve',
  module: ['estimations', 'purchases'],
  startDate: '2025-11-01',
  endDate: '2025-11-30'
}

ENTONCES

  • Sistema retorna solo registros que cumplen TODOS los filtros
  • Resultados ordenados por timestamp desc (más reciente primero)
  • Query ejecuta en < 500ms
  • Paginación funciona correctamente

AC3: Alertas Automáticas

DADO 5 intentos de login fallidos en 10 minutos CUANDO ocurre el 5to intento ENTONCES

  • Sistema envía alerta por email a Admin de TI
  • Cuenta se bloquea automáticamente por 30 minutos
  • IP se agrega a lista de vigilancia
  • Alerta contiene: usuario, IP, ubicación, timestamp

AC4: Trazabilidad de Cambios

DADO un presupuesto que cambió de $10M a $15M CUANDO se consulta auditoría ENTONCES

  • Log muestra cambio detallado:
    {
      "field": "totalAmount",
      "oldValue": 10000000,
      "newValue": 15000000
    }
    
  • Log muestra quién lo cambió, cuándo, desde dónde
  • Si hay justificación, se incluye en metadata

AC5: Retención Diferenciada

DADO logs de diferentes severidades CUANDO se ejecuta proceso de limpieza automática ENTONCES

  • Logs low severity: eliminados tras 90 días
  • Logs medium severity: eliminados tras 1 año
  • Logs high severity: eliminados tras 5 años
  • Logs critical severity: eliminados tras 10 años
  • Proceso no elimina logs antes de expiresAt

🧪 Escenarios de Prueba

Test 1: Logging Automático

describe('RF-ADM-004: Audit Logging', () => {
  it('should automatically log critical operations', async () => {
    const engineer = await loginAs('engineer');

    // Aprobar estimación
    const response = await api.patch('/estimations/123/approve', {}, {
      headers: { Authorization: engineer.token }
    });

    expect(response.status).toBe(200);

    // Verificar log
    const logs = await getAuditLogs({
      action: 'approve',
      entityId: '123',
      userId: engineer.id
    });

    expect(logs).toHaveLength(1);
    expect(logs[0]).toMatchObject({
      userId: engineer.id,
      action: 'approve',
      module: 'estimations',
      entityId: '123',
      severity: 'critical',
      success: true
    });
  });
});

Test 2: Inmutabilidad de Logs

describe('RF-ADM-004: Log Immutability', () => {
  it('should not allow editing or deleting logs', async () => {
    const log = await createAuditLog({
      action: 'login',
      userId: 'user-123'
    });

    // Intentar modificar
    const updateResponse = await api.patch(`/audit-logs/${log.id}`, {
      action: 'logout'
    });

    expect(updateResponse.status).toBe(403);
    expect(updateResponse.data.error).toBe('Audit logs are immutable');

    // Intentar eliminar
    const deleteResponse = await api.delete(`/audit-logs/${log.id}`);

    expect(deleteResponse.status).toBe(403);
    expect(deleteResponse.data.error).toBe('Audit logs cannot be deleted');
  });
});

🔗 Referencias


Generado: 2025-11-20 Versión: 1.0 Autor: Sistema de Documentación Técnica Estado: Completo