agent-pane-policy: status and peer_reconnect replies keep what the Swift host keeps; a shape that does not parse fails closed
For _acpmux/status, the Swift agent pane host keeps each peer's transport, connected, state, lastSeen and attempts, plus the cached health warning inputs. transport is only the scheme of the peer's url: ssh, ws or wss. For _acpmux/peer_reconnect, it keeps transport, connected, state, lastSeen, attempts and error (AcpmuxPaneMethods+ReplyShapes.swift; b0fa7941918, 62e81abb3dd, de58118cc95, 9328d559498). The crate keeps only name for status, and name, state, error for reconnect. It has no bool or scheme shape. A host that runs the crate would therefore lose the environment picker's SSH/Cloud split, the connected marks and the load warnings.
What changes in the crate:
ReplyShape::Booltakes only a JSONtrueorfalse.ReplyShape::Schemetakes onlyssh,wsorwssfrom the siblingurl, read as Swift'sURLComponents(string:)reads it: RFC 3986 characters only, a valid scheme, lower-cased.policy.jsonhas the Swift host's two shapes.- Fail closed: a shape that
policy.jsonnames but the crate cannot read now filters to an empty result. Before, the method lost its shape. A host that relays unshaped replies as they are would then send the whole reply, with URLs and tokens, to the page. - A filtered error's
codeis read as Swift'sas? Intreads it (2.0is 2,trueis 1), not as -32603.
This is one of the Swift-only drifts that must reach the crate before the app calls it (rm-pane-policy, layer-ownership V-23). The app does not call the crate yet, and cmux-app-ffi does not link it, so nothing changes in the app and this PR is no FFI input.
Security
Each kept field is the running Swift host's, field for field. The URL never reaches the page; only its scheme does, from a fixed list of three. The loader change removes a fail-open path. No method or param is newly allowed.
Changelog
none
Observed / Not run
Observed (fleet, Linux, scripts/ci/cmux-tui-rust-check.sh test <filter>):
- red 2bcf78773411 (the cases, no fix),
replies: job eef38cd55e85ba3b00869b56, FAILparity replies. - green 515bf828a7d5:
replies50825d2ec0660ce0fa742b63 PASS (48 run, 48 passed);every_reply_shape_parses0d5421e80bc551a21465f113 PASS.
tests/cases/replies.json holds 21 cases. Every expected reply, the 7 old ones included, comes from a line-for-line Python copy of the Swift filter. Two old expectations changed, because the old ones were the drifted Rust shape. The new cases port AgentPaneStatusReplyShapeTests.
Not run: clippy (the workspace clippy was red on base, #31462); no Swift compile (no Swift change). reported_scheme checks the url's RFC 3986 components (userinfo without @, a reg-name or [IPv6] host, a port of digits, path, query and one fragment of their own characters). Where it is stricter than Foundation, a peer only loses its transport; the result is always ssh, ws, wss or nothing, and the url never reaches the page.
Review round 1 (FIX at 515bf828a7d5: five urls URLComponents refuses still reported a scheme): red e3fed9857dd4 job 3c93ecc6c63596478aa4bea6; green baa073d47bc0 replies 3d9312a4e774856d5239ca62, whole crate f893a31f6a56d3c9ecd8b5ee.