Files
glm-5.3-flash e196ed43e3 docs: remove em dashes from repo prose and forbid them going forward
- Rewrote em dash prose across the whole tree outside docs/reviews/
  (the historical reviews stay verbatim, matching the alktunnels and
  alktty precedent): src doc comments and inline comments (587),
  docs/architecture (319), docs/research + sdd_process (484), tests
  (361), tasks (899), fuzz (28), README/CHANGELOG/Cargo.toml (77),
  AGENTS.md (85), and the .opencode/agents prompts (109)
- Fenced content follows the precedent: comments, ASCII-diagram label
  separators, and template placeholders rewritten; wire data, JSON/BAST
  documents, byte diagrams, and transcripts survive verbatim; assert,
  expect, panic, error-display, and format message literals rewritten
  as prose; no code, fixture, or test data change
- src/rfc1928/LICENSE: the two dashes in alksocks' own provenance
  header rewritten; the MIT legal text untouched
- AGENTS.md adds Project Convention 18: no em dashes in prose; varied
  restructure, no spaced-hyphen substitutes, fenced prose rule, en
  dash numeric ranges exempt, docs/reviews/ exempt from the greps
- tasks/*.md frontmatter: the name values rewritten by the sweep are
  now quoted (a raw colon inside an unquoted YAML scalar parsed as
  null); taskgraph validate reports 37 tasks, no issues

Verification: cargo test; cargo clippy --all-targets -D warnings;
cargo fmt --check; cargo doc --no-deps; fuzz corpus replay
(cargo test --manifest-path fuzz/shared/Cargo.toml); wasm check and
clippy for wasm32-unknown-unknown with -D warnings; em dash grep over
the repo returns matches only in docs/reviews/ and the bast.md BAST
JSON data fence
2026-11-03 19:31:53 +00:00

3.4 KiB

ADR-001: ALPN, Open Op, and Trivial Params

Status

Accepted (2026-09-20, Phase 1)

Context

The crate rides alkcall channels: a produced SOCKS5 resource is an openable ALPN-op, opened by consumers via ChannelClient (alkcall ADR-037/043). The ALPN string is wire-stable once published (AGENTS.md conventions 5/16: decide via ADR before the first consumer). Phase 0's POCs (#1, #2, #5) all ran one ALPN (alk/socks5), one open op (channels/socks5/sub), with trivially empty params, the natural reading of "the RFC conversation is the data plane": the SOCKS5 target is unknown at open time (it arrives in-stream post-negotiation), so there is nothing for params to carry (poc-connect-wasm-findings.md §Wire/API notes).

Decision

  • ALPN: alk/socks5 (provisional → stable on first publish; the alk/ prefix per the alkcall ADR-004 ALPN-string convention; AGENTS.md convention 16's "ADR-004/ADR-006" shorthand cites the naming family, of which ADR-004 is the operative one). One ALPN per protocol.
  • One open op: channels/socks5/sub: the SOCKS5 session op, flavor-form like alktunnels' (…/sub; alkcall ADR-047: openable ALPNs are operations). All three RFC 1928 commands (CONNECT, BIND, UDP ASSOCIATE) ride this one op, selected in-stream at command dispatch (the command is an RFC-1928 wire fact, not a wire-format choice of ours).
  • Params: the trivial object {} (schema {type: object}, additionalProperties false). Nothing else is needed at open time (the establisher is a session gate, not a dial; the target is unknown). Extensibility: if a later need surfaces per-session options (e.g. a requested local bind hint), that is an additive params schema change while no params were ever required; consumers that send {} stay valid. Params are a self-contained JSON object identifying the produced resource (alkcall ADR-039's shape, following alktunnels ADR-001's template).
  • Reply: {"channel_id": <u32>}: the Sub-typed operation reply, as with alktunnels. No extra reply fields in v1 (the establishment phase is a session gate and has nothing to project; the alkcall 0.8.0 with_reply_field seam remains available additively if a future need appears).

Consequences

  • The wire surface is minimal and stable: one ALPN + one op + empty params + one reply field. The one-way-door surface is the ALPN string, the op id, and the (trivial) params shape, all frozen at first publish.
  • Command-level differentiation (CONNECT vs ASSOCIATE vs BIND) lives in the RFC 1928 stream and in the ACL scope check at command dispatch (see ADR-006), not in the op set. No per-command ops: that would re-encode the RFC's own command byte in our wire format for no benefit.
  • POC-validated: all three POCs served CONNECT/ASSOCIATE/BIND on the same registration (connect_still_served_on_the_same_ registration, POC #2; test 7, POC #5).

References

  • OQ-SK-01 (params context), OQ-SK-03 (the handle swap, why no correlation params), OQ-SK-08 (BIND rides the same op)
  • POC #1 poc-connect-wasm-findings.md (the trivial-params finding), POC #2 poc-udp-associate-findings.md (one-op regression guard), POC #5 poc-bind-findings.md (one-registration-three-commands)
  • Upstream: alkcall ADR-037 (channel open ops), ADR-039 (params is ALPN-specific), ADR-047 (flavor-form op ids)
  • Sibling template: alktunnels ADR-001/ADR-002