- Status: Accepted (identity hardening, 2026 Q3) — 2026-07-21 — security P0 subset is unconditional
- Date: 2026-07-21
- Builds on: ADR-0009 (mutation trust substrate)
Context (verified at HEAD 91794a0f)
- Session metadata is caller-supplied.
SessionContextis parsed from_session_*keys inside tool-call arguments (session_context.rs:28-35):_session_id,_session_project_path,_session_deferred_tool_loading, principal fields. In a shared HTTP daemon any client can forge another session's identity, rebind its project, or spoof its principal — argument-derived identity is inherently untrusted. - Coordination fails open. When the coordination DB is unavailable,
register_agent_work/claim_files/release_filesfall back to a per-process in-memory map and return success with only atracing::warn!(agent_coordination.rs:440,548,630). Two processes (or one restart) later disagree about who owns which files — silent split-brain. - Hosts now own agent coordination natively (worktrees, task ownership, teams); a server-side claim registry duplicates that at lower fidelity.
Decision
- Identity moves to the transport layer. Session id, project binding, deferred
state, and principal derive from the HTTP session (connection-scoped server state
established at
initialize/prepare_harness_session), or from authenticated headers under RBAC._session_*argument keys are accepted only from the stdio transport (single-client by construction), ignored elsewhere, and removed from public schemas. - Coordination fails closed. Store failure returns a typed error
(
coordination_unavailable) — never a fabricated success. No in-memory fallback. - Deprecate
register_agent_work/claim_files/release_files/list_active_agents. Hosts own work distribution and worktrees; CodeLens keeps only snapshot/preflight evidence (verify_change_readiness,get_changed_files, diff-bound approval in the mutation gate). Removal gate: one release of deprecation telemetry showing no legitimate callers. - Companion P0 audit tracked in the same epic: LSP server
command/argsmust resolve against a vetted allowlist (no config-supplied arbitrary executables); remote project roots rejected by default; no trust in unauthenticated forwarded headers. (These claims from the external review are accepted as audit items; each lands with a failing-then-passing test.)
Consequences
- A shared daemon becomes safe for mutually untrusted sessions on one machine, and the RBAC story (ADR-0009) stops being bypassable via argument forgery.
- Losing the claim registry removes a false safety signal; hosts that relied on it get honest errors instead of best-effort bookkeeping.
Verification (exit criteria)
- Forgery test: a second session sending
_session_id/_session_principal_idof the first is rejected (HTTP) — zero cross-session reads or writes. - Chaos test: coordination store outage yields typed errors, zero silent successes.
- P0 audit: LSP exec allowlist, remote-root rejection, and header-trust removal each covered by a regression test that fails on the pre-fix code.
Verification status (2026-07-24, evidence audit at HEAD 27c897e5)
- Forgery — met.
from_json_ignores_unprovenanced_principal_idandtransport_scope_authenticates_server_injected_identity(session_context.rs) pin argument-forgery rejection; server-owned injection is centralized inserver/session_injection.rs. - Chaos — met.
every_coordination_operation_fails_closed_when_store_is_unavailableandcoordination_store_outage_fails_closed_across_processes(agent_coordination.rs): typedcoordination_unavailableerrors, no in-memory fallback path remains. - P0 LSP exec allowlist — met. Registered-recipe policy plus
lsp/command_security_tests.rs(engine) landed in #402. - P0 forwarded headers — met at the transport-config layer. Non-local HTTP
listen requires auth + TLS (
server/http_config.rs::validate_remote_transport_config); cross-origin POST rejected (post_from_remote_origin_is_forbidden). - P0 remote project roots — met.
ProjectRoot::new/new_exactreject roots on network filesystems by default (project/remote_root.rs: statfs kind detection, fail-open on detection error, opt-out viaCODELENS_ALLOW_REMOTE_PROJECT_ROOT=1). Rationale: the.codelensSQLite index is unsafe on network mounts and a stalled mount wedges the shared daemon. FUSE-backed remotes present as local and stay out of scope. - Decision 3 — in progress. The coordination quartet entered the deprecation window (569513da) with persisted removal-gate telemetry (27c897e5); removal lands in v2.0 after one clean release of telemetry.
Removal-gate verdict (2026-09-16)
Usage telemetry from the window open (2026-07-24) through 2026-09-16 holds 45,731 rows. The
coordination quartet registers one call (list_active_agents, client telemetry-verify, the
window-open verification itself); the memory family registers one (list_memories, client
e6-verify). No organic caller touched the wave, and v1.13.35 shipped as the one clean release
the gate required. Deletion is authorized for the v2.0 cut.