Prune the channels spec to reflect the stream-unification resolution
(docs/research/stream-unification/findings.md): the channels wire format
goes from 9 bytes to 8 bytes, the channels layer no longer carries a
stream_type concept, into_sub_streams() is removed, and TTY always uses
its 5-byte format (carried transparently in the channels payload).
ADR-093 is the umbrella decision (the channels-layer consequence of
ADR-092's BiStream handler leaf): every channel is a BiStream, the
handler owns its sub-stream multiplexing, the channels layer routes by
channel_id only. Amends ADR-071 (8-byte header, no stream_type),
ADR-074 (into_sub_streams removed, accept_bi yields BiStream), reverses
ADR-077 (TTY always 5-byte), and the channels-facing clauses of
ADR-072/073/075/076/080/081. Adds ADR-092 forward-reference note
(into_sub_streams preservation subsequently reversed by ADR-093) and
the missing ADR-092 cross-reference on ADR-070.
Adds OQ-68 (add/strip API shape — built-in vs utility; the contract is
decided in ADR-093, the function surface is open; two-way door, low
priority, decision-ready when the channels crate's implementation
begins).
Rewrites the 7 channels spec docs (README, overview, channels-wire,
channels-connection, channels-adapter, channel-operations, channel-client)
to describe the post-amendment shape as current, with the 8-byte header,
the add/strip composition, single accept_bi accessor, BiStream per
channel, and TTY-always-5-byte.
Touch-up cross-references in hub README, client README, ADR-085, and
the OQ-45/47/65 question files (TTY-internal stream_type 3 →
STREAM_CTRL_IN; channels 9-byte → 8-byte).
The earlier draft kept from_stream as an 'escape hatch' for already-split
transports. That bakes the split into the constructor API — the same
split-leaf shape pushed one step earlier. The cleaner normalization: the
split never crosses a crate boundary as part of a constructor.
- Connection::from_bidi is the only public stream constructor.
- Connection::from_stream(send, recv, ...) is removed.
- The channels reassembly path joins MpscSendStream/MpscRecvStream itself
via tokio::io::join (one line) and calls from_bidi.
- The call crate's 5 test stub sites do tokio::io::split(x) then
from_stream — they become from_bidi(x) directly. The split was always
gratuitous at the call site.
- SendStream::from_stream / RecvStream::from_stream (per-half boxing for
into_sub_streams() and the SubStreamHandle leaves) are retained — not
constructors that feed Connection.
The crate-extraction findings Phase 6 deferred the alknet-http rework
on the grounds that the QuicStream wrapper (44 lines) is a necessary
adapter. The finding was right about the symptom, wrong about the
cause: the root is that the leaf type is split, so every consumer
re-joins or bypasses. Five abstractions exist for one concept
(BiStream trait vestigial in code, Connection, SendStream/RecvStream,
WsStream, MpscSendStream/MpscRecvStream).
ADR-092 resurrects ADR-007's BiStream as a concrete newtype leaf
(the bounds survive, the trait becomes a concrete struct for
Pin<&mut Self> projection), moves the join into core's quinn/iroh
BidiStreamSource impls once, and removes the per-handler wrappers:
- HttpAdapter::handle drops QuicStream (44 lines) and QuicStreamDuplex
(38 lines); serve_io is unchanged.
- WebSocket runs through Connection::from_bidi + the call-protocol
handler. WsBidiStream (~50-80 lines) implements AsyncRead/AsyncWrite
over axum WS binary messages. WsStream trait, drive_ws_session loop,
and ~150 lines of dispatch glue removed. ADR-044/048's 'WS message
stream is BiStream-satisfying' becomes literal.
- Tunnel/SSH handlers call tokio::io::split(bidi) for their two pumps
(same stdlib idiom as TcpStream/TlsStream). ADR-078 preserved.
- SendStream/RecvStream collapse to thin newtypes (quinn enum dispatch
gone); retained for ADR-074 into_sub_streams() and channels
reassembly (ADR-071 unidirectional sub-streams).
- 'VPN-like without being a VPN' over WS in v1 becomes real: the
webtransport.md path, over WS, now. WASM SSH parser implements
BiStream over a WS-message adapter on the browser side.
- WebTransport h3 extraction recorded as a future channels-variant
move enabled by the unification (out of scope per ADR-044).
Amends ADR-065 (from_bidi primary, from_stream escape hatch),
ADR-070 (accept_bi returns BiStream), ADR-074
(ChannelBidiStreamSource::accept_bi returns BiStream; into_sub_streams
unchanged). ADR-077 two-mode TTY design preserved. Resolves the
findings.md Phase 6 deferral.
Three open questions recorded with defaults (WsBidiStream home,
SendStream/RecvStream long-term home, from_stream vs from_bidi
primacy) — none blocking.