Saltar a contenido

Comunicacion entre Servicios

Protocolos

El ecosistema GDI utiliza tres protocolos de comunicacion:

Protocolo Uso Formato
REST (HTTP/JSON) Comunicacion general entre todos los servicios JSON sobre HTTP
MCP (Model Context Protocol) Integracion con clientes IA (Claude, ChatGPT, Gemini) JSON-RPC sobre HTTP
S3 API Almacenamiento de PDFs en Cloudflare R2 AWS S3 compatible

Tabla de Comunicaciones

Origen Destino Protocolo Autenticacion Puerto destino URL tipo
GDI-FRONTEND GDI-Backend REST Auth0 JWT (Bearer) 8000 Public
GDI-BackOffice-Front GDI-BackOffice-Back REST Auth0 JWT (Bearer) 8010 Public
GDI-Backend GDI-PDFComposer REST API Key (X-API-Key) 8002 Docker internal
GDI-Backend GDI-Notary REST API Key (X-API-Key) 8001 Docker internal
GDI-Backend Cloudflare R2 S3 API Access Key + Secret Key 443 External (HTTPS)
GDI-AgenteLANG GDI-Backend REST JWT / Internal API Key 8000 Docker internal
GDI-AgenteLANG OpenRouter REST API Key (Bearer) 443 External (HTTPS)
GDI-AgenteLANG PostgreSQL TCP Connection string 5432 Docker internal
Cliente MCP GDI-MCP Server MCP (JSON-RPC) OAuth 2.0 (Auth0 JWT) 8005 Public
GDI-BackOffice-Back PostgreSQL TCP Connection string 5432 Docker internal

Autenticacion Inter-Servicio

Auth0 JWT (Frontend a Backend)

Los frontends autentican usuarios mediante Auth0. El JWT se envia en el header Authorization: Bearer <token>. Los backends validan el token contra Auth0 JWKS.

Frontend → Auth0 (login) → JWT
Frontend → Backend (Authorization: Bearer <jwt>)
Backend → Auth0 JWKS (validacion)

API Key (Backend a Microservicios)

La comunicacion entre el Backend y los microservicios (PDFComposer, Notary) usa API Keys simples en el header X-API-Key.

# Ejemplo: Backend llamando a PDFComposer
headers = {"X-API-Key": PDFCOMPOSER_API_KEY}
response = await client.post(f"{PDFCOMPOSER_URL}/generate-pdf", headers=headers, ...)

OAuth 2.0 (MCP Server)

Los clientes MCP externos (Claude Code, ChatGPT, Gemini) se autentican via OAuth 2.0 con Auth0:

sequenceDiagram
    participant C as Cliente MCP
    participant M as MCP Server
    participant A as Auth0

    C->>M: POST /mcp (sin auth)
    M-->>C: 401 + WWW-Authenticate
    C->>M: GET /.well-known/oauth-protected-resource
    M-->>C: {authorization_servers: ["auth0..."]}
    C->>A: Login (navegador)
    A-->>C: JWT
    C->>M: POST /mcp (Authorization: Bearer jwt)
    M->>M: Valida JWT, extrae user_id y municipality_id
    M-->>C: Respuesta MCP

REST API Publica (API Key + User ID)

La REST API del MCP Server tambien soporta autenticacion por API Key para integraciones programaticas:

curl -H "X-API-Key: sk-gdi-xxx" \
     -H "X-User-ID: uuid-del-usuario" \
     https://mcp.tu-dominio.com/api/v1/cases/search

Comunicacion Interna (Docker Networking)

URLs Internas (servicio a servicio)

Los servicios dentro de la misma red Docker Compose se comunican usando el nombre del servicio como hostname. Estas no pasan por internet, lo que reduce latencia y aumenta seguridad.

http://<nombre-servicio>:<puerto>

Ejemplos:

# Backend → PDFComposer
PDFCOMPOSER_URL=http://pdfcomposer:8002

# Backend → Notary
NOTARY_URL=http://notary:8001

# AgenteLANG → Backend
GDI_BACKEND_URL=http://backend:8000

Ventajas de Docker Networking

  • Sin exposicion a internet
  • Menor latencia (misma red)
  • Sin costos de bandwidth externo
  • Nombres DNS estables (nombre del servicio en Docker Compose)

URLs Publicas (usuario a servicio)

Los frontends y clientes externos acceden via URLs publicas configuradas con reverse proxy o dominio:

# Frontends (navegador del usuario)
https://tu-frontend.tu-dominio.com     # GDI-FRONTEND
https://tu-backoffice.tu-dominio.com   # GDI-BackOffice-Front

# APIs publicas
https://mcp.tu-dominio.com/mcp            # MCP Server (dominio custom)

Comunicacion Externa

Algunos servicios se comunican con APIs externas que siempre usan HTTPS publico:

# Cloudflare R2 (storage)
CF_R2_ENDPOINT=https://{account}.r2.cloudflarestorage.com

# Auth0 (autenticacion)
AUTH0_DOMAIN=tu-tenant.us.auth0.com

# OpenRouter (modelos IA)
OPENROUTER_API_KEY=sk-or-...

# Resend (emails)
# Integrado en BackOffice-Back via Resend API

Patrones de Comunicacion

Request-Response sincrono

Todas las comunicaciones entre servicios son sincronas. El servicio que inicia la llamada espera la respuesta antes de continuar.

# Backend: genera PDF y luego lo firma
pdf_bytes = await call_pdfcomposer_generate_pdf(html_content)
signed_pdf = await call_notary_sign_pdf(pdf_bytes, signer_data)
await upload_to_r2(signed_pdf, filename)

Polling asincrono (AIWorker)

El unico patron asincrono es el AIWorker de GDI-AgenteLANG, que hace polling cada 60 segundos sobre las tablas de documentos para generar resumenes y embeddings.

AIWorker (cada 60s) → PostgreSQL
  1. document_draft WHERE status='sent_to_sign' AND resume IS NULL
  2. official_documents WHERE resume IS NULL
  3. official_documents sin chunks en document_chunks
  4. official_documents tipo 'Importado' con content IS NULL

Retry con fallback (Notary FULLPAGE)

Cuando Notary detecta que la ultima pagina no tiene espacio para la firma, responde con error FULLPAGE. El Backend agrega automaticamente una pagina en blanco y reintenta:

Backend → Notary: /sign-pdf (PDF original)
Notary → Backend: 400 FULLPAGE
Backend: agrega pagina en blanco
Backend → Notary: /sign-pdf (PDF aumentado)
Notary → Backend: 200 (PDF firmado)

Timeouts

Comunicacion Timeout Motivo
Frontend a Backend 30s Request HTTP estandar
Backend a PDFComposer 60s Generacion PDF puede ser lenta
Backend a Notary 30s Firma es rapida
Backend a R2 30s Upload/download de archivos
AgenteLANG a OpenRouter 60s Respuesta de LLM