Disciplines · Decisions (ADRs)

ADR-0092: Fail-closed external integration registry

Eve currently has one production external-tool surface: the oshun-workbench MCP stdio server used by external coding agents.

4sections5 minread

On this page
  • Status: Accepted
  • Date: 2026-09-16
  • Decision owners: Eve platform, Oshun workbench, security, and privacy maintainers
  • Registry contract: eve.external-integration-registry.v1

Context#

Eve currently has one production external-tool surface: the oshun-workbench MCP stdio server used by external coding agents. It holds a scoped workbench bearer and exposes seven tools. The registry also contains the executable bellona-protected-http reference peer. That peer is exercised locally over a real Streamable HTTP transport, but is not a deployed endpoint and exposes only the read-only bellona_ping proof tool. Task 4.6 pins both records' owners, sources, versions, transports, tool risk classes, credential destinations, and protocol versions.

There is no adopted external-agent protocol or production external-agent integration. ADR-0091 deliberately defers A2A, and the A2A-shaped Iris and Oshun libraries are private, unmounted, non-conformant prototypes. They are not registry entries.

The admin integrations store is not this boundary. It manages operator-created API keys, webhooks, and connector status; it does not decide whether Eve may load or call an external tool or agent. The enforceable boundary is the client admission path immediately before the workbench server registers tools.

Decision#

EXTERNAL_INTEGRATION_REGISTRY in tools/workbench-mcp/trust.mjs is the authoritative source-controlled registry. MCP_SERVER_INVENTORY remains an alias for existing MCP callers. Each entry must identify:

  • integration kind and protocol;
  • accountable owner;
  • source path, version, SHA-256, and transport;
  • integration-level risk class and per-tool risk classes;
  • explicit permissions, credentials, configuration, destination origins, and data classes sent there;
  • lifecycle state (active, quarantined, or revoked);
  • health status, observation time, expiry, and evidence;
  • evaluation status, observation time, expiry, and evidence;
  • owner review time, expiry, reviewer, and evidence; and
  • the exact name set plus SHA-256 pins for every tool input schema and description.

Admission is default-deny. An absent entry, missing required field, unknown kind or lifecycle, quarantine, revocation, unhealthy or unknown status, failed or pending evaluation, expired health/evaluation/review, changed source, version, transport, tool set, schema, or description makes the integration unavailable. Each failure has a stable refusal code. The server performs this governance decision before registering its first tool, and a caller's combined tool-call admission repeats it before considering protocol, annotation, credential, authorization, and consent controls.

The registry currently has two entries. The production workbench entry's seven schema and description pins were measured from a live MCP tools/list response. The protected-HTTP reference entry's single tool is measured through an official MCP SDK client against a real local HTTP server; its deployment: local-reference field makes its non-production status explicit. Both records' health expires after 30 days and their evaluation and owner review after six months. Renewal means rerunning the relevant tests, reading source and surface diffs, recording new evidence, and deliberately updating the dates and hashes. Merely extending an expiry is not a review.

Publish-class workbench tools do not rely on a third-party client's approval UI. A first MCP call without a consent id creates an exact non-executing impact preview in the BFF. A distinct operator credential approves or declines it, and the BFF binds the one-shot approval to actor, tenant, tool, and canonical arguments before either shipment or verification can execute. The step-up credential must differ from the shared bearer and every per-agent bearer.

The schema permits kind: agent, but there are zero agent entries. A future agent integration must first satisfy ADR-0091's adoption conditions, then add its protocol-specific discovery/card and capability pins. Unknown agents are unavailable by absence; the registry does not create a placeholder that could be mistaken for admission.

New live third-party admissions also remain subject to the dependency gates owned by Tasks 4.8, 12.7, 13.7, and 14.7. This ADR prepares and enforces the registry mechanism; it does not waive those release, red-team, operational, or privacy obligations and does not claim Task 16.5 closed while its prerequisites remain open.

Consequences#

Review is now operational state rather than prose. A forgotten integration ages out; a changed description is treated as tool poisoning rather than a cosmetic edit; and quarantine/revocation stop startup instead of relying on an operator to remember not to call a tool. Source-controlled metadata makes every admission change reviewable and binds the permission and data-destination story to the same commit as the executable gate.

The deliberate cost is maintenance. Health checks must be renewed monthly, evaluations and reviews must be renewed at least every six months, and ordinary tool edits require new schema/description and source pins. A stale registry can stop the workbench MCP server with exit code 78; that is the intended safe failure.

Verification#

The adversarial trust suite produces and asserts every refusal code, including missing metadata, quarantine, revocation, unhealthy and unevaluated states, three expiry paths, and schema and description drift. The stdio interop suite launches the real workbench server with the official MCP SDK, negotiates a protocol version, reads the live seven-tool surface, and checks its schemas, descriptions, and policy-derived annotations against the registry. Separate live negative cases prove bad credential destinations prevent the server from serving any tools.

The protected-HTTP integration suite starts a real local HTTP server, discovers its path-aware protected-resource metadata, connects an official Streamable HTTP MCP client with an exact-audience token, lists and calls bellona_ping, then observes a wrong-audience token refused on the wire. The Task 16.3 suite separately proves the same resource identifier is sent on both OAuth resource indicator legs. Workbench route tests prove a preview performs no mutation, an agent bearer cannot self-approve, exact approved arguments execute once, and a replay or argument change is refused; a PostgreSQL integration test observes the single real shipped transition.

Task 16.5 evidence and checklist closure are deferred until all dependency tasks named by the evidence-exit matrix are complete.