Files
alksocks/tasks/implementation/core-test-harness.md
T
glm-5.3-flash f8773521b9 harness: the producer/consumer integration test harness over duplex
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).
2026-09-23 18:48:16 +00:00

11 KiB

id, name, status, depends_on, scope, risk, impact, level
id name status depends_on scope risk impact level
implementation/core-test-harness Core — integration test harness (duplex transport + identities + in-process seams) completed
implementation/core-seam-types
implementation/core-params-errors
moderate medium phase implementation

Description

Build tests/harness.rs — the producer↔consumer wiring over a tokio::io::duplex carrying the channels 8-byte chunk format — so every subsequent core task tests end-to-end without the local feature. This is the alkcall-0.8.0-first-consumption task: the POCs ran 0.7.1; the harness proves the 0.8.0 establishment surface (register_openable_with_establisher, Establishment, ChannelClient::open_channel) works for this crate's shape before the producer task builds on it. Template: /workspace/@alkdev/alktunnels/tests/harness.rs (the sibling's harness — same topology, adapted to this crate's seams).

Topology (the alktunnels harness shape):

  • producer (connect side of the channels connection — runs ChannelClient::from_connection_with_serving): serves the socks5 open op + generic channel ops on its serving registry. Its manager allocates the channel IDs (ChannelSide::Connect — the serving side allocates; the initiator adopts).
  • consumer (accept side): the ChannelsAdapter + capturing install hook. The hook captures the consumer's channel-0 CallConnection and ChannelManager.
  • The POC #1 wiring requirement is load-bearing here (producer.md §Harness wiring requirement): the accept-side install hook must call channel0_conn.set_identity(resolved) before building the CallConnection — without it, scope-gated opens fail closed with FORBIDDEN "authentication required" (correct behavior, implicit wiring). The harness makes the requirement explicit and tested.

