core: the cross-cutting integration suite + docs sync
The batch-1 closing task: nine cross-cutting integration tests
(tests/core-integration.rs) pinning the whole protocol core end to
end over the channels harness, plus the architecture-sync docs pass.
Tests:
- One registration, all three commands: CONNECT + ASSOCIATE + BIND
interleaved live on the one channels/socks5/sub op; a teardown
ends only its own session (mux/demux isolation) — the POC #2/#5
regression guard, complete.
- Concurrency: nine concurrent mixed-command sessions (raw topology)
and six through the typed consumer sessions (consumer-side
topology) — the mux/demux pinned in both channel-id allocation
directions; fresh round-trips after the burst; no channel leaks.
- Teardown matrix (wire.md §Sentinels and lifecycle): CONNECT
half-close, ASSOCIATE EOF, BIND client-gone (a parked accept so
the quiet-wait exit is deterministic) — each followed by fresh
sessions of every command (no connection poisoning).
- Identity/scope matrix (ADR-006 end to end): open-only (CONNECT +
ASSOCIATE serve, BIND refused 0x02 at the command gate), bind-only
fail-closed at the open gate for all commands (the spec drift the
task's phrasing carried, reconciled — ADR-006's open gate requires
socks5:open unconditionally), both-scopes (everything, granted
explicitly); the CF-006 witness asserted per row.
- The readiness contract re-pinned under concurrent load: a
hot-Ok(None) egress across concurrent associations does not starve
the datagram stage's channel branch.
Docs sync: README Current State ("the protocol core is implemented"
+ the landed inventory; the decomposition residue gone); consumer.md
§Wiring reconciled to the landed session signatures; ADR-006
§Consequences states the grant asymmetry explicitly; lib.rs crate
docs describe the landed surface.
Verification: cargo test 302 green; --all-features green; clippy
--all-targets -D warnings clean; fmt --check clean; both wasm checks
clean; cargo doc --no-deps clean. Batch boundary holds: no
local/composed code, the default crate is protocol-only.
This commit is contained in:
1 parent
c57451545d
commit
1ad8d9d489
6 files changed
+1196
-37
No files matched your search
+24
-13
@@ -1,10 +1,10 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-09-22 (the targeted fork — ADR-013; the module is
|
||||
`src/rfc1928/`; the vendor posture retired. The vendor extraction
|
||||
amendment ADR-011 §Amendment 2026-09-21; Phase 1 initial draft
|
||||
2026-09-20 — the OQ-SK ledger promoted into ADRs 001-012 and
|
||||
open-questions.md)
|
||||
last_updated: 2026-09-24 (the protocol core landed + the cross-cutting
|
||||
integration suite; the rfc1928 doc's targeted fork 2026-09-22; the
|
||||
vendor extraction amendment ADR-011 §Amendment 2026-09-21; Phase 1
|
||||
initial draft 2026-09-20 — the OQ-SK ledger promoted into ADRs
|
||||
001-012 and open-questions.md)
|
||||
---
|
||||
|
||||
# alksocks — Architecture
|
||||
@@ -20,16 +20,27 @@ architecture spec docs and the ADRs.
|
||||
|
||||
## Current State
|
||||
|
||||
Phase 1 (Architecture) — initial draft. Phase 0
|
||||
(`docs/research/phase-0.md`) is converged (2026-09-14) and
|
||||
POC-complete (all numbered POCs passed or were dropped with the
|
||||
scope decision); the OQ-SK ledger's Phase 1 inputs are collected and
|
||||
promoted into ADRs 001–012. All docs are `draft` — they transition
|
||||
Phase 1 (Architecture) — the **protocol core is implemented**. Phase
|
||||
0 (`docs/research/phase-0.md`) is converged (2026-09-14) and
|
||||
POC-complete (all numbered POCs passed or were dropped with the scope
|
||||
decision); the OQ-SK ledger's Phase 1 inputs are collected and
|
||||
promoted into ADRs 001–013. All docs are `draft` — they transition
|
||||
to `reviewed` when their open questions resolve and the architecture
|
||||
review passes. The RFC 1928 core is implemented (the targeted fork,
|
||||
review passes.
|
||||
|
||||
The landed core (the protocol-only batch; no `local`/`composed` code
|
||||
exists yet): the RFC 1928 core in `src/rfc1928/` (the targeted fork,
|
||||
ADR-013 — the vendor group's six tasks landed and passed the
|
||||
extraction review); the remaining layers follow the decomposition
|
||||
phase.
|
||||
extraction review), the ASSOCIATE datagram frame codec (`src/wire.rs`,
|
||||
ADR-003), the open-op params + typed error surface (`src/params.rs` /
|
||||
`src/error.rs`, ADR-001), the three seam types (`src/egress.rs`,
|
||||
ADR-004), the producer half (`src/producer.rs` — the session-gate
|
||||
establisher, the command-dispatch pump, the three commands, the scope
|
||||
gates), and the consumer half (`src/consumer.rs` — the
|
||||
connect/associate/bind session types with teardown ownership). The
|
||||
batch-1 cross-cutting integration suite (`tests/core-integration.rs`)
|
||||
pins the core's whole behavior end to end; the `local` and
|
||||
`composed` provider groups follow (batch 2).
|
||||
|
||||
## Documents
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-09-20 (Phase 1 initial draft)
|
||||
last_updated: 2026-09-24 (the landed session signatures reconciled —
|
||||
`&ChannelClient` constructors, `impl ToTargetAddr` datagrams, the
|
||||
`Option`-shaped `recv_datagram`; Phase 1 initial draft 2026-09-20)
|
||||
---
|
||||
|
||||
# alksocks — The Consumer Half
|
||||
@@ -120,12 +122,12 @@ address) is assembly-layer configuration.
|
||||
|
||||
```rust
|
||||
let session = Socks5ChannelSession::connect(
|
||||
&mut channel_client, target)?;
|
||||
&channel_client, target).await?;
|
||||
let (mut read, mut write) = session.split(); // post-reply payload pipe
|
||||
|
||||
let assoc = AssociateSession::associate(&mut channel_client)?;
|
||||
assoc.send_datagram(dst, &bytes).await?;
|
||||
let (src, bytes) = assoc.recv_datagram().await?;
|
||||
let assoc = AssociateSession::associate(&channel_client).await?;
|
||||
assoc.send_datagram(dst, &bytes).await?; // frames once, ADR-003
|
||||
let (src, bytes) = assoc.recv_datagram().await?.expect("a datagram");
|
||||
|
||||
let door = FrontDoor::builder()
|
||||
.credentials(cred_table) // RFC 1929 mapping, ADR-005
|
||||
@@ -134,6 +136,14 @@ let door = FrontDoor::builder()
|
||||
door.serve(channel_client).await?;
|
||||
```
|
||||
|
||||
The landed session signatures: the constructors take `&ChannelClient`
|
||||
(shared — many sessions ride one client, the concurrency posture);
|
||||
`send_datagram` takes `impl ToTargetAddr` (the CONNECT session's
|
||||
target-construction posture, ADR-012); `recv_datagram()` returns
|
||||
`Result<Option<(TargetAddr, Bytes)>, SocksSessionError>` — `None` is
|
||||
the channel EOF (the association's clean end), never an empty
|
||||
datagram (F-2: an empty payload is a legal datagram).
|
||||
|
||||
## Design Decisions
|
||||
|
||||
| ADR | Decision | Summary |
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
## Status
|
||||
|
||||
Accepted (2026-09-20, Phase 1; scope gates POC-validated in shape —
|
||||
POC #1 (`socks5:open`), POC #5 (`socks5:bind` at command dispatch))
|
||||
POC #1 (`socks5:open`), POC #5 (`socks5:bind` at command dispatch);
|
||||
consequence asymmetry pinned by the integration suite, 2026-09-24)
|
||||
|
||||
## Context
|
||||
|
||||
@@ -60,7 +61,14 @@ distinction at command dispatch from the per-call opener identity.
|
||||
- Two grants, clean separation: `socks5:open` (egress) and
|
||||
`socks5:bind` (ingress listeners) — never implied by each other
|
||||
(the alktunnels ADR-006 Amendment 1 posture: a capability on its
|
||||
own scope).
|
||||
own scope). The implication asymmetry is pinned by the integration
|
||||
suite (`tests/core-integration.rs`, the identity/scope matrix):
|
||||
`socks5:open` alone serves CONNECT + ASSOCIATE and is refused BIND
|
||||
(0x02) at the command gate; `socks5:bind` alone grants *nothing*
|
||||
on the op — the open gate's `required_scopes = ["socks5:open"]`
|
||||
fails closed for every command (the establisher never runs, no
|
||||
phantom channel); both scopes, granted explicitly, serve
|
||||
everything. A BIND-capable deployment grants both.
|
||||
- BIND's security boundary is enforced even though BIND rides the
|
||||
same op (ADR-001): the command gate is the mechanism, and it is
|
||||
POC-validated (POC #5).
|
||||
|
||||
+41
-6
@@ -9,14 +9,49 @@
|
||||
//! binds a port — kernel binds exist only as explicit, feature-gated
|
||||
//! assembly shapes (`local`), never in the protocol layer.
|
||||
//!
|
||||
//! The RFC wire vocabulary and the explicit typestate live in
|
||||
//! [`rfc1928`]: a targeted fork of fast-socks5 v1.0.0's `T`-generic
|
||||
//! subset (MIT, third-party upstream) carrying two deliberate changes
|
||||
//! (BIND support, `new_reply` publication) — see
|
||||
//! `docs/architecture/rfc1928.md`, ADR-013, and ADR-011.
|
||||
//! ## The landed surface (the protocol core)
|
||||
//!
|
||||
//! - **The wire vocabulary and the explicit typestate** live in
|
||||
//! [`rfc1928`]: a targeted fork of fast-socks5 v1.0.0's `T`-generic
|
||||
//! subset (MIT, third-party upstream) carrying two deliberate
|
||||
//! changes (BIND support, `new_reply` publication) — see
|
||||
//! `docs/architecture/rfc1928.md`, ADR-013, and ADR-011.
|
||||
//! - **The wire codec** ([`wire`]): the ASSOCIATE datagram frame
|
||||
//! (`[len: u16 BE][addr + data]`, ADR-003) — framing is applied
|
||||
//! exactly once, by this layer; the egress speaks inner bytes.
|
||||
//! - **The wire-stable open-op surface** ([`params`]): the
|
||||
//! `channels/socks5/sub` op id, the `alk/socks5` ALPN, the
|
||||
//! trivial `{}` params (ADR-001), and the two scope constants
|
||||
//! (`socks5:open`, `socks5:bind` — two grants, never implied,
|
||||
//! ADR-006). The typed open-error vocabulary lives in [`error`].
|
||||
//! - **The three seams** ([`egress`]): `DialFn` / `EgressFactory` /
|
||||
//! `BindAcceptFactory` (ADR-004) — functions, not traits, at the
|
||||
//! three I/O planes; ownership rides the handle structurally; the
|
||||
//! egress readiness contract (`next_reply` `Pending` when nothing
|
||||
//! is ready) is load-bearing API.
|
||||
//! - **The producer half** ([`producer`]): the session-gate
|
||||
//! establisher, the command-dispatch pump (CONNECT pass-through /
|
||||
//! ASSOCIATE datagram stage / BIND phase model), the scope gates
|
||||
//! (the open gate `socks5:open` at the registry; the command gate
|
||||
//! `socks5:bind` at BIND dispatch), and
|
||||
//! [`register_socks5_openable`] — substrate-agnostic over the
|
||||
//! seams; never a bind in the protocol layer.
|
||||
//! - **The consumer half** ([`consumer`]): the typed channels-native
|
||||
//! sessions — [`Socks5ChannelSession`] (CONNECT),
|
||||
//! [`AssociateSession`] (the framed datagram stage),
|
||||
//! [`BindSession`] (the reply#1/reply#2 reader) — each owning its
|
||||
//! channel's teardown; no `Clone`.
|
||||
//!
|
||||
//! `local` and `composed` (the feature-gated assembly-layer
|
||||
//! providers: the front doors, the socket-backed/composed seams) are
|
||||
//! not yet present — the default crate is protocol-only and
|
||||
//! wasm-clean by construction (ADR-009).
|
||||
//!
|
||||
//! Architecture: `docs/architecture/overview.md` (spec set:
|
||||
//! wire.md, producer.md, consumer.md, rfc1928.md).
|
||||
//! wire.md, producer.md, consumer.md, rfc1928.md); the cross-cutting
|
||||
//! behavior is pinned end to end by `tests/core-integration.rs`
|
||||
//! (one registration, all three commands; concurrency; the teardown
|
||||
//! matrix; the identity/scope matrix; the readiness contract).
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: implementation/core-integration-suite
|
||||
name: Core — cross-cutting integration suite + docs sync
|
||||
status: pending
|
||||
status: completed
|
||||
depends_on: [implementation/core-consumer-associate, implementation/core-consumer-bind]
|
||||
scope: moderate
|
||||
risk: medium
|
||||
@@ -56,15 +56,97 @@ Deliverables:
|
||||
`--all-targets -- -D warnings`, `cargo fmt --check`, both wasm
|
||||
checks, and `cargo doc --no-deps` (docs changed).
|
||||
|
||||
## Acceptance Criteria
|
||||
## Notes
|
||||
|
||||
- [ ] The three-command regression + concurrency + teardown-matrix +
|
||||
identity-matrix tests all pass
|
||||
- [ ] Docs reconciled (README Current State; any drift fixed)
|
||||
- [ ] The full verification sweep is green (test, all-features,
|
||||
clippy, fmt, both wasm checks, doc)
|
||||
- [ ] No `local`/`composed` code exists yet (the batch boundary
|
||||
holds — the default crate is protocol-only)
|
||||
- **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<RoundTrip>` (`Pin<Box<dyn Future>>` — 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
|
||||
|
||||
@@ -79,8 +161,8 @@ Deliverables:
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
> Filled by the implementation agent — see the Notes above.
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
> Filled on completion — see the Summary above.
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user