- ADR-014 accepted (review 002 C-2): the pre-command handshake, the
BIND quiet wait, and the association lifetime are all
teardown-governed; the protocol layer never times out (option 1)
- the BIND relationship recorded as same regime (ADR-007 decided one
phase's ends by designing BIND; ADR-014 records the inherited
resolution — one principle, not two)
- the doors' accept-path obligations recorded pre-batch-2 (accept-stage
idle bound, per-credential/per-peer caps, accept-queue bounds);
revisitable additively (an optional producer-side idle seam would
be config, not wire)
- spec lines carry the decided posture: wire.md (association-lifetime
bullet, no-in-band-control bullet, preamble, frontmatter);
producer.md (the open handler, the local-backend section, decision
table, frontmatter); overview.md ADR index
- one upstream-fidelity correction: upstream's dial timeout maps to
0x06 (TTL expired), not 0x01 as the review sketch suggested
- open-questions.md unchanged (C-2 was never tracked there)
Verification: cargo test green (357 passed), clippy -D warnings clean,
fmt clean, cargo doc clean, wasm check + clippy (wasm32) clean
- C-3: Socks5ProducerBuilder.bind_policy(bool) — the substrate-free
entry's explicit BIND gate, defaulting to the accept seam's
presence; seam presence is never the sole gate
- D-2: RegisterMode::ProducerBuilder + an integration test wiring the
full builder through .register(...) serving all three commands
- S-1: run_datagram_stage's doc names the hot-Ok(None) residual
- N-2: wire.md §UDP ASSOCIATE carries the inline-send backpressure line
Verified: cargo test (352 green), clippy/fmt/doc clean, wasm checks clean.
- frame(addr, payload): [len: u16 BE][addr + data] over
TargetAddr::to_be_bytes() + payload; the joint bound enforced at
frame time (checked_add; 65507 + 255-char domain = 65766 > 65535 →
Oversize) with addr_encoding_len exposed (7 v4 / 19 v6 / 259 max
domain) and MAX_INNER_LEN pinned
- DatagramReader: incremental reassembly across chunk boundaries
(split frames, batched frames, partial headers), infallible,
returning per-frame Results; the addr sub-layout decoded by hand
(ATYP-keyed, UTF-8-validated) with typed decode errors —
BadAtyp / ShortAddress / DomainNotUtf8 / EmptyFrame — so the
producer stage fails the association loud on protocol garbage
(udp_undecodable_frame_ends_association, POC #2)
- module docs state the framing-once invariant (the egress speaks
inner bytes; this layer owns the single length prefix — the
double-framing bug class POC #2 caught), the F-2 invariant at
payload level (a zero-length payload is a legal empty datagram,
never EOF; wire len == 0 is unreachable garbage), and the EOF
layering (the channels-level sentinel, outside the codec)
- doc-sync: wire.md + bast.md residue corrected — "len == 0 is a
legal empty datagram" replaced with the payload-level F-2
statement (len == 0 unreachable since addr >= 7 bytes)
- lib.rs re-exports frame, DatagramReader, addr_encoding_len,
MAX_INNER_LEN, WireError (convention 15)
Verification: cargo test (58 lib + 37 differential), clippy
--all-targets -- -D warnings, fmt --check, doc --no-deps, and both
wasm checks (check + clippy on wasm32-unknown-unknown) — all clean.