PLAN — M0 · Cimientos
Plan del hito en curso. Se marca conforme avanza. El mapa completo de hitos vive en
docs/PLAN_MAESTRO.md; las reglas de cómo se escribe código, en
docs/00-agents.md.
Objetivo del hito: el repositorio construye, migra, genera código jOOQ, pasa sus puertas de calidad y sirve un endpoint contra la base real.
Tareas
- T0.4 · Generación jOOQ — perfil manual
-Pjooq-codegen, fuentes versionadas encom.sineltek.lis.jooq. Ver ADR-0002. - T0.5 · Dependencias y puertas — JPA fuera (ADR-0004); Flyway, Testcontainers, ArchUnit, JaCoCo y Spotless dentro. Falta el primer test de integración que las ejerza.
- Entorno de trabajo —
Makefile,Dockerfile,.dockerignore,.env.example,docker-composecon pgAdmin y healthcheck,application.yamlcon defaults de desarrollo, y.tool-versionsversionado. - T0.1 · Migración base — el DDL como
V1__esquema_base.sql, con dos desviaciones documentadas en su cabecera: sinbegin;/commit;(Flyway ya abre transacción) y conbtree_gistfijado al esquemalis. Ver ADR-0003. - T0.2 · Catálogos frente a demostración —
V2__catalogos_estado.sqllleva los nueve roles, los cuatro catálogos de estado y las dos matrices de transición: lo que el esquema necesita para funcionar y no depende de la institución. El resto del archivo de ejemplo essrc/test/resources/db/demo/datos_demostracion.sql, que Flyway no ve y se carga conmake demo. Lo institucional —tipos de muestra, unidades, secciones, pruebas, tarifas— es configuración clínica y le corresponde a M2. - T0.3 · Transiciones faltantes —
V3__transiciones_faltantes.sqlañade 8 transiciones (2 de orden, 6 de prueba), todas con motivo obligatorio.MatrizTransicionesTestlas verifica sobre un PostgreSQL real migrado desde cero: 16 casos, incluidos el rechazo sin motivo, el rechazo de lo que no figura en la matriz y quepublicadayentregadasiguen siendo terminales. - T0.6 · Walking skeleton —
GET /api/v1/sedesatraviesa api → aplicación → dominio → adaptador jOOQ → PostgreSQL. El módulocompartidoestrena las cuatro capas, yArquitecturaTestconvierte la regla de dependencias en cinco reglas de ArchUnit que rompen el build. Verificado introduciendo una violación a propósito.
Hecho en este hito
- ADR-0001 a ADR-0009 escritos.
- Flyway 12.4.0 conecta con PostgreSQL 18.4 y crea el esquema
lis(verificado). V1aplicada y reconstruida desde cero conmake db-reset: 90 tablas, 6 vistas, 12 funciones, 18 triggers, 9 restricciones de exclusión, 259 índices y 2 particiones.make jooq-codegengenera las clases del esquema ymake verifypasa en verde. Las 212 funciones de soporte debtree_gistquedan fuera del código generado.V2cargada: 9 roles, 8+8+8+6 estados, 11 transiciones de orden y 10 de prueba. Verificado contra los triggers: una transición válida entra,registrada → completadase rechaza por no estar en la matriz, yregistrada → en_tomasin motivo se rechaza por exigirlo.make democarga la jornada completa de demostración sobre la base local.- Primer test de integración con Testcontainers: 16 casos sobre PostgreSQL 18 real, sin un solo mock, porque las reglas que verifica viven en triggers. Matriz final: 13 transiciones de orden y 16 de prueba.
- La aplicación arranca y responde
/actuator/healthcon las sondaslivenessyreadiness. - Actuator expone dos endpoints:
healtheinfo. - Las tres señales llegan al backend. Los logs necesitaban un appender de Logback que el
starter no trae: sin él la tubería OTLP estaba configurada y vacía
(ADR-0006). Verificado en
Grafana → Loki con el mismo
traceIdque la traza de la petición; el procedimiento y su resultado están enwiki/TELEMETRIA.md. - La observabilidad deja de ser un endpoint de salud. El SLO de
00-agents.mdpasa a ser medible (histograma y cubetas sobrehttp.server.requests), el muestreo deja de ser un literal de desarrollo, los límites de atributos acotan lo que puede escaparse y las métricas de pool y de contenedor quedan publicadas. Las convenciones de instrumentación —nombres, cardinalidad, nada de PII en ninguna de las tres señales, el dominio no loguea— están en ADR-0007, para que los 22 slices de M1 las hereden en lugar de improvisar una cada uno.
M0 cerrado
Las seis tareas están hechas. El repositorio construye, migra desde cero, genera su código
jOOQ, pasa cinco reglas de arquitectura y sirve un endpoint real contra PostgreSQL 18.
make verify: 40 tests en verde.
La API se puede ejercer a mano: make dev-full levanta todo con el perfil dev y
make curls corre los .http de wiki/http con sus aserciones.
Deudas declaradas
Salieron de revisar la salida real de make curls. Ninguna bloquea M1; las dos tienen dueño.
La tercera —traza OTel sin observar— está pagada: las trazas y los logs se miraron en
Grafana el 2026-09-25 y ExportacionLogsOtelTest impide que el cableado de logs se caiga en
silencio, que era la forma en que este fallo se esconde.
| Deuda | Qué falta | Dónde se paga |
|---|---|---|
| Sin contrato de errores propio | El 404 devuelve el cuerpo por defecto de Spring (timestamp, status, error, path) y el 401 no trae cuerpo. Faltan los errores tipados del dominio y su traducción a HTTP en api/ |
S1.01 |
| Sin identificador de correlación | Ninguna respuesta lleva traceparent ni X-Trace-Id, así que no hay forma de saltar de una petición fallida a su traza |
S1.01 |
Las dos restantes son la arquitectura de errores que el marco pide decidir antes de implementar: la semántica se fija una vez y los veinte endpoints siguientes la heredan. Si se deja para después, lo que se hereda es el formato por defecto de Spring.
Siguiente acción
Empieza M1. El primer slice es S1.01: contexto de ejecución —identificadores tipados, errores de
dominio, reloj, organización, sede y actor—, que es también lo que le falta a SedeRepositorio
para filtrar por organización y donde caen las dos deudas que siguen abiertas.
Sus requisitos están en
docs/02-requirements/CAP-01-contexto-de-ejecucion.md,
y su primera mitad ya está construida: identificadores tipados, actor resuelto desde la
credencial, alcance por organización en la lectura de sedes y reloj inyectable. 57 tests en verde y
make curls en verde contra la aplicación real.
Se empezó por ahí porque es el trabajo cuyo coste crece más rápido con cada commit: el alcance por
organización atraviesa las cuatro capas de los trece módulos, y su omisión no se nota —devuelve
datos, no un error—.
Queda de S1.01 la parte «sede», bloqueada por DR-02: ni cuenta_usuario ni cuenta_rol llevan
sede, así que «un empleado accede a los de su sede» no es hoy expresable con este esquema.
Lo siguiente, en orden:
- Hecho: ADR-0009 · identidad externa. La autenticación sale del servicio: passkeys, OTT, MFA y
login federado son configuración del proveedor de identidad, y el LIS valida tokens.
SecurityConfigsigue siendo Basic con usuariodevcomo andamiaje hasta M8. - Hecho: ADR-0008 · arquitectura de errores. Catálogo de los 22 rechazos del esquema con su
regla y su familia, y la decisión: un SQLSTATE propio de clase
LSpor regla, errores de dominio tipados, y RFC 9457 en el borde. Lo que sigue es implementarlo: la migración que reasigna los 22 códigos con su regeneración de jOOQ, la tabla de traducción en el adaptador, el@RestControllerAdvicey el test que impide que un rechazo nazca con SQLSTATE estándar. - El
PLAN.mdpropio de M1 con los 22 slices, que es transcripción dePLAN_MAESTRO.md§5. Este archivo sigue siendo el de M0 y ya debería relevarse. - RLS como red del aislamiento, en su ADR: coste plano, pero exige antes un rol de aplicación
sin privilegios de dueño, porque hoy la app conecta como
postgresy una política sería inerte. - Retirar
TestControlleryWebPaths, y reescribir con ellos la receta de comprobación dewiki/TELEMETRIA.md, que depende de/api/v1/public/test.