Overview
PROD-SYS maintains comprehensive audit logs for all critical system changes, personnel actions, and data modifications. The audit system provides accountability, compliance documentation, and forensic investigation capabilities.Audit Architecture
Database Schema
Table:auditoria
backend/database/sqlite.js:1184-1195
Audit Service
File:backend/shared/audit/AuditService.js
Centralized service for logging all auditable events:
backend/shared/audit/AuditService.js:3-93
Audited Events
System Events
System Initialization
Action:SYSTEM_INITIALIZATION
Trigger: First-time bootstrap process
Logged Data:
backend/domains/bootstrap/bootstrap.service.js:71-79
Personnel Events
Status Changes
Action:STATUS_CHANGE
Triggers:
- Employment status update (Activo → Incapacitado, Baja, etc.)
- Absence registration
- Automatic return from absence
backend/domains/personal/personal.service.js:191-192
Data Updates
Action:UPDATE
Triggers:
- Personnel information changes (email, phone, area)
- Any modification to persona record
backend/domains/personal/personal.service.js:194
Role Changes
Action:ROLE_CHANGE
Trigger: System role assignment
Example:
backend/domains/personal/personal.service.js:255-266
Operational Assignments
Action:OPERATIONAL_ASSIGNMENT
Trigger: Personnel assigned to production process/machine
Example:
backend/domains/personal/personal.service.js:339-351
User Account Events
Access Control Toggle
Action:TOGGLE_ACCESO
Trigger: Admin enables/disables system access
Example:
backend/domains/personal/personal.service.js:217-230
Password Reset
Action:PASSWORD_RESET
Trigger: Administrator resets user password
Example:
backend/domains/personal/personal.service.js:284-290
Passwords are never logged. Only the fact that a reset occurred is recorded.
Audit Categories
Predefined Categories
Enum:AuditService.CATEGORIAS
backend/shared/audit/AuditService.js:4-8
Automatic Categorization
The audit service automatically assigns categories based on context:backend/shared/audit/AuditService.js:22-30
Category Validation
Only predefined categories are accepted:backend/shared/audit/AuditService.js:32-36
Correction Tracking
Marking Corrections
Flag:es_correccion (boolean)
Purpose: Distinguish intentional changes from error corrections
Effect:
- Prefixes action with
CORRECCION_ - Prefixes
motivo_cambiowith[CORRECCIÓN] - Auto-assigns
ERROR_CAPTURAcategory if not specified
backend/shared/audit/AuditService.js:38-49
Example Correction:
Querying Audit Logs
API Endpoint
Endpoint:GET /api/auditoria
Permission: VIEW_AUDIT
Allowed Roles: Administrador, Inspector, Gerencia
Location: backend/shared/audit/audit.routes.js:14-26
Query Parameters
Filter by User
usuario contains “admin” (partial match)
Filter by Entity
Persona entities (exact match)
Filter by Date
Combined Filters
Query Implementation
backend/shared/audit/AuditRepository.js:29-46
Response Format
valor_anterior and valor_nuevo are stored as JSON strings. Parse them to access structured data.Entity-Specific Audit Trails
Query by Entity
Method:findByEntity(entidad, entidad_id)
Purpose: Retrieve complete history for a specific record
Example:
backend/shared/audit/AuditRepository.js:24-27
Use Cases:
- Personnel history review
- Investigation of specific incidents
- Compliance documentation for individual records
Implementation in Services
Audit logging is embedded in business logic:backend/domains/personal/personal.service.js:191-195
Audit Reliability
Non-Blocking Design
Philosophy: Audit failures should not block business operations Implementation:backend/shared/audit/AuditService.js:52-59
Required Fields
Mandatory:usuario: Who performed the actionaccion: What action was takenentidad: What type of entity was affected
motivo_cambio: Required whenes_correccion = truecategoria_motivo: Must be valid if provided (from closed catalog)
entidad_id: Specific record affectedvalor_anterior: State before changevalor_nuevo: State after change
Compliance Features
Immutability
Audit logs are append-only:- No UPDATE or DELETE operations on
auditoriatable - Timestamp auto-generated on insert
- Primary key auto-increment (sequential)
Traceability
Who:usuario field stores username
What: accion field describes action type
When: fecha_hora automatically timestamped
Where: entidad and entidad_id identify affected record
Why: motivo_cambio provides justification
How: valor_anterior and valor_nuevo show delta
Data Retention
Current Implementation: Unlimited retention Query Limit: 200 most recent records per query (performance protection) Recommendations:- Implement archival process for old logs (>1 year)
- Export to long-term storage (S3, archive database)
- Maintain indexes on
fecha_horafor performance
backend/shared/audit/AuditRepository.js:44
Audit Reports
Common Queries
User Activity Report
Role Change History
Corrections Audit
System State Changes
Access Control Changes
Audit Best Practices
For Developers
- Log all state-changing operations
- Always include
motivo_cambioin audit calls - Use specific action types (avoid generic “UPDATE”)
- Store before/after states for data changes
- Use
es_correccionflag for error fixes - Choose appropriate
categoria_motivo - Don’t log sensitive data (passwords, tokens)
- Handle audit failures gracefully (log but don’t block)
For Administrators
- Review audit logs weekly for anomalies
- Investigate unexpected role changes
- Monitor high-frequency correction actions
- Verify
motivo_cambioquality in user training - Export audit logs for long-term retention
- Ensure audit access is restricted (VIEW_AUDIT permission)
- Document investigation procedures
For Compliance
- Establish audit retention policy
- Define automated alerting for sensitive actions
- Require detailed justifications for corrections
- Perform regular audit log reviews
- Maintain audit trail for regulatory inspections
- Separate audit storage from operational database
- Implement audit log backups
Troubleshooting
Missing Audit Entries
Check:- Audit service initialization in business logic
- Error logs for audit failures
- Database write permissions
- Transaction rollbacks (audit may be rolled back with operation)
auditService.logChange() is called after successful database operations
Performance Issues
Symptoms: Slow queries on large audit tables Solutions:- Add index on
fecha_hora:CREATE INDEX idx_audit_fecha ON auditoria(fecha_hora); - Add index on
usuario:CREATE INDEX idx_audit_usuario ON auditoria(usuario); - Implement archival (move old records to archive table)
- Increase query limit cautiously (currently 200)
Invalid Category Warnings
Log Message:Categoría de motivo inválida detectada: CUSTOM_CATEGORY
Cause: Application code passed invalid categoria_motivo
Solution:
- Use only predefined categories from
AuditService.CATEGORIAS - Or pass
nullto allow automatic categorization - Update code to use valid enum values
Related Documentation
User Management
Understanding audited user operations
Roles & Permissions
Who can access audit logs
Configuration
Logging levels and settings