Expand description
P5-1 (COMPOSABLE-HARNESS-DESIGN.md §2 module 10, §2.10): approval policy
plumbing — the POLICY + session-scoped CACHE + a non-interactive decision
path. The INTERACTIVE ask-UI itself is the tui module (P5 row 4, not
this unit) — PermissionsApprovalHandler is the seam a CLI/TUI/SDK
embedder implements to plug an interactive (or scripted/headless) prompt
into crate::agent::Agent’s tool-dispatch gate, mirroring the existing
crate::reduce::summarize::SpanSummarizer/crate::session_title::SessionTitler
“installing one alone changes nothing, the Config gate is what turns it
on” pattern (Agent::set_span_summarizer/Agent::set_session_titler).
Structs§
- Approval
Cache - Session-scoped “approve for session” decision cache (§2.10). Keyed by
Self::key—(tool, subject)— so a repeated identical call (the SAME canonical command, or the same path) skips re-prompting for the rest of this agent’s lifetime, exactly like CC’s “don’t ask again”/oc’s “always” (cc§4, oc§4). Cheap and unconditional to construct — an agent that never enablescapabilities.permissionssimply never populates or consults it (§1.13-style “zero cost when off”). - Approval
Request - One
Ask-tier request handed to aPermissionsApprovalHandler— enough context for an interactive prompt (or a scripted policy) to render a decision without needing back-references intoAgent’s private state.
Enums§
- Approval
Outcome - What a
PermissionsApprovalHandlerdecides for oneAsk-tier request.
Traits§
- Permissions
Approval Handler - The non-interactive decision seam a CLI/TUI/SDK embedder implements. The
engine (
crate::agent::Agent’s gate) callsSelf::askONLY when the rule engine has already resolved a call toDecision::Ask—Denyshort-circuits before ever reaching a handler (a hard floor, never consulted), andAllownever needs one. No handler installed (the default) denies everyAsk— fail-closed, the same postureConfig::approval_handler’s doc comment already documents for the pre-P5-1 gate (“absent handler denies, so an OnRequest/Untrusted policy is fail-closed” — agent.rs).
Functions§
- decision_
to_ approved - Convenience: fold a
Decisioninto the boolean “may this call proceed” the tool-dispatch gate needs, given aresolve_ask-style callback for theAskcase.Denynever reachesask_fn(hard floor);Allownever needs it either. - resolve_
ask - Resolve one
Ask-tier request against the cache + an optional handler: cache hit →true(no handler call); no handler →false(fail-closed); handlerDeny/Allow/AllowForSession→false/true/true(recording the grant incachefor the last case). This is the single call sitecrate::agent::Agent’s gate uses, factored out so it’s unit- testable without a fullAgent.