--- id: implementation/core-integration-suite name: Core — cross-cutting integration suite + docs sync status: completed depends_on: [implementation/core-consumer-associate, implementation/core-consumer-bind] scope: moderate risk: medium impact: phase level: implementation --- ## Description The batch-1 closing task: the cross-cutting integration suite that pins the whole protocol core's behavior in one place, plus the docs sync that records what landed. The per-command tasks own their verticals; this task owns the cross-cutting invariants and the spec-vs-implementation reconciliation. Deliverables: 1. **Cross-cutting integration tests** (`tests/`): - **One registration, all three commands** (the POC #2/#5 regression guard, now complete): CONNECT + ASSOCIATE + BIND all served on the same `channels/socks5/sub` op, interleaved sessions on one connection. - **Concurrency**: multiple concurrent sessions of mixed command types over one channels connection (the mux/demux under load — the POCs tested sequentially; this pins concurrency). - **Teardown semantics matrix**: client half-close ends a CONNECT data plane cleanly (the producer's pump exits, the connection stays healthy); ASSOCIATE EOF ends the association; BIND client-gone teardown releases the accept; a fresh session succeeds immediately after each teardown (no connection poisoning). - **Identity/scope matrix**: `socks5:open`-only (CONNECT + ASSOCIATE yes, BIND 0x02), `socks5:bind`-only (BIND yes, CONNECT/ASSOCIATE FORBIDDEN at the open gate), both-scopes (everything) — the two-grants-never-implied posture (ADR-006) pinned end to end. - **The readiness contract** re-pinned at the integration level (the producer-associate task owns the unit-level test; this pins it under concurrent load). 2. **Docs sync** (the architecture-sync check): - `docs/architecture/README.md` Current State + the doc statuses reflect the landed core (the rfc1928 doc's "remaining layers follow the decomposition phase" line updated). - Any spec drift the implementation surfaced (naming, shapes, the wire.md/bast.md residue already fixed in the wire-codec task) reconciled in the same change — never silently diverged. - `lib.rs` crate docs updated to describe the landed surface (producer + consumer + wire + seams), pointing at the specs. 3. **Full verification sweep** (the batch gate's input): `cargo test`, `cargo test --all-features` (features are still empty — verify the flag combination compiles), clippy `--all-targets -- -D warnings`, `cargo fmt --check`, both wasm checks, and `cargo doc --no-deps` (docs changed). ## Notes - **The identity-matrix spec drift, reconciled (the one real drift the implementation surfaced):** this task's Description row 2 expected a `socks5:bind`-only identity to serve BIND ("BIND yes, CONNECT/ASSOCIATE FORBIDDEN at the open gate"). The landed ADR-006 + implementation pin the open op's `required_scopes = ["socks5:open"]` **unconditionally** (the single op, all three commands; ADR-001) — a bind-only identity fails closed at the open gate for every command (FORBIDDEN, the establisher never runs, no phantom channel), and a BIND-capable deployment grants both scopes explicitly. The suite pins the landed posture (`identity_matrix_bind_only_fails_closed_at_the_open_gate`), producer- and consumer-side; ADR-006 §Consequences now states the asymmetry explicitly (never implied, in either direction). The task's phrasing was a Phase-0-era guess at the gate shape, not a spec row the code contradicted — the spec (ADR-006 + producer.md) and the implementation already agreed. - **Test-shape notes:** the suite rides the established `tests/harness.rs` topologies (the raw producer-side topology — the producer's serving side allocates channel ids — and the consumer-side topology — the consumer allocates; the mux/demux is pinned in both allocation directions). The mixed-command concurrency tests box the per-command round-trip futures into one `Vec` (`Pin>` — the three async fns have distinct opaque types, so a shared boxed type is the `join_all` vehicle). The BIND client-gone row uses a parked accept factory so the quiet-wait exit is the only possible end (the deterministic client-gone probe). - **Readiness contract under load:** the integration-level pin reuses the producer-associate unit test's hot-`Ok(None)` egress shape across concurrent associations (with a CONNECT interleaved) — the stage's re-park tolerance must hold concurrently, not just sequentially. ## Summary Landed the batch-1 closing task: `tests/core-integration.rs` — nine cross-cutting integration tests pinning the whole protocol core end to end over the channels harness (the alkcall 0.8.0 establishment surface, both topology directions): 1. **One registration, all three commands** (the POC #2/#5 regression guard, complete): CONNECT + ASSOCIATE + BIND opened back to back on the one `channels/socks5/sub` op, all three live simultaneously, each exercised mid-life of the others; a teardown ends only its own session (mux/demux isolation). 2. **Concurrency**: nine concurrent mixed-command sessions over one channels connection (the raw topology), six through the typed consumer sessions (the consumer-side topology — the other allocation direction), then a fresh round-trip of each command after the burst; no channel entry leaks on either side. 3. **The teardown matrix** (wire.md §Sentinels and lifecycle): a client half-close ends a CONNECT data plane cleanly (the producer's pump exits); channel EOF ends the association; the BIND client-gone teardown releases the parked accept; fresh sessions of every command succeed immediately after each teardown (no connection poisoning). 4. **The identity/scope matrix** (ADR-006 end to end): open-only → CONNECT + ASSOCIATE serve, BIND refused 0x02 at the command gate (CONNECT still serves after); bind-only → fail-closed at the open gate for all commands (the reconciled posture, above); both-scopes → everything, granted explicitly; the CF-006 identity witness asserted per row. 5. **The readiness contract** re-pinned under concurrent load: a hot-`Ok(None)` egress across concurrent associations (with a CONNECT interleaved) does not starve the datagram stage's channel branch. Docs sync (the architecture-sync check): `docs/architecture/README.md` Current State rewritten — "the protocol core is implemented," the landed per-module inventory, `tests/core-integration.rs` named as the batch-1 pin, batch 2 (`local`/`composed`) as the follow; the "remaining layers follow the decomposition phase" residue gone. `consumer.md` §Wiring reconciled to the landed signatures (`&ChannelClient` constructors, `impl ToTargetAddr` datagrams, the `Option`-shaped `recv_datagram` — `None` is the channel-EOF association end, never an empty datagram). ADR-006 §Consequences now states the grant asymmetry explicitly. `src/lib.rs` crate docs rewritten to describe the landed surface (rfc1928 fork, wire codec, params, seams, producer, consumer) pointing at the specs and the integration suite. Verification: `cargo test` 302 green (118 lib + 38 connect + 39 associate + 40 bind + 40 integration + 30 differential + 37 rfc1928 + 3 doctests), `cargo test --all-features` green (the empty features `local`/`composed` compile), `cargo clippy --all-targets -- -D warnings` clean, `cargo fmt --check` clean, both wasm checks (`check` + `clippy -D warnings` on `wasm32-unknown-unknown`) clean, `cargo doc --no-deps` clean. The batch boundary holds: no `local`/`composed` code exists; the default crate is protocol-only. ## References - docs/architecture/wire.md §Sentinels and lifecycle (the teardown matrix's normative source) - docs/architecture/decisions/006-access-control.md (the identity matrix) - POC regression guards: `udp_composed_egress_round_trip`-adjacent tests in `/workspace/alksocks-udp-poc`, test 7 in `/workspace/alksocks-bind-poc` - docs/sdd_process.md (the architecture-sync-check posture) ## Notes > Filled by the implementation agent — see the Notes above. ## Summary > Filled on completion — see the Summary above.