Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions docs/LOCAL_DEV_WITH_K8S_CORE.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,15 @@ dotnet run --project Tracker.Presentation
admin con todos los permisos; se niega a arrancar fuera de Development). Postgres (`tracker-ci-pg`)
ya está arriba con las credenciales `evolith` / `evolith_tracker` / `localdev` que esta cadena espera.

> **Aviso de `CoreApi__BaseUrl` (gap `LV-18`):** `appsettings.json` trae `.../api/core/api/v1`,
> pero al pegar **directamente al pod** del Core (como hace el port-forward) el prefijo `/api/core`
> no está — el pod sirve `/api/v1`. Tres rutas (`/gates`, `/architecture`, `/reference`) siguen
> dando `404` en la imagen actual del Core de todos modos; solo `/capabilities` existe. Esa
> discrepancia de contrato está registrada como `LV-18` y **no** se resuelve corriendo en local:
> verás fallar esas tres llamadas hasta que se arregle.
> **`CoreApi__BaseUrl` (era el gap `LV-18`):** `appsettings.json` ahora tiene por defecto
> `http://localhost:3001/api/v1` — la superficie **directa** `/api/v1` del Core (el Core del compose
> en `:3001`). El ADR T-038 hace del BFF tracker-api el ÚNICO cliente del Core, llamando `/api/v1`
> directo, nunca el tracker-gateway; el prefijo `/api/core` del gateway es un facade de agregación
> para consumidores externos (ADR T-052) y no existe en el pod del Core. Este runbook reenvía el
> Core de **k8s** a `:8090`, así que el comando de arriba sobrescribe `CoreApi__BaseUrl` a
> `http://localhost:8090/api/v1` — la misma superficie directa `/api/v1`, distinto host:puerto. El
> default roto anterior (`http://localhost:4000/api/core/api/v1`, el prefijo imaginario del gateway)
> está corregido.

## 4. Arrancar tracker-gateway (superficie MCP) en :4000

Expand Down
14 changes: 8 additions & 6 deletions docs/LOCAL_DEV_WITH_K8S_CORE.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,14 @@ dotnet run --project Tracker.Presentation
full-permission admin; it refuses to start outside Development). Postgres (`tracker-ci-pg`) is
already up with the `evolith` / `evolith_tracker` / `localdev` credentials this string expects.

> **`CoreApi__BaseUrl` caveat (gap `LV-18`):** `appsettings.json` ships `.../api/core/api/v1`,
> but hitting the Core **pod directly** (as the port-forward does) the `/api/core` prefix is not
> there — the pod serves `/api/v1`. Three routes (`/gates`, `/architecture`, `/reference`) still
> `404` on the current Core image regardless; only `/capabilities` exists. That contract
> mismatch is tracked as `LV-18` and is **not** solved by running locally — you'll see those
> three tool calls fail until it's resolved.
> **`CoreApi__BaseUrl` (was gap `LV-18`):** `appsettings.json` now defaults to
> `http://localhost:3001/api/v1` — the Core's **direct** `/api/v1` surface (the compose Core on
> `:3001`). ADR T-038 makes the tracker-api BFF the Core's SOLE client, calling `/api/v1` directly,
> never the tracker-gateway; the gateway's `/api/core` prefix is an aggregation facade for external
> consumers (ADR T-052) and does not exist on the Core pod. This runbook port-forwards the **k8s**
> Core to `:8090`, so the run command above overrides `CoreApi__BaseUrl` to
> `http://localhost:8090/api/v1` — same direct `/api/v1` surface, different host:port. The old
> broken default (`http://localhost:4000/api/core/api/v1`, the imaginary gateway prefix) is fixed.

## 4. Run tracker-gateway (MCP surface) on :4000

Expand Down
1 change: 1 addition & 0 deletions docs/audit/tracker-gap-reference-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3990,6 +3990,7 @@ La prueba HTTP del bucle completo pasó a la primera, y al mutar la regla de aut

