Files
buzz/crates
HaytandWill Pfleger 386e63f273 feat(buzz-agent): gate LLM tool calls on session/request_permission
Every LLM-issued MCP tool call now asks the client to authorize it
before executing. buzz-agent always asks; the client applies
BUZZ_ACP_PERMISSION_POLICY. The agent never reads policy, matching the
layering of the other ACP harnesses.

A crate-local PermissionBroker owns the full correlation lifecycle: a
process-wide admission semaphore (BUZZ_AGENT_MAX_PENDING_PERMISSIONS,
default 32) acquired before any correlation entry is inserted, a
monotonic id allocator, an abort-safe PendingPermission lease whose Drop
synchronously removes the entry and releases the slot, claim-before-wake
delivery for at-most-once resolution, and a single absolute deadline
(BUZZ_AGENT_PERMISSION_TIMEOUT_SECS, default 330s) shared by admission
and response wait. Cancellation races inside the wait, never depending
on the outer abort drain.

The request builder is version-aware, keyed on the protocol version
negotiated at initialize and stored for the connection lifetime: v2
nests the tool call under subject, v1 uses the legacy top-level shape.
Authorization is fail-closed: execute IFF outcome is "selected" and the
selected optionId equals the offered allow option; every other shape
denies with a synthetic tool error and the turn continues.

Argument-shape validation is hoisted ahead of the ask so a malformed
call is rejected locally without prompting. load_skill and _Stop/
_PostCompact lifecycle hooks are exempt — they are not model-issued.

Tests: a subprocess + fake-MCP boundary suite proves no call reaches
MCP before approval, exact-allow reaches it once, and reject/cancelled/
error/malformed/unknown-outcome/wrong-option/stale-id all fail closed,
plus crossed-parallel isolation and the two exemptions; broker unit
tests prove timeout, abort, and multi-session admission invariants with
an injectable deadline.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
2026-08-12 18:40:15 -04:00
..