Sistema Médico Hospital Nacional d. Ingenieros y Programadores 11. Sistema HNSM en construcción

📡 Estado en vivo

Snapshot: 13 de junio 2026 · GT · Fase A · Cimientos cerrada · verificado por SSH directo en VM Toscana y por HTTP sobre sistema-medico.com + toscanasystems.com/pages/sistema-medico-spa/
  • Semáforo GENERAL 🟢 30 / 30 servicios UP · 0 fallidos bajo systemd · topología racionalizada (12–13 jun): de 36 a 30 JVMs tras retirar 2 duplicados muertos (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.
  • Infra VM AMD EPYC 9354P · 4 vCPU · 16 GB RAM (~9.6 GB en uso por 30 JVMs tras racionalizar; antes ~14–15 GB / 36) · 193 GB SSD · Ubuntu · Java 25 LTS Temurin · PostgreSQL 18 con max_connections=300 (conexiones activas 115→17) · Nginx + Cloudflared (sin Docker/K8s). HikariCP árbol español 10→3, listeners Kafka apagados (sin broker).
  • Datos sintéticos QA 11 módulos clínicos antes vacíos ahora poblados con datos sintéticos coherentes referenciando pacientes reales del MPI vía 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.
  • Datos BD 25+ BD PostgreSQL 18 con role y schema dedicado por servicio (database-per-service). citas-svc V3 (16-may-26): adopción legacy HNSM — 32 clínicas reales (23 CE + 9 ER), 21 especialidades, trazabilidad legacy_id + origen=LEGACY_HNSM_V2.
  • Frontend FRONT sih-frontend 100% PROD · 10 / 10 portales productivos (incluye Financiero + Farmacia PROAM independientes) · 4 portales clínicos (Admisión CE, Admisión ER, Consulta Externa, Emergencia) TERMINADOS al 100% · nueva pantalla Configurar agenda (autoservicio) en Consulta Externa · nueva sub-sección Servicios Generales en Administración con 4 ítems WIP (Mantenimiento, Ambulancias, Oxígeno, Lavandería) · nueva sub-página Cocina · bandejas en Apoyo. React 19 + Vite 6 + TypeScript estricto · desplegado en Cloudflare Workers (hospital-toscana-systems-app) servido en sistema-medico.com.
  • Outbox OPS Kafka hardening 16-may: 19 OutboxPublishers protegidos con @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.

11.1 Estado general del proyecto

IndicadorValor real (verificado en VM)Meta fase AEstado
SemanaS03 de 34S08en curso
FaseA · CimientosCierre fin de juniocerrada anticipada
Microservicios diseñados25 diseñados · llegó a 36 implementados · racionalizado a 30 activos (12–13 jun: −2 duplicados muertos, Servicios Generales 4→1, −1 stub icu)25racionalizado
Servicios desplegados y UP30 / 30 en VM Toscana (verificado por /actuator/health y systemctl is-active · 0 failed)21100%
API GatewayOperativo en :8080 · Spring Cloud Gateway WebFlux · 25+ rutas /api/v1/**OperativoUP
IAM (auth + JWKS)Operativo en :8086 · OAuth2 + JWT (RS256) · /.well-known/jwks.jsonOperativoUP
BD PostgreSQL provisionadas36 (con role y schema dedicado por servicio)21creadas
BD con migraciones Flyway aplicadas20 de 20 con flyway_schema_history poblado (1 baseline + 41 filas migration · CRC32 zlib)20evidencia auditable
Java runtimeTemurin OpenJDK 25.0.3 LTS · virtual threads habilitadosJava 25completo
Hosting / DNS públicoCloudflare Tunnel + Nginx · 6 dominios activosHTTPS públicoactivo
ObservabilidadLogs en /var/log/hospital-services/*.log · OTel collector definido pero no corriendoPrometheus + Grafana + Loki + Tempoparcial
ADRs firmados14 de 1414completo
Datos sintéticos / piloto11 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 episodiosparcial
Backup / DRPRespaldo 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úblicaPolítica de backupsoperativo
CapacitaciónNo iniciadaS31–S32programada

11.2 Microservicios · estado real (verificado en VM)

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.

25
Microservicios diseñados
30 / 30
Servicios UP en PROD
100%
Health checks OK
25+
BD PostgreSQL 18
25+
Rutas en gateway
14
ADRs MADR
~9.6 GB
RAM JVMs (de 16 GB) · −3 GB

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)PuertoBase de datosRuta gatewayResponsabilidadEstado
1puerta-de-enlace-apiapi-gateway-service8080— (sin BD propia)Spring Cloud Gateway WebFlux · BFF · 25+ rutas /api/v1/** · valida JWT (iss/aud) · X-Hospital-Trace-Id · cabeceras de seguridadUP
2identidad-paciente-svcpatient-mpi-service8081patient_mpi_db/api/v1/pacientes/**MPI · pacientes con DPI/carné · identidad clínicaUP
3admision-recepcion-svcreception-admission-service8082reception_admission_db/api/v1/admision/**Visitas · carné · reposicionesUP
4citas-svcappointments-service8083appointments_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
5triaje-emergencias-svcemergency-triage-service8084emergency_db/api/v1/emergencias/**Emergencias · síntomas → diagnóstico → Rx automática · vínculo a hospitalización-adtUP
6quirofano-svcsurgery-service8085surgery_db/api/v1/quirofano/**Cirugía perioperatoria · workflow PROGRAMADA → EN_CURSO → COMPLETADA · consume-stockUP
7identidad-y-acceso-svcidentity-access-service8086identity_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 ServersUP
8catalogo-inventario-svcinventory-catalog-service8087inventory_catalog_db/api/v1/inventario/**Bodegas · ubicaciones · lotes · catálogo de insumosUP
9existencias-svcstock-ledger-service8088stock_ledger_db/api/v1/existencias/**Libro mayor de stock · movimientos · referencias farmacia/cirugíaUP
10maternidad-neonatal-svcmaternity-neonatal-service8089maternity_neonatal_db/api/v1/maternidad/**Maternidad y neonatos · prefill de formulariosUP
11formularios-sigsa-svcforms-sigsa-service8090forms_sigsa_db/api/v1/formularios-sigsa/**Formularios SIGSA · integración MSPASUP
12farmacia-recetas-svcpharmacy-prescriptions-service8091pharmacy_db/api/v1/farmacia/**Receta · dispensación · comprobante · cola por módulo · Resilience4jUP
13hospitalizacion-adt-svcinpatient-adt-service8092inpatient_adt_db/api/v1/hospitalizacion/**ADT hospitalario · admisión · traslado · alta · cama y servicioUP
14laboratorio-clinico-svcclinical-laboratory-service8093clinical_lab_db/api/v1/laboratorio/**LIS · órdenes y resultados de laboratorio clínicoUP
15imagenologia-clinica-svcclinical-imaging-service8094clinical_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
16enfermeria-emar-svcnursing-emar-service8095nursing_emar_db/api/v1/enfermeria/**eMAR · administración de medicamentos por enfermeríaUP
17facturacion-reclamos-svcbilling-claims-service8096billing_claims_db/api/v1/facturacion/**Facturación y reclamosUP
18firma-clinica-svcclinical-signature-service8097clinical_signature_db/api/v1/firmas/**Firma electrónica clínica · trazabilidadUP
19expediente-encuentros-svcehr-encounter-service8098ehr_encounter_db/api/v1/expediente/**EHR · encuentros longitudinales · evolución clínicaUP
20banco-sangre-svcblood-bank-service8099blood_bank_db/api/v1/banco-sangre/**Banco de sangre · tipificación · cross-match · trazabilidad bolsasUP
21uci-svcicu-service8100icu_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
22almacen-general-svcalmacen-general-service8101almacen_general/api/v1/almacen-general/**Almacén general · existencias y despachos hacia bodegas de servicioUP
23citas-clinicas-svccitas-svc8103citas/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_V2UP
24recursos-humanos-svcrrhh-svc8104rrhh/api/v1/rrhh/**RRHH · plantilla · turnos · asistencia · novedades de personalUP
25presupuesto-svcpresupuesto-svc8105presupuesto/api/v1/presupuesto/**Presupuesto · ejecución por programa y renglón · enlace SICOINUP
26adquisiciones-svcadquisiciones-svc8110adquisiciones_db/api/v1/compras/**15-may Compras del Estado (Decreto 57-92) · 4 slices: Requerimientos / Eventos NOG / Órdenes / Juntas · catalog (BORRADOR→…→CERRADO)UP
27mantenimiento-svcmantenimiento-svc8111mantenimiento/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
28flota-svcflota-svc8112flota/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
29gases-medicinales-svcgases-medicinales-svc8113gases/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
30lavanderia-svclavanderia-svc8114lavanderia/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
31dietas-svcdietas-svc8115dietas (schema dietas)/api/v1/dietas/**16-may Tree B Dietas · menus y régimen dietético hospitalarioUP
32nutricion-clinica-svcnutricion-clinica-svc8116sih_nutricion (schema nutricion)/api/v1/nutricion/**16-may Tree B Nutrición clínica · valoración y planesUP
33anatomopatologia-svcanatomopatologia-svc8117patologia (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 + RECHAZADAUP
34banco-leche-svcbanco-leche-svc8118banco_leche/api/v1/banco-leche/**16-may Tree B Banco de leche humana · donación · trazabilidadUP
35imagenes-svcimagenes-svc8120imagenes/api/v1/imagenes/**16-may Tree B Imágenes · V3 agrega ruta_archivo_externo + formato_archivo en estudio · cola SOLICITADO/EN_PROGRESO/COMPLETADOUP
36datos-referencia-svcreference-data-svc8121reference_data_dbcatálogos compartidos · internoCatálogos compartidos (datos de referencia) consumidos internamente por los demás serviciosUP
37servicios-generales-svcservicios-generales-svc8123servicios_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
Cómo se verificó (13-jun-26): (1) systemctl list-units --state=running 'hospital-*.service' adquisiciones-svc.service30 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).

11.2.1 Pendientes priorizados

PendientePor qué importaResponsableFecha objetivo
Validar visualmente los 4 portales de Servicios Generales (mantenimiento, flota, gases-medicinales, lavandería) con login realVerificado 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 12026-06-13
Sub-página Cocina · bandejas en portal Apoyo — backend dietas-svc :8115 YA en PRODPermitirá al chef de cocina ver bandejas del día por sala/cama. Hoy WIP.Senior 12026-05-22
Tabla §11.2 ya actualizada con los 30 servicios activos (racionalizado de 36) — mantener verificación por SSH al cierre de sesiónLa 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 1continuo
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íaS04–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 12026-05-23

11.2.2 CI/CD · ambientes · estrategia despliegue por publicar S04

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).

11.3 Entornos

EntornoPropósitoUbicaciónURLEstadoResponsable
QAPruebas integradas + dataset sintéticoVM Toscana (mismo host, perfil Spring distinto · pendiente)pendientepor habilitarToscana · Ingeniería
STAGINGPre-producción · UAT con HNSMSuperservidor HNSMinterno HNSMpor provisionarErick (HNSM) + Toscana · Ingeniería
PROD-HNSMProducción · pacientes realesSuperservidor HNSMinterno HNSMpor provisionarErick + Toscana 24×7

11.3.A VM Toscana · ya verificada

Acceso confirmado el 2026-05-08:
  1. IP pública 177.7.57.79 · puerto SSH 22 estándar.
  2. Usuario root · clave SSH ed25519 cargada (id_ed25519 · misma clave que Hostinger).
  3. SO: Ubuntu Linux · arch x86_64.
  4. Recursos: 4 vCPU AMD EPYC 9354P · 16 GB RAM · 193 GB SSD (5.5 GB usado).
  5. Puertos 80 y 443 expuestos · TLS terminado en Cloudflare Tunnel.
  6. Firewall: solo Nginx :80 hacia Internet · servicios :8080–:8100 en localhost.
  7. Servicios extra: fail2ban, chrony, cloudflared, postgresql@18-main.

11.3.B Checklist · onboarding Servidor HNSM (Erick)

Reunión pendiente con Erick (Jefe Informática HNSM). Cuestionario para la primera reunión:
Hardware
  1. Marca/modelo (HP / Dell / otro) y año.
  2. CPU: cores físicos / hilos · arquitectura.
  3. RAM total y libre (referencia: VM Toscana corre los 21 con 9 GB).
  4. Almacenamiento: tipo (NVMe/SSD/HDD), capacidad libre, RAID.
  5. ¿Cluster con réplica/HA o servidor único?
  6. UPS · autonomía · generador.
SO y virtualización
  1. SO actual (VMware ESXi / Proxmox / Hyper-V / bare metal Linux).
  2. ¿VMs nuevas o contenedores directamente?
  3. Cuota de recursos para SIH (ideal: 32 vCPU · 64 GB · 2 TB).
  4. ¿Exclusivo SIH o compartido?
Red
  1. IP en LAN HNSM · subnet · máscara.
  2. VLAN clínica vs administrativa.
  3. Ancho de banda (1 Gbps / 10 Gbps).
  4. Salida a Internet · proxy corporativo.
  5. VPN site-to-site Toscana ↔ HNSM.
Acceso y seguridad
  1. Conexión actual (SSH / RDP / consola / VPN).
  2. Política: claves SSH o contraseñas.
  3. Usuarios admin para Toscana · Ingeniería y Senior 1 (Giordano).
  4. Antivirus corporativo · ¿bloquea Java/JARs en /opt?
  5. Política y frecuencia de backups.
  6. Retención de datos clínicos (ley GT · MSPAS).
Integraciones existentes
  1. SIGSA: ¿conexión actual? URL/cert/VPN.
  2. SICOIN, RENAP, IGSS · credenciales.
  3. LIS / PACS / monitores · protocolo (HL7v2 / FHIR / propietario).
  4. IPs de analizadores, PACS, monitores.
Operacional
  1. ¿24×7 o turnos?
  2. Canal alertas Sev1 (WhatsApp/correo).
  3. Ventanas de mantenimiento.
  4. Prometheus/Grafana/Zabbix HNSM existentes.

11.4 Historial de deploys

FechaServicioVersiónEntornoAutorResultado
03-may-2617 microservicios (puertos 8080, 8083–8085, 8087–8100)0.1.0-SNAPSHOTDEV · VM ToscanaToscana · IngenieríaUP
04-may-26icu-service (8100) + patient-mpi-service (8081)0.1.0-SNAPSHOTDEV · VM ToscanaToscana · IngenieríaUP
05-may-26identity-access-service (8086) + reception-admission-service (8082)0.1.0-SNAPSHOTDEV · VM ToscanaToscana · IngenieríaUP
15-may-26adquisiciones-svc (8110) — módulo Compras Estado GT completo (4 slices: Requerimientos, Eventos NOG, Órdenes, Juntas)0.1.0-SNAPSHOTPROD · VM ToscanaSenior 1UP
16-may-26Tree B: dietas-svc (8115) + nutricion-clinica-svc (8116) + anatomopatologia-svc (8117) + banco-leche-svc (8118) + imagenes-svc (8120)0.1.0-SNAPSHOTPROD · VM ToscanaSenior 1UP
16-may-26Servicios Generales: mantenimiento-svc (8111) + flota-svc (8112) + gases-medicinales-svc (8113) + lavanderia-svc (8114)0.1.0-SNAPSHOTPROD · VM ToscanaSenior 1UP
16-may-26citas-svc V3 — adopción legacy HNSM (32 clínicas + 21 especialidades + agenda admin) · JAR swap con backup .bak.202605160.1.0-SNAPSHOTPROD · VM ToscanaSenior 1UP
11-jun-26Reverificació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-SNAPSHOTPROD · VM ToscanaSenior 1UP
12-jun-26Macroservicio 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-SNAPSHOTPROD · VM ToscanaSenior 1UP
13-jun-26Datos 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-SNAPSHOTPROD · VM ToscanaSenior 1UP
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%.

11.5 ADRs firmados

ADRDecisiónFechaFirmaEstado
ADR-01Microservicios con database-per-service07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-02Java 25 LTS + Spring Boot + Loom (virtual threads)07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-03React 19 + TanStack Query + Tailwind v407-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-04PostgreSQL 18 como BD primaria (database-per-service)07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-05MongoDB para notas clínicas (futuro · no en VM hoy)07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-06TimescaleDB para signos vitales (futuro · no en VM hoy)07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-07Apache Kafka como bus de eventos (futuro · no en VM hoy)07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-08Mirth Connect para HL7 v2 (futuro)07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-09FHIR R4 para interoperabilidad externa07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-10OAuth2 Resource Server + JWT (RS256) con JWKS07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-11Despliegue JAR nativo vía systemd (sin Docker en MVP)07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-12Auditoría WORM con hash encadenado07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-13Observabilidad OpenTelemetry → Prometheus + Grafana + Loki + Tempo07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
ADR-14CI/CD con GitHub Actions (Temurin 25)07-may-26Senior 1 (Giordano) + Toscana · Ingenieríaaceptado
Texto completo: en hn-ing-adrs.php.

11.6 Bitácora completa

Tipos: KICKOFF · ARQ · DEV · QA · DEPLOY · DOC · PLAN · INTEGR · OPS · INC · UAT · INFRA · FRONT.

FechaSem.TipoAvanceResponsable
13-jun-26OPSBackup 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_INVENTORYEXPIRED). Copia local en C: + git bundle. Docs: docs/00-AUDITORIA-FORENSE-SEED.md.Senior 1
13-jun-26QADatos 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.LocalDateClassCastException 500 en los 7 KPI; fix con helper toLocalDate, rebuild y redeploy → 200 OK.Senior 1
12-jun-26ARQRacionalizació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-26OPSReverificació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-26S03OPSKafka 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-26S03DEPLOYServicios 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-26S03FRONTConfigurar 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-26S03ARQcitas-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-26S03DEPLOY5 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-26S03ARQMó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-26S03FRONTSidebar 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-26S02INFRACierre 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-26S02FRONTCierre 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-26S02UATAuditorí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-26S02FRONTPortal 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-26S02FRONTPortal 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: useEffectapi.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-26S02ARQSesiones 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.liberarestudio-liberado.v1; DietasService.upsertDesdeOrdenprescripcion-upserted.v1; QuirofanoService.avanzarcirugia-avanzada.v1; TrabajoSocialService.cambiarEstadocaso-estado-cambiado.v1; SesionTerapiaService.completarsesion-completada.v1; CamasService.liberarcama-liberada.v1; NutricionService.crearevaluacion-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-26S02ARQSesió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-26S02QASuite 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-26S02ARQAuditorí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-26S02OPSCierre 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-26S02OPSCierre 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-26S02OPSRevisió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-26S02OPSLimpieza 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-26S02QABitá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-26S02ARQStack 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-26S02OPSHallazgo 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-26S02OPSHallazgo 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-26S02OPSHallazgo 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-26S02FRONTPack dev-up.ps1 + SIH-HNSM-README.md documentado. Frontend SPA hospital-web pendiente publicar a /var/www/html.Senior 1
07-may-26S01ARQ14 ADRs firmados (ADR-01 a ADR-14) en formato MADR.Senior 1 (Giordano) + Toscana · Ingeniería
07-may-26S01OPSWhatsApp a Toscana · Ingeniería (VM Toscana) y Erick (HNSM) solicitando acceso.Senior 1
07-may-26S01DOCBotón 11 publicado: bitácora viva del sistema.Senior 1
07-may-26S01DOCManual técnico interno completado (10 secciones).Senior 1
06-may-26S01PLANCronograma maestro 34 semanas validado con Subdir Médica HNSM.Senior 1 (Giordano) + Toscana · Ingeniería + HNSM
05-may-26S01DEPLOYidentity-access-service (8086) + reception-admission-service (8082) deployados. 20/21 y 21/21 UP.Toscana · Ingeniería
05-may-26S01EQUIPOEquipo Toscana confirmado: Senior 1 (Giordano) + Toscana · Ingeniería + 2 Junior + DevOps/QA compartidos.Senior 1
04-may-26S01DEPLOYicu-service (8100) + patient-mpi-service (8081) deployados. 18/21 y 19/21 UP.Toscana · Ingeniería
04-may-26S01KICKOFFInicio formal del proyecto. Acta de gobernanza HNSM/MSPAS firmada.Toscana + HNSM + MSPAS
03-may-26S01DEPLOYPrimer 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

11.7 Hallazgos e incidentes

FechaSevDescripciónResoluciónLecció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.
Severidad: Sev1 = caída total · Sev2 = degradación significativa · Sev3 = error contenido · Sev4 = cosmético.

11.8 Próximos 7 días

FechaTareaResponsableEstado
15-may-26Módulo Compras Estado GT COMPLETO · adquisiciones-svc :8110 · 4 slices PROD (Requerimientos / Eventos NOG / Órdenes / Juntas) · 4 SPAs en portal AdministraciónSenior 1cerrado
16-may-265 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 1cerrado
16-may-264 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 BSenior 1cerrado
16-may-26citas-svc V3 adopción legacy HNSM · 32 clínicas reales (23 CE + 9 ER) + 21 especialidades + agenda admin · JAR swap con backup .bak.20260516Senior 1cerrado
16-may-26Configurar Agenda (autoservicio) en portal Consulta Externa · AgendaAdminPage.tsx + 3 endpoints (POST/DELETE/GET /v1/citas/ce/agenda) · UI con badges color por turno y tipoSenior 1cerrado
16-may-26Kafka hardening · 19 OutboxPublishers protegidos con @ConditionalOnProperty("sih.outbox.enabled") · 0 warnings tras restart · Redpanda descartado en VM Toscana por RAMSenior 1cerrado
16-may-26Documentación institucional · sincronizar hospital-nacional.php, hn-ingenieros.php, hn-ing-construccion.php con estado 34/34 svcs UP · Compras Estado GT · SG · Tree BSenior 1cerrado
17/18-may-264 SPAs Servicios Generales en portal Administración (mantenimiento, flota, gases-medicinales, lavandería) — backends ya en PRODSenior 1S04 inmediato
19/20-may-26Cocina · bandejas sub-página en portal Apoyo · consume dietas-svc :8115 · vista por sala/cama del díaSenior 1S04
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 1continuo
21/22-may-26Adopción legacy HNSM Fase 2 · V4 citas-svc con médicos reales + horarios HNSM actuales (V3 cerró con clínicas+especialidades)Senior 1S04
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íapendiente
S05+FHIR (planificado) · módulo de interoperabilidad para MSPAS · stubs locales primero, despliegue una vez consensuado el subset de recursosToscana · Ingenieríaplanificado
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ódigoToscana · Ingenieríaplanificado
Cómo se mantiene esta página viva: al cierre de cada sesión se actualizan 11.1 (semáforo), 11.2 (estados verificados por SSH), 11.4 (deploys), 11.6 (entrada nueva), 11.7 (incidentes resueltos) y 11.8 (próximos 7 días). Tiempo objetivo: < 10 min por sesión.
← Volver a d. Ingenieros y Programadores 🏥 Inicio del Sistema Médico 🏠 Inicio Toscana