- C-1: BindSession::await_inbound is take-guarded — the first read
takes the session's stream; the returned BindDataPlane owns it (the
TakenInner pairing posture; the session stays the teardown owner),
so a second call returns the family's spent shape Ok(None) and can
never re-read the live data plane. A failed read restores the inner
(the phase is only consumed on success; the producer ends the
session on every post-reply#1 failure exit, so a re-call EOFs —
never a live data-plane re-read either way). Pinned by the
double-await_inbound integration test (the spent shape + the
data-plane bytes asserted untouched) and the spent-BIND unit test.
- D-1: one normative reply#2 reader (option a) — the session's
await_inbound; BindReply1::await_inbound is cut and reply1() is
documented as a view (bind_addr + raw_mut), matching its actual
usage; the reply1()-twice re-entry path is closed (pinned by the
view test).
- N-6: the three session constructors' prologues collapsed into one
private open_and_negotiate helper (teardown-at-birth in one place);
zero behavior change.
- S-2: the EOF-propagation doc line on all three reap sites (the
dropped teardown_channel handle is deliberate — the graceful shape;
clear_all aborts instead).
- BindDataPlane is un-lifetimed (owns the stream); into_inner returns
the owned Socks5Stream<BiStream>; docs synced (module + session
docs, consumer.md §The BIND client).
Verification: cargo test 352 green (all-features too), clippy
-D warnings clean, fmt clean, cargo doc clean, both wasm checks clean.