Capa de interoperabilidad · Prueba técnica de arquitectura

ADR-016: todo error del borde sale en Problem Details

Aceptado el 10/11/2026 por Andrés.

Contexto

Requisito de Andrés (10/11/2026): todo error que recibe un partner usa el formato Problem Details (RFC 9457, application/problem+json) de docs/to-be/07-contratos-api.md, con code y correlationId. Ningún error viaja sin cuerpo.

La prueba de punta a punta del borde (make edge-test, carril f5-borde) mostró que KrakenD edición comunitaria 3 no lo cumple por sí solo:

Origen del error Ejemplos Qué sale hoy
Servicios de dominio y adaptadores 404, 409, 422, 500 Problem Details (la plantilla ya lo hace)
KrakenD 401 sin token, 403 sin scope, 429 por tope Sin cuerpo; el 429 sin Retry-After
KrakenD 404 y 405 de ruta desconocida Cuerpo fijo, sin correlationId
Envoy (Istio), generados por el propio proxy 503 sin destino sano o circuito abierto, 504 por timeout, 429 de la cuota por partner (ADR-006), 413 por cuerpo grande Texto plano

Además KrakenD CE no genera X-Correlation-Id cuando falta y no limita el tamaño del cuerpo (es de la edición Enterprise). Los plugins, que podrían resolverlo, salieron de CE en la versión 3.

Opciones

Opción Cómo Costo
A. Gateway de entrada de Istio delante de KrakenD Normaliza toda respuesta de error antes de salir al partner Un filtro Lua pequeño que hay que mantener y probar
B. KrakenD Enterprise Cuerpos de error y límites nativos Licencia paga; contradice ADR-001 (edición comunitaria). No cubre los errores que genera Envoy
C. Reemplazar KrakenD por un gateway basado en Envoy Una sola pieza en el borde Rehace ADR-001 y ADR-012 (gateway modular) a una semana de la entrega
D. Aceptar errores sin cuerpo Nada Incumple el requisito

Decisión

Opción A. El gateway de entrada de Istio es el único punto por donde sale una respuesta al partner, así que ahí se garantiza el formato para los tres orígenes:

  1. Errores que genera el propio Envoy (503, 504, 429, 413): configuración de respuestas locales del administrador de conexiones HTTP de Envoy, que reescribe el cuerpo a Problem Details según el código. Es configuración estable de Envoy.
  2. Errores que llegan de KrakenD sin cuerpo o con cuerpo fijo: filtro Lua en el gateway de entrada que, si la respuesta es 4xx o 5xx y no es application/problem+json, la reemplaza por Problem Details con el code del contrato que corresponde al estado y agrega Retry-After al 429.
Estado code (enum del OpenAPI)
401 UNAUTHENTICATED
403 INSUFFICIENT_SCOPE
404 (también método no declarado, como ya hace el borde) NOT_FOUND
413 PAYLOAD_TOO_LARGE (nuevo: se agrega al enum del OpenAPI y a la tabla de 07-contratos-api.md)
429 RATE_LIMITED
503 y 504 DEPENDENCY_UNAVAILABLE
Otro 5xx INTERNAL_ERROR
3. X-Correlation-Id: si la petición no lo trae, el gateway de entrada lo toma de x-request-id, que Envoy genera siempre; viaja hacia adentro y vuelve en la respuesta y en el cuerpo de error.
4. Tamaño del cuerpo: filtro de buffer de Envoy con tope por ruta; el exceso responde 413 en Problem Details por el punto 1.

Los servicios no cambian: ya responden Problem Details desde la plantilla.

Verificación

Se construye en F6. La prueba del borde pasa de imprimir brecha a fallar: para cada clase de error (401, 403, 404, 413, 429, 503, 504) a través de la cadena completa, la respuesta es application/problem+json, trae code y correlationId, y el 429 trae Retry-After. Mientras F6 no exista, las brechas siguen visibles en make edge-test.

Por verificar en la documentación de Envoy e Istio al implementar: nombres exactos de la configuración de respuestas locales y del filtro Lua, y cómo se aplican al gateway de entrada con EnvoyFilter.

Qué se sacrifica