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.
3.2 KiB
3.2 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | ||
|---|---|---|---|---|---|---|---|---|---|
| implementation/core-consumer-associate | Core — consumer ASSOCIATE: AssociateSession + e2e tests | pending |
|
moderate | medium | component | implementation |
Description
Implement the UDP ASSOCIATE consumer session in src/consumer.rs
per consumer.md §The associate session (POC #2's shape): the typed
client that opens the channel, receives the sentinel, and speaks the
framed datagram stage.
Deliverables (port from /workspace/alksocks-udp-poc/src/consumer.rs,
adapted to the crate's wire codec):
AssociateSession::associate(client): opens the channel, negotiates (NoAuth), sends ASSOCIATE, reads the reply — receives the sentinel BND.ADDR and never uses it for addressing (the handle is the channel; ADR-003).send_datagram(dst, bytes): frames once ([len: u16 BE][addr + data]via the crate's wire codec — the framing-once mirror) and writes the frame.recv_datagram()returns(source_addr, bytes)per datagram — the incremental reader state (mid-frame position + batched-datagram pending queue) persists across calls: a datagram split across channel chunks survives a caller-driven receive loop (POC #2's finding — the first cut dropped the reader state per call; the 2-byte-prefix chunk test exposed it). Write the persistence test (the POC's chunk-splitting echo shape).shutdown()half-closes the stream — the mux's implicit-EOF sentinel reaches the producer's stage as EOF and the association ends (association lifetime = channel lifetime).- Teardown ownership: the session owns the channel; on Drop it
closes/joins (alktunnels ADR-005 posture). No
Clone(compile-asserted). - Tests (end-to-end through the harness): associate → send/recv round-trips (multiple in-order datagrams, one association); the split-datagram persistence test; empty-payload datagram round-trip; shutdown → the producer's stage ends and a fresh associate succeeds immediately (the POC's test 4, from the consumer side); Drop teardown (drop mid-stream → the producer's stage sees EOF, the connection stays healthy); CONNECT + ASSOCIATE on the same registration (the regression guard extends).
Acceptance Criteria
AssociateSessionwithassociate/send_datagram/recv_datagram/shutdownper the POC shape- Reader state persists across
recv_datagramcalls (the split-datagram test) - Framing-once mirror (send frames exactly once; recv decodes incrementally)
- Teardown ownership on Drop; no
Clone(compile-asserted) - E2E tests through the harness (round-trips, shutdown, Drop teardown, regression guard)
cargo testgreen; clippy/fmt clean; both wasm checks clean
References
- docs/architecture/consumer.md §The associate session
- docs/architecture/decisions/003-udp-handle-swap.md (the consumer mirror invariants)
- POC source:
/workspace/alksocks-udp-poc/src/consumer.rs(UdpAssociation— the reader-state finding's origin)
Notes
To be filled by implementation agent
Summary
To be filled on completion