Contenedores, red y volúmenes. Solo web publica puertos; el resto conversa en una red interna de Docker. Las imágenes propias corren sin privilegios de root y cada contenedor tiene un límite de memoria.
Contenedor
Imagen
Función
Memoria máxima
web
trazo-web (Nginx sin root + React compilado)
Termina TLS 1.2+, sirve la interfaz, reenvía /api
128 MB
api
trazo-app (Python 3.12, FastAPI)
API REST, autenticación, SCIM, licencia; aplica las migraciones al arrancar
768 MB
worker
trazo-app
Cola de trabajos en PostgreSQL: antivirus, extracción, transcripción, enmascaramiento, generación, exportación, correo, conservación
1,5 GB
postgres
postgres:16-alpine
Base de datos y cola (SELECT … FOR UPDATE SKIP LOCKED), sin Redis
512 MB
clamav
clamav/clamav:1.4
Antivirus; las firmas vienen en la imagen del paquete y la plataforma no las descarga de internet
1,5 GB
Las imágenes trazo-app y trazo-web corren sin root y con no-new-privileges; api y worker tienen /tmp en
memoria.
Modelo de datos. Cada artefacto guarda versiones inmutables y su historial de estados; cada generación deja sus invocaciones con tokens y costo. Notación: 1 a N.
Áreas y procesos (código, nombre, dueño, estado de revisión, confidencialidad).
Insumos y su texto (transcripción con marcas de tiempo o texto por página, servicio usado, evidencia de
borrado del objeto temporal, tabla de reemplazos del enmascaramiento), con personas asociadas para la
conservación (RD-16).
Artefactos (bpmn, documento, raci, sipoc, registros) con versiones inmutables (autor, origen
ia/manual/importacion/restauracion, resumen, diferencias) y historial de estados (RD-15).
Comentarios anclados a elementos (RD-04), anotaciones de riesgos, controles, activos y datos personales
(RD-05, RD-06), esfuerzo (horas y reuniones, RD-08).
Generaciones e invocaciones de IA (usuario, fecha, modelo, tokens, costo) y cuotas por usuario y mes (RO-09).
Auditoría (RO-08), usuarios, grupos y sesiones; licencia; políticas de conservación;
exportaciones; respaldos; notificaciones; configuración.
Cola de trabajos. Vive en PostgreSQL, sin Redis: varios workers pueden competir sin pisarse y un bloqueo de un worker caído se libera solo.
El worker toma trabajos de la tabla trabajos con bloqueo por fila, reintenta con espera creciente y deja el
resultado o el error. Cuando la cola está vacía programa las tareas periódicas (notificaciones cada 5 minutos;
conservación, alerta de almacenamiento y limpieza de exportaciones una vez al día), sin cron ni servicios extra.