Skip to content

fix(acpmux): bind cached remote receipts to local reservations - #34045

Merged
teamleaderleo merged 2 commits into
feat-cmux-nextfrom
lane/native-workflow-remote-cache-guard
Nov 3, 2026
Merged

teamleaderleo merged 2 commits into
feat-cmux-nextfrom
lane/native-workflow-remote-cache-guard

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

A remote durable dispatch response is cached only against the local reservation that requested it. cache_remote now requires the peer row to carry the requested briefId and durable:true, validates both the local and peer identities, and merges peer result fields onto the locally owned reservation. Host, caller, session, prompt, fingerprint, and other routing/security fields cannot be replaced by peer-controlled values.

Regression coverage rejects a mismatched peer key, rejects an advisory downgrade, preserves the local host/caller and dispatch-local boundary, preserves an existing victim row, and keeps a finished receipt terminal when a late pending response arrives. This fixes the blocking finding from review 5755116810 carried from the inherited cache path.

Validation: final fleet run 41677423510 passed formatting, the new cache_remote regression, terminal replay coverage, all three dispatch_durable integration tests, and strict acpmux lib clippy. The base compile blocker was repaired by #34053 (merged as e3bb5b2e357986d16086b1ef497401b12d72b94c).

Independent review: Opus 5.5 medium SHIP at c3cef983.

Review follow-ups: reject a null outcome as terminal, preserve cleanup eligibility for error-only terminal rows, and avoid rewriting an unchanged terminal ledger row.

Leo asked on 2026-11-02: "go do all those/help out where you can + examine how you can improve yourself and your available options and capabilities and speed".

Leo-ask: ask-6ef2624788

🤖 Generated with Codex

Agent session: agent session

Co-authored-by: Codex <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-b5794201d7e16745a0a4
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review c3cef98: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr34045 -f ref=lane/native-workflow-remote-cache-guard -f platform=macos -f backend_mode=local

Shipped in:

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 3, 2026
Co-authored-by: Codex <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-b5794201d7e16745a0a4
@cursor

cursor Bot commented Nov 3, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot 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.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (subagent claude-opus-5-5 medium): SHIP at c3cef98

Security read of cache_remote (cmux-tui/crates/acpmux/src/server/requests/workflow_dispatch.rs:178-222) against its merge base. This closes the #33811 finding: a peer reply can no longer write a different brief's ledger row.

What I checked:

  • Row selection: the local reservation must exist, be durable:true and have briefId == id (:186-194). The peer row must also carry briefId == id and durable:true (:195-201), and then pass check on fingerprint, sessionId and promptId (:202-203). put_durable keys on merged.briefId, and merged starts from the local reservation, so the key is always the requested id. The peer cannot choose the key.
  • Local fields: merged = previous, and only status, outcome, error, harness, model, dispatchCancelled come from the peer (:215-220). host, fromSession, the identity fields, durable and dispatchLocal are never taken from the peer, so the old remove("dispatchLocal") step is no longer needed. The test confirms that an attacker's host, fromSession and dispatchLocal are dropped.
  • Terminal results: once the local row has an outcome, it is returned unchanged (:209-214). A late or conflicting peer reply cannot replace it. The existing durable_dispatch_keeps_one_destination... test still holds: merging status and outcome into the pending reservation gives exactly finished.
  • Regression test: on base, the wrong_id row passes check (same fingerprint) and put_durable writes it under other-id, returning Ok. So both assert!(is_err()) and the victim-unchanged assert fail on base. The test fails without the fix.
  • Panics: none on peer input. Every access is get/as_str/as_bool. merged.set acts on a stored reservation object, not on peer data.
  • Behaviour change: a reply with no prior reservation now returns not_found instead of being cached. The only caller (server/requests.rs:423-455) always calls reserve_remote first, so this is fine.

CI: the failing jobs (acpmux lib tests, clippy, Windows cargo check, IR, SDK conformance) all fail at the cmux-tui compile step. That matches the base compile break that #34053 is fixing, not this diff. The new test still needs a green run once base compiles.

Follow-ups:

  • [follow-up] A peer can send "outcome": null (or an outcome with a non-final status). previous.get("outcome").is_some() then treats the receipt as terminal, which freezes the brief at a null result. Base behaves the same way and it only affects the brief's own receipt. Consider importing outcome only when it is non-null.
  • [follow-up] A terminal row that has error/status but no outcome can still be overwritten by a later non-terminal reply. Base behaves the same way.
  • [follow-up] The terminal early return calls put_durable(previous), which rewrites an unchanged ledger (an fsync). Returning previous directly would skip that.

This branch was previously deployed

3 inactive deployments
artifacts — c3cef983 Deployed Nov 3, 2026 by teamleaderleo via publish tree-addressed cmux-tui #106871
sentry-dsyms — c3cef983 Deployed Nov 3, 2026 by teamleaderleo via upload cmux-tui dSYMs to Sentry #106871
ci-routing-agent — c3cef983 Deployed Nov 3, 2026 by teamleaderleo via cmux-tui tree preflight #106871
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant