Auditoría
El log de auditoría (audit_log) registra toda mutación del sistema: quién la hizo, sobre
qué entidad, con qué acción, y el estado antes y después del cambio. Es append-only
(inmutable) y forma parte del Core Value de TankOS —la auditoría completa— junto con los cálculos
custody correctos y los tickets sin huecos: si todo funciona pero no se puede rastrear quién cambió qué, el
sistema no sirve para el cliente. El visor de auditoría vive en /admin/audit. Esta página está
orientada al auditor (administrador) y al supervisor: cómo investigar quién cambió qué, cuándo y
de qué valor a qué valor.
Quién puede ver y quién puede exportar
El acceso al visor usa semántica OR, no AND: GET /admin/audit está protegido con
@AnyAuthority('admin:system', 'lab:approve'), así que lo ve el administrador O el supervisor. El
export en CSV, en cambio, es exclusivo del administrador (admin:system,
POST /admin/audit/export): el supervisor ve el botón "Exportar CSV" deshabilitado (con tooltip), y
solo el administrador lo puede usar.
Esto es least-privilege deliberado (D-03): el administrador no tiene autoridades operativas —no afora, no aprueba, no emite tickets—, pero sí posee la auditoría y su export. El supervisor, que sí es un actor operativo, puede investigar el log (su rol de "segundo par de ojos") pero no puede extraerlo masivamente. Un administrador comprometido no escala a operaciones de producción, y un supervisor no puede exfiltrar el log completo.
| Acción | Ruta / autoridad | admin | supervisor | otros roles |
|---|---|---|---|---|
| Ver la auditoría | GET /admin/audit (admin:system OR lab:approve) | ✓ | ✓ | – |
| Exportar CSV | POST /admin/audit/export (admin:system) | ✓ | ✗ (botón deshabilitado) | – |
La tabla de auditoría
El visor muestra una tabla virtualizada de entradas de audit_log con cursor pagination (50 por
página): a medida que avanzas, el sistema pagina por cursor en lugar de cargar todo de golpe, de modo que
el log pueda crecer indefinidamente sin penalizar la pantalla. Cada fila representa una mutación: el
usuario, la entidad afectada, la acción, el instante y un resumen del cambio.
Screenshot pendiente del barrido diferido — ver 61-DEFERRED-SWEEP.md (/admin/audit tabla de auditoría con cursor pagination).
Filtros — acotar la búsqueda
La AuditFilterBar permite acotar el log a lo que estás investigando, combinando varios criterios:
| Filtro | Para qué sirve |
|---|---|
| Usuario | Todas las acciones de una persona |
| Entidad | Un tipo de objeto (p. ej. ticket de custodia, muestra de lab, tanque) |
| IDEntidad | Un objeto concreto por su identificador |
| Acción | Un tipo de operación (creación, edición, anulación, vista…) |
| Desde / Hasta | Una ventana de tiempo (rango de fechas) |
Combinándolos respondes preguntas precisas: "¿qué le hizo el usuario X al ticket Y entre el lunes y el miércoles?". Los mismos criterios se reutilizan al exportar (ver abajo).
El AuditDrawer y el JSON diff
Al hacer click en una fila se abre el AuditDrawer —un panel lateral— con el JSON diff
old→new: el estado antes y después del cambio, lado a lado. Es la herramienta clave del
auditor: no solo muestra que algo cambió, sino exactamente qué campo cambió y de qué valor a qué
valor. Para un sistema custody-grade —donde un nivel, una densidad o un número de ticket alterados tienen
consecuencias regulatorias— ese diff antes/después es la evidencia forense que reconstruye el cambio
con precisión de campo.
Screenshot pendiente del barrido diferido — ver 61-DEFERRED-SWEEP.md (/admin/audit AuditDrawer abierto con JSON diff old→new).
Exportar el log en CSV
El administrador puede exportar el audit_log —completo o filtrado por los mismos criterios de
la AuditFilterBar— como CSV vía GET /api/v1/admin/audit/export (admin:system). Es el mismo
artefacto que el tipo de reporte AUDIT_CSV del flujo de reportes: la auditoría exportable se
entrega como un reporte custody-grade más. La generación, el versionado y la verificación de ese export se
documentan en la hermana reportes.
El supervisor ve el botón pero lo tiene deshabilitado: puede investigar en pantalla, no extraer el log en masa.
Inmutabilidad y retención
El audit_log es append-only. Toda mutación del sistema pasa por un interceptor que escribe la
entrada de auditoría, con un trigger de base de datos como respaldo de último recurso: aunque algo
intentara saltarse el interceptor, el trigger garantiza el registro. Nadie edita ni borra una entrada
una vez escrita. La retención custody-grade es de 7 años: el rastro de cambios persiste a largo plazo
para auditorías y disputas posteriores.
Esta inmutabilidad de largo plazo es alto valor para el auditor y para el cumplimiento regulatorio
(SENCAMER / MINPET / Pdvsa): combinada con el JSON diff old→new, garantiza que cualquier cambio
—incluido un error y su corrección— quede registrado de forma completa, atribuible e inalterable. Por
eso un ticket de custodia nunca se "edita": se anula y se reemite, y toda esa cadena queda en el
audit_log (ver el correctivo en VOID de los
tickets de custodia).
Páginas relacionadas
- Los reportes cubren el export
AUDIT_CSVy el resto de tipos generables. - Los tickets de custodia dejan su rastro
TICKET_ISSUED(y la cadena VOID → reemisión) en elaudit_log. - Los roles y módulos detallan qué ve y qué puede hacer cada perfil, incluida la regla OR de la auditoría y el export admin-only.
- Las guías por rol del auditor se publicarán próximamente.