External MCP Service-Key Policy

External MCP Service-Key Policy (ENG-6796, P2.5) — RETIRED (ENG-7010) #

Classification: Restricted (describes source code, infrastructure, and access control).

This design was retired before any service key was ever issued. tofu-external-mcp is JWT-only (Clerk OAuth pass-through) end to end now — the Tofu-API-Key credential path described below no longer exists in the codebase: src/service-key-policy.ts is deleted, src/middleware/auth.ts has no API-key branch, src/auth-context.ts has no apiKey/getApiKey, and no tool declares a service-key-compatible operation. The rest of this page is kept as a historical record of the design that was implemented and then removed — do not use it as current documentation.

What a service key was going to be #

A bonsapi ApiKey (the same row/HMAC-digest mechanism the customer-facing “API keys” org settings page already creates via createApiKey), presented on the Tofu-API-Key header instead of a Clerk-issued Authorization: Bearer token. bonsapi’s BonsaiUserOrApiKey / BonsaiUserInEntityOrApiKey extractors (apps/bonsapi/src/model/app/bonsai_user.rs) accept either credential; a plain BonsaiUser / BonsaiUserInEntity extractor accepts only the Clerk header — that bonsapi-side extractor split is unaffected by this retirement, only tofu-external-mcp’s own use of it was removed.

An API-key-authenticated request would have gotten permissions = all_access() and skipped entity-scoping entirely on bonsapi’s side — a key acts org-wide, never per-user.

Credential map (historical — ENG-6768, verified 2026-07-22 against main) #

168/168 external.yaml operations mapped. Exactly 8 were API-key-compatible; every other mapped operation was JWT-only.

Endpoint Method operationId MCP tool at the time
/api/v1/documents POST createDocument none yet
/api/v1/documents GET getDocuments list_documents
/api/v1/documents/stale GET getStaleDocuments none yet
/api/v1/documents/{documentId} GET getDocument get_document
/api/v1/documents/{documentId}/download GET downloadDocumentFile download_document_file
/api/v1/documents/{documentId}/metadata GET getDocumentMetadata none yet
/api/v1/entities GET getEntities none yet
/api/v1/entities/{entityId} GET getEntity none yet

Why it was removed #

No headless consumer ever appeared and no key was ever issued (zero live traffic throughout this design’s lifetime — see the Issuance policy note below). ENG-7010 simplified the server to a single JWT-only auth model rather than carry an unused second credential path and its policy-gate/allowlist maintenance burden.

Issuance policy (as designed — never executed) #

  • Super-user issued. Would have been created via bonsapi’s existing createApiKey endpoint by BonsAI ops/engineering, not by an end-user org’s own admin.
  • Named per purpose. The name field passed to createApiKey would identify the consumer, not a person.
  • Stored and rotated in Doppler, under the TOFU_EXTERNAL_MCP_* prefix.
  • Never handed to end users.
  • First key was to be issued only when a headless consumer actually appeared — that never happened.