# ADR-0075: Eve → Metis Workbench Read Transport

**Status**: Proposed — engineering direction agent-adopted; named production
ratification pending

**Date**: 2026-09-01

**Authors**: Eve SOTA gap-closure task 1.2

**Reviewers**: _pending_ — Metis service owner, Platform Identity owner,
Security owner; Data Governance for protected data

> This ADR records a real engineering decision without fabricating human
> approval. It is effective for implementation and CI on merge. Production
> activation remains blocked until the named owners ratify it. It does not
> ratify or supersede [ADR-M0.5](ADR-M0.5-metis-persistence-ownership.md).

## Context

The task-1.1 source-hashed survey found three incompatible path layers: the
Metis browser calls `/api/metis/v1`, its Next proxy targets `/api` on
`http://localhost:4020`, the Node gateway registers only an explicit subset
below `/api/v1`, and the authoritative FastAPI OpenAPI declares 803 paths below
`/api`. The BFF's current Metis HTTP adapter instead calls `/v1/metis` on a
development origin at `http://localhost:4601`; normal reads have neither an
abort deadline nor retries. The app defaults to the partial in-process Metis
adapter.

Identity is also incompatible: Oshun access tokens are issued for `oshun-bff`,
while the Metis validator currently verifies neither issuer nor audience and
understands only a coarse role rather than Oshun tenant and scopes. Forwarding
the caller's bearer would therefore be both incorrect and over-broad.

## Decision

**Selected: direct, versioned HTTP from the Oshun BFF to the Metis FastAPI
service.** The narrow contract is `eve.metis.workbench-read.v1`, exposed as
explicit GET operations below `/api/v1/eve/workbench-read`. The BFF bypasses the
browser Next proxy and the incomplete Node gateway. It never queries Metis
PostgreSQL, filesystem ledgers, Redis, S3, SQLAlchemy models, or migrations.

| Concern       | Normative decision                                                                                                               |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Transport     | `oshun-bff-workbench-kit-read` calls `metis-fastapi-service` directly over HTTPS via `OSHUN_METIS_API_BASE_URL`.                 |
| Route         | Explicit `GET` operations below `/api/v1/eve/workbench-read`; no catch-all and no unversioned fallback.                          |
| Deadline      | 1000 ms per attempt, 2250 ms total, 524288 response-byte cap.                                                                    |
| Retry         | At most 1 retry for GET on network/timeout or 429, 502, 503, 504; fixed 250 ms delay inside the total deadline.                  |
| Circuit       | Open after 5 consecutive transient failures for 30 s; close after 3 half-open successes.                                         |
| Identity      | Platform-issued delegated JWT, `iss=oshun-auth`, `aud=metis-workbench-api`, TTL ≤60 s, exact per-view scope, subject and tenant. |
| Degraded mode | Typed 502/503/504 failures, `no-store`, never empty-success, stale cache, direct store, or in-process fallback.                  |

### Version and compatibility lane

The URI carries the breaking major version. Every response carries
`x-metis-contract-version: 1.0.0`. Metis produces a canonical OpenAPI slice
containing only the admitted operations; the BFF decoder and service contract
tests pin the same slice digest. Additive changes require a minor-version bump
and passing consumer tests. Breaking schema, authorization, or meaning changes
require a new URI major with an overlap window. There is no fallback to the
moving unversioned `/api` contract.

This is the task-1.1 **versioned compatibility exception**: implementation need
not wait for the whole Metis contract to remain unchanged for seven days, but
the exception applies only to explicitly admitted routes under the new prefix.
It registers no view by itself. A route is admitted only when all of these hold:

- explicit FastAPI route and operationId exist in the canonical OpenAPI artifact
- bearer security and exact delegated scope are declared and enforced
- the route response schema is present in the pinned Eve OpenAPI slice
- the BFF decoder and FastAPI contract tests pass for the same slice digest
- authorization, timeout, service-loss, malformed-payload, and version-mismatch
  controls fail loud
- the data classification is ratified for exposure or the view contains only
  already-public data

### Identity propagation

The BFF first authenticates and authorizes the Oshun session. Platform Identity
then issues a short-lived delegated JWT with required claims
`act, aud, exp, iat, iss, jti, nbf, scope, sub, tid`, audience
`metis-workbench-api`, actor `oshun-bff`, and exact scope
`metis:eve:read:<view>`. Metis validates the signature, issuer, audience, time
window, subject, tenant, and exact view scope again before query execution. The
verified `tid` claim is authoritative; an `x-tenant-id` header or request
parameter cannot grant or widen access and a mismatch is refused.

