Repository navigation
fix(agent-pane): authenticate CEF question Return targets - #26813
teamleaderleo wants to merge 8 commits into
Conversation
Adds behavioral channel tests before the new host API. Base has no private channel API, so this intermediate commit is not an executable red receipt; hosted final verification will exercise the new boundary. Agent-Session: https://cmux.com/deeplink/agent?id=aid-66c88286003b549b3069
Bind a private DevTools function only to a named main-frame isolated context. A one-use nonce stays in that world and the native channel rejects main-world contexts, wrong secrets and replay. Trusted Return must target the focused pending question Other field; navigation, hide, page retirement and native target changes revoke the channel synchronously. The agent owner must separately match its native person-key witness and live pending identity. Agent-Session: https://cmux.com/deeplink/agent?id=aid-66c88286003b549b3069
An empty or incomplete Other answer keeps the question pending. Keep the isolated listener while that target stays live and authenticate strictly increasing per-key serials, each accepted once. The native owner still supplies the matching person-key witness; replaying an earlier empty Return grants nothing. Agent-Session: https://cmux.com/deeplink/agent?id=aid-66c88286003b549b3069
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
|
|
Found 4 test failures on Blacksmith runners: Failures
|
|
Bead |
Capture an immutable reply and original card/Other-field references in the isolated key handler. A channel-private issuer ticket redeems once after checking focus, labels, reply, text and attachment state in that same context. Focus leave, payload/identity mutation and detach/re-attach revoke the old proof while a later genuine key remains usable. Keep one pending snapshot and a native-approved target collection; unchanged membership is idempotent. The agent-pane owner still supplies authoritative pending state, canonical answer policy and the native person-key witness. Agent-Session: https://cmux.com/deeplink/agent?id=aid-66c88286003b549b3069
Register the private main-frame focus guard as a new-document isolated-world script before the agent page loads, without runImmediately. Its earliest window capture observes focus leave despite later page stopImmediatePropagation; a separate private liveness probe rejects document.open resets that keep the JS global but clear listeners. Binding, trusted key capture and redemption all require that early guard. Existing unarmed documents fail closed, with no late reinstall. Keep the accepted collection/snapshot API and native owner boundaries. Agent-Session: https://cmux.com/deeplink/agent?id=aid-66c88286003b549b3069
|
Orphaned: no activity for 15 h, and no lane holds a lease on it. Adopted by the orphan sweep: merged |
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Owned by an agent session · session |
|
Review (codex gpt-6-astra high, next-review): BLOCK at eb40a85
Both cases reproduced using the extracted script and the PR’s DOM test model. |
|
Review (codex gpt-6-astra high, next-review): SHIP at 31a700e No blocking findings. |
|
Backlog lander (drain-native-app) note: the Astra SHIP is at 31a700e (after the base merge), but this PR's own test fails on the fleet at that head. |
A newer verdict blocks 18ee299 (no independent SHIP at the head).
|
Review (next-review patch-id; carried): SHIP at 18ee299 The independent SHIP at 31a700e carries to this head: the PR's own change ( |
* test(agent-pane): reject forged CEF question key reports Adds behavioral channel tests before the new host API. Base has no private channel API, so this intermediate commit is not an executable red receipt; hosted final verification will exercise the new boundary. Agent-Session: https://cmux.com/deeplink/agent?id=aid-66c88286003b549b3069 * fix(agent-pane): isolate CEF question key target proofs Bind a private DevTools function only to a named main-frame isolated context. A one-use nonce stays in that world and the native channel rejects main-world contexts, wrong secrets and replay. Trusted Return must target the focused pending question Other field; navigation, hide, page retirement and native target changes revoke the channel synchronously. The agent owner must separately match its native person-key witness and live pending identity. Agent-Session: https://cmux.com/deeplink/agent?id=aid-66c88286003b549b3069 * fix(agent-pane): reserve a distinct proof for every question Return An empty or incomplete Other answer keeps the question pending. Keep the isolated listener while that target stays live and authenticate strictly increasing per-key serials, each accepted once. The native owner still supplies the matching person-key witness; replaying an earlier empty Return grants nothing. Agent-Session: https://cmux.com/deeplink/agent?id=aid-66c88286003b549b3069 * fix(agent-pane): bind CEF answer snapshots to original key targets Capture an immutable reply and original card/Other-field references in the isolated key handler. A channel-private issuer ticket redeems once after checking focus, labels, reply, text and attachment state in that same context. Focus leave, payload/identity mutation and detach/re-attach revoke the old proof while a later genuine key remains usable. Keep one pending snapshot and a native-approved target collection; unchanged membership is idempotent. The agent-pane owner still supplies authoritative pending state, canonical answer policy and the native person-key witness. Agent-Session: https://cmux.com/deeplink/agent?id=aid-66c88286003b549b3069 * fix(agent-pane): arm question focus guard before page scripts Register the private main-frame focus guard as a new-document isolated-world script before the agent page loads, without runImmediately. Its earliest window capture observes focus leave despite later page stopImmediatePropagation; a separate private liveness probe rejects document.open resets that keep the JS global but clear listeners. Binding, trusted key capture and redemption all require that early guard. Existing unarmed documents fail closed, with no late reinstall. Keep the accepted collection/snapshot API and native owner boundaries. Agent-Session: https://cmux.com/deeplink/agent?id=aid-66c88286003b549b3069 * fix(agent-pane): wire isolated question Return replies into transport Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(agent-pane): rebind question Return after visibility changes Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix: surface native question Return refusal and retry Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * test: expect the mapped invalid-intent refusal message Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(questions): preserve held Return proof and retry revoked bindings Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(questions): recognize Claude AskUserQuestion natively Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(questions): reject stale same-ID Return bindings Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(questions): recognize keypad Enter as Return Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(questions): refresh binding after Chromium context loss Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(questions): accept Claude native answer keys and reject lost Return Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(questions): revoke Return witness on ordinary grants Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * test(questions): cover captured Return admission and close races Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(questions): reject captured Return replies across transport closure Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix question key capture against page event races Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(acpmux): resolve string request ids Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325 * fix(tests): use PageWebView fixture roots Agent-Session: https://cmux.com/deeplink/agent?id=aid-9c822a1be5e4adcfa325
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
The CEF question-card keyboard repair needs a target-specific proof. The current page input callback carries only uptime and the page's main world can call it; a composer Return must never become an answer key for a pending question.
This is the CmuxNextPages transport prerequisite for the native ledger/person-key repair #26820. #26739 is visual-only and supplies no authorization contract. It uses the existing CEF DevTools/isolated-world primitives; it changes no browser shim, daemon protocol, AgentPane ledger, web attributes, or gesture policy. It does not claim that the unwired full question repair works today.
The native API is:
PageQuestionKeyTargetnames a native-approved session and permission. The collection contains every live pending question, so a visible oldest card need not be the first dictionary entry. Unchanged membership is idempotent; changing it revokes unused proofs. The original trusted key event's target/path chooses one approved card. Neither a page request nor a fresh later selector chooses the target.PageQuestionKeySnapshotexposes immutabletargetandreplyJSONonly, with no public initializer. Its private issuer/ticket binds it to this page, channel, generation and key serial.replyJSONis the exact{optionId, answers, annotations?}captured at key time; annotations absent and{}remain distinct. No session or permission override is allowed in it. Harness-specific canonical answers/annotations remain the native question owner's policy.The isolated closure keeps the nonce and original fieldset/Other textarea references private. Its binding exists only in the returned main-frame execution context. Native delivery checks that context, nonce, approved target and increasing per-key serial, retaining at most one unused snapshot. Redemption consumes the native ticket before awaiting and checks the same captured references, focus, labels, field text and raw reply in the same isolated context. The native owner then rechecks its pending decision nonce/person-instance and spends its matching fresh person-key witness. Generic input uptime and a later page callback grant nothing.
Integration DOM contract:
.acpmux-questioncarriesdata-cmux-question-session,data-cmux-question-idanddata-cmux-question-enter-reply..acpmux-question-other[data-row-editing="true"] textarea.The private focus guard is registered and awaited during agent-page setup with
Page.addScriptToEvaluateOnNewDocument(worldName:)beforepage.load, withoutrunImmediately. Its first window capture precedes page listeners, so an earlier-than-binding pagestopImmediatePropagationhandler cannot hide focus leave+return. Bind setup, key capture and redemption all require its private focus generation and liveness witness. The liveness probe uses a separate unguessable event type and closure-private acknowledgment; it never changes focus. Adocument.openreset that retains the private JS global but clears its early listeners fails closed, as does an already-loaded document with no early guard. Nothing late-installs that guard. Its constant-time listener belongs to the document/page; per-snapshot observers/listeners end with their ticket.Lifecycle: focus leave (including leave+return), input, label/reply mutation (including change+restore), detach/re-attach, target collection change, context replacement, navigation, hiding, retarget, crash and close revoke unused proof. Listeners and the observer are removed on revocation. A new genuine key may capture a fresh snapshot on the same pending card; empty/incomplete Enter never permanently disarms it. Binding may precede card mount. The observer watches only the bound ancestor chain and named attributes, without a subtree/row scan; record processing is bounded. No timer or polling loop is added. Async setup checks a generation after each suspension; late old setup/cleanup cannot replace a newer listener.
Validation at
d6b7cb618e3ddc02a96aa58fb7d1a7ec25fdfd61:a8cf0869912888dffb4b870dand focusedCmuxNextPagesTests0621102409c707f9946cc095. Both requests were accepted; native execution has no terminal verdict yet. Their supported waits retain the same IDs through controller read timeouts; no duplicate request follows a timeout.895cdee9ab6b46f396429c1a765339b4). It executes the exact extracted Swift JS templates, source SHA-25632cc87e6f52d185b5e43f8ecca28010ecba34190773dbb223bb2da7c9a63c543. Trusted Enter → hostile page capture-suppressed focus ABA rejects the old snapshot and accepts a fresh Enter. Payload, identity and detach ABA reject then recover; document.open listener reset rejects old tickets and mints no new proof; an unarmed existing document refuses binding, while a freshly secured document works. Main-world binding calls and ordinary composer Return produce no proof. This is Chromium/CDP script evidence, not a native CEF app launch or Swift compile.git diff --checkpasses. Review (Codex Astra, high) is SHIP atd6b7cb618e3ddc02a96aa58fb7d1a7ec25fdfd61. Primary independently inspected the final source and exact hosted result. Native compile/tests remain required and unverified. No local heavy checks ran.Agent session: agent session