Capa de interoperabilidad · Prueba técnica de arquitectura

ADR-031: recorrido en vivo de una petición, reconstruido desde Tempo

Aceptado el 15/11/2026 (regla de Andrés: ADR necesario y no absorbido por otro, aprobado; lo comunicó la sesión de planeación). Propuesto ese mismo día por el carril `recorrido-en-vivo` (número confirmado por planeación: 030 es de `integracion`, 032 de `monitoreo-en-vivo`, 033 de `panel-de-control`).

Contexto

En el demo hay que mostrar la tesis (el legado sale del camino de la petición, docs/comparativo-as-is-to-be.md) con peticiones reales, no solo con diagramas. Grafana muestra la traza como cascada de spans y Kiali el grafo de la malla, pero ninguno de los dos la pone sobre la arquitectura por capas del entregable ni dice qué componente del diseño es cada tramo.

Hechos medidos el 15/11/2026 con la pila integrada de F4 y Tempo 3 en local (apps/flow-explorer/dev/):

Opciones

Opción A favor En contra
A. Solo enlaces a Grafana y Kiali Nada que construir No muestra el diseño; un span no dice a qué componente o regla corresponde
B. Vista propia que llama a Tempo desde el navegador Sin backend Expone la API de Tempo al navegador; los atributos completos llegan a la pantalla; sin lista blanca del lado del servidor
C. Vista propia con un backend mínimo de solo lectura que consulta Tempo, filtra atributos y mapea cada span al archivo de datos de la arquitectura Una sola fuente del diagrama; la lista blanca se aplica antes del navegador; Tempo queda dentro del clúster; la malla limita la salida a Tempo Una carga más que construir y operar; el mapeo depende de los nombres de los spans y de los servicios

Decisión

Opción C (apps/flow-explorer, contrato contracts/openapi/flow-explorer.v1.yaml):

  1. El diagrama sale de un único archivo versionado, apps/flow-explorer/web/data/architecture.json (nodos, capas y aristas con tipo), y make flow-explorer-check falla si no casa con los C4 de contenedores del entregable (TO-BE y AS-IS) o si un canal toca el legado en TO-BE.
  2. El backend solo hace GET a las API HTTP de Tempo (/api/search con TraceQL y /api/traces/{id}) y de Prometheus (/api/v1/query). Busca una petición por correlationId (atributos http.request.header.x-correlation-id y messaging.header.ce_correlationid, o la llave del tópico de auditoría), por orderId (llave de Kafka), por traceId o la última orden, y une todas las trazas del mismo correlationId y de la misma orden. Los nombres de los atributos están en la configuración.
  3. Lista blanca de atributos mostrables en el backend (src/whitelist.js); todo lo demás se descarta antes de responder, y un valor permitido con forma de correo o de tarjeta también.
  4. Cada span mapea a un nodo y a sus aristas por reglas fijas (src/mapper.js). Un span sin nodo se lista aparte, no se esconde. El camino del borde, que no emite spans, se dibuja punteado como inferido, sin duración.
  5. La carga vive en edge, en la malla: la AuthorizationPolicy flow-explorer-from-ingress, que genera la malla (ADR-032), deja entrar solo al gateway de entrada, y un Sidecar con REGISTRY_ONLY deja salir solo hacia Tempo y Prometheus. Así la malla, no solo el código, impide que el backend llame a un servicio de dominio, al legado o a Kafka.
  6. Sin clúster, la vista reproduce una traza real grabada (fixtures/tempo-orden.json), rotulada como ejemplo con su fecha y su origen. Es también el fixture de las pruebas.
  7. Tráfico del momento sobre el mismo diagrama: peticiones por segundo, 5xx y p95 de la malla por par de cargas, y llamadas de los adaptadores al legado, leídos de Prometheus cada 5 segundos y asignados a aristas con el mismo archivo de datos. El color sigue los SLO de docs/to-be/10-observabilidad.md (300 ms de p95, 99.9% sin 5xx). Las órdenes recientes de Tempo abren su recorrido con un clic. Guiado y en vivo comparten diagrama y controles, sin recargar.

Qué se sacrifica