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

78 lines
3.7 KiB
Markdown

# ADR-008: Egress/Accept Provider Defaults: Local Socket and Composed (Direct Op)
## Status
Accepted (2026-09-20, Phase 1; the A/B assembly-layer choice
(OQ-SK-01's residue), with the composed vehicle settled by
alktunnels 0.2.0 ADR-007)
## Context
OQ-SK-01's dialer-trait-vs-callback half is closed (ADR-004); what
remained was the **default provider set**: where does the dial
callback come from in the base crate's optional shapes? Option A
(dial via alktunnels, the composed shape), Option B (dial directly,
local TCP), Option C (injected dialer trait, rejected, ADR-004).
alktunnels 0.2.0 removed Option A's blocker (the direct op
`channels/tunnel/direct` is the dynamic-target channel: one open
per CONNECT target, what it was graduated for), and POC #2 measured
its per-destination open cost (~0.8 ms, loopback), fine for DNS +
browsing.
## Decision
- **The base crate ships both provider kinds, both feature-gated:**
- **Local-socket providers** (behind the `local` feature): a real
`TcpStream` dial (CONNECT), a real `UdpSocket` egress
(ASSOCIATE, one socket per association, per-datagram
`send_to`/`recv_from`; no flow table; domain destinations
resolve at the egress, the ssh `-D` semantic), a real
`TcpListener` accept (BIND, ADR-007 variant 1). These are the
faithful-RFC shapes and the simplest assembly story.
- **Composed providers** (behind the composition feature): the
dial callback opens an alktunnels direct-op channel naming the
target (`open_direct`, `Substrate::Tcp`/`Substrate::Udp`); the
UDP table is a lazy destination→tunnel table (open on first
datagram, LRU-evict at a cap, POC #2's `ComposedEgress` shape).
Hub relaying is per-target terminate-and-re-produce
(alkcall ADR-051).
- **Neither provider is a dependency of the protocol layer**;
both are assembly-layer wiring (ADR-004); the features exist so
the providers ship *in the crate* rather than forcing every
deployment to hand-roll them. The feature gates and module
placement are in [overview.md](../overview.md) §Feature gates.
- **No default in the abstract**: registration always takes the
callbacks explicitly; there is no implicit "default dialer."
The feature-gated providers are convenience constructors over
the same seams. A missing callback means that command refuses
RFC-faithfully (`CommandNotSupported`-class reply), never a
panic: the command gate is the open handler's dispatch, and a
provider-less command is an unprovided capability, not an error
condition.
- **Per-target ACL is the composed variant's benefit** (each
destination rides its own `tunnel:direct`-governed channel,
ADR-006); the local variant's target policy is the dial
callback itself.
## Consequences
- The "no ports" story has two halves, both covered: the
consumer-facing half (the handle swap, ADR-003) and the
producing-side half (local egress behind `local`; composed egress
behind the composition feature; the protocol layer sees neither).
- The 256-channel default cap bounds composed fan-out; the
documented proxy-workload recommendation (ADR-010) covers the
deployment guidance.
- The composed egress's open cost is measured and acceptable for
the target workloads (DNS + browsing); a high-fanout deployment
that dislikes per-destination opens uses the local variant or
raises the cap (config, not wire).
## References
- OQ-SK-01 (the A/B choice), OQ-SK-03 variant 2 (the composed
egress), OQ-SK-05 (per-target ACL), OQ-SK-09 (the cap)
- POC #2 `poc-udp-associate-findings.md` (both variants; the open
cost), POC #5 `poc-bind-findings.md` (the composed accept)
- alktunnels ADR-007 (the direct op), alkcall ADR-051 (the hub
relay), ADR-004 (the seams), ADR-006 (the ACL posture)