acpmux: a peer's pending prompts reach this daemon's watchers

Merged
TE
19d ago
+365-31

A prompt raised on a peered daemon now shows up for apps watching this daemon. When a peer sends _acpmux/permission_pending, this daemon relays it (via: "peer") to its unix-socket and app watchers that didn't attach the session. The relay carries the peer's decisionNonce and personInstance, so the app that holds the peer's key can answer. The answer still goes to the peer, and the peer counts an allow only with its own person's proof.

The relay only happens when all of these hold:

  • the session is one that peer listed as its own, and isn't one of this daemon's sessions;
  • the prompt carries the daemon run the peer named at its handshake;
  • that run isn't this daemon's run, and no other peer named it.

A relayed prompt never goes to a Web client or on to another peer daemon. The decision proof covers the prompt's ids, not its text, and a peer could claim a third daemon's run. The threat model in hub/person.rs (c) covers both.

This is slice 1 of #20653's split. It's the peer-prompt part only; start modes come in a later slice. Two changes from #20653's version:

  • peer_pending_counts finds the peer's session by its receipt's mux_session_id. Since #21397, remote_sessions on feat-cmux-next is keyed by qualified id.
  • The permission_pending and event_value builders now live in server/pending.rs.

Verification

  • cargo test -p acpmux --test peer_integration: 16 passed. That includes the 5 new tests: the end-to-end relay with proof-only allow, and four lying-peer cases (a local session, this daemon's run, an unknown session, the legitimate relay).
  • cargo clippy -p acpmux --all-targets --locked -- -D warnings: clean.
  • cargo test -p acpmux --lib: 133 passed and 1 failed. The failure is protocol::tests::protocol_ir_is_current, from IR description drift left by #21397. It's identical on feat-cmux-next and doesn't come from this change.
  • All of the above ran on Linux; macOS lanes run in CI.

Freeze WINDOW areas: CORE (cmux-tui/crates/acpmux and the acpmux protocol). No Cargo file changed, so not LOCK. The Air Blue coordinator merges this PR.

Changelog

Added: acpmux relays a peered daemon's pending permission prompts to this daemon's app watchers.

🤖 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

Relays a peer daemon's pending permission prompts to this daemon's unix-socket and app watchers.

A peer's _acpmux/permission_pending now reaches watchers that didn't attach the session, marked via: "peer" and carrying the peer's decision nonce and person instance, so the app holding the peer's key can show and answer it. The answer still goes to the peer, which counts an allow only with its own person's proof. Relaying happens only for a session the peer listed as its own and that is not this daemon's, in the run the peer named at its handshake, which is neither this daemon's run nor one another peer named, and never goes to a Web client or on to another peer daemon. Since a peer can still claim a third daemon's run, the app must refuse to prove a via: "peer" prompt whose person instance is a daemon it enrolled directly.

Two changes from #20653's split: peer_pending_counts finds the peer's session by its receipt's mux_session_id (#21397 re-keyed remote_sessions), and the permission_pending and event_value builders moved to server/pending.rs.