The `composed` feature's ASSOCIATE egress (ADR-008's composed
variant, ADR-009's gate): `composed::direct_egress` — each
destination dials through an alktunnels 0.2.0 direct-op channel
(`TunnelSession::open_direct`, `Substrate::Udp`), per-target ACL
for free, the POC #2 `ComposedEgress` shape ported to the landed
seam types.
- `Cargo.toml` — `composed = ["dep:alktunnels"]` (alktunnels pinned
"0.2.0"; rides `composed` alone, `cargo tree --edges normal`
spot-checked); dev-dep for the composed suite.
- `src/composed/mod.rs` — the lazy destination→tunnel table
(LRU-capped, `DEFAULT_MAX_TUNNELS` = 256), per-tunnel relay tasks
draining a shared inbound queue, `SessionOwner` (the owner wrapper
shared with the composed accept — the batch-1 review's
Sync-bound wrinkle), the readiness contract (real async park;
ended relays → association-end `Err`, never a hot `Ok(None)`),
framing-once, domain pass-through unresolved (ADR-012), the
backpressure bound documented on the constructor.
- Two deliberate deviations from the POC shape, documented in the
task's Notes: the closed-queue condition is a live-relay count
(the egress holds its own `Sender`, so the POC's queue-close arm
was unreachable through this surface); the tunnel codec is
alktunnels' (`[len]` + payload), not the RFC-framed reader.
- `tests/composed-egress.rs` — round-trips per destination → one
tunnel each, table reuse, LRU eviction/re-dial, the readiness
park, the closed-relay-set `Err`, framing-once through the wire
layer, domain pass-through — over a `wire_tunnel_direct` harness
topology (the consumer-side shape with the direct op on the
producer's serving registry).
Verification: `cargo test` + `--all-features` pass (13 suites);
`cargo check --features composed --target wasm32-unknown-unknown`
clean (the hard gate); clippy `--all-targets --all-features
-- -D warnings` clean; `cargo fmt --check` clean; `cargo doc
--no-deps` clean.
The `local` feature's first-party providers (ADR-008's local variants,
ADR-009's gate): the three seams' faithful-RFC assembly-layer
constructors over the landed seam types; the protocol layer never
sees them.
- Cargo.toml: `local = ["tokio/net"]` (no socket2 — the POCs ran
tokio-only); the default graph stays net/mio/socket2-free
(cargo tree spot-checked both ways)
- src/local/: `tcp_dial()` (real TcpStream per CONNECT, domain
resolution at the provider — the ssh -D semantic; the resolved
address set iterated, faithful SocksDialError mapping,
NotAllowed never synthesized), `udp_egress()` (one real UdpSocket
per association bound 127.0.0.1:0 — the explicit bind decision;
the POC #2 LocalEgress readiness shape: park on readable(),
try_recv_from, WouldBlock -> spurious Ok(None); inner bytes
to_be_bytes() + data, framing-once; resolve at the egress),
`bind_accept(bind_host)` (real TcpListener per BIND session,
ADR-007 variant 1: requested port honored when non-zero, local_addr
as reply#1's BND.ADDR, the accept future owning the listener
end-to-end, peer byte-exact; two-stage failure mapping; the bind
host is the caller's explicit choice)
- lib.rs: cfg-gated module + re-exports; crate doc updated
- tests: 12 unit (real-socket round-trips, the readiness contract's
park-then-datagram, the drop-closes-the-listener witness, the
refusal mappings) + 6 integration (tests/local-providers.rs,
feature-gated: the three commands end to end through the producer's
real dispatch path with real targets, connect-refused -> 0x05
through the producer's reply, the readiness contract re-pinned
through the datagram stage, client-gone -> the advertised port
frees)
- task status -> completed (acceptance criteria checked; Notes +
Summary filled)
Verification: cargo test (157 green) + --all-features green,
clippy -D warnings clean (default + all-features), fmt --check clean,
both wasm checks clean, the dependency-graph spot-checks green.
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)
- Cargo.toml: alkcall = "0.8.0" (convention 11 — pinned, first
consumption of the 0.8.0 surface), serde/serde_json, bytes, and
the std-only futures subset (BoxFuture seam shape). tokio's
wasm-clean subset and the empty local/composed features unchanged.
- lib.rs: the six skeleton modules per overview.md §Module Map
(params, wire, producer, consumer, egress, error) — stub files
with module docs naming their filling tasks; no re-exports yet
(each implementation task adds its own).
Verified: cargo test (76 tests), clippy --all-targets -D warnings,
fmt --check, cargo doc --no-deps, both wasm checks
(check + clippy on wasm32-unknown-unknown), and the dep-graph
spot-checks (no mio/socket2/tokio::net in the default normal graph;
normal tokio features = bytes/io-util/macros/rt/sync/time only).
alkcall 0.8.0 from crates.io confirmed wasm-clean via probe build
before wiring.
Task: tasks/implementation/core-crate-deps.md (completed)