From fcb74a5031e36e2176afc9ecda10572634ec4ce6 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Auad Date: Thu, 30 Apr 2026 20:39:23 +0000 Subject: [PATCH] =?UTF-8?q?Actualizada=20la=20documentaci=C3=B3n=20del=20p?= =?UTF-8?q?royecto=20y=20el=20archivo=20de=20configuracion=20de=20entorno?= =?UTF-8?q?=20de=20ejemplo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 110 ++++++++++++++++++++---- README.md | 234 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 285 insertions(+), 59 deletions(-) diff --git a/.env.example b/.env.example index ff96852..4ea6d9c 100644 --- a/.env.example +++ b/.env.example @@ -1,27 +1,98 @@ -NODE_BASE_URL=http://localhost -# Configuración del contenedor de NGINX (ajusta según tus necesidades, por ejemplo, para SSL) -NGINX_CONF=http -# NGINX_CONF=http +# ============================================================================= +# IPS Nodo Dominio — Variables de entorno +# Copiar este archivo a .env y completar los valores requeridos. +# ============================================================================= + +# ============================================================================= +# NODO +# ============================================================================= + +# URL pública del nodo (usada por GDHCN para construir sus URLs) +NODO_BASE_URL=http://localhost + +# URL base del nodo (usada por bus-gateway internamente) +NODO_URL_BASE=http://localhost + +# Zona horaria para todos los servicios +TZ=America/Argentina/Buenos_Aires + +# ============================================================================= +# BUS DE SALUD — Requeridas +# ============================================================================= + +# URL base del Bus de salud nacional +BUS_URL=https://bus-host/fhir + +# Secreto compartido para firmar tokens JWT (HS256) contra el Bus +BUS_JWT_SECRET=your-shared-secret + +# Identificador del emisor JWT (ej.: URL del repositorio del nodo) +BUS_ISSUER=https://your-repositorio-url + +# Scopes OAuth para el Master Patient Index +MPI_SCOPE=Patient/*.read,Patient/*.write + +# Scopes OAuth para el Document Registry +DOCUMENT_REGISTRY_SCOPE=DocumentReference/*.read,DocumentReference/*.write + +# ============================================================================= +# BUS DE SALUD — Opcionales (por defecto usan BUS_URL) +# ============================================================================= + +# URL del Master Patient Index si difiere del Bus principal +# MPI_URL=https://mpi-host/fhir + +# URL del Document Registry si difiere del Bus principal +# DOCUMENT_REGISTRY_URL=https://document-registry-host/fhir + +# Habilita logs detallados de requests/responses salientes al Bus (true | false) +BUS_DEBUG=false + +# ============================================================================= +# NGINX +# ============================================================================= + +# Modo de operación del proxy inverso: http (default) o https +NGINX_CONF=http + +# Rutas a los certificados TLS del servidor (solo necesarias en modo https) # SSL_CERT_PATH=./certs/server.crt # SSL_KEY_PATH=./certs/server.key -# Bus FHIR (base, usado como fallback si se definen MPI_URL o DOCUMENT_REGISTRY_URL) -BUS_URL=http://bus-host:8080 -BUS_JWT_SECRET=your-shared-secret -BUS_ISSUER=https://your-repositorio-url +# ============================================================================= +# CERTIFICADOS / DOCKER SECRETS +# Los archivos se inyectan como Docker secrets. +# Los valores por defecto apuntan a ./certs/ — reemplazar en producción. +# ============================================================================= -# Servicios del Bus (opcionales, por defecto usan BUS_URL) -MPI_URL=http://mpi-host:8080 -DOCUMENT_REGISTRY_URL=http://document-registry-host:8080 +# Certificado de la red de confianza (TNG/GDHCN) +SIGNATURE_CERT_PATH=./certs/trust-network.pem +SIGNATURE_KEY_PATH=./certs/trust-network.key -# Scopes por servicio -MPI_SCOPE=Patient/*.read,Patient/*.write -DOCUMENT_REGISTRY_SCOPE=DocumentReference/*.read,DocumentReference/*.write +# Clave privada para firma de documentos (Document Signing Certificate) +SSL_DCC_KEY_PATH=./certs/signature.key +# ============================================================================= +# VERIFIABLE HEALTH LINKS (VHL) +# ============================================================================= -# Habilita logs de requests/responses salientes al Bus (true | false) -BUS_DEBUG=false +# Ruta a una clave EC P-256 en formato PEM para firmar CWTs. +# Si se omite, se genera una clave efímera en memoria (se pierde al reiniciar). +# VHL_PRIVATE_KEY_FILE=./certs/vhl.key +# URI del emisor VHL (iss del CWT). Por defecto usa BUS_ISSUER. +# VHL_ISSUER=https://your-repositorio-url + +# URL pública del gateway para construir las URLs de manifiesto y documento. +# Requerida si se usan los endpoints /vhl/*. +# VHL_BASE_URL=https://your-nodo-url + +# TTL del token VHL en segundos (default: 604800 = 7 días) +# VHL_TOKEN_TTL=604800 + +# ============================================================================= +# HAPI FHIR (Spring Boot) +# ============================================================================= SPRING_CONFIG_LOCATION="file:///data/hapi/application.yaml" SPRING_DATASOURCE_URL="jdbc:postgresql://hapi-db:5433/root" @@ -29,6 +100,11 @@ SPRING_DATASOURCE_USERNAME="root" SPRING_DATASOURCE_PASSWORD="hapifhir2023" SPRING_DATASOURCE_DRIVERCLASSNAME="org.postgresql.Driver" SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT="ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect" + +# ============================================================================= +# POSTGRESQL (hapi-db) +# ============================================================================= + POSTGRES_DB="root" POSTGRES_USER="root" -POSTGRES_PASSWORD="hapifhir2023" \ No newline at end of file +POSTGRES_PASSWORD="hapifhir2023" diff --git a/README.md b/README.md index d8ccf72..916b959 100644 --- a/README.md +++ b/README.md @@ -1,56 +1,85 @@ -# IPS Dominio Backend +# IPS Nodo Dominio -Proyecto Docker Compose con los servicios necesarios para el nodo de dominio IPS (International Patient Summary). +Plataforma de interoperabilidad en salud basada en Docker Compose que implementa el **Nodo de Dominio IPS** (International Patient Summary). Actúa como gateway de integración entre servicios FHIR locales y el Bus nacional de salud (Federador MSAL). + +## Arquitectura + +``` +Internet / Red interna + │ + nginx:80/443 + │ + ┌────┴─────────────────────────────────────────┐ + │ /fhir/IPSTransaction → bus-gateway:3000 │ + │ /fhir/IPSDocument → bus-gateway:3000 │ + │ /fhir/DocumentReference→ bus-gateway:3000 │ + │ /fhir/Patient → bus-gateway:3000 │ + │ /vhl/* → bus-gateway:3000 │ + │ /gdhcn/* → gdhcn-validator │ + │ /fhir/* (resto) → hapi-fhir:8080 │ + └──────────────────────────────────────────────┘ +``` ## Servicios -| Servicio | Imagen / Fuente | Descripción | -|---|---|---| -| `hapi-fhir` | `hapiproject/hapi:latest` | Servidor FHIR R4 (implementación Spring Boot) | -| `hapi-db` | `postgres:14.6` | Base de datos PostgreSQL para HAPI FHIR | -| `bus-gateway` | `./bus-gateway` | Gateway hacia el Bus de salud (MPI y Document Registry) | -| `nginx` | `nginx:alpine` | Proxy inverso — punto de entrada HTTP/HTTPS | +| Servicio | Imagen / Fuente | Puerto | Descripción | +|---|---|---|---| +| `hapi-fhir` | `hapiproject/hapi:latest` | 8080 (interno) | Servidor FHIR R4 (Spring Boot) con búsqueda Lucene | +| `hapi-db` | `postgres:14.6` | 5433 (interno) | Base de datos PostgreSQL para HAPI FHIR | +| `bus-gateway` | `./bus-gateway` (Node.js) | 3000 (interno) | Gateway al Bus de salud nacional (MPI + Document Registry) | +| `gdhcn-validator-service` | `createchile/gdhcn-validator_backend:v1.1` | 8182 | Validador de documentos de salud verificables (firmas digitales) | +| `gdhcn-db` | `postgres:16-alpine` | 5432 (interno) | Base de datos PostgreSQL para el validador GDHCN | +| `nginx` | `nginx:alpine` | 80 / 443 | Proxy inverso — punto de entrada HTTP/HTTPS | -### Routing nginx +**Red interna**: todos los servicios se comunican a través de la red Docker `hapi-network`. -| Ruta | Destino | -|---|---| -| `/bus-gateway/*` | `bus-gateway:3000` | -| todo lo demás | `hapi-fhir:8080` | +**Volúmenes persistentes**: `hapi-data` (PostgreSQL de HAPI), `gdhcn-data` (PostgreSQL de GDHCN). + +## Transacciones IHE implementadas + +El `bus-gateway` implementa los siguientes perfiles de interoperabilidad: + +| Transacción | Método | Ruta | Descripción | +|---|---|---|---| +| **ITI-65** | POST | `/fhir/IPSTransaction` | Provide Document Bundle (transacción) | +| **ITI-65** | POST | `/fhir/IPSDocument` | Provide Document Bundle (documento IPS) | +| **ITI-67** | GET | `/fhir/DocumentReference` | Find Document References | +| **ITI-78** | GET | `/fhir/Patient` | Patient Demographics Query (búsqueda) | +| **ITI-78** | GET | `/fhir/Patient/:id` | Patient Demographics Query (por ID) | +| **ITI-104** | POST | `/fhir/Patient` | Patient Identity Feed (alta) | +| **ITI-104** | PUT | `/fhir/Patient/:id` | Patient Identity Feed (actualización) | +| **VHL** | POST | `/vhl/:patientId` | Emitir Verifiable Health Link (token QR) | +| **VHL** | GET | `/vhl/manifest/:id` | Servir manifiesto VHL | +| **VHL** | GET | `/vhl/document/:id` | Servir documento VHL cifrado | ## Requisitos - Docker >= 20.10.8 - Docker Compose >= 1.29.2 -## Configuración +## Instalación y configuración ### 1. Variables de entorno -Copia el archivo de ejemplo y completa los valores: - ```bash cp .env.example .env ``` -| Variable | Descripción | -|---|---| -| `BUS_URL` | URL base del Bus de salud | -| `BUS_JWT_SECRET` | Secreto compartido para JWT con el Bus | -| `BUS_ISSUER` | Issuer del token JWT | -| `MPI_URL` | URL del servicio MPI (default: `BUS_URL`) | -| `DOCUMENT_REGISTRY_URL` | URL del Document Registry (default: `BUS_URL`) | -| `MPI_SCOPE` | Scopes OAuth para MPI | -| `DOCUMENT_REGISTRY_SCOPE` | Scopes OAuth para Document Registry | -| `BUS_DEBUG` | Habilita logs de requests al Bus (`true` / `false`) | -| `SPRING_DATASOURCE_URL` | JDBC URL de la BD — debe usar puerto `5433` (`jdbc:postgresql://hapi-db:5433/root`) | -| `SPRING_DATASOURCE_USERNAME` | Usuario de la base de datos | -| `SPRING_DATASOURCE_PASSWORD` | Contraseña de la base de datos | -| `POSTGRES_DB` | Nombre de la base de datos PostgreSQL | -| `POSTGRES_USER` | Usuario PostgreSQL | -| `POSTGRES_PASSWORD` | Contraseña PostgreSQL | +Editar `.env` completando al menos las variables marcadas como requeridas. Ver la sección [Variables de entorno](#variables-de-entorno) para la descripción completa. -### 2. Configuración de nginx (HTTP o HTTPS) +### 2. Certificados + +Los certificados se inyectan como **Docker secrets**. Las rutas se configuran en el `.env` (todas tienen valores por defecto apuntando a `./certs/`): + +| Archivo por defecto | Descripción | +|---|---| +| `./certs/server.crt` / `./certs/server.key` | Certificado TLS para nginx (solo modo HTTPS) | +| `./certs/trust-network.pem` / `./certs/trust-network.key` | Certificado de la red de confianza (GDHCN/TNG) | +| `./certs/signature.key` | Clave privada para firma de documentos (DSC) | + +> Ver [certs/README.md](certs/README.md) para instrucciones de generación de certificados de prueba. + +### 3. Configuración de nginx (HTTP o HTTPS) La variable `NGINX_CONF` en el `.env` selecciona el modo: @@ -59,20 +88,20 @@ La variable `NGINX_CONF` en el `.env` selecciona el modo: NGINX_CONF=http ``` -**HTTPS** (requiere certificados): +**HTTPS** (requiere certificados válidos en `./certs/`): ```env NGINX_CONF=https SSL_CERT_PATH=./certs/server.crt SSL_KEY_PATH=./certs/server.key ``` -Los certificados se inyectan como Docker secrets y nginx los lee desde `/run/secrets/ssl_cert` y `/run/secrets/ssl_key`. En modo HTTPS el tráfico HTTP (puerto 80) se redirige automáticamente a HTTPS (443). +En modo HTTPS el tráfico HTTP (puerto 80) se redirige automáticamente a HTTPS (443). Los certificados los lee nginx desde `/run/secrets/ssl_cert` y `/run/secrets/ssl_key`. Los archivos de configuración están en [nginx/http.conf](nginx/http.conf) y [nginx/https.conf](nginx/https.conf). -### 3. Configuración HAPI FHIR +### 4. Configuración HAPI FHIR -Los parámetros del servidor FHIR se ajustan en [hapi-config/application.yaml](hapi-config/application.yaml). El servidor usa **Lucene** como backend de búsqueda (índice local, no requiere servicio externo). +Los parámetros del servidor FHIR se ajustan en [hapi-config/application.yaml](hapi-config/application.yaml). El servidor usa **Lucene** como backend de búsqueda (índice local, no requiere servicio externo). CORS está habilitado para todos los orígenes (`*`). ## Levantar los servicios @@ -80,19 +109,22 @@ Los parámetros del servidor FHIR se ajustan en [hapi-config/application.yaml](h docker compose up -d ``` -HAPI FHIR tarda aproximadamente **30-40 segundos** en arrancar completamente. +HAPI FHIR tarda aproximadamente **30–40 segundos** en inicializar. El `bus-gateway` espera activamente a que el servidor FHIR esté listo antes de aceptar conexiones (hasta ~3 minutos de reintentos). ## Verificar el despliegue ```bash -# Estado de los contenedores (hapi-db debe aparecer "healthy") +# Estado de los contenedores docker compose ps # CapabilityStatement FHIR a través de nginx curl http://localhost/fhir/metadata -# Bus Gateway a través de nginx -curl http://localhost/bus-gateway/health +# Health check del Bus Gateway a través de nginx +curl http://localhost/fhir/Patient?_summary=count + +# Logs de un servicio específico +docker compose logs -f bus-gateway ``` ## Detener los servicios @@ -101,6 +133,124 @@ curl http://localhost/bus-gateway/health # Solo detener docker compose down -# Detener y eliminar volúmenes (borra datos de la BD) +# Detener y eliminar volúmenes (borra todos los datos) docker compose down -v ``` + +## Variables de entorno + +Todas las variables se definen en el archivo `.env` de la raíz del proyecto. + +### Bus de salud (requeridas) + +| Variable | Requerida | Descripción | +|---|---|---| +| `BUS_URL` | Sí | URL base del Bus de salud nacional | +| `BUS_JWT_SECRET` | Sí | Secreto compartido para firmar JWT (HS256) | +| `BUS_ISSUER` | Sí | Identificador del emisor JWT (ej.: URL del repositorio) | +| `MPI_SCOPE` | Sí | Scopes OAuth para el MPI (ej.: `Patient/*.read,Patient/*.write`) | +| `DOCUMENT_REGISTRY_SCOPE` | Sí | Scopes OAuth para el Document Registry | + +### Bus de salud (opcionales) + +| Variable | Default | Descripción | +|---|---|---| +| `MPI_URL` | `BUS_URL` | URL del Master Patient Index (si difiere del Bus principal) | +| `DOCUMENT_REGISTRY_URL` | `BUS_URL` | URL del Document Registry (si difiere del Bus principal) | +| `BUS_DEBUG` | `false` | Habilita logs detallados de requests/responses al Bus | + +### Nodo + +| Variable | Default | Descripción | +|---|---|---| +| `NODO_BASE_URL` | `http://localhost` | URL pública del nodo (usada por GDHCN para construir URLs) | +| `NODO_URL_BASE` | `http://localhost` | URL base del nodo (usada por bus-gateway) | +| `TZ` | `America/Argentina/Buenos_Aires` | Zona horaria para todos los servicios | + +### FHIR local (gestionada internamente) + +| Variable | Valor fijo | Descripción | +|---|---|---| +| `FHIR_URL` | `http://hapi-fhir:8080/fhir` | URL del servidor FHIR interno (fijada en docker-compose) | + +### Nginx + +| Variable | Default | Descripción | +|---|---|---| +| `NGINX_CONF` | `http` | Modo de operación: `http` o `https` | +| `SSL_CERT_PATH` | `./certs/server.crt` | Ruta al certificado TLS del servidor | +| `SSL_KEY_PATH` | `./certs/server.key` | Ruta a la clave privada TLS del servidor | + +### Certificados / Secrets + +| Variable | Default | Descripción | +|---|---|---| +| `SIGNATURE_CERT_PATH` | `./certs/trust-network.pem` | Certificado de la red de confianza (TNG/GDHCN) | +| `SIGNATURE_KEY_PATH` | `./certs/trust-network.key` | Clave privada de la red de confianza | +| `SSL_DCC_KEY_PATH` | `./certs/signature.key` | Clave privada para firma de documentos (DSC) | + +### Verifiable Health Links (VHL) + +| Variable | Default | Descripción | +|---|---|---| +| `VHL_PRIVATE_KEY_FILE` | *(efímera)* | Ruta a clave EC P-256 en PEM para firmar CWTs. Si se omite, se genera una clave en memoria que se pierde al reiniciar | +| `VHL_ISSUER` | `BUS_ISSUER` | URI del emisor VHL (iss del CWT) | +| `VHL_BASE_URL` | — | URL pública del gateway para construir URLs de manifiesto y documento. Requerida para usar endpoints VHL | +| `VHL_TOKEN_TTL` | `604800` | TTL del token VHL en segundos (default: 7 días) | + +### HAPI FHIR / PostgreSQL + +| Variable | Default | Descripción | +|---|---|---| +| `SPRING_CONFIG_LOCATION` | `file:///data/hapi/application.yaml` | Ruta al archivo de configuración de HAPI | +| `SPRING_DATASOURCE_URL` | `jdbc:postgresql://hapi-db:5433/root` | URL JDBC de la BD (debe usar puerto `5433`) | +| `SPRING_DATASOURCE_USERNAME` | `root` | Usuario de la base de datos | +| `SPRING_DATASOURCE_PASSWORD` | `hapifhir2023` | Contraseña de la base de datos | +| `SPRING_DATASOURCE_DRIVERCLASSNAME` | `org.postgresql.Driver` | Driver JDBC | +| `SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT` | `ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect` | Dialecto Hibernate | +| `POSTGRES_DB` | `root` | Nombre de la base de datos PostgreSQL | +| `POSTGRES_USER` | `root` | Usuario PostgreSQL | +| `POSTGRES_PASSWORD` | `hapifhir2023` | Contraseña PostgreSQL | + +## Estructura del proyecto + +``` +ips-nodo-dominio/ +├── docker-compose.yml # Orquestación principal (6 servicios) +├── .env.example # Plantilla de variables de entorno +├── hapi-config/ +│ └── application.yaml # Configuración de HAPI FHIR (Spring Boot) +├── nginx/ +│ ├── http.conf # Config nginx modo HTTP +│ └── https.conf # Config nginx modo HTTPS +├── certs/ # Certificados TLS y claves de firma +│ └── README.md # Instrucciones para generar certificados de prueba +├── bus-gateway/ # Gateway Node.js/Express +│ ├── controllers/ # Manejadores de transacciones IHE (ITI-65/67/78/104, VHL) +│ ├── routes/ # Definición de rutas Express +│ ├── services/ # Clientes de servicios externos (MPI, Document Registry, FHIR) +│ ├── utils/ # Utilidades (auth, logging, criptografía VHL) +│ ├── docs/ # Diagramas de secuencia Mermaid +│ └── tests/ # Suite de pruebas Jest +├── json/ # Fixtures y schemas JSON +└── tests/ + └── fixtures/ # Fixtures para pruebas de integración +``` + +## Desarrollo + +### Ejecutar tests del bus-gateway + +```bash +cd bus-gateway +npm install +npm test +``` + +### Debug remoto + +El `bus-gateway` arranca con `--inspect=0.0.0.0:9229`, por lo que se puede conectar un debugger Node.js al puerto `9229`. + +### Diagramas de secuencia + +Los flujos de cada transacción están documentados como diagramas Mermaid en [bus-gateway/docs/](bus-gateway/docs/).