You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit cb3e3e6
Browse filesBrowse the repository at this point in the historyBrowse files
feat(permission): add harness-owned worker grant envelope (#1222)
* feat(permission): add harness-owned worker grant envelope
A worker deny-on-ask registers a denied-call envelope keyed by worker
session with single-parent-turn expiry. The deny reason names only the
envelope requestId and the parent retries via resume_agent with exact
args.
* fix(permission): bind ask to its denial, expire open, consume once
Ask names its denial via grant_request_id; unnamed keeps
first-pending. Expiry yields a fresh gate round that mints a fresh
envelope. Precheck-to-consume serializes per fingerprint.
* fix(subagent): thread grant_request_id through ask_director leaf
* test(subagent): follow test-helper move to repo-root testkit
origin/main relocated shared test helpers from tests/helpers to
testkit; the grant threading test follows the mock-module import.
* test(permission): cover envelope reuse across reactor retries
Two denies of the same exact call under fresh call ids name the same
grant request instead of prompting the parent twice.
* fix(permission): spend worker grant at execution, session-scope precheck
Authorize leaves the envelope pending so the granted retry survives the
execution backstop, which now spends it exactly once; precheck no longer
vetoes sibling sessions, and unwired helpers are removed.
* test(permission): keep two-stage execute and per-session envelopes
Copy file name to clipboardExpand all lines: docs/ARCHITECTURE.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -101,6 +101,10 @@ OAuth stores serialize refresh writes and treat the value observed under the sto
101
101
102
102
The interactive TUI may offer an explicit alternate-provider/model selector only after the same-profile retry also ends in a terminal credential failure. That choice is generation-scoped and consumed once. It may continue the original operator message only when the failed attempt emitted no committing inference event; after any commitment it switches the live provider without replaying the message. `/connect` replaces or adds credentials and `/model` switches the live source explicitly. Exec and fleet workers use the same one-shot same-profile recovery but never open an auth or alternate-provider prompt; an exhausted failure terminates that attempt with a sanitized recovery diagnostic.
103
103
104
+
### Worker permission grants
105
+
106
+
A worker deny-on-ask registers a harness-owned denied-call envelope (`src/permission/worker-grant.ts`): the exact denied ToolCall plus a stable path-aware fingerprint, keyed by worker session with a ten-minute wall-clock TTL. The `turnId` on the envelope is metadata only — no turn enforcement exists, so expiry is purely `expiresAt`-driven. The deny reason names only the envelope's requestId; the worker's `ask_director` prose carries no authority and plain `send_input` text can never mint, consume, or extend an envelope. The worker quotes that requestId back as `grant_request_id`, binding the ask to its own denial at register time; an unnamed ask keeps the legacy first-pending bind. The parent observes the envelope on the ask record via the session-store subscription, replays the exact call through its own gate operator path, and retries the retained worker via the existing `resume_agent` with exact args plus the questionId ref. The first covering-grant retry consumes the envelope; replays, tampered args/cwd/tool/session, decline, or interrupt fail closed with a truthful blocker. Expiry deliberately does not fail closed: the lapsed envelope is marked, skipped, and the retry falls through to a fresh gate round that denies fresh with a new grant id, so a lapsed window can never strand the worker. Expiry is lazy — every pendency read sweeps overdue envelopes, and no periodic scheduler exists by decision, not omission. Concurrent identical retries serialize on a per-fingerprint mutex across the precheck-to-consume gap, so one envelope allows exactly once. There is no dedicated grant verb — single-use and exactness are enforced by the envelope sidecar, not by tool plumbing. Phase 2 (by design, not here): a broad parent session grant can cover more than the exact denied subject; binding the grant to the envelope args needs the atomic grant-and-retry verb.
107
+
104
108
### TUI Runner (`src/tui/runner/`)
105
109
106
110
- Builds a chat-mode agent using the `ChatDirector`
0 commit comments