The browser bearer and refresh token never cross this seam. The BFF propagates
only `traceparent, tracestate, x-correlation-id, x-request-id` alongside the
delegated credential, and neither tokens nor secrets may be logged.

### Timeouts, retries, and degraded behavior

Each attempt is aborted at 1000 ms and the entire operation, including the
single 250 ms retry delay, is capped at 2250 ms. Only idempotent GET reads
retry: network errors, timeouts, and HTTP 429/502/503/504. Authentication,
authorization, validation, not-found, and contract/version failures do not
retry.

Timeout is `504 metis_timeout`; service loss or an open circuit is
`503 metis_unavailable`; a malformed or wrong-version response is
`502 metis_contract_violation`. The kit records `execution-failed`. It does not
turn any failure into `[]`, `null`, a fixture, stale cache, direct-store read,
or the in-process adapter.

## Rejected options

| Option                             | Reason                                                                                                                                             |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `direct-store`                     | It bypasses Metis authorization and service invariants, couples Eve to migrations and physical stores, and violates the proposed owner boundary.   |
| `current-in-process-metis-adapter` | It is a partial Oshun member adapter with truthful empty placeholders, not the Metis workbench authority or an independently authorizing boundary. |
| `browser-next-proxy`               | The /api/metis/v1 browser path is a client façade and forwards browser credentials; server-side Eve must not depend on a web application hop.      |
| `metis-node-api-gateway`           | The /api/v1 gateway exposes only a small explicit subset of current FastAPI paths and cannot provide a generic or implied workbench route.         |
| `unversioned-fastapi-routes`       | The current /api routes are the moving web contract; calling them directly would not create an independently versioned compatibility seam.         |

## Implementation gates

| Gate                               | Current state     | Exact condition                                                                                                                                      | Owner    |
| ---------------------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `versioned-fastapi-facade`         | `not-implemented` | Metis registers explicit GET routes under /api/v1/eve/workbench-read with OpenAPI operation IDs, schemas, and bearer security.                       | Task 1.3 |
| `delegated-identity`               | `not-implemented` | Platform Identity issues and Metis validates the down-scoped audience-bound JWT; tenant headers alone never authorize.                               | Task 1.3 |
| `bounded-bff-client`               | `not-implemented` | The Eve Metis adapter enforces this decision's deadlines, retry set, response cap, circuit breaker, schema decoder, and typed failures.              | Task 1.3 |
| `direct-fastapi-service-discovery` | `not-implemented` | OSHUN_METIS_API_BASE_URL resolves to the residency-correct FastAPI service origin, not port 4020, the browser proxy, or the incomplete Node gateway. | Task 1.3 |
| `per-view-admission`               | `not-implemented` | Each candidate independently passes the compatibility-exception conditions; this decision admits zero views by itself.                               | Task 1.3 |

These gates make current non-compliance visible. They are not assertions that
the transport already exists.

## Ratification and data boundary

| Reviewer                | Status                       |
| ----------------------- | ---------------------------- |
| Metis service owner     | `pending`                    |
| Platform Identity owner | `pending`                    |
| Security owner          | `pending`                    |
| Data Governance         | `pending-for-protected-data` |

Implementation posture is `effective-on-merge`; production posture is
`blocked-pending-named-ratification`. ADR-M0.5 must be ratified or superseded
before protected learner, assessment, grade, integrity, or authoring records are
exposed.

## Consequences

- Metis remains the data and authorization owner; Eve consumes a versioned
  service contract and never becomes a second repository or migration client.
- The existing BFF domain adapter, port-4601 default, in-process default,
  browser proxy, and Node gateway do not satisfy this decision for Eve.
- Task 1.3 must build the narrow façade/client and independently prove each real
  view. Task 1.4 owns exact subject, tenant, scope, classification, and refusal
  controls.
- The source-hashed machine record is
  [`../audits/eve-sota-metis-transport-decision/2026-09-01.json`](../audits/eve-sota-metis-transport-decision/2026-09-01.json).

## Limitations

- This decision authorizes an implementation direction and narrow compatibility
  exception; it does not claim that the versioned FastAPI façade, delegated
  identity, or bounded BFF client already exists.
- No Metis Eve view is registered by task 1.2; task 1.3 must prove every route
  independently.
- Named production ratification remains pending and is not inferred from agent
  authorship or a merged document.
- ADR-M0.5 remains Proposed, so this decision cannot admit protected or
  mixed-boundary data.
- The source observations are repository evidence, not a staging or production
  network probe.
