- 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.
- Socks5ChannelSession::connect: open_channel(OP_SOCKS5_OPEN, {},
SOCKS5_ALPN) then the forked client typestate's use_stream path
over the channel BiStream (POC #1's fit); post-reply the session
is the raw byte pipe (0 B framing)
- Target construction via ToTargetAddr: IP-string forms parse to IP
targets, domain form passes through unresolved (ADR-012)
- split() borrowed halves (SplitPipe) / into_inner() owned pipe
(TakenInner — the session rides along as the teardown owner);
channel_id() for correlation
- Teardown ownership (alktunnels ADR-005 posture): Drop sync-reaps
the adopted entry (teardown_channel is sync; Drop cannot await) +
the pipe drop EOFs the producer pump structurally; close() is the
graceful path (write-half shutdown, then reap); the in-stream
refusal tears the channel down in connect (teardown-at-birth —
no phantom channel); no Clone (compile_fail doctest)
- Error surface: open failures are the typed SocksOpenError reasons
(ADR-049 §4); a refused target is the RFC reply code through
SocksSessionError::Rfc (consumer.md §Error surface)
- Harness: the consumer-side topology (wire_consumer_side[_with] —
the consumer dials with a real ChannelClient; the producer accepts
with the real registration) + witnessing_echo_dial; the
allow(dead_code) attr rides the alktunnels harness posture
- tests/consumer-connect.rs: 9 e2e tests — echo round-trip + CF-006
witness, target forms at the dial seam (ADR-012), refused dial →
typed RFC error + no phantom channel, FORBIDDEN open → typed open
error + no session, drop teardown + connection health, half-close
EOF semantics, into_inner pairing, Send shape
Verified: cargo test (219 green incl. the compile_fail doctest),
clippy --all-targets -D warnings, fmt --check,
check/clippy --target wasm32-unknown-unknown
The TCP BIND dispatch arm replaces its refusal with the full phase
model (POC #5-validated scope), plus the command gate at dispatch:
- The command gate: TCP BIND requires socks5:bind from the per-call
opener identity (CF-005/CF-006) — the pump handler resolves it
from the open-op AuthContext; serve_socks5_over<T> takes the
resolved can_bind boolean explicitly. A scope-less identity gets
the RFC-faithful ConnectionNotAllowed (0x02) with no factory call
(the gate precedes the seam) while CONNECT still serves it.
- The phase model (wire.md §BIND): the BindAcceptFactory at the
command-read interception point → reply#1 carrying BND.ADDR (the
factory's bind_addr) → the quiet wait (single-shot select!, exactly
two exits: the one accept, or the control stream's EOF/garbage/
error; any byte = protocol garbage → session ends, no data plane;
the accept future's drop IS the client-gone teardown) → reply#2
carrying the peer address (via the fork's published new_reply) →
pump_bidi inline (the CONNECT shape, R-02).
- Two-stage RFC-faithful failure mapping: factory failure → reply#1's
mapped code; accept-stage failure → reply#2's mapped code, no data
plane. No phantom listeners, no phantom data planes.
- The no-factory default is the wrapper-aware in-band variant
(ADR-007 variant 3, documented): sentinel reply#1 + sentinel reply#2
(0.0.0.0:0), the full phase model preserved — the channel is the
connection.
- The accept wait lives in the teardown-governed pump phase, never
under the establishment bound (ADR-007).
Tests: 16 unit tests (raw RFC client over duplex) + 7 harness
integration tests over channels — happy path, the gate (0x02 while
CONNECT serves, both scopes), quiet-wait garbage, client-gone
teardown (owner-flag witness), both failure stages over channels,
no-factory variant 3, and the three-command regression guard (CONNECT
serves, BIND serves under its gate, ASSOCIATE still refuses).
Verification: cargo test green (96 lib + 26 harness + 37
differential); clippy -D warnings clean (all targets, native +
wasm32-unknown-unknown); cargo fmt clean; wasm check clean.
Task: tasks/implementation/core-producer-bind.md (status → completed)
The crate's core task (implementation/core-producer-connect): the
producer half of src/producer.rs per producer.md, adapted to the
crate's seam types and the alkcall 0.8.0 establishment surface.
- The session-gate establisher (`socks5_session_establisher`):
validates/records the opener identity (the CF-005/CF-006 seam,
ADR-005) via the optional `identity_witness` probe (the alktunnels
posture); returns `Establishment::default()` — no plan payload
(the dial happens post-establishment; POC #1's wire note).
- The pump handler (`make_socks5_pump_handler`): `accept_bi()` →
the forked typestate over the `BiStream` (`accept_no_auth →
read_command`) → dispatch. CONNECT: the dial seam (`DialFn`,
ADR-004) at the command-read interception point; success:
`reply_success(sentinel)` then `pump_bidi` awaited inline (R-02 —
the JoinHandle tracks the data-plane lifetime). Refusal:
`reply_error` with the mapped RFC code — no phantom data plane.
- The ASSOCIATE/BIND arms land as RFC-faithful refusals
(`CommandNotSupported`) — the pre-vertical posture (ADR-008); the
dispatch skeleton + registration signature carry the seam
parameters from day one so the associate/bind tasks swap the arms
without touching the registration shape.
- `register_socks5_openable`: spec + establisher + pump via
`register_openable_with_establisher` (`timeout: None` = the 10s
default), scope-gated `socks5:open`. Missing callbacks = those
commands refuse RFC-faithfully, never a panic.
- `serve_socks5_over<T>`: the substrate-free protocol entry (the
POC shape), directly testable without channels; the builder
(`Socks5Producer::builder()`) is the spec'd assembly shape.
- Tests: 11 in-module (substrate-free duplex-driven — round-trip +
half-close teardown, refusal mapping per variant, missing-dial
refusal, ASSOCIATE/BIND arms, dispatch guard, establisher witness,
builder shape) + 5 harness integration (end-to-end CONNECT echo
with the identity witness, dial refusal 0x05 with no phantom data
plane, scope-class refusal 0x02, ASSOCIATE/BIND refusals with
CONNECT still serving, repeated CONNECTs on one registration).
The harness retargeted to the real producer (`RegisterMode::
Producer`); the minimal stand-in is a harness-internal helper.
Verification: cargo test 87+19+37 green; clippy --all-targets -D
warnings clean; fmt clean; wasm check + wasm clippy clean; cargo
doc clean; --all-features green.
tests/harness.rs — the producer<->consumer wiring over one
tokio::io::duplex carrying the channels 8-byte chunk format, the
alkcall 0.8.0 establishment surface consumed for the first time by
this crate (register_openable_with_establisher + the call/adopt
dance) — the first-consumption risk retired.
- Identities: consumer (socks5:open) / bind (socks5:bind only) /
both-scopes (explicit, ADR-006) + TestIdProvider (token path).
- In-process seams, no sockets, no `local`: echo_dial /
refusing_dial (variant-preserving), echo_egress (readiness
contract verified — next_reply parks Pending when idle) /
refusing_egress, echo_accept / refusing_accept_factory /
refusing_accept (two-stage BIND refusal shapes, mapped through
to_reply_error()).
- Producer-side registration helper: register_socks5_openable_minimal
+ socks5_session_establisher + RegisterMode — the single place the
producer wiring lives; the CF-006 identity witness rides it and is
asserted end-to-end.
- RawRfcClient: the hand-rolled RFC 1928 client helper over any
AsyncRead + AsyncWrite, round-tripped against a byte-level
hand-rolled server (success + refusal replies).
- Smoke test: harness up -> producer registered -> consumer open +
adopt -> raw RFC CONNECT -> echo round-trip through pump_bidi.
Fail-closed probe: scope-less identity -> FORBIDDEN, no channel
anywhere (the load-bearing POC #1 set_identity wiring requirement,
explicit in the install hook and tested).
14 harness tests. Verification: cargo test (127 green), clippy
(all-targets + wasm32) clean, fmt clean, doc zero warnings,
test --all-features green, both wasm checks clean (harness is
dev-only).