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:
- 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.
- 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 elcodedel contrato que corresponde al estado y agregaRetry-Afteral 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
- Código propio en Lua dentro del borde, con su prueba. Es pequeño y se limita a mapear estado a
code. - El formato de error queda garantizado en dos capas (servicios y borde). Una ruta que se salte el gateway de entrada no tendría la garantía; por eso el mTLS estricto de ADR-008 rechaza el tráfico que no entra por él.