feat: añadir diseño de auditoría centralizada y actualizar README
This commit is contained in:
parent
5dfb50e13a
commit
dfb0a699eb
@ -7,6 +7,7 @@ Aplicación interna para soporte técnico a pequeñas empresas.
|
||||
- [Organización del código](docs/arquitectura/capas-del-servidor.md)
|
||||
- [Organización web y guía para nuevas entidades y operaciones](docs/estructura-web-por-entidades-y-operaciones.md)
|
||||
- [Usuarios y acceso](docs/usuarios-y-acceso.md)
|
||||
- [Diseño de auditoría centralizada](docs/auditoria-centralizada.md)
|
||||
- [Compañías, contactos y sedes](docs/companias-contactos-y-sedes.md)
|
||||
- [Personas y departamentos](docs/personas-y-departamentos.md)
|
||||
- [Cuentas, grupos y recursos](docs/cuentas-grupos-y-recursos.md)
|
||||
|
||||
179
docs/auditoria-centralizada.md
Normal file
179
docs/auditoria-centralizada.md
Normal file
@ -0,0 +1,179 @@
|
||||
# Diseño de auditoría centralizada
|
||||
|
||||
Estado: diseño acordado para futura implementación; no describe una funcionalidad ya disponible.
|
||||
Fecha: 2026-10-10.
|
||||
|
||||
## Objetivo y decisiones acordadas
|
||||
|
||||
Permitir conocer quién hizo qué, cuándo, en qué compañía y qué cambios se produjeron como consecuencia. La auditoría se consulta globalmente o dentro de una compañía y complementa los historiales propios de las entidades.
|
||||
|
||||
Regla obligatoria: ninguna operación que modifique datos mediante el backend puede confirmarse sin registrar su auditoría. Afecta a todas las entidades actuales y futuras, sus relaciones, catálogos, configuraciones y operaciones de mantenimiento integradas.
|
||||
|
||||
Las modificaciones ejecutadas directamente en MariaDB quedan fuera del alcance, por decisión del usuario. No se implementarán triggers ni un sistema de auditoría de SQL directo. Los scripts que deban quedar registrados utilizarán el mecanismo común del backend.
|
||||
|
||||
Persistencia normalizada: tablas y columnas tradicionales, sin JSON ni documentos serializados para valores o diferencias. JSON puede utilizarse como transporte HTTP.
|
||||
|
||||
## Situación de partida
|
||||
|
||||
Existen historiales de distintas entidades con revisiones, autor y fecha. El servidor registra solicitudes HTTP con identificador de petición y resultado técnico. No existe un registro central que agrupe cambios entre módulos ni asegure cobertura uniforme de eliminaciones y consecuencias.
|
||||
|
||||
Los historiales existentes se conservan: aportan la evolución propia de cada entidad. La auditoría central explica operaciones transversales, incluidas entidades eliminadas. No sustituye los registros técnicos del servidor ni convierte la aplicación en un sistema de event sourcing.
|
||||
|
||||
## Operaciones, eventos y causalidad
|
||||
|
||||
Una operación representa una solicitud del usuario o una ejecución autónoma. Contiene uno o varios eventos que representan efectos reales sobre entidades.
|
||||
|
||||
Cada evento puede señalar otro evento como causa. Todos los efectos de una misma operación comparten identificador de operación; el identificador HTTP sirve para diagnóstico, pero no sustituye esa identidad de negocio.
|
||||
|
||||
Ejemplo ilustrativo, sujeto a las reglas reales de retirada:
|
||||
|
||||
| Evento | Naturaleza | Causa |
|
||||
| --- | --- | --- |
|
||||
| Retirar el perfil de Ana | Directa | Solicitud de David |
|
||||
| Retirar su configuración de correo | Derivada | Retirada del perfil |
|
||||
| Retirar su configuración de impresora | Derivada | Retirada del perfil |
|
||||
|
||||
David permanece como iniciador. El backend puede ejecutar los efectos derivados, pero no se pierde la atribución al usuario. Una tarea autónoma tiene origen sistema y carece de iniciador humano; no se inventa un usuario para ella.
|
||||
|
||||
Solo se registran efectos ocurridos. Retirar una configuración no equivale a eliminar el recurso referenciado. No se generan eventos ficticios por compañías cuando cambia la disponibilidad de un catálogo global sin modificar registros particulares.
|
||||
|
||||
Las operaciones masivas agrupan sus eventos. Si permiten resultados parciales, cada unidad atómica conserva su resultado y la operación refleja el resultado parcial. Las consecuencias diferidas conservan la causa y la operación iniciadora; cada ejecución tiene su propio resultado y transacción. El diseño inicial no exige introducir tareas asíncronas.
|
||||
|
||||
## Cobertura obligatoria
|
||||
|
||||
- Altas, modificaciones, eliminaciones, activaciones, desactivaciones y cambios de estado.
|
||||
- Asignaciones, desasignaciones, relaciones y modificaciones de sus atributos.
|
||||
- Compañías, personas, sedes, departamentos, puestos de trabajo y perfiles de usuario.
|
||||
- Activos y recursos; campos, agrupaciones, plantillas, marcas y catálogos globales o particulares.
|
||||
- Cuentas, grupos, accesos, configuraciones de correo, aplicaciones, carpetas, impresoras, certificados y demás entidades existentes.
|
||||
- Tickets, intervenciones, plantillas de intervención, pasos y procesos de personas.
|
||||
- Sustitución y eliminación de fotos y logotipos, registrando el hecho y la referencia segura, no el contenido binario.
|
||||
- Gestión de usuarios y seguridad: cambios de contraseña, autenticación y resultados relevantes de acceso, sin almacenar credenciales.
|
||||
- Importaciones, operaciones masivas, tareas automáticas y scripts de mantenimiento integrados.
|
||||
|
||||
Esta enumeración no es una lista cerrada de entidades. Toda entidad nueva que permita escrituras debe incorporar auditoría antes de darse por terminada.
|
||||
|
||||
Las lecturas, navegación y peticiones de consulta ordinarias no generan eventos de negocio. Las exportaciones o descargas sensibles se registran expresamente cuando se incorporen. Los intentos rechazados o fallidos generan un resultado seguro, sin aparentar que se produjeron cambios.
|
||||
|
||||
Guardar sin diferencias puede registrar la operación como sin cambios, pero no crea eventos ficticios de modificación ni nuevas revisiones. Las repeticiones idempotentes no duplican efectos: se distingue el intento del cambio efectivo y se conserva la referencia a la operación original cuando corresponda.
|
||||
|
||||
## Mecanismo común en el backend
|
||||
|
||||
La implementación debe ofrecer un contrato sencillo, compartido e independiente de entidades concretas:
|
||||
|
||||
1. Abrir una operación con contexto validado: iniciador, origen, petición y ámbito.
|
||||
2. Ejecutar las escrituras mediante una unidad de trabajo que exige auditoría.
|
||||
3. Capturar altas, diferencias semánticas y eliminaciones en el punto común de persistencia.
|
||||
4. Enriquecer los eventos con acciones de negocio y causas desde Application.
|
||||
5. Confirmar conjuntamente las escrituras y la auditoría.
|
||||
|
||||
El autor procede de la sesión del servidor, nunca de un identificador enviado libremente por el navegador. El contexto se transmite mediante dependencias y contratos explícitos, conforme a la composición de módulos. No se introduce un Service Locator ni se obliga a propagar datos de auditoría por componentes React.
|
||||
|
||||
Los repositorios no pueden ofrecer un camino ordinario de escritura que eluda este mecanismo. La creación, modificación, eliminación y escritura de tablas de relación deben quedar cubiertas, incluidas operaciones en bloque. La captura se realiza sobre valores realmente persistidos, después de aplicar las reglas de negocio; las diferencias se comparan semánticamente.
|
||||
|
||||
Cada entidad declara sus campos auditables y sensibles. Los campos nuevos se auditan por defecto salvo exclusión explícita y justificada por sensibilidad o carácter técnico. Un alta o eliminación conserva los valores relevantes para entender el registro, incluso cuando deja de existir su historial. Los cambios de relaciones conservan identificadores y nombres seguros de los extremos.
|
||||
|
||||
Los hooks de Sequelize pueden servir como apoyo técnico, pero no son la única garantía: operaciones masivas, cascadas y SQL interno pueden eludir hooks individuales. Los efectos en cascada deben identificarse antes de borrar y registrarse en la misma transacción. El middleware HTTP aporta contexto y resultado, pero no sustituye eventos de negocio.
|
||||
|
||||
La infraestructura de persistencia implementa el contrato con Sequelize y MariaDB. Los módulos funcionales no acceden a modelos ORM de auditoría. La composición del servidor conecta los consumidores; la ubicación final del módulo se decide al implementar conforme a los consumidores reales, sin crear un framework genérico anticipado.
|
||||
|
||||
## Atomicidad y errores
|
||||
|
||||
Los cambios de negocio y sus eventos se guardan en la misma transacción MariaDB. Si falla la escritura de auditoría, se revierte la modificación completa. No se envía una respuesta de éxito ni se invalida caché como si hubiese cambiado el registro.
|
||||
|
||||
Los intentos fallidos se registran en una transacción independiente después del rollback. Se conserva un código de resultado seguro, nunca SQL, stack ni secretos. No se intenta guardar este resultado dentro de una transacción ya revertida.
|
||||
|
||||
Si también falla el registro del intento, el servidor emite un error técnico seguro con identificador de petición. No puede prometerse persistencia en MariaDB mientras la propia base de datos no está disponible; la garantía estricta es que no se confirma una escritura de negocio sin evidencia persistida.
|
||||
|
||||
Las acciones externas o de sistema de ficheros no comparten la transacción MariaDB. Las fotos y logotipos necesitan preparación, limpieza o compensación conforme al almacenamiento existente: la auditoría distingue el cambio confirmado de su preparación o de un fallo. No se afirmará una atomicidad inexistente entre servicios.
|
||||
|
||||
## Modelo relacional propuesto
|
||||
|
||||
Todas las filas con identidad de negocio utilizan UUID v7. Fechas almacenadas en UTC.
|
||||
|
||||
| Tabla | Contenido |
|
||||
| --- | --- |
|
||||
| `audit_operations` | Identidad, fechas, usuario iniciador y nombre conservado, origen, acción solicitada, identificador de petición y resultado. |
|
||||
| `audit_events` | Operación, evento causante opcional, fecha, compañía opcional, entidad afectada, nombre conservado, acción y naturaleza directa o derivada. |
|
||||
| `audit_field_changes` | Evento, clave y etiqueta de campo conservadas, tipo de dato y valores anteriores/posteriores en columnas tipadas. |
|
||||
|
||||
Los identificadores y nombres de usuario, compañía y entidad deben conservarse aunque desaparezca el registro original. No deben existir borrados en cascada desde esas entidades hacia la auditoría. Las referencias vivas que se necesiten para navegación serán opcionales y estarán separadas de la identidad histórica conservada.
|
||||
|
||||
Una entidad afectada se identifica mediante código de tipo e identificador; no se simula una FK polimórfica a distintas tablas. La eliminación del evento causante no se permite. Se valida que causa y evento pertenezcan a la misma operación y que no haya ciclos.
|
||||
|
||||
Los valores anteriores y posteriores tienen discriminador de tipo y columnas para texto, número, booleano, fecha o referencia. Debe distinguirse ausente, nulo y cadena vacía. Solo se utiliza la columna correspondiente al tipo, con restricciones de coherencia. Las colecciones se representan mediante filas ordenadas de cambio de miembros, sin concatenaciones ambiguas ni serialización JSON. Los campos de catálogo conservan su identificador y etiqueta aunque se renombren después.
|
||||
|
||||
Índices iniciales: compañía + fecha + identidad; iniciador + fecha + identidad; operación; tipo e identificador de entidad + fecha. La paginación tiene orden estable por fecha e identidad y se ejecuta en servidor.
|
||||
|
||||
Los códigos de acción son estables e independientes del idioma. Los textos de presentación se traducen en la interfaz; los nombres y etiquetas históricos se conservan como datos. Un código desconocido debe tener representación legible sin romper la consulta.
|
||||
|
||||
## Ámbitos, privacidad e integridad
|
||||
|
||||
- Compañía concreta: únicamente sus eventos autorizados.
|
||||
- Vista global: compañías permitidas y eventos realmente globales.
|
||||
- Operación con varias compañías: la vista particular no revela eventos o valores de otras compañías.
|
||||
- Cambio global: se registra una vez; solo produce eventos locales si hay modificaciones locales reales.
|
||||
- El acceso a una entidad mediante un enlace vuelve a comprobar autorización y pertenencia.
|
||||
|
||||
Nunca almacenar contraseñas, hashes de contraseña, tokens, cookies de sesión, CSRF, claves privadas ni secretos de licencias o credenciales. Para un secreto se registra que se estableció, sustituyó o retiró, sin copiar su contenido. Los datos personales se limitan a lo necesario para explicar el cambio. No se guarda el cuerpo HTTP completo.
|
||||
|
||||
La auditoría es de solo lectura para usuarios de la aplicación: no hay endpoints de edición o eliminación. La credencial de escritura tendrá los privilegios mínimos compatibles con el despliegue. Esto no convierte el registro en inalterable frente a un administrador de MariaDB; esa protección adicional no forma parte del alcance.
|
||||
|
||||
Aplicar las autorizaciones existentes. La futura ampliación de roles no condiciona la primera implementación; no se crea ahora un sistema paralelo de permisos.
|
||||
|
||||
## Interfaz de consulta
|
||||
|
||||
Añadir Auditoría al ámbito global y al menú de compañía. Reutilizar el [patrón de listados](patron-de-listados-de-entidades.md) y los componentes comunes.
|
||||
|
||||
Columnas: fecha/hora, usuario, compañía solo en vista global, acción, entidad, resultado y número de consecuencias. Filtros: fechas, usuario, compañía, tipo de entidad, acción, resultado y origen. Búsqueda por referencias y nombres conservados; limpiar filtros y configuración de columnas según el patrón común.
|
||||
|
||||
La vista principal agrupa por operación para no presentar cada consecuencia como una acción independiente del usuario. El detalle muestra los eventos ordenados, su causa y diferencias Antes → Después. Permite consultar también eventos por entidad.
|
||||
|
||||
Enlaces destacados, subrayado al pasar el cursor y puntero de enlace, respetando la excepción de los menús de navegación. Entidades eliminadas se muestran como referencias históricas sin enlaces rotos. Fechas en la zona del usuario, estados accesibles y textos en español e inglés. Mantener estados de carga, vacío y error.
|
||||
|
||||
Los historiales actuales siguen disponibles. La actividad reciente del dashboard podrá consumir esta fuente posteriormente, sin duplicar eventos. No requiere rediseñar el dashboard para implementar la auditoría.
|
||||
|
||||
## Implantación y evolución
|
||||
|
||||
1. Inventariar todas las rutas de escritura, repositorios, transacciones, cascadas y scripts existentes.
|
||||
2. Crear esquema, contratos y unidad de trabajo auditada; probar atomicidad y causalidad.
|
||||
3. Adaptar todos los caminos actuales de escritura, incluyendo eliminaciones y operaciones masivas.
|
||||
4. Incorporar consulta global y por compañía, detalle y filtros.
|
||||
5. Añadir la regla de cobertura a la documentación de desarrollo y a las pruebas de integración para futuras entidades.
|
||||
|
||||
La auditoría central se inicia en una fecha conocida. No se inventan autores, causas ni eventos anteriores. Los historiales previos se conservan como tales; cualquier importación histórica futura identifica expresamente su procedencia y limitaciones.
|
||||
|
||||
Sin borrado automático inicial. La política de conservación y archivo se decidirá antes de incorporar purgas. No se mezclan esas purgas con la eliminación ordinaria de entidades.
|
||||
|
||||
No se considerará completada la implantación mientras quede una escritura del backend sin cobertura. Durante la entrega incremental se documentarán las operaciones cubiertas y pendientes, sin anunciar una garantía total prematuramente.
|
||||
|
||||
## Criterios de aceptación y pruebas
|
||||
|
||||
- Toda alta, modificación, eliminación o cambio de relación confirmado genera sus eventos y valores relevantes.
|
||||
- Ninguna entidad actual o futura con escritura puede darse por terminada sin cobertura de auditoría.
|
||||
- Una operación registra todos sus efectos reales, con iniciador y causalidad correctos.
|
||||
- Una modificación concurrente registra el valor anterior realmente sustituido, no un valor leído fuera de la transacción.
|
||||
- Un fallo de auditoría revierte el cambio de negocio; un fallo de negocio no deja eventos de éxito.
|
||||
- Repeticiones idempotentes no duplican cambios; guardar sin diferencias no inventa modificaciones.
|
||||
- Eliminaciones y cascadas conservan evidencia aunque desaparezcan entidades e historiales.
|
||||
- Cambios de catálogos globales y locales respetan su ámbito.
|
||||
- Las consultas particulares y operaciones con varias compañías no filtran datos ajenos.
|
||||
- Credenciales y secretos no aparecen en tablas, respuestas, exportaciones ni logs.
|
||||
- Tareas autónomas, mantenimiento e importaciones se distinguen de acciones iniciadas por usuarios.
|
||||
- La paginación, filtros, navegación y detalle funcionan con estados de carga, vacío y error.
|
||||
|
||||
Verificar con pruebas de integración MariaDB sobre los caminos reales de persistencia. Mantener un inventario de cobertura revisable y exigir estas pruebas al incorporar entidades. No basta con probar el servicio de auditoría de forma aislada ni con confiar en una convención documental.
|
||||
|
||||
## Referencias y documentación relacionada
|
||||
|
||||
Referencias funcionales consultadas el 2026-10-10; no implican reproducir su arquitectura interna:
|
||||
|
||||
- [GLPI: historial de cambios y acciones automáticas](https://help.glpi-project.org/documentation/modules/tabs/historical).
|
||||
- [Snipe-IT: informe de actividad con filtros por entidad y acción](https://snipe-it.readme.io/reference/reportsactivity).
|
||||
- [Freshservice: auditoría global y por espacio](https://support.freshservice.com/support/solutions/articles/232444-audit-log).
|
||||
- [Freshservice: actividad de tickets y automatizaciones](https://support.freshservice.com/support/solutions/articles/155562-viewing-ticket-activity-history).
|
||||
- [Composición de módulos](arquitectura/composicion-de-modulos.md).
|
||||
- [Capas del servidor](arquitectura/capas-del-servidor.md).
|
||||
- [Modelo DDD e identificadores](arquitectura/modelo-ddd-e-identificadores.md).
|
||||
- [Normalización de la persistencia](normalizacion-de-la-persistencia.md).
|
||||
- [Pruebas del proyecto](arquitectura/pruebas.md).
|
||||
Loading…
Reference in New Issue
Block a user