257 lines
11 KiB
Markdown
257 lines
11 KiB
Markdown
# IPS Nodo Dominio
|
||
|
||
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 | 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 |
|
||
|
||
**Red interna**: todos los servicios se comunican a través de la red Docker `hapi-network`.
|
||
|
||
**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
|
||
|
||
## Instalación y configuración
|
||
|
||
### 1. Variables de entorno
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
```
|
||
|
||
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. 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:
|
||
|
||
**HTTP** (por defecto):
|
||
```env
|
||
NGINX_CONF=http
|
||
```
|
||
|
||
**HTTPS** (requiere certificados válidos en `./certs/`):
|
||
```env
|
||
NGINX_CONF=https
|
||
SSL_CERT_PATH=./certs/server.crt
|
||
SSL_KEY_PATH=./certs/server.key
|
||
```
|
||
|
||
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).
|
||
|
||
### 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). CORS está habilitado para todos los orígenes (`*`).
|
||
|
||
## Levantar los servicios
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
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
|
||
docker compose ps
|
||
|
||
# CapabilityStatement FHIR a través de nginx
|
||
curl http://localhost/fhir/metadata
|
||
|
||
# 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
|
||
|
||
```bash
|
||
# Solo detener
|
||
docker compose down
|
||
|
||
# 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/).
|