Commit Graph
20 Commits
Author SHA1 Message Date
glm-5.3-flash 4e1673eefc composed: the bind-first accept — the listener on a listen resource
Lands the composed accept (ADR-007 variant 2 / ADR-008): the BIND
accept whose listener lives on an alktunnels 0.2.0 bind-first listen
resource, at the graduation's vanilla fidelity.

- `composed::bindfirst_accept` — the BindAcceptFactory: opens the
  listen channel (reply#1 advertises the open-op reply's real
  `bound`, the 0.8.0 reply projection — no expected-addr stand-in),
  inserts the minted `listen` token into the correlation registry,
  and returns the accept future parked on the token's oneshot.
- `composed::register_forwarded_serving` — the forwarded-op serving
  half on the SOCKS5 producer's connection: the shared handler
  correlates by token and owns the middle pump (either-EOF
  completion; a three-party per-direction shutdown cascade would
  deadlock).
- The Sync-bound wrinkle: `SyncHalves`/`OwnedWrite` (mutex
  Sync-proof, no unsafe) over the forwarded halves; the owner
  (`ForwardedOwner`, the TunnelListener) rides inside the write
  payload — dropping the handle drops the session, halves, and
  listener together (teardown structural, compiler-enforced).
- `tests/composed-accept.rs`: the full story (real bound, real peer,
  raw pass-through round trip), client-gone teardown drop-witness,
  distinct tokens for concurrent BINDs, per-accept isolation of a
  FORBIDDEN forwarded open, late-forwarded correlation miss.
- The producer-side adopted forwarded entry rides the per-adopter
  contract (transport-EOF reap), as upstream's bind-first suites
  concede; the no-leak probe reflects that shape.

Verification: cargo test (default + --all-features), wasm
check/clippy (hard gate), clippy --all-targets --all-features -D
warnings, fmt --check — all clean.
2026-09-25 22:13:17 +00:00
glm-5.3-flash 3128d2bd4f composed: the direct-op egress — the lazy destination→tunnel table
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.
2026-09-25 14:53:18 +00:00
glm-5.3-flash 29569d9afd local: the producer-side local backend — the producer's front door
- ProducerDoor (feature local, src/local/producer_door.rs): a real
  TcpListener accept loop handing each accepted connection to the
  landed Socks5Producer::serve_socks5_over — the NoAuth in-stream RFC
  conversation with the local seam providers dialing/egressing/accepting;
  no new protocol-layer code.
- The accept path owns ADR-014's two knobs: the idle-first-byte peek
  (non-consuming) and the max-concurrent-sessions cap (try_acquire —
  an accept beyond the bound is refused door-side).
- ProducerDoorGuard: the listener's lifetime is the caller's — graceful
  close() awaits the loop's end; Drop aborts best-effort (the
  alktunnels TunnelListener teardown posture). In-flight sessions are
  never force-closed.
- Per-connection failures are logged + isolated (the loop continues).
- The BIND gate on this path is the builder's bind_policy (no open-op
  identity here; the pump handler's identity-derived gate does not
  apply) — pinned by the 0x02-refusal test.
