a73x

80c68b96

docs: side-channel passthrough, and what it measured

a73x   2026-08-16 07:44

Commit message
docs: side-channel passthrough, and what it measured

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

README.md
Old New
@@ -127,6 +127,14 @@ kills the daemon with them), though not a reboot.
127 `muxd run` refuses a socket another daemon already owns; there is no 127 `muxd run` refuses a socket another daemon already owns; there is no
128 socket-stealing. 128 socket-stealing.
129 129
130 Copy and paste work through the session: an application's OSC 52 write
131 reaches your terminal's clipboard (including from a remote box over QUIC,
132 where nothing else can), a paste arrives bracketed when the application
133 asked for bracketed paste, the window title follows the session, and a
134 bell rings. The clipboard READ direction (`OSC 52` query) is refused
135 deliberately — answering it would let anything in any session read
136 whatever you last copied.
137
130 ## How it works 138 ## How it works
131 139
132 Both ends run a real terminal engine. The daemon's is authoritative: shell 140 Both ends run a real terminal engine. The daemon's is authoritative: shell
docs/decisions.md
Old New
@@ -3620,3 +3620,43 @@ alone. The claim that native selection works is reasoned plus confirmed in
3620 the negative (the escapes are absent); nobody has dragged a mouse across a 3620 the negative (the escapes are absent); nobody has dragged a mouse across a
3621 real mux screen to check wide chars and trailing spaces, and that is named 3621 real mux screen to check wide chars and trailing spaces, and that is named
3622 as unverified in `063cec67` rather than assumed. 3622 as unverified in `063cec67` rather than assumed.
3623
3624 ## 2026-08-16 (side-channel passthrough close-out)
3625
3626 **Classification came before implementation.** Four symptoms reduce to two
3627 delivery mechanisms, which is why this landed as one coherent change rather
3628 than four special cases. Sampled state — bracketed-paste mode and title — is
3629 read after the engine feed, sent on change and on attach, then undone when
3630 the client detaches. Events — clipboard writes and bells — are intercepted
3631 at the engine boundary, drained by the daemon and replayed by the client.
3632 That split gives a new client the state it needs on attach without turning a
3633 bell into state or losing the occurrence of a clipboard write.
3634
3635 **Replay follows the grid's own resync verdict.** Every event is stamped
3636 with the grid sequence current when it was observed. A reconnect receiving a
3637 delta gets the last pending event of each kind whose watermark it can serve;
3638 a reconnect receiving a snapshot gets none. Pending storage is one slot per
3639 kind, so a reconnect can deliver the current clipboard write and one bell,
3640 not a stale history or an unbounded queue. An event whose watermark becomes
3641 unservable is dropped rather than waiting indefinitely.
3642
3643 **Clipboard is write-only by design.** OSC 52 set is forwarded only for the
3644 allowed clipboard target and bounded base64 payload; its query/read form is
3645 refused. Replying to that query would make any program in any session able
3646 to read the host's last copied text, which is a boundary mux must not cross.
3647
3648 **The measurements inverted.** The discovery capture counted zero OSC 52
3649 writes at the host; the e2e capture now counts one. The real-editor pin
3650 measured the nvim autoindent staircase changing from eight spaces to the
3651 four spaces the pasted block contains. The xterm title-stack probe was run
3652 in Alacritty and restored the original title, so mux pushes on terminal
3653 setup and pops on teardown rather than leaving the session title behind.
3654
3655 **The gates were made able to disagree.** Removing the clipboard
3656 interception makes precisely the new OSC 52 e2e fail. Neutering the
3657 bracketed-paste mirror makes the nvim scenario fail on the four-space
3658 assertion. Cross-version runs against the real v0.0.1-5 build passed on
3659 socket and QUIC; replacing the old client with the new one failed both legs,
3660 naming the clipboard, title and bracketed-paste frames it rendered. Bells
3661 coalesce to one replay per drain, so a binary full of BEL bytes cannot turn
3662 into one host-terminal write per byte.
docs/roadmap.md
Old New
@@ -404,6 +404,21 @@ that understood the name can produce.
404 the M18 block drives it by name and asserts it returns one session's 404 the M18 block drives it by name and asserts it returns one session's
405 grid and not its neighbour's. `--diff-since` is still owed. 405 grid and not its neighbour's. `--diff-since` is still owed.
406 406
407 ## Side-channel passthrough — complete
408
409 Shipped 2026-08-16. The three discovery issues are now accounted for:
410 `7c777ec6`'s OSC 52 **set** reaches the host clipboard (the query direction
411 is deliberately refused, with a 64 KiB cap); `ee062dd9`'s bracketed-paste
412 half is mirrored; and `063cec67` remains the deliberately separate
413 copy-mode problem. Window-title state and bells rode the same delivery
414 mechanisms.
415
416 What remains banked is intentionally narrower: mouse mirroring, whose
417 terminal-side reporting would take away native drag selection until
418 copy-mode exists; OSC 10/11 colour queries; and browser clipboard support.
419 The cross-version gate now also proves, over socket and QUIC, that a real
420 v0.0.1-5 client ignores the new daemon-to-client frames and keeps parsing.
421
407 ## M16 candidates — and still outranked by trial feedback 422 ## M16 candidates — and still outranked by trial feedback
408 423
409 What remains is what was ranked behind M13 and M14 and survived M15, 424 What remains is what was ranked behind M13 and M14 and survived M15,