Files
glm-5.3-flash f4b5f896b4 docs: sweep em dashes from all markdown prose
Renames the written-usage rule into practice across the contract surface:
docs/ (architecture, research, plans, sdd), tasks/ (all 43 task files,
taskgraph validate passes), AGENTS.md, README.md, CHANGELOG.md, and the
.opencode/agents/ prompts. Every replacement is a sense-preserving
rewrite (colons, semicolons, commas, parentheses, sentence splits, varied),
never a mechanical swap; no spaced hyphens were substituted. Enum fields,
frontmatter, tables, wire data, and cited identifiers survive verbatim;
en dashes inside numeric ranges keep their meaning.

Verification: taskgraph validate (43 tasks), repo grep clean (single
exempt hit: the verification command's own search pattern in AGENTS.md),
cargo test, clippy --all-targets -D warnings, fmt --check, doc all green.
2026-11-04 20:28:00 +00:00

5.4 KiB

status, last_updated
status last_updated
reviewed 2026-10-28

ADR-001: The alk/ssh ALPN pin (edge-termination contract for SshAdapter)

Status

Accepted (2026-10-26). One-way door (ledger rule 1: ALPN registry entries are stable; "once published, does not change"). The first consumer is alkforge (family ADR-003 decision 4: the pin lands before alkforge becomes the consumer).

Context

Family ADR-003 (decision 4) requires alkssh to pin exactly one alk/ssh ALPN via its own ADR. Four alkcall ADRs constrain what that pin means:

  • ADR-004 (ALPN convention + connection model) reserves alk/ssh → SshAdapter as a custom protocol.
  • ADR-034 (channels wire format) grants alk/ssh stream_types [0, 1] ("SSH multiplexes internally, including its own control"). The channels layer is byte-blind to SSH; it must never parse SSH channel data.
  • ADR-042 / ADR-051 (hub relay): "The hub never runs a handler for alk/tty, alk/ssh, or alk/tunnel"; SSH channels are relayed payload-blind between spokes (translate + byte-forward with id rewrite, ACL fired at channel/open by the hub's CallAdapter).
  • ADR-009 (BiStream handler leaf) sketches the browser route: a browser opens a WebSocket/WebTransport session to /alk/ssh; the h3/WS handler hands each bidi stream to SshAdapter::handle as a Connection; a WASM SSH parser speaks vanilla SSH over the stream.

Phase 0 left the topology open (mapping-table.md §topology; vision scope question 1): whether alk/ssh carries raw vanilla-SSH bytes between alkssh instances (a relay leg), serves the browser route, or both, and how that coexists with ADR-042's relay ruling. POC-3 settled what could be settled by evidence: the served topology is edge termination (russh terminates vanilla SSH at the alkssh endpoint; family seams are consumed in-process or via alk/channels bridge legs), worked end to end with vanilla clients through published sibling crates, and no leg of it requires the hub to parse SSH.

The decision that remains is the pin: what contract alk/ssh commits to on the ledger, so the ALPN string cannot be reinterpreted later.

Decision

  1. The pin. alk/ssh is pinned for exactly one contract: a connection opened under alk/ssh carries a raw vanilla-SSH byte stream, unchanged and uninterpreted, and the receiving endpoint is SshAdapter::handle(Connection), alkssh's russh server stack mounted at an alkcall channel/open boundary. Each bidi stream is one independent SSH transport with its own KEX, auth, and channel multiplexing (hence ADR-034's [0, 1]: SSH owns its own multiplexing, and the channels layer stays byte-blind, per ADR-042's relay ruling).
  2. Payload-blind relay is part of the contract. Any intermediate (the hub in ADR-042's topology, or a spoke forwarding to a spoke) relays alk/ssh streams as opaque bytes; it runs ACL at channel/open and never an SSH handler. This is ADR-042's ruling, restated as the ALPN's own contract so it cannot drift.
  3. Phase 1 serves edge termination only. The first deployment shape (russh terminating vanilla SSH at the alkssh edge, family seams consumed in-process) does not speak alk/ssh itself: it is a door, not a relay party. No pin behavior in this ADR requires the relay leg to exist.
  4. The relay leg and the browser-WASM route remain compatible by construction. Because the contract is a transport-blind raw byte stream, either future leg (hub-relayed SSH, browser WS → SshAdapter::handle) satisfies it without a pin change. Their consumers are a use-case question for assemblies/family work, not alkssh decisions (OQ-01 resolved: this ADR is the entire decision surface; nothing in the crate is gated on a consumer).
  5. What the pin is not. It is not a carrier for alkcall's framed channels traffic (that has its own protocol); it is not a second SSH-flavored control channel; and honesty cuts both ways: an endpoint that declines to serve alk/ssh must refuse the open, never accept-and-stall (the same honest-advertisement rule that runs through every alkssh decision).

Consequences

  • Positive: the ALPN decouples the endpoint-adjacency contract (frozen here) from the served edge topology (which evolves with the family seams); the browser and relay routes are pre-enabled at zero pin cost; the ledger gets a single unambiguous entry.
  • Negative: the pin is a one-way door; the raw-vanilla-SSH-stream contract binds every future consumer (alkforge first). If a consumer ever needed framed or pre-parsed SSH over alk/ssh, that would be a new ALPN + new ADR, not a reinterpretation.
  • Neutral: SshAdapter::handle mounts the full russh server stack per stream, so endpoints pay per-connection bounded-resource limits (window, auth-attempt, inactivity ceilings); the alkssh limits contract applies per alk/ssh stream, not per transport.

References

  • Family ADR-003 (003-alkssh-russh-adapter.md), decisions 1 and 4
  • alkcall ADR-002 (ProtocolHandler ALPN claim), ADR-004 (the alk/ssh → SshAdapter reservation), ADR-009 (browser-WASM sketch), ADR-034 (alk/ssh stream_types [0, 1]), ADR-042/051 (relay: payload-blind, hub handler-free)
  • docs/research/mapping-table.md §topology, docs/research/vision.md scope Q1, docs/research/poc-3-mapping-bakeoff.md (edge termination, proven)
  • OQ-01 (resolved: no consumer in scope; this ADR is the entire decision surface)