docs(arch): add alknet-channels specs — ADRs 071-080, 7 spec docs, OQ-56/57

Phase 1 architecture for alknet-channels (multiplexing proxy on
alknet/channels). Grounded in the completed de-risk POC (28 tests) and the
landed ADR-070 (BidiStreamSource trait + Connection::from_source).

ADRs:
- 071: 9-byte chunk wire format (generalizes TTY's 5-byte)
- 072: channel 0 pre-negotiated as alknet/call (no special control plane)
- 073: channel lifecycle operations on the call protocol — channel/open,
  close, control, resources/subscribe; direction field pinned; subscribe
  from day one (not poll-for-v1 — StreamingHandler machinery exists)
- 074: ChannelBidiStreamSource implements BidiStreamSource (ADR-070);
  into_sub_streams() typed accessor for TTY; accept_bi() generic path
- 075: ChannelsAdapter + ChannelManager; REQ-CH-01..04 wire invariants
- 076: bounded-buffer backpressure (1 MiB), 256-channel cap, monotonic IDs
- 077: TTY inside channels uses sub-streams, not own wire format;
  amends ADR-052 scope to direct-connect TTY; channels feature on tty
- 078: two-pump shutdown-on-completion contract (handler-level)
- 079: hub relay translates channel 0, byte-forwards data channels
- 080: ChannelClient (QUIC-only); AlknetClient core extraction deferred (OQ-55)

Spec docs: overview, channels-wire, channels-connection, channels-adapter,
channel-operations, channel-client.

OQ-56 (full windowing) and OQ-57 (two-pump helper extraction) are genuine
deferred(scope) deferrals with concrete blocking conditions; the contracts
are decided, only the extensions are deferred.

Hedging audit converted three research hedges into decisions:
resources/subscribe (not poll), server-assigned IDs (not if-zero-RTT),
bounded-buffer (not if-HOL-becomes-a-problem).
This commit is contained in:
glm-5.2 committed 2026-07-12 12:57:18 +00:00
1 parent f997c81d2f
commit 2313c51f12
21 files changed
+3411

No files matched your search

@@ -0,0 +1,34 @@
# OQ-56: Full Channel-Level Flow-Control Windowing
- **Origin**: `docs/research/alknet-channels/phase-0-findings.md` §DP-5,
§OQ-CH-03; `docs/architecture/decisions/076-backpressure-channel-limits-id-reuse.md`
- **Status**: deferred(scope)
- **Door type**: two-way (additive — per-channel window tracking does not
change the wire format)
- **Priority**: low
- **Blocked on**: a real deployment observes head-of-line blocking on a
saturated channel where the bounded-buffer's stop-reading mitigation is
insufficient. The trigger is specific: a channel whose consumer is
persistently slower than its producer, causing the demux to stall that
channel's reads frequently enough that other channels' throughput is
measurably affected. The intended use cases (TTY, SSH, tunnels) are not
high-throughput in the HOL-blocking sense; the trigger requires a
high-throughput use case (e.g., file transfer over a tunnel) that
saturates a channel.
- **Resolution**: Not yet decidable. The bounded-buffer backpressure
(ADR-076, default 1 MiB per `(channel_id, stream_type)`) is the decided
v1 mechanism — validated by the POC's 1 MiB `tunnel_large_payload` test
with no deadlock and no cross-channel blocking. Full channel-level
windowing (SSH-style sliding-window per channel) is an additive extension
that does not change the wire format; it adds per-channel window tracking
to the demux/mux. The decision to add it depends on whether the
bounded-buffer mitigation is sufficient in practice, which can only be
determined by a deployment that hits the limitation.
- **What does NOT block on this**: the bounded-buffer mechanism is decided
and is the v1 implementation. Full windowing is an extension, not a
prerequisite. The channels crate ships with bounded-buffer backpressure;
full windowing is added if and only if the trigger condition is observed.
- **Cross-references**: ADR-076 (bounded-buffer decision), ADR-071 (wire
format — unchanged by windowing extension),
`docs/research/alknet-channels/poc-summary.md` §POC Target 1
(backpressure validation)
@@ -0,0 +1,32 @@
# OQ-57: Two-Pump Helper Extraction to alknet-core
- **Origin**: `docs/research/alknet-channels/poc-summary.md` §Issues
Surfaced #7; `docs/architecture/decisions/078-two-pump-shutdown-on-completion.md`
- **Status**: deferred(scope)
- **Door type**: two-way (additive — a helper function does not change any
API surface; handlers that inline the pattern continue to work)
- **Priority**: low
- **Blocked on**: a second two-pump handler existing, so the shape
convergence is observable. The tunnel handler is the first two-pump
consumer; the SSH `direct-tcpip` channel will be the second. Extracting
the helper from one consumer (the tunnel) would bake in a shape that the
second consumer (SSH) might not fit — the `fn pump_bidi<R, W>(recv: R,
send: W, ...) -> impl Future` signature is a cross-crate API surface if
it lives in `alknet-core`. The trigger is: two real two-pump handlers
exist and their inline implementations have converged on the same shape.
- **Resolution**: Not yet decidable. The shutdown-on-completion *contract*
is decided (ADR-078) — a two-pump handler MUST shut down the opposite
sink when one pump completes, or it deadlocks. The *helper* extraction is
an implementation convenience: ~10 lines of inline code per handler vs. a
shared function in `alknet-core`. The contract is pinned; only the
extraction is deferred. The helper is extracted when two real consumers
exist and their shapes converge, so the extraction is grounded in two
implementations rather than guessed from one.
- **What does NOT block on this**: the two-pump pattern is documented
(ADR-078) and the tunnel handler implements it inline. The SSH crate's
`direct-tcpip` handler will implement it inline too. Both work without a
shared helper. The friction is copy-paste with documentation (~10 lines),
not a missing capability.
- **Cross-references**: ADR-078 (the shutdown-on-completion contract),
ADR-074 (the `accept_bi` that yields the stream pair the pumps operate
on), `docs/research/alknet-channels/poc-summary.md` §Issues Surfaced #7