mirror of
https://github.com/block/buzz.git
synced 2026-11-13 21:01:53 +00:00
fix(acp): extend description extraction to codex v1.1.7; protect prose gate with integrated render test
B1 (F2 — codex v1.1.7 command/file-change approvals):
- Add two extraction paths to `description_from_request_permission`:
4. `params.toolCall.rawInput.command` — codex v1.1.7 command execution
(no title; command string in rawInput). Wire shape cited from tag v1.1.7.
5. `params._meta.codex.params.reason` — codex v1.1.7 file-change
(no title or rawInput; reason in codex metadata). Wire shape cited.
- Two new Rust tests use verbatim v1.1.7 wire shapes from
`buildCommandPermissionRequest` / `buildFileChangePermissionRequest`
in `codex-acp tag v1.1.7 CodexApprovalHandler.ts`. Both go red if the
extraction pointers are changed back.
- Three new PermissionRequestCardBlock component tests (Carl's F2 bar):
hostile markup renders as inert text (no <script>/<b> created),
control characters render safely, description accessible to AT
(not aria-hidden).
B2 (F3 — MessageRow call-site mutation protection):
- Replace `hasPermissionRequestCard` with `selectPermissionRequest` in
`permissionRequestAuthPubkey.ts`: computes the full card payload ONCE,
folding in channelId + isAgent + signer trust + computePermissionRequest.
Returns `PermissionRequestSelection | null` so prose suppression and the
card block share a single result — prose suppressed iff card renders,
by construction.
- MessageRow now calls `selectPermissionRequest(message, isKnownAgentPubkey,
channelId)` once (line 382), uses `permReq !== null` as the prose gate
(line 431), and passes `permReq` to `PermissionRequestCardBlock`.
- Add `MessageRowProseGate.test.mjs`: renders the REAL MessageRow with
a forged-signer sentinel (signerPubkey ≠ registered agent). Asserts
the sentinel body nonce appears in DOM prose. Goes red when line 431
is mutated from `permReq !== null` to `isPermissionRequestSentinel(body)`
(Thufir's exact mutation). Stubs `useAppNavigation` (used by markdown.tsx
and SentFromThreadLine via router hooks) and `MessageActionBar` so the
test runs in JSDOM without a live RouterProvider.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
@@ -354,9 +354,11 @@ additional round trip.
|
||||
The event content is a compact JSON object that matches the D6 frozen schema
|
||||
(`requestNonce`, `optionIds`, `labels`, `expiresAt`, `description`, …). `description`
|
||||
is sourced from `params.title` (buzz-agent v2), `params.subject.toolCall.title`
|
||||
(v2 fallback), or `params.toolCall.title` (buzz-agent v1 / codex-acp) of the
|
||||
(v2 fallback), `params.toolCall.title` (buzz-agent v1 / codex-acp permissions-request),
|
||||
`params.toolCall.rawInput.command` (codex-acp v1.1.7 command requests), or
|
||||
`params._meta.codex.params.reason` (codex-acp v1.1.7 file-change requests) of the
|
||||
`session/request_permission` message — the first non-empty value wins. It is
|
||||
`null` when no adapter-provided title is found. `optionIds` is a
|
||||
`null` when no adapter-provided description is found. `optionIds` is a
|
||||
**two-action contract**: exactly one `allow_once` and one `reject_once`, in that
|
||||
order — the harness selects them via `select_card_actions` and fails closed if
|
||||
either is absent or ambiguous, so no other option (e.g. `allow_always`) can ever
|
||||
@@ -426,9 +428,11 @@ an unrenderable card. Labels and `description` are lossy display strings and are
|
||||
only fields truncated rather than rejected; truncation lands on a UTF-8 char boundary
|
||||
so the result is always valid UTF-8 within the byte limit the Desktop parser accepts.
|
||||
Label values in the sentinel come directly from the ACP options' `name` fields;
|
||||
render them verbatim. `description` is sourced from the adapter's title field —
|
||||
render them verbatim. `description` is sourced from the adapter's operation field —
|
||||
`params.title` (buzz-agent v2), `params.subject.toolCall.title` (v2 fallback),
|
||||
or `params.toolCall.title` (v1 / codex-acp) — and describes the operation being
|
||||
`params.toolCall.title` (v1 / codex-acp permissions-request),
|
||||
`params.toolCall.rawInput.command` (codex-acp v1.1.7 command), or
|
||||
`params._meta.codex.params.reason` (codex-acp v1.1.7 file-change) — and describes the operation being
|
||||
authorized.
|
||||
|
||||
### Sentinel authenticity
|
||||
|
||||
Reference in New Issue
Block a user