From 1fbc308d66e766c692509cdd6ccf6594b151530f Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Auad Date: Mon, 13 Jul 2026 03:16:43 +0000 Subject: [PATCH] Agregar proxy de transformaciones IPS hacia el nodo nacional (bundle-signer) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nuevas rutas GET /fhir/Bundle/:id/$ddcc, $dvc, $icvp2 y $meow: obtienen el Bundle del HAPI FHIR local y delegan la transformación al nodo nacional (bundle-signer), que es quien tiene las claves de firma, devolviendo la respuesta tal cual. Se agrega BUNDLE_SIGNER_URL como variable de entorno requerida para configurar la URL del nodo nacional. Co-Authored-By: Claude Sonnet 5 --- .env.example | 7 +++ bus-gateway/.env.example | 3 ++ bus-gateway/README.md | 5 ++ bus-gateway/app.js | 4 ++ bus-gateway/config/index.js | 4 ++ bus-gateway/controllers/bundleSigner.js | 71 +++++++++++++++++++++++++ bus-gateway/routes/bundleSigner.js | 14 +++++ docker-compose.yml | 1 + 8 files changed, 109 insertions(+) create mode 100644 bus-gateway/controllers/bundleSigner.js create mode 100644 bus-gateway/routes/bundleSigner.js diff --git a/.env.example b/.env.example index 740e53c..df56270 100644 --- a/.env.example +++ b/.env.example @@ -52,6 +52,13 @@ DOCUMENT_REGISTRY_URL=https://bus-test.msal.gob.ar/fhir/DocumentReference # Habilita logs detallados de requests/responses salientes al Bus (true | false) BUS_DEBUG=false +# ============================================================================= +# NODO NACIONAL +# ============================================================================= + +# URL del nodo nacional (bundle-signer): ejecuta las transformaciones IPS ($ddcc, $dvc, $icvp2, $meow) +BUNDLE_SIGNER_URL=https://conectaton.msal.gob.ar/nodo/fhir + # ============================================================================= # NGINX # ============================================================================= diff --git a/bus-gateway/.env.example b/bus-gateway/.env.example index f846386..e8402af 100644 --- a/bus-gateway/.env.example +++ b/bus-gateway/.env.example @@ -16,6 +16,9 @@ DOCUMENT_REGISTRY_SCOPE=DocumentReference/*.read,DocumentReference/*.write # HAPI FHIR Server FHIR_URL=http://hapi-fhir-host:8080/fhir +# Nodo nacional (bundle-signer): ejecuta las transformaciones IPS ($ddcc, $dvc, $icvp2, $meow) +BUNDLE_SIGNER_URL=https://conectaton.msal.gob.ar/nodo/fhir + LOG_LEVEL=debug # Habilita logs de requests/responses salientes al Bus (true | false) diff --git a/bus-gateway/README.md b/bus-gateway/README.md index 06463c8..0183409 100644 --- a/bus-gateway/README.md +++ b/bus-gateway/README.md @@ -20,6 +20,10 @@ El componente actúa exclusivamente como gateway: no contiene lógica de negocio | ITI-78 | `GET` | `/fhir/Patient/:id` | Patient Demographics Query: obtención de un paciente por ID en el MPI. | | ITI-104 | `POST` | `/fhir/Patient` | Patient Identity Feed: alta de paciente en el MPI. | | ITI-104 | `PUT` | `/fhir/Patient/:id` | Patient Identity Feed: actualización de paciente en el MPI. | +| — | `GET` | `/fhir/Bundle/:id/$ddcc` | Obtiene el Bundle IPS del HAPI FHIR local y delega la transformación DDCC al nodo nacional (bundle-signer). | +| — | `GET` | `/fhir/Bundle/:id/$dvc` | Obtiene el Bundle IPS del HAPI FHIR local y delega la transformación DVC al nodo nacional (bundle-signer). | +| — | `GET` | `/fhir/Bundle/:id/$icvp2` | Obtiene el Bundle IPS del HAPI FHIR local y delega la transformación ICVP (HCERT) al nodo nacional (bundle-signer). | +| — | `GET` | `/fhir/Bundle/:id/$meow` | Obtiene el Bundle del HAPI FHIR local y delega la transformación MeOW (HCERT) al nodo nacional (bundle-signer). | ## Variables de entorno @@ -39,6 +43,7 @@ cp .env.example .env | `MPI_URL` | No | URL base del servicio MPI (Master Patient Index). Si no se define, usa `BUS_URL`. | | `DOCUMENT_REGISTRY_URL` | No | URL base del Document Registry. Si no se define, usa `BUS_URL`. | | `FHIR_URL` | Sí | URL base del servidor HAPI FHIR local. | +| `BUNDLE_SIGNER_URL` | Sí | URL base del nodo nacional (bundle-signer) donde se ejecutan las transformaciones IPS (`$ddcc`, `$dvc`, `$icvp2`, `$meow`). | | `PORT` | No | Puerto en que escucha el servidor. Por defecto `3000`. | ### Usar la misma URL para todos los servicios del Bus diff --git a/bus-gateway/app.js b/bus-gateway/app.js index 4079147..51aedb9 100644 --- a/bus-gateway/app.js +++ b/bus-gateway/app.js @@ -8,6 +8,7 @@ var iti65Router = require('./routes/iti65'); var iti67Router = require('./routes/iti67'); var iti78Router = require('./routes/iti78'); var iti104Router = require('./routes/iti104'); +var bundleSignerRouter = require('./routes/bundleSigner'); var app = express(); @@ -27,6 +28,9 @@ app.use('/fhir', iti78Router); // ITI-104: Patient Identity Feed → POST /fhir/Patient, PUT /fhir/Patient/:id app.use('/fhir', iti104Router); +// Transformaciones IPS (nodo nacional) → GET /fhir/Bundle/:id/$ddcc, $dvc, $icvp2, $meow +app.use('/fhir', bundleSignerRouter); + // 404 app.use(function (req, res, next) { const host = req.get('host') || 'localhost'; diff --git a/bus-gateway/config/index.js b/bus-gateway/config/index.js index 6cb3451..fc48736 100644 --- a/bus-gateway/config/index.js +++ b/bus-gateway/config/index.js @@ -13,6 +13,9 @@ const config = { fhir: { url: process.env.FHIR_URL, }, + bundleSigner: { + url: process.env.BUNDLE_SIGNER_URL, + }, logging: { enabled: true, level: 'debug', @@ -35,6 +38,7 @@ const required = [ ['MPI_SCOPE', config.bus.mpiScope], ['DOCUMENT_REGISTRY_SCOPE', config.bus.documentRegistryScope], ['FHIR_URL', config.fhir.url], + ['BUNDLE_SIGNER_URL', config.bundleSigner.url], ]; const missing = required.filter(([, val]) => !val).map(([key]) => key); diff --git a/bus-gateway/controllers/bundleSigner.js b/bus-gateway/controllers/bundleSigner.js new file mode 100644 index 0000000..70cb9de --- /dev/null +++ b/bus-gateway/controllers/bundleSigner.js @@ -0,0 +1,71 @@ +const axios = require('axios'); +const config = require('../config'); + +/** + * Fetches the Bundle from the local HAPI FHIR server and delegates the + * transformation to the national node (bundle-signer), which holds the + * signing keys. Returns the national node's response as-is. + */ +async function transformBundle(id, operation, query) { + const bundleUrl = `${config.fhir.url}/Bundle/${id}`; + const { data: bundle } = await axios.get(bundleUrl); + + const response = await axios.post( + `${config.bundleSigner.url}/Bundle/$${operation}`, + bundle, + { params: query }, + ); + return response; +} + +/** + * GET /fhir/Bundle/:id/$ddcc + */ +async function getDDCC(req, res, next) { + try { + const response = await transformBundle(req.params.id, 'ddcc', req.query); + res.status(response.status).json(response.data); + } catch (err) { + next(err); + } +} + +/** + * GET /fhir/Bundle/:id/$dvc + */ +async function getDVC(req, res, next) { + try { + const response = await transformBundle(req.params.id, 'dvc', req.query); + res.status(response.status).json(response.data); + } catch (err) { + next(err); + } +} + +/** + * GET /fhir/Bundle/:id/$icvp2 + */ +async function getICVP2(req, res, next) { + try { + const response = await transformBundle(req.params.id, 'icvp2', req.query); + res.status(response.status).json(response.data); + } catch (err) { + next(err); + } +} + +/** + * GET /fhir/Bundle/:id/$meow + */ +async function getMeow(req, res, next) { + try { + const response = await transformBundle(req.params.id, 'meow', req.query); + res.status(response.status).json(response.data); + } catch (err) { + next(err); + } +} + +module.exports = { + getDDCC, getDVC, getICVP2, getMeow, +}; diff --git a/bus-gateway/routes/bundleSigner.js b/bus-gateway/routes/bundleSigner.js new file mode 100644 index 0000000..ea80891 --- /dev/null +++ b/bus-gateway/routes/bundleSigner.js @@ -0,0 +1,14 @@ +const express = require('express'); +const router = express.Router(); +const { + getDDCC, getDVC, getICVP2, getMeow, +} = require('../controllers/bundleSigner'); + +// Transformaciones IPS delegadas al nodo nacional (bundle-signer): +// obtienen el Bundle del HAPI FHIR local y postean al nodo nacional. +router.get('/Bundle/:id/([\$])ddcc', getDDCC); +router.get('/Bundle/:id/([\$])dvc', getDVC); +router.get('/Bundle/:id/([\$])icvp2', getICVP2); +router.get('/Bundle/:id/([\$])meow', getMeow); + +module.exports = router; diff --git a/docker-compose.yml b/docker-compose.yml index 155e4a1..69e3916 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -56,6 +56,7 @@ services: MPI_SCOPE: ${MPI_SCOPE} DOCUMENT_REGISTRY_SCOPE: ${DOCUMENT_REGISTRY_SCOPE} FHIR_URL: http://hapi-fhir:8080/fhir + BUNDLE_SIGNER_URL: ${BUNDLE_SIGNER_URL} BUS_DEBUG: ${BUS_DEBUG} ports: - 9229:9229