Files
buzz/crates
HaytandWill Pfleger d8be3386ec feat(desktop): permission policy config + actionable Allow/Deny card (#4938)
Add per-agent and fleet-wide permission policy configuration with
an actionable Allow/Deny card for the ask policy.

**Rust (desktop/src-tauri)**
- Add `permission_policy` module: `PermissionPolicy` enum (ask | allow |
  reject, lowercase serde), `PermissionPolicySource` (agent | global_default |
  built_in), and `resolve_effective_permission_policy` (precedence: per-agent
  > global > built-in ask)
- Add `permission_policy: Option<PermissionPolicy>` to `ManagedAgentRecord`
  (per-agent override) and `GlobalAgentConfig` (fleet default)
- Inject resolved policy as `BUZZ_ACP_PERMISSION_POLICY` env var at spawn;
  add to `RESERVED_ENV_KEYS` so users cannot override via env-vars UI
- Include `permission_policy` in `SpawnSnapshot` / restart-diff so edits
  surface in the existing `needsRestart` flow
- Expose `permission_policy` + `permission_policy_source` on
  `ManagedAgentSummary` (resolved values)
- Extend `UpdateManagedAgentRequest` with double-Option `permission_policy`
  (None = unchanged, Some(None) = clear, Some(Some(v)) = set); reject edits
  to remotely deployed agents with a clear error message
- Add remote-deployed agent path in `agents_deploy.rs`: read per-record
  policy, fall back to desktop default, inject into `policy_env`

**TypeScript (desktop/src)**
- `PermissionPolicy = "ask" | "allow" | "reject"` and
  `PermissionPolicySource = "agent" | "global_default" | "built_in"` in
  `types.ts`; add to `ManagedAgent`, `CreateManagedAgentInput`, and
  `UpdateManagedAgentInput` (null = clear per-agent override)
- `tauri.ts`: add `permission_policy` / `permission_policy_source` to
  `RawManagedAgent` with safe defaults; map in `fromRawManagedAgent`
- `agentSessionTypes.ts`: add `authorization?: { requestNonce, actionable,
  reason? }` to `ObserverEvent`; extend `lifecycle` `TranscriptItem` with
  `requestNonce`, `actionable`, `authorizationReason`, `options`
- `agentSessionTranscript.ts`: add `pendingPermissionsByNonce` map; parse
  `authorization` envelope from `session/request_permission` events;
  handle `control_result/permission_decision` to retire cards on terminal
  outcomes, including the pinned uncertain message
- `agentControl.ts`: add `sendPermissionDecision(pubkey, nonce, optionId)`
  fire-and-forget control API
- `LifecycleActivity.tsx`: `PermissionDecisionButtons` component renders
  per-option buttons styled by kind (reject_* = destructive); local pending
  state with retry on error; rendered when `actionable && !outcome`
- `AgentInstanceEditDialog.tsx`: permission policy select (Inherit / Ask /
  Allow / Reject) for local agents; read-only for remote-deployed agents with
  a shutdown+redeploy hint; shows effective value and source

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
2026-08-06 16:34:20 -04:00
..