Batch 1 of the Phase 1 decomposition: the default, wasm-clean crate (producer + consumer + wire + seams + params/errors), per the architecture spec set (ADRs 001-013) and the three POCs' validated shapes. The assembly layer (local/composed providers, front doors) is batch 2, decomposed after review-protocol-core opens. - foundation: crate-deps (alkcall 0.8.0 first consumption), wire-codec (the ASSOCIATE frame + the joint bound), seam-types (the three ADR-004 seams), params-errors (the one-way-door surface) - harness: duplex transport + identities + in-process seams (the alkcall 0.8.0 establishment surface proven before the producer) - verticals: producer/consumer splits per command (CONNECT, ASSOCIATE, BIND) — each POC's scope, producer tasks test via the raw RFC client, consumer tasks e2e through the harness - closing: integration suite (three-command regression, teardown matrix, identity matrix, docs sync) + review-protocol-core (the batch gate) taskgraph: 8 generations, no cycles, risk path 2.55 (no high-risk tasks). Also records the wire.md/bast.md len=0 residue (payload-level F-2 is the operative invariant) as a doc-sync deliverable of the wire-codec task. Verification: cargo test (76 passed), fmt clean; taskgraph validate/cycles/parallel/critical clean.
2.8 KiB
2.8 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | ||
|---|---|---|---|---|---|---|---|---|---|
| implementation/core-consumer-bind | Core — consumer BIND: BindSession (reply#2 reader) + e2e tests | pending |
|
narrow | medium | component | implementation |
Description
Implement the BIND consumer session in src/consumer.rs per
consumer.md §The BIND client (POC #5's read_reply2 sketch): the
wrapper-aware client that opens the channel, sends BIND, reads
reply#1, awaits the inbound accept, and reads reply#2 before riding
the pass-through data plane.
Deliverables (port from /workspace/alksocks-bind-poc/src/consumer.rs,
adapted to the crate's error surface):
BindSession::bind(client, target): opens the channel, negotiates, sends the BIND command — the forked clientrequest()reads reply#1 (carrying BND.ADDR).- The reply#2 reader (
await_inbound): reply#2 is hand-read with the forked publicread_addresscodec (reply#1's codec applied again — no second codec, ADR-011's rationale). The session then rides the pass-through data plane (BindDataPlane-shaped:into_inner()/get_socket_mut()). - Error surface: a refused BIND (the command gate's 0x02, or a
factory failure's reply#1 code) surfaces as a typed session
error carrying the RFC reply code; accept-stage failures surface
at
await_inboundas reply#2's mapped code. - Teardown ownership: the session owns the channel; on Drop it
closes/joins. No
Clone(compile-asserted). - Tests (end-to-end through the harness): bind → reply#1
(BND.ADDR as the harness accept advertises) → reply#2 (the peer
address) → pass-through echo both directions; the command-gate
refusal surfaced as a typed error (a
socks5:open-only identity cannot bind); factory-failure and accept-stage-failure mappings surfaced; quiet-wait garbage from the client side ends the session; the three-command regression guard from the consumer side.
Acceptance Criteria
BindSessionwithbind/await_inbound/data-plane accessors per the POC shape- Reply#2 read via the forked
read_addresscodec (no second codec) - Typed error surface (reply-code-carrying session errors)
- Teardown ownership on Drop; no
Clone(compile-asserted) - E2E tests through the harness (round-trip, gate refusal, failure mappings, regression guard)
cargo testgreen; clippy/fmt clean; both wasm checks clean
References
- docs/architecture/consumer.md §The BIND client
- docs/architecture/decisions/007-bind-in-base.md (the client-side phase reading)
- POC source:
/workspace/alksocks-bind-poc/src/consumer.rs(BindReply1/BindDataPlane/read_reply2)
Notes
To be filled by implementation agent
Summary
To be filled on completion