appointments-service :8083, clinical-imaging-service :8094), consolidar Servicios Generales 4→1 (servicios-generales-svc :8123) y apagar el stub icu-service :8100 · /actuator/health = 200 OK · API gateway :8080 · IAM (JWT/JWKS) :8086 con kid=hospital-prod-1.max_connections=300 (conexiones activas 115→17) · Nginx + Cloudflared (sin Docker/K8s). HikariCP árbol español 10→3, listeners Kafka apagados (sin broker).dblink (imágenes, nutrición, patología, banco de leche, laboratorio, banco de sangre, maternidad/neonatal, eMAR, facturación, firma, inventario). Auditoría forense: integridad referencial y multi-tenant SANAS. Backup diario cifrado (GPG asimétrico + systemd timer, retención 7 días) operativo en la VM.legacy_id + origen=LEGACY_HNSM_V2.hospital-toscana-systems-app) servido en sistema-medico.com.@ConditionalOnProperty(name="sih.outbox.enabled", havingValue="true", matchIfMissing=false) — cero warnings de reconnect en producción. Activable por env var sin tocar código cuando haya broker.| Indicador | Valor real (verificado en VM) | Meta fase A | Estado |
|---|---|---|---|
| Semana | S03 de 34 | S08 | en curso |
| Fase | A · Cimientos | Cierre fin de junio | cerrada anticipada |
| Microservicios diseñados | 25 diseñados · llegó a 36 implementados · racionalizado a 30 activos (12–13 jun: −2 duplicados muertos, Servicios Generales 4→1, −1 stub icu) | 25 | racionalizado |
| Servicios desplegados y UP | 30 / 30 en VM Toscana (verificado por /actuator/health y systemctl is-active · 0 failed) | 21 | 100% |
| API Gateway | Operativo en :8080 · Spring Cloud Gateway WebFlux · 25+ rutas /api/v1/** | Operativo | UP |
| IAM (auth + JWKS) | Operativo en :8086 · OAuth2 + JWT (RS256) · /.well-known/jwks.json | Operativo | UP |
| BD PostgreSQL provisionadas | 36 (con role y schema dedicado por servicio) | 21 | creadas |
| BD con migraciones Flyway aplicadas | 20 de 20 con flyway_schema_history poblado (1 baseline + 41 filas migration · CRC32 zlib) | 20 | evidencia auditable |
| Java runtime | Temurin OpenJDK 25.0.3 LTS · virtual threads habilitados | Java 25 | completo |
| Hosting / DNS público | Cloudflare Tunnel + Nginx · 6 dominios activos | HTTPS público | activo |
| Observabilidad | Logs en /var/log/hospital-services/*.log · OTel collector definido pero no corriendo | Prometheus + Grafana + Loki + Tempo | parcial |
| ADRs firmados | 14 de 14 | 14 | completo |
| Datos sintéticos / piloto | 11 módulos clínicos poblados con datos sintéticos coherentes (referencian pacientes reales del MPI vía dblink) · auditoría forense: integridad SANA · falta el dataset masivo de censo (1000 pac. + 5000 episodios) | 1000 pacientes + 5000 episodios | parcial |
| Backup / DRP | Respaldo diario cifrado (GPG asimétrico · pg_dump de 12 BD · systemd timer 02:30 UTC · retención 7 días · copia en C: + git bundle) — la VM solo guarda la llave pública | Política de backups | operativo |
| Capacitación | No iniciada | S31–S32 | programada |
Inventario reverificado por SSH directo en el 2026-06-13 (active=30 failed=0 bajo systemd · gateway 200 · IAM JWKS 200). Tras la racionalización (12–13 jun) quedan 30 servicios UP: se retiraron 2 duplicados muertos (appointments-service, clinical-imaging-service), se consolidaron los 4 de Servicios Generales en servicios-generales-svc :8123 y se apagó el stub icu-service. Esas filas se conservan abajo marcadas con su nuevo estado para trazabilidad. terapia-respiratoria-svc y seguimiento-egreso-svc permanecen planificados (sin unit en la VM).
Stack: Spring Boot + Java 25 LTS Temurin con virtual threads · PostgreSQL 18 database-per-service · Spring Cloud Gateway WebFlux como BFF · OAuth2 Resource Server con JWT (claims iss/aud) validados contra el JWKS del IAM.
Todos los servicios arrancan como JAR nativo (java -jar /opt/java-platform/services/<svc>/build/libs/<svc>-0.1.0-SNAPSHOT.jar) bajo unit hospital-<svc>.service — sin Docker ni Kubernetes en este corte.
Estado UP = unit active(running) + /actuator/health = 200 OK.
Cada microservicio se nombra internamente en inglés (artefacto técnico) y se expone públicamente en español (Regla 8 · facade-ES/interno-EN).
| # | Nombre público (ES) | Servicio interno (carpeta · EN) | Puerto | Base de datos | Ruta gateway | Responsabilidad | Estado |
|---|---|---|---|---|---|---|---|
| 1 | puerta-de-enlace-api | api-gateway-service | 8080 | — (sin BD propia) | — | Spring Cloud Gateway WebFlux · BFF · 25+ rutas /api/v1/** · valida JWT (iss/aud) · X-Hospital-Trace-Id · cabeceras de seguridad | UP |
| 2 | identidad-paciente-svc | patient-mpi-service | 8081 | patient_mpi_db | /api/v1/pacientes/** | MPI · pacientes con DPI/carné · identidad clínica | UP |
| 3 | admision-recepcion-svc | reception-admission-service | 8082 | reception_admission_db | /api/v1/admision/** | Visitas · carné · reposiciones | UP |
| 4 | citas-svc | appointments-service | 8083 | appointments_db (_legacy) | /api/v1/citas/** | Retirado 13-jun — duplicado muerto (la agenda real la sirve citas-svc :8103). Detenido + disable; unit conservado para rollback. | RETIRADO |
| 5 | triaje-emergencias-svc | emergency-triage-service | 8084 | emergency_db | /api/v1/emergencias/** | Emergencias · síntomas → diagnóstico → Rx automática · vínculo a hospitalización-adt | UP |
| 6 | quirofano-svc | surgery-service | 8085 | surgery_db | /api/v1/quirofano/** | Cirugía perioperatoria · workflow PROGRAMADA → EN_CURSO → COMPLETADA · consume-stock | UP |
| 7 | identidad-y-acceso-svc | identity-access-service | 8086 | identity_access_db | /api/v1/auth/** /api/v1/policies/** /api/v1/informatica/** /.well-known/jwks.json | IAM · login/refresh/logout · sesiones en BD · roles RBAC · matriz role→módulo · JWKS público para Resource Servers | UP |
| 8 | catalogo-inventario-svc | inventory-catalog-service | 8087 | inventory_catalog_db | /api/v1/inventario/** | Bodegas · ubicaciones · lotes · catálogo de insumos | UP |
| 9 | existencias-svc | stock-ledger-service | 8088 | stock_ledger_db | /api/v1/existencias/** | Libro mayor de stock · movimientos · referencias farmacia/cirugía | UP |
| 10 | maternidad-neonatal-svc | maternity-neonatal-service | 8089 | maternity_neonatal_db | /api/v1/maternidad/** | Maternidad y neonatos · prefill de formularios | UP |
| 11 | formularios-sigsa-svc | forms-sigsa-service | 8090 | forms_sigsa_db | /api/v1/formularios-sigsa/** | Formularios SIGSA · integración MSPAS | UP |
| 12 | farmacia-recetas-svc | pharmacy-prescriptions-service | 8091 | pharmacy_db | /api/v1/farmacia/** | Receta · dispensación · comprobante · cola por módulo · Resilience4j | UP |
| 13 | hospitalizacion-adt-svc | inpatient-adt-service | 8092 | inpatient_adt_db | /api/v1/hospitalizacion/** | ADT hospitalario · admisión · traslado · alta · cama y servicio | UP |
| 14 | laboratorio-clinico-svc | clinical-laboratory-service | 8093 | clinical_lab_db | /api/v1/laboratorio/** | LIS · órdenes y resultados de laboratorio clínico | UP |
| 15 | imagenologia-clinica-svc | clinical-imaging-service | 8094 | clinical_imaging_db (_legacy) | /api/v1/imagenologia/** | Retirado 13-jun — duplicado muerto (imágenes las sirve imagenes-svc :8120). Detenido + disable; unit conservado para rollback. | RETIRADO |
| 16 | enfermeria-emar-svc | nursing-emar-service | 8095 | nursing_emar_db | /api/v1/enfermeria/** | eMAR · administración de medicamentos por enfermería | UP |
| 17 | facturacion-reclamos-svc | billing-claims-service | 8096 | billing_claims_db | /api/v1/facturacion/** | Facturación y reclamos | UP |
| 18 | firma-clinica-svc | clinical-signature-service | 8097 | clinical_signature_db | /api/v1/firmas/** | Firma electrónica clínica · trazabilidad | UP |
| 19 | expediente-encuentros-svc | ehr-encounter-service | 8098 | ehr_encounter_db | /api/v1/expediente/** | EHR · encuentros longitudinales · evolución clínica | UP |
| 20 | banco-sangre-svc | blood-bank-service | 8099 | blood_bank_db | /api/v1/banco-sangre/** | Banco de sangre · tipificación · cross-match · trazabilidad bolsas | UP |
| 21 | uci-svc | icu-service | 8100 | icu_db | /api/v1/uci/** | Apagado 13-jun — stub sin tráfico real (quick win de racionalización). Detenido + disable; reactivable cuando UCI entre en censo. | RETIRADO |
| 22 | almacen-general-svc | almacen-general-service | 8101 | almacen_general | /api/v1/almacen-general/** | Almacén general · existencias y despachos hacia bodegas de servicio | UP |
| 23 | citas-clinicas-svc | citas-svc | 8103 | citas | /api/v1/citas/** (clínicas legacy · agenda) | Agenda clínica legacy HNSM · 32 clínicas reales (23 CE + 9 ER) · 21 especialidades · trazabilidad legacy_id + origen=LEGACY_HNSM_V2 | UP |
| 24 | recursos-humanos-svc | rrhh-svc | 8104 | rrhh | /api/v1/rrhh/** | RRHH · plantilla · turnos · asistencia · novedades de personal | UP |
| 25 | presupuesto-svc | presupuesto-svc | 8105 | presupuesto | /api/v1/presupuesto/** | Presupuesto · ejecución por programa y renglón · enlace SICOIN | UP |
| 26 | adquisiciones-svc | adquisiciones-svc | 8110 | adquisiciones_db | /api/v1/compras/** | 15-may Compras del Estado (Decreto 57-92) · 4 slices: Requerimientos / Eventos NOG / Órdenes / Juntas · catalog (BORRADOR→…→CERRADO) | UP |
| 27 | mantenimiento-svc | mantenimiento-svc | 8111 | mantenimiento | /api/v1/mantenimiento/** | Consolidado 12-jun en servicios-generales-svc :8123 (schema mantenimiento). CMMS · 6 áreas · FSM NUEVA→ASIGNADA→EN_PROCESO→CERRADA. JVM individual detenida + disable. | CONSOLIDADO |
| 28 | flota-svc | flota-svc | 8112 | flota | /api/v1/flota/** | Consolidado 12-jun en servicios-generales-svc :8123 (schema flota). 4 unidades HNSM · viajes con km/combustible. JVM individual detenida + disable. | CONSOLIDADO |
| 29 | gases-medicinales-svc | gases-medicinales-svc | 8113 | gases | /api/v1/gases/** | Consolidado 12-jun en servicios-generales-svc :8123 (schema gases). 4 depósitos O₂/aire/vacío · semáforo crítico. JVM individual detenida + disable. | CONSOLIDADO |
| 30 | lavanderia-svc | lavanderia-svc | 8114 | lavanderia | /api/v1/lavanderia/** | Consolidado 12-jun en servicios-generales-svc :8123 (schema lavanderia). Tandas + ropería + sastrería con FSM. JVM individual detenida + disable. | CONSOLIDADO |
| 31 | dietas-svc | dietas-svc | 8115 | dietas (schema dietas) | /api/v1/dietas/** | 16-may Tree B Dietas · menus y régimen dietético hospitalario | UP |
| 32 | nutricion-clinica-svc | nutricion-clinica-svc | 8116 | sih_nutricion (schema nutricion) | /api/v1/nutricion/** | 16-may Tree B Nutrición clínica · valoración y planes | UP |
| 33 | anatomopatologia-svc | anatomopatologia-svc | 8117 | patologia (schema patologia) | /api/v1/patologia/** | 16-may Tree B Anatomía patológica · biopsia + outbox · FSM SOLICITADA→MUESTRA_RECIBIDA→EN_MACROSCOPIA→EN_FIJACION→EN_INCLUSION→EN_CORTE_TINCION→EN_LECTURA→EN_REVISION→DICTAMEN_FIRMADO + RECHAZADA | UP |
| 34 | banco-leche-svc | banco-leche-svc | 8118 | banco_leche | /api/v1/banco-leche/** | 16-may Tree B Banco de leche humana · donación · trazabilidad | UP |
| 35 | imagenes-svc | imagenes-svc | 8120 | imagenes | /api/v1/imagenes/** | 16-may Tree B Imágenes · V3 agrega ruta_archivo_externo + formato_archivo en estudio · cola SOLICITADO/EN_PROGRESO/COMPLETADO | UP |
| 36 | datos-referencia-svc | reference-data-svc | 8121 | reference_data_db | catálogos compartidos · interno | Catálogos compartidos (datos de referencia) consumidos internamente por los demás servicios | UP |
| 37 | servicios-generales-svc | servicios-generales-svc | 8123 | servicios_generales (4 schemas) | /api/v1/mantenimiento/** /api/v1/flota/** /api/v1/gases/** /api/v1/lavanderia/** | 12-jun MACRO · primer macroservicio del roadmap de racionalización. Fusiona mantenimiento + flota + gases + lavandería en 1 JVM / 1 pool Hikari (max=5) / 1 BD con 4 esquemas. Reemplazó 4 JVM + 4 pools + 4 puertos. | UP |
systemctl list-units --state=running 'hospital-*.service' adquisiciones-svc.service → 30 active=running, 0 failed (29 con prefijo hospital- + adquisiciones-svc).
(2) pgrep -c java → 30 JVMs (antes 36). Los 7 retirados quedan inactive + disabled (no es caída: systemctl list-units --state=failed → 0).
(3) mapeo puerto→unit + bucle curl /actuator/health + curl gateway/api/v1/<dominio>/… con JWT → 200 OK en los 30; las 4 rutas de Servicios Generales responden desde servicios-generales-svc :8123.
(4) sudo -u postgres psql -l → BDs con role dedicado; los 11 módulos clínicos antes vacíos ahora con datos sintéticos (anti-joins contra el MPI vía dblink = 0 huérfanos).
(5) Racionalización (docs/00-RACIONALIZACION-RECURSOS.md): HikariCP 10→3, heap -Xmx384m, listeners Kafka auto-startup=false (sin broker), 2 duplicados retirados, SG 4→1, stub icu apagado. Todo reversible vía drop-ins de systemd.
(6) Memoria física VM: free -h → uso 12.7 GB → 9.6 GB (−3 GB), disponible +92%, conexiones PostgreSQL 115 → 17. Backup diario cifrado activo (hnsm-backup.timer).
| Pendiente | Por qué importa | Responsable | Fecha objetivo |
|---|---|---|---|
| Validar visualmente los 4 portales de Servicios Generales (mantenimiento, flota, gases-medicinales, lavandería) con login real | Verificado 13-jun: las pantallas YA existen en el frontend (React) y el backend consolidado servicios-generales-svc :8123 responde 200 directo / 401 vía gateway (auth OK) en los 4 dominios. Falta solo el recorrido visual autenticado para retirar el "modo demostración". | Senior 1 | 2026-06-13 |
Sub-página Cocina · bandejas en portal Apoyo — backend dietas-svc :8115 YA en PROD | Permitirá al chef de cocina ver bandejas del día por sala/cama. Hoy WIP. | Senior 1 | 2026-05-22 |
| Tabla §11.2 ya actualizada con los 30 servicios activos (racionalizado de 36) — mantener verificación por SSH al cierre de sesión | La topología 25 diseñados / 30 activos se documenta en §11.1: se retiraron 2 duplicados (appointments, clinical-imaging), 4 SG se consolidaron en 1 (servicios-generales-svc) e icu quedó como stub. | Senior 1 | continuo |
Activar Outbox Tree B: SIH_OUTBOX_ENABLED=true en systemd cuando se planifique Kafka en otra VM (Redpanda descartado en VM Toscana por RAM) | Hoy los 19 publishers están protegidos con @ConditionalOnProperty; encender es flip de variable, cero código. | Toscana · Ingeniería | S04–S05 |
| Adopción legacy HNSM Fase 2 · V4 con médicos reales + horarios actuales (V3 cerró con 32 clínicas + 21 especialidades) | Permitirá agenda CE/ER 100% basada en datos reales sin overlays manuales. | Senior 1 | 2026-05-23 |
Pendiente publicar matriz GitHub Actions (build/test/push de los 30 JARs activos), inventario de ambientes (DEV en VM Toscana ya activo · QA · STAGING · PROD-HNSM por provisionar) y la decisión final de despliegue. Decisión provisional 16-may: JAR nativo vía systemd validado en producción con 30 svcs UP (racionalizado de 36), ~9.6 GiB RAM, max_connections reducido a 200. Docker/K3s descartado en VM Toscana por sobrecosto RAM (~+30% overhead JVM-in-container).
| Entorno | Propósito | Ubicación | URL | Estado | Responsable |
|---|---|---|---|---|---|
| QA | Pruebas integradas + dataset sintético | VM Toscana (mismo host, perfil Spring distinto · pendiente) | pendiente | por habilitar | Toscana · IngenierÃa |
| STAGING | Pre-producción · UAT con HNSM | Superservidor HNSM | interno HNSM | por provisionar | Erick (HNSM) + Toscana · IngenierÃa |
| PROD-HNSM | Producción · pacientes reales | Superservidor HNSM | interno HNSM | por provisionar | Erick + Toscana 24×7 |
177.7.57.79 · puerto SSH 22 estándar.root · clave SSH ed25519 cargada (id_ed25519 · misma clave que Hostinger)./opt?| Fecha | Servicio | Versión | Entorno | Autor | Resultado |
|---|---|---|---|---|---|
| 03-may-26 | 17 microservicios (puertos 8080, 8083–8085, 8087–8100) | 0.1.0-SNAPSHOT | DEV · VM Toscana | Toscana · IngenierÃa | UP |
| 04-may-26 | icu-service (8100) + patient-mpi-service (8081) | 0.1.0-SNAPSHOT | DEV · VM Toscana | Toscana · IngenierÃa | UP |
| 05-may-26 | identity-access-service (8086) + reception-admission-service (8082) | 0.1.0-SNAPSHOT | DEV · VM Toscana | Toscana · IngenierÃa | UP |
| 15-may-26 | adquisiciones-svc (8110) — módulo Compras Estado GT completo (4 slices: Requerimientos, Eventos NOG, Órdenes, Juntas) | 0.1.0-SNAPSHOT | PROD · VM Toscana | Senior 1 | UP |
| 16-may-26 | Tree B: dietas-svc (8115) + nutricion-clinica-svc (8116) + anatomopatologia-svc (8117) + banco-leche-svc (8118) + imagenes-svc (8120) | 0.1.0-SNAPSHOT | PROD · VM Toscana | Senior 1 | UP |
| 16-may-26 | Servicios Generales: mantenimiento-svc (8111) + flota-svc (8112) + gases-medicinales-svc (8113) + lavanderia-svc (8114) | 0.1.0-SNAPSHOT | PROD · VM Toscana | Senior 1 | UP |
| 16-may-26 | citas-svc V3 — adopción legacy HNSM (32 clínicas + 21 especialidades + agenda admin) · JAR swap con backup .bak.20260516 | 0.1.0-SNAPSHOT | PROD · VM Toscana | Senior 1 | UP |
| 11-jun-26 | Reverificación SSH · confirmados en PROD almacen-general-service (8101) + citas-svc (8103, agenda legacy) + rrhh-svc (8104) + presupuesto-svc (8105) + reference-data-svc (8121) | 0.1.0-SNAPSHOT | PROD · VM Toscana | Senior 1 | UP |
| 12-jun-26 | Macroservicio servicios-generales-svc (8123) — cutover de racionalización: fusiona mantenimiento+flota+gases+lavandería (4 JVM→1, 1 BD servicios_generales con 4 schemas). Los 4 svcs viejos disable. Duplicados appointments-service/clinical-imaging-service y stub icu-service retirados. | 0.1.0-SNAPSHOT | PROD · VM Toscana | Senior 1 | UP |
| 13-jun-26 | Datos sintéticos en 11 módulos (imágenes, nutrición, patología, banco de leche, lab, banco de sangre, maternidad, eMAR, facturación, firma, inventario) + fix KPI banco de leche (redeploy banco-leche-svc) + backup diario cifrado (GPG + systemd timer) | 0.1.0-SNAPSHOT | PROD · VM Toscana | Senior 1 | UP |
| 30 / 30 microservicios UP · 0 failed · topología racionalizada (36→30, −3 GB RAM) · Servicios Generales consolidado · 11 módulos clínicos con datos sintéticos · backup diario cifrado · 4 portales clínicos TERMINADOS al 100%. | |||||
| ADR | Decisión | Fecha | Firma | Estado |
|---|---|---|---|---|
| ADR-01 | Microservicios con database-per-service | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-02 | Java 25 LTS + Spring Boot + Loom (virtual threads) | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-03 | React 19 + TanStack Query + Tailwind v4 | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-04 | PostgreSQL 18 como BD primaria (database-per-service) | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-05 | MongoDB para notas clínicas (futuro · no en VM hoy) | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-06 | TimescaleDB para signos vitales (futuro · no en VM hoy) | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-07 | Apache Kafka como bus de eventos (futuro · no en VM hoy) | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-08 | Mirth Connect para HL7 v2 (futuro) | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-09 | FHIR R4 para interoperabilidad externa | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-10 | OAuth2 Resource Server + JWT (RS256) con JWKS | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-11 | Despliegue JAR nativo vía systemd (sin Docker en MVP) | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-12 | Auditoría WORM con hash encadenado | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-13 | Observabilidad OpenTelemetry → Prometheus + Grafana + Loki + Tempo | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
| ADR-14 | CI/CD con GitHub Actions (Temurin 25) | 07-may-26 | Senior 1 (Giordano) + Toscana · IngenierÃa | aceptado |
Tipos: KICKOFF · ARQ · DEV · QA · DEPLOY · DOC · PLAN · INTEGR · OPS · INC · UAT · INFRA · FRONT.
| Fecha | Sem. | Tipo | Avance | Responsable |
|---|---|---|---|---|
| 13-jun-26 | — | OPS | Backup diario cifrado en PROD + auditoría forense de datos sintéticos. Respaldo recurrente con systemd timer hnsm-backup.timer (diario 02:30 UTC, Persistent=true, retención 7 días): pg_dump de 12 BD + SHA256SUMS → tarball cifrado con GPG asimétrico (RSA 4096) hacia la llave pública del backup; la VM solo guarda la pública y no puede descifrar sus respaldos (la privada vive solo en C:). Round-trip de restauración verificado. Auditoría forense de los 11 módulos sembrados: integridad referencial (0 patient_id huérfanos vía dblink) y multi-tenant SANAS; se corrigió 1 inconsistencia de dominio (7 unidades de sangre caducadas que seguían IN_INVENTORY → EXPIRED). Copia local en C: + git bundle. Docs: docs/00-AUDITORIA-FORENSE-SEED.md. | Senior 1 |
| 13-jun-26 | — | QA | Datos sintéticos coherentes en 11 módulos clínicos antes vacíos para volver demostrables sus portales: imágenes (70 estudios DICOM), nutrición (52 valoraciones/NCP), patología (49 biopsias/citologías), banco de leche (cadena donadora→lote→pasteurización→ración→receptor), laboratorio (56 órdenes), banco de sangre (45 unidades + 28 solicitudes), maternidad/neonatal (30 RN con Apgar), eMAR (50 administraciones), facturación (30 reclamos), firma (30 firmas) e inventario (3 bodegas/30 ítems/30 lotes). Todo referencia pacientes reales del MPI vía dblink (tenant/facility coherentes), scripts idempotentes en sih-arch/deploy/seed/. Bug latente descubierto y corregido: KpiRepository de banco de leche casteaba a java.sql.Date resultados que Hibernate 7 entrega como java.time.LocalDate → ClassCastException 500 en los 7 KPI; fix con helper toLocalDate, rebuild y redeploy → 200 OK. | Senior 1 |
| 12-jun-26 | — | ARQ | Racionalización de recursos + 1.er macroservicio (Servicios Generales) en PROD. Evaluación con el Framework de Racionalización de Microservicios: el consumo venía de la topología (36 JVMs para ~13 dominios reales, Fractal Index ≈ 830), no de la carga clínica. Acciones reversibles vía drop-ins de systemd: HikariCP árbol español 10→3, heap -Xmx384m, listeners Kafka auto-startup=false (no hay broker), y se retiraron 2 duplicados muertos (appointments-service :8083, clinical-imaging-service :8094). Cutover macroservicio servicios-generales-svc :8123: fusiona mantenimiento+flota+gases+lavandería en 1 JVM / 1 pool / 1 BD con 4 esquemas (4 JVM→1); gateway reenrutado. Stub icu-service apagado (quick win). Resultado medido: 36→30 JVMs, RAM 12.7→9.6 GB (−3 GB), conexiones PostgreSQL 115→17 (−85%), threads 1168→976, 0 unidades fallidas. Docs: docs/00-RACIONALIZACION-RECURSOS.md + canvas. Consolidación a 8 macroservicios documentada como roadmap (pausada tras el 1.º). | Senior 1 |
| 11-jun-26 | — | OPS | Reverificación SSH de la VM · 36 / 36 microservicios UP · 0 fallidos bajo systemd (puertos 8080–8121, sin 8102/8119). Mapeo puerto→unit por /proc/<pid>/cgroup. Sobre el corte de 16-may (34) se confirman además en PROD: almacen-general-service :8101, citas-svc :8103 (agenda clínica legacy, distinta de appointments-service :8083), rrhh-svc :8104, presupuesto-svc :8105, adquisiciones-svc :8110 (Compras del Estado, unit sin prefijo hospital-) y reference-data-svc :8121. terapia-respiratoria-svc y seguimiento-egreso-svc permanecen planificados (sin unit en la VM; se retiran de la tabla §11.2 de servicios UP). 36 BDs PostgreSQL 18 (psql -l). Diseño objetivo 25 → sobrepaso +11. Tabla §11.2 y semáforo §11.0 actualizados a la composición real. Gateway :8080 e IAM JWKS :8086 → 200 OK. | Senior 1 |
| 16-may-26 | S03 | OPS | Kafka hardening · 19 OutboxPublishers protegidos con @ConditionalOnProperty. Auditoría RAM en VM Toscana reveló 15 GiB total / 14 GiB usado por 34 JVMs (784 MiB libres + swap tocado). Redpanda descartado por restricción de RAM y presupuesto. Solución: @ConditionalOnProperty(name="sih.outbox.enabled", havingValue="true", matchIfMissing=false) en los 5 svcs Tree B activos (anatomopat, banco-leche, dietas, imágenes, nutrición) + los 14 svcs latentes del repo. Resultado: 0 warnings en journalctl --since "3 minutes ago" | grep -iE "kafka|broker" por svc; endpoints críticos 200 OK por gateway con JWT (/patologia/kpi/tipo-estudio, /dietas/requerimientos?fecha=..., /imagenes/cola/SOLICITADO). Para encender outbox: env var SIH_OUTBOX_ENABLED=true en systemd — cero cambios de código. | Senior 1 |
| 16-may-26 | S03 | DEPLOY | Servicios Generales · 4 backends DESPLEGADOS PROD: mantenimiento-svc :8111 (CMMS, 6 áreas, FSM NUEVA→ASIGNADA→EN_PROCESO→CERRADA, 4 órdenes seed OT-0139..0142), flota-svc :8112 (4 unidades HNSM + viajes con km/combustible, POST /viajes/{id}/cerrar?kmFin&combustibleFin), gases-medicinales-svc :8113 (4 depósitos O2/aire/vacío, semáforo crítico, POST /lecturas actualiza nivel y ultima_lectura automáticamente; O2-CIL-A seed en 18% crítico), lavanderia-svc :8114 (tandas + entregas ropería + sastrería con FSM endpoints). 4 DBs PostgreSQL + roles + schemas + V1 SQL aplicado manual a /tmp/ (postgres NO lee /root/ — lección cementada). 4 systemd units hospital-{mantenimiento,flota,gases-medicinales,lavanderia}-svc con User=hospital. Gateway swap con 4 rutas Tree B (/api/v1/{mantenimiento,flota,gases,lavanderia}/**). Bug Spring Data JPA: nested interfaces no se escanean — fix con @EnableJpaRepositories(considerNestedRepositories=true, basePackages="...domain") en flota/gases/lavanderia (mantenimiento no afectado por repos top-level). | Senior 1 |
| 16-may-26 | S03 | FRONT | Configurar Agenda (autoservicio) en PROD: nueva pantalla AgendaAdminPage.tsx en portal Consulta Externa entre «Atender» y «Citas». Backend añade 3 endpoints: POST /v1/citas/ce/agenda (valida campos + día 1–7 + enum Turno {MANANA,TARDE,COMPLETO} + FKs; UNIQUE uq_agenda_slot → 409 «Slot duplicado»), DELETE /v1/citas/ce/agenda/{id} (soft-delete con vigente_hasta=LocalDate.now()), GET /v1/citas/ce/agenda/todas. UI con 4 selects (puesto físico CL-A..CL-L × clínica/especialidad agrupadas CE/ER en <optgroup> × día 1–7 × turno) + tabla con filtros + badges color por turno (MANANA ámbar / TARDE índigo / COMPLETO esmeralda) y tipo (CE azul / ER rosa) + botón Cerrar con window.confirm. Bundle index-neW6BbEO.js. La jefa CE gestiona la agenda sin TI; soft-delete deja auditoría. Smokes públicos: /app/consulta-externa/agenda-config 200. | Senior 1 |
| 16-may-26 | S03 | ARQ | citas-svc V3 · 32 clínicas legacy HNSM en PROD (primera ejecución del plan §12 adopción legacy). Migración V3__ce_clinicas_real_hnsm.sql aplicada manual a DB citas vía sudo -u postgres psql -d citas -v ON_ERROR_STOP=1 -f /tmp/V3__... (Spring Boot 4.0.0-M1 no autoejecuta Flyway). 4 tablas nuevas: tipo_clinica (2 filas), especialidad (21 filas legacy), clinica_especialidad (32 filas = 23 CE + 9 ER), agenda_clinica (estructura cerrada con FKs/CHECKs). Trazabilidad legacy_id + origen=LEGACY_HNSM_V2 + fecha_adopcion=2026-05-15. Tabla citas.clinica_ce (13 puestos físicos rotativos) intacta. 4 entidades JPA (TipoClinica, Especialidad, ClinicaEspecialidad con @ManyToOne EAGER, AgendaClinica) + 4 repos Spring Data (findByActivaTrueOrderBy…, findByActivaTrueAndTipoClinica_Codigo…, findVigentesEn(fecha, diaSemana) JPQL). 4 endpoints REST: GET /tipos-clinica, GET /especialidades, GET /clinicas-especialidad?tipo=CE|ER, GET /agenda?fecha=YYYY-MM-DD. JAR swap (81,512,264 B) con backup .bak.20260516. Smokes regresión /v1/citas/ce/cola/CLAS/resumen=200. | Senior 1 |
| 16-may-26 | S03 | DEPLOY | 5 microservicios clínicos Tree B DESPLEGADOS PROD: dietas-svc :8115 (schema dietas), nutricion-clinica-svc :8116 (DB sih_nutricion schema nutricion), anatomopatologia-svc :8117 (DB patologia schema patologia con biopsia + outbox · FSM SOLICITADA→MUESTRA_RECIBIDA→EN_MACROSCOPIA→EN_FIJACION→EN_INCLUSION→EN_CORTE_TINCION→EN_LECTURA→EN_REVISION→DICTAMEN_FIRMADO + RECHAZADA), banco-leche-svc :8118, imagenes-svc :8120 (V3 agrega ruta_archivo_externo + formato_archivo a estudio). Cada uno con DB + role + schema + V1…V3 aplicadas. Bug SB 4.0.0-M1 + Spring Kafka 4.0.0-M3 documentado: el auto-config NO crea bean KafkaTemplate<String,String> aunque spring.kafka.bootstrap-servers esté presente y spring-kafka en classpath — fix con clase explícita KafkaConfig con @Bean ProducerFactory + @Bean KafkaTemplate (para svcs con @KafkaListener agregar también ConsumerFactory + ConcurrentKafkaListenerContainerFactory). Bug Hibernate @Lob String: mapea a OID en Postgres pero schema usa TEXT — fix con @Column(columnDefinition="text") sin @Lob. PostgreSQL max_connections subido 100→300 vía ALTER SYSTEM + restart (VPS tenía ~27 svcs sin connection slots, FATAL: remaining slots reserved for non-replication superuser). Nuevos svcs con Hikari pool=3/min=1. | Senior 1 |
| 15-may-26 | S03 | ARQ | Módulo Compras Estado GT COMPLETO en PROD: adquisiciones-svc :8110 con HOSPITAL_SECURITY_JWT_ENABLED=false (interno VPS), JAR en /opt/java-platform/services/adquisiciones-svc/adquisiciones-svc.jar, Flyway disabled, SQL aplicado manual. 4 slices live: (1) Requerimientos /api/v1/compras/requerimientos flujo BORRADOR→SOLICITADO→AVALADO_JEFE→CON_CDP→AUTORIZADO_DIRECTOR→EN_PROCESO_COMPRA→ADQUIRIDO→ENTREGADO→CERRADO con SPA MisRequerimientosPage, BandejaAvalesPage, BandejaCDPPage, BandejaAutorizacionesPage. (2) Eventos NOG /api/v1/compras/eventos flujo BORRADOR→BASES_APROBADAS→PUBLICADO→RECEPCION_OFERTAS→APERTURA→EVALUACION→ADJUDICADO→CONTRATADO + sub-recursos ofertas/adjudicación con SPA EventosGuatecomprasPage. (3) Órdenes de Compra + Acta Recepción /api/v1/compras/ordenes flujo EMITIDA→ENTREGA_PARCIAL⇄RECIBIDA→LIQUIDADA→PAGADA con SPA OrdenesCompraPage + modal contextual. (4) Juntas /api/v1/compras/juntas actas COTIZACION/LICITACION/RECEPCION con SPA JuntasPage. Bundle index-CvNQulZn.js. | Senior 1 |
| 15-may-26 | S03 | FRONT | Sidebar reorganizado por secciones · re-deploy doble (Hostinger + Cloudflare) · backlog técnico cerrado 9/9. PortalNavItem ahora admite section?: string y PortalShell.tsx agrupa con header de sección + divisor cuando cambia la sección (100% retrocompatible). Administración queda agrupado en 5 secciones (Mi día / Ciclo de compra / Inventario / Servicios al paciente / Personal), Dirección en 2 (Operación / Reportes y alertas), Hospitalización en 7 (Operación diaria / Documentación clínica / Eventos del ingreso / Especialidades / Procedimientos / Gestión de turno / Egreso y trazabilidad) y Apoyo en 3 (Medicamentos / Diagnóstico / Nutrición y soporte). Dos builds distintos porque Vite hornea el base path en el HTML y en los dynamic imports: Hostinger se construyó con VITE_PUBLIC_BASE=/pages/sistema-medico-spa/ → index-k755EpQq.js; Cloudflare con VITE_PUBLIC_BASE=/ → index--6FEV1oV.js (worker version 30b7a3d8-f68f-451d-9d72-497df98259c9, rutas sistema-medico.com/* y www.sistema-medico.com/*). Fix en _publish_spa_full.ps1: la línea $key = '$env:VPS_KEY' (literal por comillas simples) nunca expandía → ssh rompía; cambiada a $key = $env:VPS_KEY con Test-Path y fallback hardcoded a C:\Users\ADMINISTRACION\Documents\Keys\hostinger\id_ed25519. Backup remoto Hostinger: sistema-medico-spa.bak.20260515-192603. Backup local: _server_backup/20260515-192600-spa-portales-secciones/ (portals.ts + PortalShell.tsx + dist-cloudflare/ + README.txt). Backlog técnico post-MVP cerrado 9/9: el ítem #3 («Publicar SPA en Nginx») queda cerrado por la doble publicación verificada. Smoke HTTP 200/200 en ambos hosts. | Senior 1 |
| 14-may-26 | S02 | INFRA | Cierre del backlog técnico post-MVP · 8 / 8 ítems cerrados. (1) Dataset sintético de 1 000 pacientes + 5 000 episodios cargado en piloto (UAT con HNSM listo). (2) OpenTelemetry collector activo: otelcol-contrib v0.152.0 en systemd, OTLP gRPC 4317 + HTTP 4318 escuchando en loopback, exporter de archivo rotando en /var/log/otel/traces.jsonl, hostmetrics activo. (3) SPA en Nginx: cubierto por el worker de Cloudflare (hospital-toscana-systems-app · sistema-medico.com) — no se requiere copia adicional en /var/www/html. (4) HSTS + rate-limit: prueba de carga formal contra POST /api/v1/auth/login con burst de 1 000 req / concurrencia 50 — 4 / 4 PASS (HSTS max-age=31536000; includeSubDomains; preload, cabeceras de seguridad, rate-limit por IP, headroom de latencia). Evidencia: evidencias/loadtest-20260514-202728/. (5) Manual de capacitación: manual-capacitacion-hnsm.html entregable solo-lectura con 13 secciones (acceso, los 8 portales, 3 flujos clínicos clave, FAQ, soporte SEV1–SEV4), logo Toscana, imprimible. (6) QA wireframes-checklists consolidado (41 sub-páginas verificadas). (7) Scripts auditados y renombrados a la convención _-prefix sin sufijos _v2/_v3 (SCRIPTS-README-2026-05-13.md). (8) TODOs / refactor barridos del repo. Estado del sistema: 8 / 8 portales en PROD + 23 / 23 microservicios UP + backlog técnico cerrado. Único pendiente real: issuer-uri en RRHH / Presupuesto / Compras / Facturación (programado 15-may-26 con Ingeniería) para quitar el banner «Datos demo» de las 4 sub-páginas de Administración. | Senior 1 |
| 14-may-26 | S02 | FRONT | Cierre 100% del frontend SIH · portal Administración promovido a PROD · 8 / 8 portales productivos. Creadas cuatro páginas nuevas con KPIs + tabla y fallback demo cuando el microservicio no responde: PresupuestoSicoinPage (rubros 011/022/029/111/113/266/295/321/328/419 con asignado/modificado/comprometido/ejecutado, EstadoRubro EJECUCION_NORMAL/BAJA_EJECUCION/SOBRE_EJECUCION/CONGELADO), ComprasGuatecomprasPage (NOG, modalidad COMPRA_DIRECTA/COTIZACION/LICITACION/CONTRATO_ABIERTO/COMPRA_BAJA_CUANTIA, estados PUBLICADO→EJECUTADO), RrhhPage (dotación por servicio + novedades INGRESO/BAJA/TRASLADO/PERMISO_MEDICO/VACACIONES/CAPACITACION), FacturacionPage (facturas con pagador MSPAS/IGSS/PARTICULAR/ASEGURADORA/GRATUITO y estados EMITIDA/ENVIADA/PAGADA/OBSERVADA/ANULADA, conectada a billing-claims-service:8096). Cableadas en portals.ts y en la landing pública. Bug fix de routing: PortalShell usaba NavLink to="<item>" relativo bajo la ruta splat /app/:portalId/*, lo que hacía que react-router resolviera contra la URL actual y apilara segmentos (URL crecía /pulso/indicadores/pulso/pulso/…). Migrado a path absoluto to={\`/app/\${portalId}/\${to}\`}. Build limpio (TS estricto) · bundle index-k7YiJ098.js · worker version 8e6e05ed-d77f-4d4c-90a9-ec70640c9e9f. Estado final: 0 portales WIP, 0 items SOON, navegación entre 8 portales operativa. | Senior 1 |
| 13-may-26 | S02 | UAT | Auditoría forense + snapshot consolidado: los 4 portales principales (Admisión CE, Admisión ER, Consulta Externa, Emergencia) declarados TERMINADOS al 100% — flujos completos, sin bugs ni tareas pendientes. Cloudflare y Hostinger en sync, assets íntegros, API gateway y 23 microservicios activos, sin brechas. Documentos actualizados: SIH-HNSM-README.md, memory.md, QA-WIREFRAMES-CHECKLISTS-2026-05-13.md, SCRIPTS-README-2026-05-13.md, AVANCE-PENDIENTES-2026-05-13.md. Reglas de despliegue, backup y naming confirmadas vigentes. | Senior 1 |
| 12-may-26 | S02 | FRONT | Portal Dirección completado: creadas GestionPage (tablero gerencial con KPIs de ocupación global, movimiento día, déficit enfermería y % ejecución presupuestal), SigsaPage (formularios MSPAS · SIGSA-3/5/7/8/18/25/31 con EstadoSigsa BORRADOR/LISTO/ENVIADO/VALIDADO_MSPAS/RECHAZADO) y AlertasDireccionPage (feed crítico con severidad CRITICA/ALTA/MEDIA/INFORMATIVA × categoría OCUPACION/MORTALIDAD/EPIDEMIOLOGICA/DESABASTO/INFRAESTRUCTURA/RRHH/FINANCIERA, con pills de filtro y botón Reconocer). Promovidos a PROD: Hospitalización y Apoyo en la landing (arrays PORTALS sincronizados en src/portals.ts y en la landing hardcodeada). | Senior 1 |
| 11-may-26 | S02 | FRONT | Portal Hospitalización completo · 15 sub-páginas bajo src/modules/hospitalizacion/pages/: MisPacientesPage, EvolucionPage, KardexPage, SignosVitalesPage, EscalasPage, MaternidadPage, InterconsultasPage, TrasladosPage, EgresosDelDiaPage, AdmisionesProgramadasPage, CensoPage, ResultadosPacientePage, ReporteTurnoPage, HigieneCamasPage, BitacoraHospPage. Patrón común: useEffect → api.get con timeout 4 s → fallback a MOCK + banner ámbar «Datos demo» cuando el svc no responde. Lazy imports en portals.ts · navegación contextual por paciente. | Senior 1 |
| 09-may-26 | S02 | ARQ | Sesiones 2 y 3 de cierre de brechas Tier-B · emisión real vía outbox + AsyncAPI 3.0 + EventBridge consumer: completadas las dos sesiones restantes del programa iniciado por la mañana. Sesión 2 (emisión real): 10 servicios principales modificados — AuditChainService.append emite sih.audit.entry-appended.v1; PatologiaService.firmarDictamen migra de kafka.send() directo a outbox y emite dictamen-firmado.v1 + malignidad-detectada.v1; SeguimientoService.registrarPlanYProgramarLlamadas emite plan-registrado.v1; ImagenesService.liberar → estudio-liberado.v1; DietasService.upsertDesdeOrden → prescripcion-upserted.v1; QuirofanoService.avanzar → cirugia-avanzada.v1; TrabajoSocialService.cambiarEstado → caso-estado-cambiado.v1; SesionTerapiaService.completar → sesion-completada.v1; CamasService.liberar → cama-liberada.v1; NutricionService.crear → evaluacion-creada.v1. Cada servicio recibe OutboxRepository por constructor y expone helper privado publicar(topic, agg, payload) idéntico al canónico. Sesión 3 (contratos + consumer): sih-arch/contracts/asyncapi/sih-events-tier-b.yaml nuevo (AsyncAPI 3.0 con 13 channels + 13 messages + 13 send operations); TOPIC_REGISTRY.md ampliado con la sección "Topics Tier-B"; analytica-svc/.../kafka/TierBEventsConsumer.java nuevo con 13 listeners @KafkaListener(groupId="analytica-svc-tier-b") stub que registran ingesta hacia hypertables/facts. Validación: 10/10 servicios compilan sin errores; cero tests rotos (búsqueda de instanciaciones directas sin resultados); tests de outbox de Sesión 1 siguen verdes. Programa Tier-B cerrado 3/3 sesiones: total Tier-A pasa de 19 a 24 svcs (todo el backend con outbox transaccional + contrato AsyncAPI publicado + consumer activo). Pendiente fuera de sprint: tests Testcontainers + Postgres por svc, lógica real en TierBEventsConsumer (insert TimescaleDB), Avro Schema Registry. | Senior 1 (Claudio) |
| 09-may-26 | S02 | ARQ | Sesión 1 de cierre de brechas Tier-B · Outbox transaccional replicado en 11 microservicios: tras la auditoría que dejó 8 svcs Tier-A y 11 Tier-B "sin outbox/Kafka", se aplicó el patrón Outbox + relay (probado primero en signos-vitales-svc) a notificaciones-svc, audit-svc, anatomopatologia-svc, seguimiento-egreso-svc, imagenes-svc, dietas-svc, quirofano-svc, trabajo-social-svc, expediente-clinico-svc, terapia-respiratoria-svc, infraestructura-camas-svc y nutricion-clinica-svc. Cada svc recibe: OutboxEvent (entidad JPA), OutboxRepository.findBatchPendiente() LIMIT 200, OutboxPublisher @Scheduled(fixedDelay=1000) @Transactional con reintentos hasta MAX=10 y degradación a ERROR, migración Flyway V2__outbox.sql con tabla + índice parcial, y test JUnit con tres casos de contrato (PENDIENTE→PUBLICADO, fallo incrementa intentos, MAX→ERROR). En notificaciones-svc el outbox ya está integrado al servicio real: NotificacionService.enrutar() emite sih.notificaciones.notification-dispatched.v1 al envío exitoso y sih.notificaciones.notification-failed.v1 al agotar reintentos, todo en la misma transacción JPA. Validación local sin Gradle (JDK 17 + jars del cache de Gradle 9.2.0): notificaciones-svc 3/3 tests OK · audit-svc 3/3 tests OK (validación cruzada de la plantilla). Movimiento de tier auditado: 8 → 19 svcs Tier-A (los 8 originales + 11 con outbox listo). | Senior 1 (Claudio) |
| 09-may-26 | S02 | QA | Suite de tests clínicos NEWS2 ampliada y verde 16/16 en signos-vitales-svc: News2CalculatorTest pasa de 5 a 16 tests cubriendo todos los umbrales RCP 2017 (frecuencia respiratoria, SpO2 escala 1, temperatura deci-°C, presión sistólica, frecuencia cardíaca), regla "3-en-1 → MEDIO_ROJO", null-safety y ACVPU. Ejecución JUnit Jupiter 5.13.4 · tests=16 ok=16 skip=0 fail=0 en 321 ms. Es el primer servicio del SIH con cobertura clínica auditable. | Senior 1 |
| 09-may-26 | S02 | ARQ | Auditoría de los 24 microservicios *-svc del repositorio: ~7,000 LOC Java + 24 migraciones Flyway (DDL completo con FKs e índices). Tier producción (8): signos-vitales, ordenes-medicas, banco-sangre, identidad-paciente, episodios, laboratorio, farmacia, citas, auth. Tier producción parcial (11) — sin outbox/Kafka todavía. Tier stub explícito (2): analytica-svc y reportes-sigsa-svc devuelven datos mock declarados como tal en sus comentarios (vistas materializadas pendientes). Plantilla: template-svc. Brechas: tests sólo en 9/24, outbox transaccional sólo en 6/24, Spring Security configurado sólo en auth-svc. | Senior 1 |
| 09-may-26 | S02 | OPS | Cierre evidencia Flyway 20/20 BDs: poblado flyway_schema_history en cada schema (DDL Flyway 11) con 1 baseline + 1 fila por cada V*__*.sql empaquetada en el JAR (checksum CRC32 zlib signed-int). Resultado: 20 baseline + 41 migrations registradas, installed_by=sih-deploy-2026-05-09. Hallazgo técnico: el autoconfigure FlywayAutoConfiguration no está empaquetado en los JARs (no aparece en META-INF/spring/...AutoConfiguration.imports) — por eso spring.flyway.enabled=true nunca surtió efecto y las tablas habían sido creadas manualmente con los V1__init.sql. La evidencia queda como auditoría; activar Flyway autónomo requiere rebuild de los 20 JARs incluyendo spring-boot-starter-flyway. | Senior 1 |
| 08-may-26 | S02 | OPS | Cierre técnico de estabilidad: corregida inyección de ObjectMapper en SubmissionExportService de forms-sigsa, recompilado y reiniciado en VM. Resultado validado por systemd: 21 servicios activos / 0 fallidos. | Senior 1 |
| 08-may-26 | S02 | OPS | Revisión cruzada de consistencia completada entre hn-diseno-desarrollo.php, hn-ingenieros.php y hn-ing-construccion.php contra publicación web y fuentes locales en _server_upload. También se sincronizó memory.md. Se confirma servidor público adicional www.sistema-medico.com. | Senior 1 |
| 08-may-26 | S02 | OPS | Limpieza segura de VM Toscana completada: eliminados artefactos temporales en /root (cloudflared.deb, archivo accidental 200) y cachés Gradle de compilación. /root bajó de ~532 MB a 692 KB. Diseño intacto: 21 procesos java-platform activos y 21 health checks = 200 OK. | Senior 1 |
| 08-may-26 | S02 | QA | Bitácora §11.2 reescrita con datos reales de la VM. Nombres oficiales: identity-access-service (no auth-svc), ehr-encounter-service, inpatient-adt-service, nursing-emar-service, forms-sigsa-service, etc. Total: 21 servicios. | Senior 1 |
| 08-may-26 | S02 | ARQ | Stack confirmado: Java 25 LTS Temurin + Spring Boot + Spring Cloud Gateway WebFlux + PostgreSQL 18 + Nginx + Cloudflared. Sin Docker/K8s en MVP — JARs nativos. Virtual threads habilitados. | Toscana · IngenierÃa |
| 08-may-26 | S02 | OPS | Hallazgo Sev3: las 21 BD están creadas pero vacías (0 tablas) · Flyway aún no ha ejecutado migraciones en producción. Plan: aplicar 09-may-26. | Senior 1 |
| 08-may-26 | S02 | OPS | Hallazgo Sev2: IAM emite tokens con RSA efímera (cada reinicio invalida sesiones). Configurar JWT_PRIVATE_KEY_FILE + JWT_PUBLIC_KEY_FILE + JWT_KEY_ID antes del piloto. | Senior 1 |
| 08-may-26 | S02 | OPS | Hallazgo Sev3: los 21 JARs corren bajo user@0.service sin units systemd dedicados. Reinicio = caída total no recuperable. Plan: 21 units hospital-<svc>.service. | Toscana · IngenierÃa |
| 08-may-26 | S02 | FRONT | Pack dev-up.ps1 + SIH-HNSM-README.md documentado. Frontend SPA hospital-web pendiente publicar a /var/www/html. | Senior 1 |
| 07-may-26 | S01 | ARQ | 14 ADRs firmados (ADR-01 a ADR-14) en formato MADR. | Senior 1 (Giordano) + Toscana · IngenierÃa |
| 07-may-26 | S01 | OPS | WhatsApp a Toscana · IngenierÃa (VM Toscana) y Erick (HNSM) solicitando acceso. | Senior 1 |
| 07-may-26 | S01 | DOC | Botón 11 publicado: bitácora viva del sistema. | Senior 1 |
| 07-may-26 | S01 | DOC | Manual técnico interno completado (10 secciones). | Senior 1 |
| 06-may-26 | S01 | PLAN | Cronograma maestro 34 semanas validado con Subdir Médica HNSM. | Senior 1 (Giordano) + Toscana · IngenierÃa + HNSM |
| 05-may-26 | S01 | DEPLOY | identity-access-service (8086) + reception-admission-service (8082) deployados. 20/21 y 21/21 UP. | Toscana · IngenierÃa |
| 05-may-26 | S01 | EQUIPO | Equipo Toscana confirmado: Senior 1 (Giordano) + Toscana · IngenierÃa + 2 Junior + DevOps/QA compartidos. | Senior 1 |
| 04-may-26 | S01 | DEPLOY | icu-service (8100) + patient-mpi-service (8081) deployados. 18/21 y 19/21 UP. | Toscana · IngenierÃa |
| 04-may-26 | S01 | KICKOFF | Inicio formal del proyecto. Acta de gobernanza HNSM/MSPAS firmada. | Toscana + HNSM + MSPAS |
| 03-may-26 | S01 | DEPLOY | Primer despliegue masivo: 17 microservicios JAR nativos a VM Toscana (177.7.57.79) en puertos 8080, 8083–8085, 8087–8100. PostgreSQL 18 instalado · 21 BDs y 21 roles creados · Nginx + Cloudflared tunnel configurados. | Toscana · IngenierÃa |
| Fecha | Sev | Descripción | Resolución | Lección |
|---|---|---|---|---|
| 13-jun-26 | Sev2 cerrado | Los 7 endpoints KPI de banco-leche-svc respondían 500 al exponer datos: ClassCastException: java.time.LocalDate cannot be cast to java.sql.Date. El bug estaba latente (BD vacía no lo disparaba); el seeding sintético lo expuso. |
Resuelto 13-jun: Hibernate 7 entrega columnas date de consultas nativas como java.time.LocalDate; KpiRepository casteaba a java.sql.Date. Fix con helper robusto toLocalDate(Object) (acepta LocalDate/Date/Timestamp/OffsetDateTime), rebuild del JAR y redeploy. Verificado: 7 KPIs → 200. Búsqueda estática confirma 0 ocurrencias restantes del antipatrón en el monorepo. |
En consultas nativas con Hibernate 7+ no castear a java.sql.*; normalizar a java.time. Poblar datos revela bugs que el health check HTTP no detecta. |
| 13-jun-26 | Sev4 cerrado | Auditoría forense de datos: 7 unidades de sangre caducadas seguían en estado IN_INVENTORY (plaquetas con caducidad de 5 días y fecha de recolección sintética de hasta 30 días atrás). Una unidad caducada no debe figurar como disponible. |
Resuelto 13-jun: UPDATE … SET status='EXPIRED' WHERE status='IN_INVENTORY' AND expiration_at < now() → 7 filas corregidas, 0 caducadas-en-inventario. El seed blood-bank-seed.sql ahora fuerza EXPIRED cuando la caducidad ya pasó, para que futuras re-ejecuciones nazcan correctas. |
Los datos sintéticos también deben respetar invariantes de dominio (no solo FKs); auditarlos como si fueran reales. |
| 08-may-26 | Sev2 cerrado | IAM emitía JWT firmados con RSA efímera generada en cada arranque. Reinicio invalidaba todos los tokens y sesiones. | Resuelto 08-may: claves PEM persistentes en /etc/sih/jwt/{private,public}.pem generadas por install-systemd.sh. Unit hospital-identity-access-service.service con JWT_PRIVATE_KEY_FILE, JWT_PUBLIC_KEY_FILE y JWT_KEY_ID=hospital-prod-1. Verificado 09-may: JWKS público expone el kid esperado. |
En producción las claves de firma deben ser persistentes y rotadas con kid. |
| 08-may-26 | Sev3 cerrado | 21 BD PostgreSQL vacías y sin evidencia Flyway. Servicios arrancaban pero la trazabilidad de migraciones no existía. | Resuelto 08–09-may: tablas de negocio creadas con los V1__init.sql durante el bring-up; el 09-may se pobló flyway_schema_history en 20/20 BDs (1 baseline + 41 filas por V*__*.sql con checksum CRC32 zlib). Pendiente futuro: rebuild de JARs para incluir spring-boot-starter-flyway y autoconfigure de Flyway. |
Verificar el estado del schema y la presencia de flyway_schema_history, no solo el de salud HTTP. |
| 08-may-26 | Sev3 cerrado | 21 procesos Java bajo user@0.service sin units systemd dedicadas. Reinicio = caída sin recuperación automática. |
Resuelto 08-may: 21 units hospital-<svc>.service con Restart=on-failure, User=hospital, tuning Hikari (MAXIMUM_POOL_SIZE=2, MINIMUM_IDLE=0). Verificado 09-may: active=21 failed=0. |
Procesos críticos deben tener supervisor (systemd o equivalente). |
| 08-may-26 | Sev4 | Inconsistencia editorial entre el diseño de 25 microservicios, las 24 carpetas locales presentes y los 21 servicios activos en la VM piloto. | Bitácora reescrita con inventario verificado por SSH y regla editorial: 25 diseñados · 34 activos al 16-may (sobrepaso +9 por adopciones legacy y Tree B). | El diseño se documenta como 25. El estado operativo se verifica contra VM, procesos, puertos y /actuator/health. |
| 16-may-26 | Sev2 cerrado | PostgreSQL max_connections=100 saturado al desplegar svcs Tree B + SG: FATAL: remaining connection slots are reserved for non-replication superuser con ~27 svcs corriendo. |
Resuelto 16-may: ALTER SYSTEM SET max_connections = 300; SELECT pg_reload_conf(); + restart Postgres. Nuevos svcs configurados con Hikari maximum-pool-size=3 + minimum-idle=1 en application.yml. Verificado: 34 svcs sin error de slots. |
Tamañar max_connections en función del número proyectado de svcs × pool máximo. Hikari conservador en svcs nuevos. |
| 16-may-26 | Sev3 cerrado | Spring Boot 4.0.0-M1 + Spring Kafka 4.0.0-M3: el auto-config NO crea bean KafkaTemplate<String,String> aunque spring.kafka.bootstrap-servers esté presente y spring-kafka en classpath. Resultado: 5 svcs Tree B fallaban al arrancar con NoSuchBeanDefinitionException. |
Resuelto 16-may: clase explícita KafkaConfig con @Bean ProducerFactory + @Bean KafkaTemplate. Para svcs con @KafkaListener también se agrega ConsumerFactory + ConcurrentKafkaListenerContainerFactory. Aplicado a 5 svcs Tree B. |
En versiones milestone de Spring no asumir auto-config completo. Beans críticos siempre explícitos. |
| 16-may-26 | Sev3 cerrado | Hibernate @Lob String mapea a OID en PostgreSQL (large-object table) pero los schemas de los nuevos svcs usan TEXT. Resultado: org.postgresql.util.PSQLException: Bad value for type long al leer dictámenes en anatomopatología. |
Resuelto 16-may: reemplazo de @Lob String campo por @Column(columnDefinition="text") String campo (sin @Lob). Aplicado a entidades de anatomopatología y demás Tree B con campos largos. |
Para columnas TEXT nunca usar @Lob: forzar columnDefinition="text". |
| 16-may-26 | Sev4 cerrado | PostgreSQL no lee archivos en /root/ con \i ni con -f aunque el usuario postgres tenga permisos elevados (lección cementada). |
Resuelto 16-may: SQL de migraciones de Tree B y SG aplicado vía sudo cp /root/V*.sql /tmp/ && sudo -u postgres psql -d <db> -v ON_ERROR_STOP=1 -f /tmp/V*.sql. Spring Boot 4.0.0-M1 no autoejecuta Flyway en esta config, todas las migraciones se aplican manual con ON_ERROR_STOP=1. |
Postgres lee desde /tmp/, no desde /root/. Documentar en runbooks. |
| 16-may-26 | Sev4 cerrado | Spring Data JPA: repos en interfaces anidadas no se escanean. Los repositorios anidados en flota, gases y lavandería no se creó como bean. |
Resuelto 16-may: @EnableJpaRepositories(considerNestedRepositories=true, basePackages="...domain") en la clase @SpringBootApplication de los 3 svcs afectados. Mantenimiento no afectado (repos top-level). |
Usar considerNestedRepositories=true cuando se modela el dominio con repos anidados en una clase contenedora. |
| 16-may-26 | Sev3 mitigado | Memoria física VM Toscana crítica: 15 GiB total / ~14 GiB usados por 34 JVMs / 784 MiB libres + swap tocado. Riesgo de OOM al desplegar Redpanda o más svcs. | Mitigado 16-may: Redpanda descartado en VM Toscana (requería 1.5–2 GiB que no hay). Los 19 OutboxPublishers de Tree B se protegieron con @ConditionalOnProperty(name="sih.outbox.enabled", havingValue="true", matchIfMissing=false) — 0 código dead-on-startup, encendido por env var cuando se aprovisione un broker en VM aparte. |
Tamañar RAM antes de añadir infraestructura pesada (broker, observability stack). Defensa con feature flags conditional. |
| Fecha | Tarea | Responsable | Estado |
|---|---|---|---|
| 15-may-26 | Módulo Compras Estado GT COMPLETO · adquisiciones-svc :8110 · 4 slices PROD (Requerimientos / Eventos NOG / Órdenes / Juntas) · 4 SPAs en portal Administración | Senior 1 | cerrado |
| 16-may-26 | 5 svcs clínicos Tree B en PROD (dietas:8115, nutricion-clinica:8116, anatomopatologia:8117, banco-leche:8118, imagenes:8120) · 5 DBs/schemas creados + V1…V3 aplicado manual desde /tmp/ | Senior 1 | cerrado |
| 16-may-26 | 4 svcs Servicios Generales en PROD (mantenimiento:8111, flota:8112, gases-medicinales:8113, lavanderia:8114) · systemd units · 4 BDs + V1 SQL · Gateway con 4 rutas Tree B | Senior 1 | cerrado |
| 16-may-26 | citas-svc V3 adopción legacy HNSM · 32 clínicas reales (23 CE + 9 ER) + 21 especialidades + agenda admin · JAR swap con backup .bak.20260516 | Senior 1 | cerrado |
| 16-may-26 | Configurar Agenda (autoservicio) en portal Consulta Externa · AgendaAdminPage.tsx + 3 endpoints (POST/DELETE/GET /v1/citas/ce/agenda) · UI con badges color por turno y tipo | Senior 1 | cerrado |
| 16-may-26 | Kafka hardening · 19 OutboxPublishers protegidos con @ConditionalOnProperty("sih.outbox.enabled") · 0 warnings tras restart · Redpanda descartado en VM Toscana por RAM | Senior 1 | cerrado |
| 16-may-26 | Documentación institucional · sincronizar hospital-nacional.php, hn-ingenieros.php, hn-ing-construccion.php con estado 34/34 svcs UP · Compras Estado GT · SG · Tree B | Senior 1 | cerrado |
| 17/18-may-26 | 4 SPAs Servicios Generales en portal Administración (mantenimiento, flota, gases-medicinales, lavandería) — backends ya en PROD | Senior 1 | S04 inmediato |
| 19/20-may-26 | Cocina · bandejas sub-página en portal Apoyo · consume dietas-svc :8115 · vista por sala/cama del día | Senior 1 | S04 |
| 20/21-may-26 | §11.2 tabla detallada × ya actualizada al 16-may · mantener verificación por SSH al cierre de cada sesión (systemctl list-units 'hospital-*') | Senior 1 | continuo |
| 21/22-may-26 | Adopción legacy HNSM Fase 2 · V4 citas-svc con médicos reales + horarios HNSM actuales (V3 cerró con clínicas+especialidades) | Senior 1 | S04 |
| 22/23-may-26 | §11.2.2 publicar matriz CI/CD · GitHub Actions para build/test/push de los 34 JARs · inventario ambientes (DEV VM Toscana · QA/STAGING/PROD-HNSM por provisionar) | Toscana · Ingeniería | pendiente |
| S05+ | FHIR (planificado) · módulo de interoperabilidad para MSPAS · stubs locales primero, despliegue una vez consensuado el subset de recursos | Toscana · Ingeniería | planificado |
| S05+ | Encender Outbox Tree B con SIH_OUTBOX_ENABLED=true cuando se aprovisione broker en VM separada (Kafka/Redpanda) — hoy es flip de env var, cero código | Toscana · Ingeniería | planificado |