Deliverables:

  1. Identities: consumer_identity() (socks5:open only), bind_identity() (socks5:bind only — the command-gate probe), both_scopes_identity() (both grants, explicitly — never implied, ADR-006), plus a TestIdProvider resolving them (the alktunnels harness shape).
  2. In-process seam closures (no sockets — the protocol layer is substrate-agnostic, so the harness dials in-process):
    • echo_dial() — a DialFn returning duplex-halves wired to an in-process echo server (the POC #1 shape); plus refusing_dial() (a failing dial for the refusal-mapping tests).
    • echo_egress() — an EgressFactory whose egress echoes datagrams back (the POC #2 shape, readiness-contract-clean: parks on a channel recv(), Pending when nothing is ready).
    • echo_accept() — a BindAcceptFactory whose accept resolves immediately with in-process halves (the POC #5 shape); plus a failing variant.
  3. The producer registration helper: a spawn_producer(...) function wiring register_socks5_openable (or its task-6 successor) with the harness seams — the single place the producer-side wiring lives, so the per-command tasks only write tests.
  4. A raw RFC client helper: a hand-rolled minimal RFC 1928 client over any AsyncRead + AsyncWrite (greeting → method selection → command with target → reply read) — the differential suite's established pattern — so producer tasks test without depending on the consumer session types (which land later).
  5. One smoke test proving the full loop: harness up → producer registered → consumer opens a channel → raw RFC CONNECT conversation → echo round-trip. (This test needs a minimal CONNECT producer path; if the producer task hasn't landed, stub the handler with the POC #1 serve_socks5_over shape inline in the harness — the producer task then replaces it. Alternatively sequence this task to land immediately before the producer task and let the smoke test be the producer task's first test — the implementer's judgment; the acceptance bar is the harness compiling with the identities + seams + helpers tested.)

Acceptance Criteria

  • Harness topology works over alkcall 0.8.0 (the establishment surface consumed successfully — the first-consumption risk retired)
  • Identity wiring explicit: set_identity in the install hook; a scope-less identity gets FORBIDDEN (fails closed) — tested
  • All three identities + all in-process seam closures unit-tested
  • The raw RFC client helper round-trips a greeting + command + reply against a hand-rolled server over a duplex
  • No local feature, no sockets — everything in-process
  • cargo test green; clippy/fmt clean; both wasm checks clean (the harness is dev-only — verify it stays out of the wasm build)

References

  • Template: /workspace/@alkdev/alktunnels/tests/harness.rs (the topology + identity shapes)
  • POC harnesses: /workspace/alksocks-connect-poc/src/harness.rs, /workspace/alksocks-udp-poc/src/harness.rs, /workspace/alksocks-bind-poc/src/harness.rs
  • docs/architecture/producer.md §Harness wiring requirement (the set_identity requirement)
  • docs/architecture/decisions/006-access-control.md (the scope identities)

Notes

Filled by the implementation agent (2026-09-23).

  • tests/harness.rs: the producer↔consumer wiring over one tokio::io::duplex carrying the channels 8-byte chunk format, in the task's topology — producer = connect side (ChannelClient::from_connection_with_serving; its manager allocates the odd channel IDs), consumer = accept side (the ChannelsAdapter + capturing install hook; the hook captures the consumer's channel-0 CallConnection + ChannelManager).
  • The load-bearing POC #1 wiring requirement is explicit and tested: the hook calls channel0_conn.set_identity(resolved) before building the CallConnection; the transport identity is set on the dialing (producer) connection before from_connection_with_serving (CF-005 (b) primary path). The scope-less identity test asserts the FORBIDDEN code and that no channel survives on either side (fail-closed).
  • Identities: consumer_identity() (socks5:open only), bind_identity() (socks5:bind only), both_scopes_identity() (both, explicit — ADR-006), TestIdProvider + TEST_AUTH_TOKEN (the token-resolver path, unit-tested both directions).
  • In-process seams (no sockets, no local): echo_dial() (echo-per-dial, exercised through pump_bidi — the producer data plane's shape), refusing_dial(err) (variant-preserving per-call reconstruction — the seam errors are not Clone), echo_egress() (a ChanEgress whose next_reply parks on mpsc::UnboundedReceiver::recv() — Pending when idle, the readiness contract verified with a 50ms timeout probe), refusing_egress(err), echo_accept() (reply#1 advertises a static in-process BND.ADDR, ECHO_BIND_PORT 2121; the accept future resolves immediately with echo-pipe halves), refusing_accept_factory(err) (pre-reply#1) and refusing_accept(err) (post-reply#1).
  • register_socks5_openable_minimal + socks5_session_establisher: the producer-side wiring helper over alkcall 0.8.0's ChannelCore::register_openable_with_establisher (spec from socks5_open_spec(), Establishment::default() — session gate only; the dial is in-stream). The establisher witnesses the per-call opener identity id (CF-006) into an IdentityWitness, asserted end-to-end in the smoke test.
  • RegisterMode (MinimalConnect(dial) / NoSocks5) controls what wire_with registers post-hoc (W2) on the producer's serving registry; generic channel ops always register.
  • The smoke test's producer path is the minimal CONNECT stand-in (make_minimal_connect_handler → serve_connect_minimal: the forked typestate's accept_no_auth → read_command → CONNECT-only dispatch → the injected DialFn → reply_success → pump_bidi inline, R-02). The producer task replaces this; the registration shape (spec/establisher/handler/auth/timeout) stays.
  • RawRfcClient<S>: hand-rolled greeting (05 01 00 → 05 00) + request encoder (all three commands, all address forms via TargetAddr::to_be_bytes()) + reply reader (v4/v6/domain BND.ADDR forms; returns (code, addr_bytes)). Round-trip-tested against a hand-rolled byte-level server over a duplex, success + refusal reply codes; the harness is producer-independent (no consumer session types).
  • Wire note: the smoke test calls the open op via consumer_call.call(OP_SOCKS5_OPEN, Socks5Params::as_json()) and adopts on consumer_manager (the alktunnels wire_with + open_reverse_channel shape) rather than ChannelClient::open_channel — in this topology the open op is served by the producer's registry and reached from the accept side's channel-0 call surface; open_channel remains the consumer-session surface for the consumer task's session types.
  • The harness is tests/harness.rs only (dev-only) — verified out of the wasm build by the targeted checks below.

Summary

Filled on completion (2026-09-23).

Built tests/harness.rs — the integration test harness: the producer↔consumer topology over one tokio::io::duplex (producer = connect side/serving; consumer = accept side/adapter + capturing hook), the alkcall 0.8.0 establishment surface consumed for the first time by this crate (register_openable_with_establisher, Establishment::default, the consumer-side call + adopt dance) — the first-consumption risk retired with 14 green tests.

  • The three identities + TestIdProvider (all unit-tested).
  • All in-process seam closures: echo_dial/refusing_dial (variant- preserving), echo_egress (readiness contract verified — a 50ms timeout probe proves next_reply parks, never a hot Ok(None)) / refusing_egress, echo_accept (immediate resolve + echo) / refusing_accept_factory / refusing_accept (two-stage refusal shapes, mapping-table-verified through to_reply_error()).
  • The producer registration helper (register_socks5_openable_minimal
    • socks5_session_establisher + RegisterMode) — the single place the producer-side wiring lives; the CF-006 identity witness rides it and is asserted.
  • RawRfcClient — the raw RFC 1928 client helper over any AsyncRead + AsyncWrite, round-tripped against a hand-rolled byte-level server (success + refusal replies).
  • The smoke test: harness up → producer registered → consumer open + adopt → raw RFC CONNECT → echo round-trip through pump_bidi, with the establisher witness asserted mid-flight. Plus the fail-closed probe (scope-less identity → FORBIDDEN, no channel anywhere) and the odd-ID allocation/adopt sanity probe.

Verification: cargo test (127 green: 76 lib + 14 harness + 37 rfc1928-differential), cargo test --all-features green, cargo clippy --all-targets -- -D warnings clean, cargo fmt --check clean, cargo doc --no-deps zero warnings, both wasm checks (cargo check + cargo clippy on wasm32-unknown-unknown) clean — the harness stays out of the wasm build.