docs: add phased implementation plan and architecture decision records
Turns the design doc into an ordered, dependency-correct build plan (phases 0-9) with an exit criterion per phase, and records the twelve architectural decisions it rests on as ADRs. Decisions: single Rust binary with routed compose services; Streamable HTTP only; per-agent bearer tokens with clientInfo as a display hint only; SQLite; get_rules delivered via session gating; full-document rule delivery; project_id from day one; enforcement tier scoped to Bridle-mediated actions; stable tool list on upstream failure; OpenAI-compatible embeddings with model/dim guarding; pattern RAG gated behind a spike; CLAUDE.md + AGENTS.md as v1 renderer targets. Deviates from the design doc's original 1-8 ordering by moving the audit log and multi-project schema into phase 1, building the admin API incrementally rather than all at the Web Panel phase, downgrading vendor guardrail sourcing to manual-first, and gating the pattern-example RAG behind a validation spike. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019RZerbsHGF9Ka3bKhCjJ9m
This commit is contained in:
32
docs/adr/0003-per-agent-bearer-tokens.md
Normal file
32
docs/adr/0003-per-agent-bearer-tokens.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# ADR-0003: Per-agent bearer tokens for identity and authorization
|
||||
|
||||
**Status:** Accepted (2026-08-08)
|
||||
|
||||
## Context
|
||||
|
||||
The design doc proposed identifying the connecting agent via "MCP handshake client info". The
|
||||
`clientInfo` object in the MCP `initialize` request is **self-reported by the client** and trivially
|
||||
forged. Hanging the permissions model off it — including `secrets: {read: false}` — would make that
|
||||
model decorative rather than enforcing. This matters more once WireGuard or Pangolin place the
|
||||
endpoint on a network beyond the operator's full control.
|
||||
|
||||
Alternatives considered: mTLS client certificates (stronger binding, but meaningful setup friction
|
||||
per agent and per machine) and full OAuth 2.1 per the MCP authorization spec (standards-correct and
|
||||
the right answer for public exposure, but an entire authorization server to build and operate for a
|
||||
single-user homelab).
|
||||
|
||||
## Decision
|
||||
|
||||
Each agent identity is issued a **Bridle bearer token**. Identity and permissions derive from the
|
||||
token presented on the connection. `clientInfo` is retained as a **display hint only** — surfaced in
|
||||
the audit log and Web Panel, never consulted for an authorization decision.
|
||||
|
||||
Tokens are issued, rotated, and revoked through the admin API and Web Panel.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Simple, revocable, and sufficient behind WireGuard.
|
||||
- Forging `clientInfo` gains an attacker nothing.
|
||||
- Token issuance/rotation/revocation is phase-1 scope.
|
||||
- If Bridle is ever exposed to clients the operator does not control, revisit in favor of OAuth 2.1
|
||||
per the MCP authorization spec.
|
||||
Reference in New Issue
Block a user