- **Status:** `DONE` (2026-07-21 — implementado según [ADR T-051](../adrs/T-051-mcp-gateway-binds-to-bff.md)). **Nota — superado por [T-052](../adrs/T-052-gateway-consumes-core-single-mcp.md):** las 6 tools `tracker_*` se eliminaron (duplicaban el MCP del Core); el problema de rutas 404 queda sin objeto. Evidencia histórica conservada abajo.
- **Cierre:** las 6 tools se reenlazaron al BFF `tracker-api`. Smoke en vivo (gateway `nx serve` + BFF stand-in) confirma las rutas exactas golpeadas: `GET /api/v1/gates/{execId}/phase/{phase}`, `GET /api/v1/architecture/topologies`, `GET /api/v1/architecture/reference` (las 3 antes-404), más `GET /api/v1/products`, `POST /api/v1/design/blueprints/{id}/submit-gate`, `POST /api/v1/audit-entries` — **6/6 `success:true`**. Guarda `mcp.contract.spec.ts` (4 asserts) + build verde. **Residual (no revalida el binding):** el smoke E2E contra el `tracker-api` sembrado real devolviendo datos de negocio queda como paso del runbook `LOCAL_DEV_WITH_K8S_CORE.md` / `OPP-003`.
- **Residual de config committeada — CERRADO (2026-07-24, GT-447 Obj-1 bring-up):** el cierre de arriba rebindeó las MCP tools, pero **el default propio del cliente Core del BFF nunca se corrigió**: `CoreApi:BaseUrl` en `src/apps/tracker-api/Tracker.Presentation/appsettings.json` seguía apuntando al path imaginario `http://localhost:4000/api/core/api/v1` — manifestación **hermana** de la misma causa raíz («`/api/core` inexistente en el Core»). Pasó desapercibido porque el compose full-stack y los Helm values lo **sobrescriben por env** (`CoreApi__BaseUrl=http://core-api:3000/api/v1` / DNS de clúster), así que sólo mordía a quien corriera el BFF con la config committeada apuntando al gateway. El cliente (`CoreEvaluationGateway`) fija `BaseAddress = BaseUrl+"/"` y hace `PostAsJsonAsync("evaluate", …)` → `…/api/core/api/v1/evaluate`, que cae al catch-all `@All('*')` del gateway (404). **Fix:** `BaseUrl` → `http://localhost:3001/api/v1` (directo al Core, ADR **T-038**: el BFF es el único cliente del Core; el `/api/core` es facade de agregación para consumidores externos, ADR **T-052**). Alineado con el default del código (`CoreEvaluationOptions.cs`), `evolith.satellite.json`, todos los Helm values, el `docker-compose.fullstack.yml` y los defaults de los tests en vivo. **Verificado e2e contra el stack vivo:** `POST :5100/api/v1/core/evaluate` → `200`, `provenance=core`, `coreEndpoint=/api/v1/evaluate`, `status=COMPLETED`; el path viejo `POST :4000/api/core/api/v1/evaluate` → `404`; `POST :3001/api/core/evaluate` en el Core → `404` («Cannot POST /api/core/evaluate»). Docs alineados: `evolith.satellite.json` (nota corregida) + `LOCAL_DEV_WITH_K8S_CORE.md`/`.es.md` (caveats).
- **Purpose / hallazgo:** Tres de las seis tools pegan a endpoints que el Core real **no expone**: `tracker_get_gate_status`→`/api/v1/gates`, `tracker_get_upstream_constraints`→`/api/v1/architecture`, `tracker_read_spec`→`/api/v1/reference`. Sondeados en vivo devuelven **HTTP 404**; sólo `/api/v1/capabilities` responde (401, existe). Aun corrigiendo despliegue (`LV-16`) y URLs (`LV-17`), la mitad del catálogo fallaría: el contrato Core nunca se verificó contra el servicio real.
- **Evidence:** `kubectl exec` (core-api pod) `curl -o /dev/null -w '%{http_code}'` → `/api/v1/gates` 404, `/api/v1/architecture` 404, `/api/v1/reference` 404, `/api/v1/capabilities` 401.
- **Component:** `Contracts/Integration` · **Module:** tracker-gateway MCP · **Type:** LV
Expand Down
2 changes: 1 addition & 1 deletion docs/audit/tracker-gap-tracking.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ This board is the single source of truth for Tracker technical debt, gaps, oppor
| [`LV-15`](./tracker-gap-reference-catalog.md#lv-15) | **Hecho — roll-out de [ADR T-034](../adrs/T-034-config-hub-vs-monitor.md)** (Config-hub vs Monitor) completo. Los **monitores** migrados a solo-lectura con la edición movida a zonas inline en Tenant configuration: Gate policies & criteria, Custom fields / artifact schemas (Gate governance 100% solo-lectura) y Tenant intelligence (`intel` solo-lectura). **Connectors (PPM intake)** y **Products** quedan como pantallas de **registro/gestión** — exentas por diseño (ADR T-034 §2.1: los registros no son monitores); sus cards de Config enlazan a su área de gestión ("Manage …"). | | | `WEB` | Cross | P2 | L | `DONE` |
| [`LV-16`](./tracker-gap-reference-catalog.md#lv-16) | El `tracker-gateway` (servidor MCP que reclama COH-006/007) no está desplegado en ningún entorno; sólo corren los servicios del Core | El código de la superficie de agentes existe pero nunca ha corrido: los cierres de COH-006/007 son "code-complete" sin una sola evidencia viva | Desplegado: `Dockerfile` (Node multi-stage) + chart `evolith-tracker-gateway`; corre en `evolith-local` y consume el Core **in-cluster por DNS** (capabilities + 47 MCP tools), sin port-forward | `Infra/Integration` | Cross | P1 | S | `DONE` |
| [`LV-17`](./tracker-gap-reference-catalog.md#lv-17) | Las 6 MCP tools del gateway resuelven Core y Tracker-API por `localhost` y nombran la variable del Core distinto que el core-proxy | Desplegado tal cual en clúster, ninguna tool alcanza su upstream: apuntan a hosts que no existen ahí | `mcp.service.ts` usa `CORE_API_BASE_URL` (default `localhost:4000/api/core`) mientras `core-proxy.service.ts` usa `EVOLITH_CORE_API_URL` (default DNS de clúster) para el MISMO Core | `Integration/Config` | Cross | P1 | S | `DONE` |
| [`LV-18`](./tracker-gap-reference-catalog.md#lv-18) | Tres de las seis MCP tools llaman rutas del Core que devuelven 404 en el servicio vivo | Aun corrigiendo despliegue y URLs, la mitad del catálogo choca con endpoints que el Core no expone: el contrato nunca se verificó contra el Core real | `/api/v1/gates`, `/api/v1/architecture` y `/api/v1/reference` → HTTP 404 en vivo; sólo `/api/v1/capabilities` responde (401, existe) | `Contracts/Integration` | Cross | P1 | M | `DONE` |
| [`LV-18`](./tracker-gap-reference-catalog.md#lv-18) | Tres de las seis MCP tools llaman rutas del Core que devuelven 404 en el servicio vivo. **Residual de config cerrado (2026-07-24):** el cierre por T-051/T-052 rebindeó las tools al BFF, pero el default propio del cliente Core del BFF —`CoreApi:BaseUrl` en `appsettings.json`— seguía en el path imaginario `…:4000/api/core/api/v1` (hermano de esta misma causa, tapado por env en compose/Helm); corregido a `http://localhost:3001/api/v1` (directo al Core, ADR T-038), alineado con el default del código, Helm, el compose full-stack y los tests en vivo. Verificado e2e contra el stack: `POST :5100/api/v1/core/evaluate` → 200 `provenance=core`, `coreEndpoint=/api/v1/evaluate`; el path viejo `POST :4000/api/core/api/v1/evaluate` → 404. | Aun corrigiendo despliegue y URLs, la mitad del catálogo choca con endpoints que el Core no expone: el contrato nunca se verificó contra el Core real | `/api/v1/gates`, `/api/v1/architecture` y `/api/v1/reference` → HTTP 404 en vivo; sólo `/api/v1/capabilities` responde (401, existe) | `Contracts/Integration` | Cross | P1 | M | `DONE` |
| [`LV-19`](./tracker-gap-reference-catalog.md#lv-19) | ⚠️ **Premisa falsa (corregido 2026-07-21)** — el Tracker SÍ tiene cliente del runtime: `AgentRuntimeGateway` (BFF) llama `POST /v1/agent/converse` vía `/api/v1/assistant/converse`, tenant-scoped y engine-agnóstico, más el puerto gobernado `IAgentExecutionPort` (EAG-16) | El cliente vive en el BFF (correcto per T-051), no en el gateway MCP; el `rg` original miró sólo el `tracker-gateway`, no el `tracker-api` | El residual real —ejercitarlo contra el runtime vivo— es `AR-02`, no un cliente faltante | `Integration` | Cross | P2 | M | `DONE` |
| [`LV-20`](./tracker-gap-reference-catalog.md#lv-20) | `COH-006` y `COH-007` siguen `BLOCKED` pese a que su bloqueante `EAG-16` está `DONE` y su código ya existe | El estado del board no refleja la realidad: ni "bloqueado" (el bloqueante cerró) ni "hecho" (sin verificar en vivo); el estado honesto es code-complete-unverified | `COH-006/007` ya no están `BLOCKED` ni pendientes: cerrados `DONE` por [ADR T-052] (la superficie de agentes es el MCP del Core, que el Tracker consume) | `Docs` | Cross | P3 | XS | `DONE` |
| [`OPP-003`](./tracker-gap-reference-catalog.md#opp-003) | RoboSoft: flota de agentes de prueba E2E determinísticos contra el stack vivo (Core real) como evidencia reproducible | El entorno vivo ya existe; RoboSoft ejercita REST + MCP tools + `/converse` con round-trips reales al Core, asevera y emite evidencia JSON + exit code para CI | RoboSoft REALIZADO: 7 robots validados en vivo (core-integration 11/13 vs Core real; governance-journey 53/53; provider-connections 19/19; tenant-isolation 10/10; gate-enforcement 25/25; exception-governance 21/21; audit-trail 14/14; intake 12/12; qa-quality-gate 13/13; scorecard 33/33; auth-perimeter 6/6 cierra RS-GAP-2; runtime-approvals 10/10 CD-23 HITL) + gate de CI en cada PR con los 9 tracker-api-only (200/200); seeds e2e arreglados (/api/v1 + CD-19); 3 gaps de cobertura registrados (inmutabilidad-en-reposo=BD, auth real=prod-standup, core-integration=Core-en-CI) | `Infra/Quality` | Cross | P2 | M | `DONE` |
Expand Down
2 changes: 1 addition & 1 deletion evolith.satellite.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@
"baseUrl": "http://localhost:3001/api/v1",
"version": "v1 (path-versioned: /api/v1)",
"openapi": "http://localhost:3001/api/v1/openapi.json (Core-API Swagger, ADR-0073 envelope); the machine-readable capabilities manifest is served at GET /api/v1/capabilities",
"baseUrlNote": "Default from CoreEvaluationOptions.BaseUrl (src/apps/tracker-api/Tracker.Presentation/Integration/CoreEvaluationOptions.cs). A deployment behind the BFF gateway overrides CoreApi:BaseUrl in appsettings.json (e.g. http://localhost:4000/api/core/api/v1)."
"baseUrlNote": "Default from CoreEvaluationOptions.BaseUrl (src/apps/tracker-api/Tracker.Presentation/Integration/CoreEvaluationOptions.cs). The Tracker BFF is the SOLE Core client (ADR T-038) and calls the Core's /api/v1 surface DIRECTLY, never through the tracker-gateway. A deployment overrides CoreApi:BaseUrl to the Core service DNS (e.g. http://core-api:3000/api/v1 in-network, http://evolith-core-api/api/v1 in-cluster). Do NOT point it at the gateway's /api/core aggregation facade: that prefix is for EXTERNAL consumers (ADR T-052) and 404s from the BFF's Core client — the earlier http://localhost:4000/api/core/api/v1 example was gap LV-18."
}
},
"canonicalModelRefs": {
Expand Down
3 changes: 2 additions & 1 deletion src/apps/tracker-api/Tracker.Presentation/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
},
"CoreApi": {
"//ApiKey": "SERVICE credential the BFF presents to the Core as 'Authorization: Bearer <key>' (Core's global ApiKeyGuard / EVOLITH_API_KEY). Required for non-mock runs. This does NOT contradict ADR-0080: that contract forbids forwarding USER tokens or tenant identity to the Core (repositoryRef + opaque workspaceRef only); a BFF->Core service key is a separate, allowed transport concern. Keep this key.",
"BaseUrl": "http://localhost:4000/api/core/api/v1",
"//BaseUrl": "The Tracker BFF is the satellite's SOLE Core client (T-038): it calls the Core's REST surface DIRECTLY, never through the tracker-gateway. The Core serves /api/v1/{capabilities,rulesets,evaluate} (ADR-0074/0098) — the /api/core prefix is the gateway's own aggregation facade for EXTERNAL consumers (ADR T-052) and is NOT reachable from the Core pod. Local host: core-api is on :3001 (docker-compose.fullstack.yml maps 3000->3001). In-cluster/compose this is overridden via CoreApi__BaseUrl to the Core service DNS (e.g. http://core-api:3000/api/v1 or http://evolith-core-api/api/v1). Pointing this at the gateway (:4000/api/core/api/v1) 404s — that path is imaginary (gap LV-18).",
"BaseUrl": "http://localhost:3001/api/v1",
"ApiKey": "local-dev-key",
"TimeoutMs": 8000,
"MockFallback": false,
Expand Down
Loading