- tests/local-backend-producer.rs (9): vanilla CONNECT round-trip on
  real sockets, faithful-RFC BIND (real reply#1/reply#2 addresses),
  UDP ASSOCIATE through the real egress, domain resolution at the
  seam, idle timeout, session cap, failure isolation, bind_policy(false).

Verification: cargo test + --all-features green; clippy clean (default,
all-features, wasm32 targets); cargo fmt --check clean; wasm checks
green (backend is local-gated).
2026-09-25 14:23:18 +00:00
glm-5.3-flash 2413646b6a door: the UDP front door — the RFC codec boundary (ADR-003)
- src/door.rs (feature local): UdpFrontDoor — a sibling of the TCP
  door (one relay UDP socket = one association; no shared accept
  loop). Inbound datagrams decode via parse_udp_request at the door's
  codec boundary and ride in-band as {addr, data} frames; replies
  encode via new_udp_header back to the client's learned source
  address. FRAG != 0 refused (dropped; association healthy). The
  association's lifetime is the channel's — the relay socket closes
  with the pump and the teardown reaps the adopted channel. The
  client idle bound (ADR-014) is constructor config.
- Pump shape: the association's stream is split (one pump owns the
  in-band write half, the other the read half) — a shared-session
  mutex deadlocks (the channel read parks holding it while the socket
  side's send needs it); the pumps join via select!.
- tests/door-udp.rs: the POC #2 test-8 shape end to end (real UDP
  echo target + local::udp_egress + vanilla RFC-header'd datagram),
  the empty-datagram invariant (F-2), FRAG refusal + health, the idle
  bound + fresh-association health.

Verification: cargo test green (default + all-features + local),
clippy -D warnings clean (default, local, wasm32 target), fmt clean,
cargo doc clean.
2026-09-25 13:20:14 +00:00
glm-5.3-flash b8fd75b9f3 door: the TCP front door — NoAuth raw pipe + RFC 1929 cred-bearing + BIND
The consumer's TCP front door (feature `local`, ADR-005/ADR-014): the
ssh `-D` local exposure vanilla clients point at.

- `src/door.rs`: `FrontDoor::builder().credentials(...).bind(...)`
  → `serve`/`serve_on`. The NoAuth door is the literal raw pipe
  (accept → channel BiStream via copy_bidirectional, zero protocol
  translation). The cred-bearing door terminates RFC 1929 locally
  (the forked accept_password_auth shape) and re-originates in-band
  via the token-carrying consumer sessions — the vanilla replies are
  re-encoded at the door (the RFC codec boundary, ADR-003), the
  password never crosses the channel as a SOCKS password. The BIND
  door rides BindSession with reply#1 fidelity (the advertised
  address passes through unchanged). UDP ASSOCIATE at the TCP door
  refuses RFC-faithfully (0x07 — the UDP door's task). The ADR-014
  accept-path defense: the idle-first-byte window (peek-based,
  door-side close) + the max-sessions cap (semaphore) as constructor
  config; per-accept failure isolation (the loop continues).
- The identity mechanism (decided + recorded in the task Notes): the
  per-credential identity rides the open-op `auth_token` payload
  (CF-005 precedence (1)) — the token is the mapped identity's id;
  the producer resolves it through ServingConfig.identity_provider.
  No per-credential ChannelClient.
- `src/consumer.rs`: `TokenClient` (the token-carrying open surface
  over the taken CallConnection + shared manager) and the
  `*_with_token` twins of the three session constructors through the
  open_with_token_and_negotiate prologue (teardown-at-birth
  preserved); `Socks5ChannelSession::reply_addr` (the CONNECT
  reply's BND.ADDR for the door's re-encoding). Existing surfaces
  untouched.
- `tests/door-tcp.rs`: 10 integration tests — the NoAuth raw-pipe
  round-trip (the POC #1 curl shape), good/bad credentials (the
  establisher witness sees the mapped identity, never the password;
  a rejection opens no channel), the never-pipes-raw-post-auth pin,
  the BIND door's vanilla conversation, the idle timeout, the
  session cap, failure isolation, and the native-session/BIND-token
  regression guards. Harness: wire_consumer_side_with_provider (the
  producer's identity provider configurable).

Verification: cargo test (375) + --all-features (423) green; clippy
-D warnings clean (default + all-features); fmt --check clean; wasm
check + wasm clippy green; default graph stays net-free.
2026-09-25 12:37:23 +00:00
glm-5.3-flash a867f0cb81 local: the socket-backed seam providers — tcp_dial / udp_egress / bind_accept
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.
2026-09-25 05:55:27 +00:00
glm-5.3-flash 07b8a74241 tests: consolidate the duplicated harness shapes (review-002 N-5)
- new tests/common/mod.rs — the single-sourced shapes, compiled into
  the lib test crate (#[cfg(test)] #[path] mod in src/lib.rs +
  extern crate self as alksocks) and the integration suite
  (tests/harness.rs declares it and re-exports under the consumed
  names; the per-test use-harness surface is unchanged)
- single-sourced: the echo dial (plain + witnessing), the refusing
  dial, the queue egress + echo factory (the harness ChanEgress /
  producer QueueEgress mutex-wrapper divergence collapsed), the
  refusing egress, the raw RFC 1928 client trio (generic over the
  stream; harness RawRfcClient delegates), the datagram frame
  codec helpers (three copies to one), the parked accept factory
- deliberately left test-local: HotNoneEgress / PureHotNoneEgress
  (R-1's two shapes), Witness / FailingSendWitness (drop flags),
  core-integration's HotNoneEgress (concurrency-load variant),
  the typed accept-refusal factories
- zero behavior change: same test population (145 lib / 38
  associate / 41 bind / 40 connect / 41 integration / 30 harness /
  37 differential / 3 doc-tests), no tests folded, net -307 lines

Verification: cargo test + --all-features green (same counts),
clippy -D warnings clean (native + wasm), fmt clean, doc clean,
both wasm checks clean, publish dry-run completes.
2026-09-25 03:39:01 +00:00
glm-5.3-flash 16b21e3447 review 002: the protocol core reviewed — readiness-contract hardening + two convention fixes
The batch-1 gate review (tasks/implementation/review-protocol-core.md):
all eight criteria examined (seam contracts, wire fidelity, access
control, teardown/lifecycle, conventions, wasm, POC fidelity, docs
sync); the gate to batch 2 opens. Findings R-1/R-2 were corrected in
the review change; R-3..R-5 are doc residues fixed in the same change;
R-6 is accepted with rationale.

- R-1 (major): the datagram stage's Ok(None) re-park is unsafe against
  a zero-yield egress — a next_reply that is a pure instantly-ready
  Ok(None) with no await wins every select! poll and livelocks the
  stage on a current-thread runtime (empirically reproduced; the
  landed unit test's mutex masked the hazard at its lock's yield
  boundary; multi-thread survives). Fix: the Ok(None) handler yields
  before re-parking; a pinning unit test drives the strictest
  zero-yield violator.
- R-2: the two into_inner expect()s (consumer sessions) become typed
  Result<_, SpentSessionError> — convention 2's no-panic rule; spent-
  session unit tests pin the shape; test call sites updated.
- R-3/R-4/R-5: doc residues — stale task-time phrasings in
  egress.rs/producer.rs, producer.md's register() sketch reconciled
  to the landed signature, the establishment-bound test doc reworded
  to what the substrate-free probe actually pins.
- R-6 (accepted): the wasm gate rides a transitive getrandom/wasm_js
  feature unification (alkcall -> jsonschema/referencing -> ahash) —
  verified compiling clean today; noted for OQ-SK2-06.

Verified: cargo test 348 green; --all-features green; clippy
--all-targets -D warnings clean; fmt --check clean; both wasm checks
clean (from a clean wasm target dir); cargo doc --no-deps clean.
The bind-only-identity reconciliation from the integration session
was independently verified as correct (ADR-006 as landed; the suite
pins it). Batch boundary holds: no local/composed code exists.
2026-09-24 09:13:08 +00:00
glm-5.3-flash 1ad8d9d489 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.
2026-09-24 07:44:54 +00:00
glm-5.3-flash c57451545d consumer: AssociateSession — the framed datagram stage + e2e suite
The UDP ASSOCIATE consumer session (POC #2's shape, consumer.md §The
associate session, ADR-003):

- `AssociateSession::associate` — open → no-auth → ASSOCIATE → reply;
  the sentinel BND.ADDR is received (`relay_addr()`, RFC fidelity)
  and never used for addressing (the handle is the channel). The
  ASSOCIATE DST.ADDR is the vanilla-mirror unspecified address.
- `send_datagram` — frames exactly once via the crate's wire
  `frame()` (the framing-once mirror; the u16 joint bound enforced
  at frame time). Takes `impl ToTargetAddr` (ADR-012 posture); a
  `ToTargetAddr for &TargetAddr` impl was added to the forked codec
  so a `TargetAddr` value survives across sends.
- `recv_datagram` — the incremental `DatagramReader` + batched-
  datagram pending queue, state persisting across calls (the POC's
  reader-state finding); `Ok(None)` on channel EOF; fail-loud on a
  stream end mid-frame and on undecodable frames (`WireError` → the
  forked `AddrError`/`UdpHeaderError` RFC classes — the consumer
  mirror of the producer stage's `UndecodableFrame` exit).
- `shutdown` — the half-close; the mux's implicit-EOF sentinel
  reaches the producer's stage as EOF (association lifetime =
  channel lifetime). `close()`/`Drop` own the teardown (sync reap +
  structural EOF, the CONNECT/BIND posture); teardown-at-birth on
  in-stream refusals; no `Clone` (compile-fail asserted).
- Typed error surface: open failures are `SocksSessionError::Open`
  (ADR-049); the missing-egress 0x07 and factory-failure codes
  surface from `associate` as `Rfc`.

E2E suite (`tests/consumer-associate.rs`, 8 tests over the harness):
round-trips (multiple in-order datagrams, one association, sentinel
relay address asserted), the split-datagram persistence test (a 60
KiB datagram reassembling across the call boundary + the pending-
queue drain — both halves of the persistence invariant), the empty-
payload round-trip (F-2, never EOF), shutdown → a fresh associate
succeeds immediately (the POC's test 4), Drop teardown + connection
health, the missing-egress refusal (typed 0x07, no phantom channel),
the egress-factory failure mapping, and the CONNECT+ASSOCIATE
regression guard (interleaved on one registration). Unit tests (4)
pin the reader internals over a duplex (`skip_auth`'s
handshake-free path).

Verification: cargo test 305 (7 suites, all green), clippy
--all-targets -D warnings, fmt, cargo doc --no-deps, and both
wasm32-unknown-unknown checks clean.
2026-09-24 07:15:27 +00:00
glm-5.3-flash 776844e2fb consumer: BindSession — the reply#2 reader + e2e suite
- BindSession::bind (open → no-auth → BIND → reply#1, capturing
  BND.ADDR) + reply1() (the BindReply1 handle) + await_inbound (the
  POC #5 read_reply2 — hand-read with the forked read_address codec,
  no second codec, ADR-011) returning BindDataPlane (into_inner /
  get_socket_mut + AsyncRead/AsyncWrite forwards)
- Teardown ownership (the CONNECT session's posture): Drop sync-reap +
  structural EOF, close() graceful, teardown-at-birth on in-stream
  refusals, no Clone (compile_fail-asserted)
- Typed error surface: open failures ride SocksSessionError::Open
  (ADR-049 reasons); the command gate's 0x02 and factory-failure
  reply#1 codes surface from bind as Rfc; accept-stage reply#2 codes
  surface at await_inbound
- tests/consumer-bind.rs: 9 e2e tests over the harness (round-trip,
  data-plane accessors, gate refusal, both failure mappings,
  quiet-wait garbage, drop teardown + health, the CONNECT+BIND
  regression guard, the Send probe)

Verification: cargo test (259 incl. the doctest), clippy -D warnings
(native + wasm), fmt, both wasm checks, cargo doc clean.
2026-09-24 00:51:46 +00:00
glm-5.3-flash 76717f3944 consumer: Socks5ChannelSession (CONNECT) — teardown ownership + e2e suite
- Socks5ChannelSession::connect: open_channel(OP_SOCKS5_OPEN, {},
  SOCKS5_ALPN) then the forked client typestate's use_stream path
  over the channel BiStream (POC #1's fit); post-reply the session
  is the raw byte pipe (0 B framing)
- Target construction via ToTargetAddr: IP-string forms parse to IP
  targets, domain form passes through unresolved (ADR-012)
- split() borrowed halves (SplitPipe) / into_inner() owned pipe
  (TakenInner — the session rides along as the teardown owner);
  channel_id() for correlation
- Teardown ownership (alktunnels ADR-005 posture): Drop sync-reaps
  the adopted entry (teardown_channel is sync; Drop cannot await) +
  the pipe drop EOFs the producer pump structurally; close() is the
  graceful path (write-half shutdown, then reap); the in-stream
  refusal tears the channel down in connect (teardown-at-birth —
  no phantom channel); no Clone (compile_fail doctest)
- Error surface: open failures are the typed SocksOpenError reasons
  (ADR-049 §4); a refused target is the RFC reply code through
  SocksSessionError::Rfc (consumer.md §Error surface)
- Harness: the consumer-side topology (wire_consumer_side[_with] —
  the consumer dials with a real ChannelClient; the producer accepts
  with the real registration) + witnessing_echo_dial; the
  allow(dead_code) attr rides the alktunnels harness posture
- tests/consumer-connect.rs: 9 e2e tests — echo round-trip + CF-006
  witness, target forms at the dial seam (ADR-012), refused dial →
  typed RFC error + no phantom channel, FORBIDDEN open → typed open
  error + no session, drop teardown + connection health, half-close
  EOF semantics, into_inner pairing, Send shape

Verified: cargo test (219 green incl. the compile_fail doctest),
clippy --all-targets -D warnings, fmt --check,
check/clippy --target wasm32-unknown-unknown
2026-09-23 23:50:01 +00:00
glm-5.3-flash df772ccbeb producer: the UDP ASSOCIATE datagram stage — the select!-driven relay (ADR-003)
- serve_udp_associate: sentinel reply (127.0.0.1:0 — the handle-swap
  surface) then the datagram stage; missing egress refuses
  RFC-faithfully (CommandNotSupported, ADR-008); egress-factory
  failure maps to reply#1's code
- run_datagram_stage: select! over channel reads ∥ egress replies
  (the concurrent full-duplex shape), typed StageExit diagnostics
  (EOF = the clean exit; undecodable frames fail loud; the egress
  readiness contract tolerated as spurious wakeups)
- wire: frame_inner — the reply-path half of framing-once (identical
  wire to frame(), pinned); egress inner bytes never re-prefixed
- tests: the readiness-contract test (instant-Ok(None) egress does
  not starve the stage), empty-payload datagram legal (never EOF),
  undecodable-frame loud fail, EOF teardown + fresh associate, the
  egress drop witness (stage owns it), missing-egress refusal +
  CONNECT guard — in-process (duplex) and over channels (harness);
  the three-command regression guard drives all commands serving

Verified: cargo test 174/174; clippy --all-targets -D warnings;
fmt --check; wasm check + clippy (wasm32-unknown-unknown); doc.
2026-09-23 21:05:33 +00:00
glm-5.3-flash cfacc8a968 producer: the session-gate establisher + the command-dispatch pump + CONNECT
The crate's core task (implementation/core-producer-connect): the
producer half of src/producer.rs per producer.md, adapted to the
crate's seam types and the alkcall 0.8.0 establishment surface.

- The session-gate establisher (`socks5_session_establisher`):
  validates/records the opener identity (the CF-005/CF-006 seam,
  ADR-005) via the optional `identity_witness` probe (the alktunnels
  posture); returns `Establishment::default()` — no plan payload
  (the dial happens post-establishment; POC #1's wire note).
- The pump handler (`make_socks5_pump_handler`): `accept_bi()` →
  the forked typestate over the `BiStream` (`accept_no_auth →
  read_command`) → dispatch. CONNECT: the dial seam (`DialFn`,
  ADR-004) at the command-read interception point; success:
  `reply_success(sentinel)` then `pump_bidi` awaited inline (R-02 —
  the JoinHandle tracks the data-plane lifetime). Refusal:
  `reply_error` with the mapped RFC code — no phantom data plane.
- The ASSOCIATE/BIND arms land as RFC-faithful refusals
  (`CommandNotSupported`) — the pre-vertical posture (ADR-008); the
  dispatch skeleton + registration signature carry the seam
  parameters from day one so the associate/bind tasks swap the arms
  without touching the registration shape.
- `register_socks5_openable`: spec + establisher + pump via
  `register_openable_with_establisher` (`timeout: None` = the 10s
  default), scope-gated `socks5:open`. Missing callbacks = those
  commands refuse RFC-faithfully, never a panic.
- `serve_socks5_over<T>`: the substrate-free protocol entry (the
  POC shape), directly testable without channels; the builder
  (`Socks5Producer::builder()`) is the spec'd assembly shape.
- Tests: 11 in-module (substrate-free duplex-driven — round-trip +
  half-close teardown, refusal mapping per variant, missing-dial
  refusal, ASSOCIATE/BIND arms, dispatch guard, establisher witness,
  builder shape) + 5 harness integration (end-to-end CONNECT echo
  with the identity witness, dial refusal 0x05 with no phantom data
  plane, scope-class refusal 0x02, ASSOCIATE/BIND refusals with
  CONNECT still serving, repeated CONNECTs on one registration).
  The harness retargeted to the real producer (`RegisterMode::
  Producer`); the minimal stand-in is a harness-internal helper.

Verification: cargo test 87+19+37 green; clippy --all-targets -D
warnings clean; fmt clean; wasm check + wasm clippy clean; cargo
doc clean; --all-features green.
2026-09-23 19:39:08 +00:00
glm-5.3-flash ac361f7610 seams: the three seam types — dial / egress / accept (ADR-004)
- egress.rs: the I/O-plane inversion point, function-not-trait at the
  three factories; Egress is the one trait (the per-association
  returned object)
- dial: TargetHandle (boxed halves, +Sync per the ChannelPlan bound),
  DialFn over the typed TargetAddr (the POCs' JSON stand-in retired),
  SocksDialError with the five-variant RFC-faithful mapping
- egress: Egress (send payload-only; next_reply returns inner bytes;
  the readiness contract — Pending when nothing is ready — documented
  on the trait), EgressFactory, EgressError, the egress_factory
  sync-lift constructor
- accept: BindAccept (the accept future owns its resources end-to-end;
  the quiet wait's drop IS the client-gone teardown), BindTargetHandle
  (ownership structural; the composed keep-alive owner rides inside
  the halves provider-side), BindAcceptFactory, the two-stage error
  pair (factory → reply#1; accept-stage → reply#2)
- no substrate type named anywhere in the module; ownership rides the
  handle structurally (no _ bindings)
- 9 new tests: the four error→reply-code tables (all variants,
  byte-compared), the sync-lift Ok/Err paths, the closure compile
  shapes, the Send/Sync/Unpin assertions; lib.rs re-exports the
  surface

Verified: cargo test (113 green), --all-features green, clippy -D
warnings clean (native + wasm32), fmt clean, cargo doc zero warnings,
wasm32 check clean.
2026-09-23 18:33:15 +00:00
glm-5.3-flash 1ccd5bbe0c params/error: the wire-stable open-op surface + the typed open-error vocabulary
- params: the ADR-001/ADR-006 constants (`channels/socks5/sub`,
  `alk/socks5`, `socks5:open`, `socks5:bind`), `socks5_open_spec()`
  (Sub/External/channel-open marker; trivial empty-object input schema
  with loud `additionalProperties: false`; reply
  `{channel_id: integer, minimum 1}` required; `socks5:open` scope),
  `Socks5Params {}` (deny_unknown_fields — empty stays valid forever),
  the `establishment_reason` helper re-export.
- error: `SocksOpenError` (the ADR-049 §4 typed surface, shaped on
  alktunnels' `TunnelOpenError`), the typed
  `SocksEstablishmentReason` vocabulary (the five reason codes,
  parse/as_str; unknown codes never aliased), `SocksOpenError::reason()`
  as the typed view, and `SocksSessionError` (open vs in-stream `Rfc`
  vs `Io` — a refused target is an RFC reply code through the session
  type, consumer.md §Error surface). `SocksError`/`SocksServerError`/
  `ReplyError` re-exported from the forked core.
- lib.rs re-exports the new public surface (convention 15).
- 9 new tests: spec shape, constants, serde round-trip +
  unknown-field rejection, the reason mapping table, the
  non-establishment classes (`FORBIDDEN`/`INVALID_INPUT`/
  `too_many_channels`), future-reason non-aliasing, the three-plane
  session surface.
- task `implementation/core-params-errors`: status → completed;
  Notes + Summary filled.

Verification: cargo test (104 green), clippy --all-targets -D
warnings clean, fmt --check clean, doc --no-deps zero warnings,
both wasm checks (check + clippy on wasm32-unknown-unknown) clean.
2026-09-23 15:17:20 +00:00
glm-5.3-flash d530eae5c4 wire: the ASSOCIATE datagram frame codec — frame + DatagramReader (ADR-003)
- frame(addr, payload): [len: u16 BE][addr + data] over
  TargetAddr::to_be_bytes() + payload; the joint bound enforced at
  frame time (checked_add; 65507 + 255-char domain = 65766 > 65535 →
  Oversize) with addr_encoding_len exposed (7 v4 / 19 v6 / 259 max
  domain) and MAX_INNER_LEN pinned
- DatagramReader: incremental reassembly across chunk boundaries
  (split frames, batched frames, partial headers), infallible,
  returning per-frame Results; the addr sub-layout decoded by hand
  (ATYP-keyed, UTF-8-validated) with typed decode errors —
  BadAtyp / ShortAddress / DomainNotUtf8 / EmptyFrame — so the
  producer stage fails the association loud on protocol garbage
  (udp_undecodable_frame_ends_association, POC #2)
- module docs state the framing-once invariant (the egress speaks
  inner bytes; this layer owns the single length prefix — the
  double-framing bug class POC #2 caught), the F-2 invariant at
  payload level (a zero-length payload is a legal empty datagram,
  never EOF; wire len == 0 is unreachable garbage), and the EOF
  layering (the channels-level sentinel, outside the codec)
- doc-sync: wire.md + bast.md residue corrected — "len == 0 is a
  legal empty datagram" replaced with the payload-level F-2
  statement (len == 0 unreachable since addr >= 7 bytes)
- lib.rs re-exports frame, DatagramReader, addr_encoding_len,
  MAX_INNER_LEN, WireError (convention 15)

Verification: cargo test (58 lib + 37 differential), clippy
--all-targets -- -D warnings, fmt --check, doc --no-deps, and both
wasm checks (check + clippy on wasm32-unknown-unknown) — all clean.
2026-09-23 15:02:24 +00:00
glm-5.3-flash ce8148d711 deps: the alkcall substrate pin + the batch-1 module skeleton
- 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)
2026-09-23 14:38:39 +00:00
glm-5.3-flash f8c34444fb rfc1928: the targeted fork — rename + convention pass (ADR-013)
The mechanical half of the posture change: src/vendor/ ->
src/rfc1928/ (module alksocks::rfc1928), tests/vendor-differential.rs
-> tests/rfc1928-differential.rs (git mv — history preserved).

- Fork point pinned: the tree as of 5b18d4d (the extraction review's
  gate commit); provenance permanent in the module docs and the
  extended LICENSE notice (upstream MIT preserved, fork-point +
  post-fork modification statement added — extend, never replace)
- The lint-allow posture dissolved: all module-level #[allow]s
  removed and the suppressed smells fixed (u8::max_value() ->
  u8::MAX, needless lifetimes elided, match_like_matches_macro
  applied, io::Error::new(Other) -> io::Error::other, the
  AuthMethod::new self-taking signature renamed
  into_starting_state, the F-4 ToSocketAddrs string re-worded — it
  no longer names the cut resolve_dns(), the unused ready! macro
  and dead AuthenticationMethod::from_u8 removed, the upstream
  commented-out async-std note folded into the impl doc)
- Module docs rewritten: ownership statement (project conventions
  apply unconditionally), extraction provenance (ADR-011) +
  ownership (ADR-013) + maintenance posture (behavioral reference,
  hand-port path)
- Differential suite survives the rename untouched (32 tests pin
  bytes, not upstream text)

Verification: cargo test (38+32 green), cargo clippy --all-targets
-D warnings, cargo fmt --check, cargo check/clippy
--target wasm32-unknown-unknown, cargo test --all-features, cargo
doc --no-deps — all pass.
2026-09-22 12:41:30 +00:00
glm-5.3-flash 57b107bdf0 vendor: crate scaffolding — Cargo.toml, lib.rs, vendor skeleton, license notice
- Cargo.toml: alksocks 0.1.0 in the sibling posture (alktunnels-style
  exclude/keywords/description); empty `local` + `composed` features
  declared (ADR-009 §Amendment — populated by their modules' tasks);
  deps = tokio wasm-clean subset (rt/sync/io-util/macros/time),
  tracing, thiserror; full tokio dev-deps. No alkcall, no net-shaped
  deps (the producer/consumer tasks pin alkcall 0.8.0).
- src/lib.rs: forbid(unsafe_code), crate docs (never-binds posture,
  vendor provenance, architecture pointer), `pub mod vendor;`.
- src/vendor/: skeleton preserving upstream fast-socks5 v1.0.0 file
  names for mechanical per-file diffs — mod.rs (provenance doc +
  server/client/util declarations), five stubs for the extraction
  tasks; socks4/ cut per ADR-011 §Amendment.
- src/vendor/LICENSE: upstream MIT text + v1.0.0 attribution header,
  referenced from the vendor module doc (ADR-011's license
  obligation; upstream has no per-file headers).
- tasks/implementation/vendor-crate-scaffolding.md: completed
  (checkboxes, notes, summary).

Verification: cargo test; clippy --all-targets -- -D warnings;
fmt --check; cargo check + clippy --target wasm32-unknown-unknown
with -D warnings — all clean; wasm gate green from birth.
2026-09-21 11:46:21 +00:00