Visión general
proteus-gateway es un middleware que recibe datos clínicos de un cliente externo en FHIR, los valida y los reenvía de forma asíncrona y confiable a proteus-backend (el sistema Proteus / PAMI). El cliente nunca habla directo con Proteus: habla con el gateway.
Cliente externo proteus-gateway proteus-backend
│ │
│ POST /fhir (FHIR + x-api-key) │
├────────────────────────────► inbox (received) │
│ ◄── 202 Accepted / 422 ──┤ (validación síncrona controlada) │
│ │ │
│ │ explota → proyecta → outbox (pending) │
│ │ │
│ │ dispatcher: POST /inbound (x-api-key) │
│ └──────────────────────────────────────► │
│ 2xx sent / 4xx denied / 5xx retry
Por qué dos etapas (síncrona + asíncrona)
- Síncrona (en
POST /fhir): el gateway valida contra su propio dominio lo que puede saber al instante (ej.: un episodio que referencia un paciente inexistente) y responde un error controlado al cliente. Ver Contrato FHIR. - Asíncrona (inbox → outbox): una vez aceptado (202), el mensaje se procesa y despacha en segundo plano con reintentos, sin bloquear al cliente y sin perder mensajes si Proteus o RabbitMQ están caídos. Ver Flujo inbox/outbox.
Las dos piezas
| Repo | Stack | Rol |
|---|---|---|
| proteus-gateway | NestJS 11 + MikroORM 6 + RabbitMQ + PostgreSQL | Recibe FHIR, valida, proyecta a su dominio, despacha al backend |
| proteus-backend | routing-controllers + TypeORM + PostgreSQL | Expone POST /inbound, proyecta al dominio real de Proteus |
El endpoint del backend y su proyección se documentan en El endpoint /inbound.
Multi-tenant
Cada cliente del gateway corresponde a una empresa distinta del backend (1:1). El gateway
guarda Client.proteusAppId y lo envía como clientAppId en cada mensaje; el backend lo
resuelve a un Company vía COMPANIES.AJOLOTEAPPID. Así, un mismo planCode puede mapear a
planes distintos según la empresa.
Autenticación (dos saltos distintos)
- Cliente → gateway: token de Ajolote (SSO), validado por
ApiKeyGuard. La API key viaja en el headerx-api-key. - Gateway → backend: secreto compartido
x-api-key(comparación timing-safe), distinto del anterior.
El detalle del primer salto (validación con ajolote, scopes y multi-tenant) está en Autenticación y scopes.
Las API keys de Ajolote, el secreto GATEWAY_INBOUND_API_KEY (gateway↔backend) y las
credenciales de base de datos son variables de entorno de cada ambiente. Nunca se commitean
ni aparecen en estos docs; los valores de ejemplo son placeholders.