Skip to content

acpmux: the caller's side of the VM boundary (vmBoundary lease, saved peer, forwarding) - #26309

Merged
teamleaderleo merged 1 commit into
feat-cmux-nextfrom
hb-acpmux/vm-boundary-caller
Oct 27, 2026
Merged

teamleaderleo merged 1 commit into
feat-cmux-nextfrom
hb-acpmux/vm-boundary-caller

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

The caller's side of the VM boundary. A caller keeps its own opt-out for a peer's remote chains, and forwards it only for the person's own clients. No machine's behaviour changes yet: the guest ignores the field until #26276 (the guest's side) lands.

The design, as agreed with the area owner: "the kind comes from outside the guest. The client side (the app or the daemon that starts the remote session) asks the Cloud API which kind the VM is, for the signed-in account, and passes that to the remote start; the guest never decides." And: "Agents keep sudo in Cloud VMs".

PR 2a of the series. The order:

This was one PR. I split it to keep each part under about 800 lines.

What changes

  • Saved peer: vmBoundary: true on a saved peer in the caller's own config.json, for a VM its fleet registry calls a dedicated agent VM. peer_add never sets it, and a re-add of the same name and URL keeps it. A config reload applies the file's value to the running peer (same URL only) with no reconnect. A leased peer keeps its lease's value.

  • Cloud link lease: _acpmux/peer_lease {vmBoundary: true} (unix socket only). PR 3's link sends it only when the Cloud API said this caller owns the VM. It is held with the lease and never saved. Only the JSON value true counts.

  • Forwarding: each session/new the caller forwards to such a peer carries _meta.acpmux.vmBoundary: true, but only for the person's own clients (vm_boundary::owner):

    • the unix socket;
    • the app (LocalApp);
    • the caller's own peer daemon asking for itself (PeerToken and Control::Peer).

    It is never added for a Web client, the listener token, a paired machine (Device, ReadOnlyDevice) or a request held to the Web's rules. Any vmBoundary the client sent itself is dropped first.

  • via: device: a request this daemon forwards for a paired machine's client credential, which is served as a peer, now says via: device. The peer then never takes it for the owner's. An older peer ignores the mark, and its folder-trust gate treats it as before (no via).

Risk

Low. Nothing reads the field on the guest yet. The lease takes one more optional param, and the forwarded session/new carries one more _meta key that older daemons ignore (vmBoundary is not a mode field).

Tests

tests/peer_lease.rs a_vm_boundary_lease_forwards_the_boundary_for_the_persons_own_clients_only uses a fake peer that records each forwarded session/new:

  • With a vmBoundary lease, the unix socket's and the app's starts carry vmBoundary: true.
  • With a plain lease, they don't, even though each client sent vmBoundary: true itself.
  • A Web client's or a paired machine's start never carries it. If either is forwarded at all, it goes as via: web or via: device.

a_reload_takes_a_saved_peers_vm_boundary_back checks that a reload turns a saved peer's boundary off and on again with no reconnect. Unit tests cover forwards and owner.

Before and after

On base 370fc61, with only the new forwarding test:

test a_vm_boundary_lease_forwards_the_boundary_for_the_persons_own_clients_only ... FAILED
panicked at crates/acpmux/tests/peer_lease.rs:377:13:
  left: Some(Bool(true))
 right: None
test result: FAILED. 6 passed; 1 failed

On base, a plain lease forwards the client's own vmBoundary.

At this head (cmux-ci, Linux):

cargo fmt -p acpmux --check: ok
cargo clippy -p acpmux --all-targets -- -D warnings: ok (with the base's collapsible_if red in cli/codex_auth_broker.rs patched locally, not in this PR)
lib vm_boundary peer_lease peers catalog_reload remote_guard: 35 passed
--test peer_lease 8, web_token_exposure 6, peer_integration 50, remote_new_hints 8, peer_origin 4, pairing 7, local_app_origin 7: all passed

The full cargo test -p acpmux fails on the tip the same way it fails here: agent_tools, codex_auth_broker, daemon_chat_open, ephemeral_run, hermetic_daemon_guard and session_pool.

Agent session: agent session
🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Implements the caller's side of the VM boundary: a caller marks a peer as a VM it owns, and its daemon forwards _meta.acpmux.vmBoundary: true on session/new for that peer. The mark comes from a saved peer's vmBoundary in config.json (a reload applies the file's value with no reconnect) or from _acpmux/peer_lease {vmBoundary: true}, which is held with the lease and never saved.

  • The boundary is forwarded only for the person's own clients: the unix socket, the app, and the caller's own peer daemon. Web clients, paired machines, and listener-token connections never get it, and any vmBoundary a client sends itself is dropped first.
  • Requests forwarded for a paired machine's client credential now carry via: device so the peer never treats them as the owner's.
  • The guest ignores the field until the next PR lands, so no behavior changes yet.

Written for commit ce17613. Summary will update on new commits.

View guided diff Turn on auto-fix

… peer, forwarding)

A caller holds its own opt-out for a peer's remote chains: `vmBoundary` on a
saved peer (config.json, followed at a reload) or on `_acpmux/peer_lease` (held
with the lease, never saved). Each `session/new` it forwards there for the
person's own clients (unix socket, the app, its own peer daemon) carries
`_meta.acpmux.vmBoundary: true`; the field from any client is dropped first. A
request forwarded for a paired machine says `via: device`, so the peer never
takes it for the owner's.

The guest ignores the field until it takes the boundary (next PR): no
behaviour changes on any machine yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Oct 27, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-qku2wl created for this PR by the cmux coordinator.

@blacksmith-sh

blacksmith-sh Bot commented Oct 27, 2026

Copy link
Copy Markdown

Found 2 test failures on Blacksmith runners:

Failures

Test View Logs
nightly.yml must derive the embedded key and sign every appcast through the helper/
nightly.yml must derive the embedded key and sign every appcast through the helper
View Logs
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@teamleaderleo
teamleaderleo marked this pull request as ready for review October 27, 2026 19:20
@teamleaderleo
teamleaderleo merged commit f4946bb into feat-cmux-next Oct 27, 2026
213 of 224 checks passed
@teamleaderleo
teamleaderleo deleted the hb-acpmux/vm-boundary-caller branch October 27, 2026 19:20
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

This branch was previously deployed

3 inactive deployments
artifacts — ce176138 Deployed Oct 27, 2026 by teamleaderleo via add the Windows daemon to the tree #66256
sentry-dsyms — ce176138 Deployed Oct 27, 2026 by teamleaderleo via upload cmux-tui dSYMs to Sentry #66256
ci-routing-agent — ce176138 Deployed Oct 27, 2026 by teamleaderleo via wait for same-key tree publisher #66256
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant