docs: N-3 decision — take_halves stays raw-framed on datagram sessions
Review 001 N-3 (tasks/tunnels/decide-take-framed-halves), decided before the first external consumer: - Option 1 (keep as-is, docs carry it), recorded as ADR-005 §Amendment. No external consumer exists (window open — the breaking reshape was available but undemonstrated); one take_halves semantic across substrates beats per-substrate divergence; pump_against composes the framed adapter (UdpHalf), not framed halves; and the take_framed_halves convenience is additive — it can land after the first consumer defines its shape. - consumer.md's datagram section states the posture; review 001 §N-3 resolution note landed; task marked completed. Docs-only (no code change). Verified: fmt --check, doc --no-deps warning-free, 63 default / 76 local tests green.
This commit is contained in:
1 parent
8cf4cc8bb5
commit
0bf4da3bb6
4 files changed
+105
-5
No files matched your search
@@ -84,7 +84,11 @@ one API, `-L` and `-R` alike.
|
||||
`Some(bytes)` per datagram — possibly empty (`len=0` is a legal
|
||||
empty datagram) — and `None` only on stream EOF (the channels-level
|
||||
sentinel; the codec never collides with it, F-2). A >65535-byte
|
||||
send is rejected at frame time (`Oversize`).
|
||||
send is rejected at frame time (`Oversize`). `take_halves()` on a
|
||||
datagram session yields the RAW halves — the wire bytes carry the
|
||||
codec framing (ADR-005's N-3 amendment: one `take_halves` semantic
|
||||
for every substrate; keep the session for codec-applied I/O, or
|
||||
compose the framed adapter at your own boundary).
|
||||
|
||||
## Lifecycle and Teardown (the point of ADR-005)
|
||||
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
|
||||
## Status
|
||||
|
||||
Accepted (2026-09-07; resolves the reverse POC W3 finding)
|
||||
Accepted (2026-09-07; resolves the reverse POC W3 finding).
|
||||
Amended (2026-09-08, review 001 N-3 decision): the datagram
|
||||
`take_halves` posture is pinned — raw framed halves stay the only
|
||||
owned-halves shape (`take_halves` keeps its semantics for every
|
||||
substrate), the datagram accessors remain the codec path, and a
|
||||
framed-halves convenience is deferred to the first consumer that
|
||||
reaches for it. See §Amendment (2026-09-08, N-3).
|
||||
|
||||
## Context
|
||||
|
||||
@@ -86,6 +92,58 @@ its teardown:
|
||||
|
||||
## Consequences
|
||||
|
||||
### Amendment (2026-09-08 — the N-3 datagram `take_halves` posture, decided before the first external consumer)
|
||||
|
||||
Review 001 N-3: a datagram session exposes codec-applied accessors
|
||||
(`send_datagram`/`recv_datagram`) until `take_halves` — then the
|
||||
caller owns RAW halves whose wire bytes carry the `[len: u16 BE]`
|
||||
framing. Documented, but a footgun asymmetry the API window
|
||||
(this ADR's surface becomes ABI-stable at the first external
|
||||
consumer) forced a decision on. Decided: **option 1 — keep as-is,
|
||||
carried by docs**, with the rationale:
|
||||
|
||||
- **No external consumer exists** (verified 2026-09-08 — no crate in
|
||||
the workspace depends on alktunnels); the window is open, so a
|
||||
breaking reshape was *available* — but nothing yet demonstrates a
|
||||
need for a different shape.
|
||||
- **The framing asymmetry is ADR-003's spec, not drift.** The
|
||||
datagram data plane is mandatory-framing by substrate
|
||||
discrimination; "raw halves of a datagram session carry the
|
||||
frames" is the same statement as "the codec lives at the substrate
|
||||
boundary." `take_halves` yielding raw halves keeps ONE semantic
|
||||
across substrates (the tunnel's wire bytes, uninterpreted); a
|
||||
per-substrate `take_halves` (option 3) diverges semantics by
|
||||
substrate — the worse confusion at the type level even as it
|
||||
removes the byte-level footgun.
|
||||
- **`pump_against` needs the framed adapter, not framed halves.** The
|
||||
adjacent seam (N-11, resolved in-review with the doc note): a UDP
|
||||
session pumped against an accepted local half requires the FRAMED
|
||||
adapter on the accepted side — the `local` feature's `UdpHalf` (or
|
||||
an assembly equivalent), not a raw socket. What composes there is
|
||||
the adapter AT the boundary, not a session-side wrapper pair; a
|
||||
`take_framed_halves` convenience would not feed this use.
|
||||
- **The convenience is additive and can land later.** Option 2's
|
||||
`take_framed_halves` breaks nothing when added after the first
|
||||
consumer (unlike a `take_halves` reshape), so its timing is
|
||||
decoupled from this window — deferring it costs nothing now, and
|
||||
the first real consumer's reach defines its shape (a
|
||||
`DatagramReader`-wrapped pair has an open design question: an
|
||||
`AsyncRead` face re-collides with the F-2 empty-datagram/EOF
|
||||
ambiguity the codec exists to prevent — the codec-side framing
|
||||
wants accessor-shaped surface, which the session already has).
|
||||
- **The docs carry the contract.** `take_halves`'s doc states the
|
||||
framing (landed with the implementation); consumer.md's datagram
|
||||
variant section now states the posture explicitly.
|
||||
|
||||
**Consequence:** datagram callers wanting codec-applied I/O after
|
||||
taking ownership should keep the session (drive `send_datagram`/
|
||||
`recv_datagram`; the session IS the owner) or compose `UdpHalf` at
|
||||
their own boundary — `take_halves` is the raw-wire escape hatch and
|
||||
stays documented as such. Revisit only on a demonstrated consumer
|
||||
need (file an OQ at that point).
|
||||
|
||||
### Consequences (original)
|
||||
|
||||
- **Assembly layers cannot leak adopted channels** by forgetting to
|
||||
reap — the type is the discipline (the W3 gap closes structurally).
|
||||
- **The reverse-flow initiator gets the same session shape** as the
|
||||
|
||||
@@ -447,6 +447,17 @@ convenience `take_framed_halves` that keeps the codec (a
|
||||
the review notes it for the API-stability window (ADR-005's surface
|
||||
becomes ABI-stable at first external consumer — decide before then).
|
||||
|
||||
**RESOLUTION (2026-09-08, decided before the first external
|
||||
consumer):** option 1 — keep as-is, docs carry it — recorded as
|
||||
ADR-005's §Amendment (2026-09-08, N-3). No external consumer exists
|
||||
(window open, so the breaking reshape was available but
|
||||
undemonstrated); one `take_halves` semantic across substrates beats
|
||||
per-substrate divergence; the `pump_against` seam composes the
|
||||
framed ADAPTER (UdpHalf), not framed halves; and the convenience
|
||||
(option 2) is additive — it can land after the first consumer
|
||||
defines its shape without breaking anything. consumer.md's datagram
|
||||
section states the posture.
|
||||
|
||||
## N-4 [minor] — `open_reverse_channel` builds the params JSON by hand instead of serializing `TunnelParams` — FIXED in-review
|
||||
|
||||
`src/consumer.rs:395-409`: the substrate is matched to its string and
|
||||
|
||||
Reference in new issue
Block a user