Commit Graph
32 Commits
Author SHA1 Message Date
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 431920ddef review: the fix-round gate closed — every review-002 finding verified, batch 2 opens
The closing checkpoint (tasks/implementation/review-fix-round-002.md):
each review-002 finding verified closed against the landed tree, the
full verification sweep green, conventions re-swept, and the gate
condition (ADR-014 accepted, no major finding) holds.

Per-finding verification (all nine checklist points):
- C-1: the take-guard verified — a second await_inbound returns the
  spent shape Ok(None), the re-read structurally impossible (the plane
  owns the stream); pinned by the double-read + reply1-twice tests.
  D-1's one-reader decision recorded (option (a), BindReply1 cut).
- C-3 closed: the builder's explicit bind_policy is the substrate-free
  gate; the presence reading is only the backward-compat default; the
  pump handler's identity-derived gate byte-identical.
- D-2 closed: the full builder chain through .register(...) serves all
  three commands end to end (RegisterMode::ProducerBuilder + the
  integration test, identity witness asserted).
- N-1/N-4 coherent: the cut list gone (zero references), keep-notes
  current, the Refused vocabulary honest at all five sites + the
  harness's minimal producer, wire untouched, provenance extended.
- D-3 resolved (declare side): the channel:open_failed ErrorDefinition
  declared, schema pinned drift-free against the typed parse table.
- N-8 re-run: 96.30% regions / 97.28% lines; every named line covered;
  the residual attributed (accept_bi log arm, fork accepted-uncovered,
  test panic-guards) — no new load-bearing gaps.
- N-5/N-6 verified: the shared module compiles into both crates via
  the crate-root mount + extern-crate-self alias; open_and_negotiate
  single-sources the teardown-at-birth prologue.
- C-2 decided: ADR-014 accepted (option 1 — teardown-governed phases),
  the spec lines carry the posture.
- Cross-cutting sweep green: test 375 green (+ all-features, local,
  composed), clippy -D warnings clean, fmt clean, doc clean, both wasm
  checks clean, publish dry-run completes; no unwrap/expect/panic in
  non-test code (mechanically attributed across src/); no local/
  composed code exists (the batch boundary holds).

One gate-round finding, F-1 (minor), fixed in this change: the
review-numbering collision — "review 002 R-1/R-2/R-4" cited the
batch-1 gate review's findings (tasks/implementation/
review-protocol-core.md) under a name that now means the general
review; reworded to "the gate review's R-N" at all six sites
(producer.rs, consumer.rs, egress.rs, the review doc). Review 002
marked resolved; the next general review doc is 003-*.

Verification: cargo test (375 green), --all-features + --features
local/composed green, clippy --all-targets -D warnings clean, fmt
--check clean, doc clean, both wasm checks clean, publish dry-run
completes, llvm-cov 96.30% regions / 97.28% lines attributed.
2026-09-25 04:02:16 +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 8dbe73d49b tests: the review-002 coverage residue — stage exits, splits, spent arms (N-8)
Eighteen new tests, zero production-code changes; every line the
review attributed in §N-8 is now covered (verified by a
`cargo llvm-cov --show-missing-lines` before/after diff).

- producer: the datagram stage's failure exits pinned as direct unit
  tests on `run_datagram_stage` (the serve layer discards StageExit,
  so the unit shape is the only place the exact matrix is assertable)
  — `ReplyFrameRejected` (a joint-bound-violating reply), `EgressEnded`
  via `next_reply`'s Err, `Io` via a failing write and a failing read;
  the `send`-failure arm got the serve-layer drop-witness treatment
  (full ASSOCIATE conversation, EOF after the refusal, the drop flag
  flips — teardown-at-birth on the failure path)
- producer: the quiet wait's `Err(_)` arm (a read *error* ends the
  wait `Ok(())`, the accept future drops with its owned state — the
  client-gone contract's error-shaped twin; driven directly on
  `bind_quiet_wait_and_serve`) and the BIND reply#2 Domain-peer
  fallback (`TargetAddr::Domain(_, port)` → `0.0.0.0:port`, the data
  plane live end to end)
- producer: the establisher's `None`-witness arm (the registration's
  optional witness seam) added to the existing unit test
- consumer: the two front-door-bridge `split`s tested on live
  `Socks5Stream<BiStream>` streams via `build_skip_auth_bi_stream`
  (two duplexes joined the `open_and_negotiate` shape) — raw framed
  bytes through both halves; the BIND split leaves the take-guard
  untouched (`await_inbound` still reads the reply#2 phase)
- consumer: the single-arm residue — spent `send_datagram`'s `Io` arm
  (+ the spent-`recv` `Ok(None)` shape asserted alongside), the
  mid-batch later-frame `Err` dropping the pending `Ok`s (the
  fail-loud-drops-pending semantics), ASSOCIATE `into_inner`'s `Ok`
  pairing, `BindDataPlane`'s `poll_flush`/`poll_shutdown`
  passthroughs (the BIND door's half-close), `read_reply2`'s
  version pin (a foreign producer's non-5 reply#2), the
  ASSOCIATE/BIND session `Debug` bodies, the spent-`close` no-op
- egress/error: the three seam-handle `Debug` renders
  (TargetHandle / BindTargetHandle / BindAccept) and
  `SocksEstablishmentReason`'s `Display` (each variant renders as
  its canonical wire code)

Coverage: 96.31% regions / 97.22% lines; no new accepted-uncovered
entries (the residual uncovered lines are the pre-existing
out-of-scope set + producer.rs 188-189's untestable `accept_bi`
substrate-failure log arm). One test-only select-shape discovery
recorded in the task Notes: `tokio::select!`'s random branch order
can drop a not-yet-polled accept future before its owned state
exists — the quiet-wait test parks once before erroring so both
branches are guaranteed started.

Verification: `cargo test` + `--all-features` green (375 tests),
clippy `-D warnings` clean (native + wasm), fmt clean, `cargo doc`
clean, both wasm checks clean.
2026-09-24 20:33:15 +00:00
glm-5.3-flash 986bd13ce7 adr-014: the idle-timeout posture — teardown-governed phases, no protocol-layer idle bound
- ADR-014 accepted (review 002 C-2): the pre-command handshake, the
  BIND quiet wait, and the association lifetime are all
  teardown-governed; the protocol layer never times out (option 1)
- the BIND relationship recorded as same regime (ADR-007 decided one
  phase's ends by designing BIND; ADR-014 records the inherited
  resolution — one principle, not two)
- the doors' accept-path obligations recorded pre-batch-2 (accept-stage
  idle bound, per-credential/per-peer caps, accept-queue bounds);
  revisitable additively (an optional producer-side idle seam would
  be config, not wire)
- spec lines carry the decided posture: wire.md (association-lifetime
  bullet, no-in-band-control bullet, preamble, frontmatter);
  producer.md (the open handler, the local-backend section, decision
  table, frontmatter); overview.md ADR index
- one upstream-fidelity correction: upstream's dial timeout maps to
  0x06 (TTL expired), not 0x01 as the review sketch suggested
- open-questions.md unchanged (C-2 was never tracked there)

Verification: cargo test green (357 passed), clippy -D warnings clean,
fmt clean, cargo doc clean, wasm check + clippy (wasm32) clean
2026-09-24 19:16:30 +00:00
glm-5.3-flash ff3295422c params: the error-schema declaration + the wire hygiene residue (review-002 D-3, N-3, N-9)
- D-3: socks5_open_spec declares the channel:open_failed
  ErrorDefinition (alktty-ported schema, adapted) — reason enum is
  the full ADR-049 §3 five-code vocabulary matching
  SocksEstablishmentReason's parse table; description carries this
  crate's gate classes (FORBIDDEN / INVALID_INPUT /
  channel:too_many_channels) + the no-phantom-channel property.
  Pinned by open_spec_declares_the_open_failed_error_definition,
  which round-trips every enum value through the typed vocabulary —
  schema and typed view cannot drift. Module doc updated from claim
  to fact.
- N-3: DatagramReader::feed's structurally-unreachable let-else
  restructured — the header read folds into the let-else's else arm
  (live-else shape); zero behavior change, wire suite green
  unchanged.
- N-9: is_mid_frame kept; doc names the anticipated batch-2 consumer
  (the front-door bridges) so dead-surface sweeps don't flag it.

Verification:
- cargo test: 357 passed, 0 failed (all suites)
- cargo clippy --all-targets -- -D warnings: clean
- cargo fmt --check: clean
- cargo doc --no-deps: clean
- cargo check --target wasm32-unknown-unknown: clean
- cargo clippy --target wasm32-unknown-unknown -- -D warnings: clean

Task: tasks/implementation/fix-hygiene-residue.md (completed)
2026-09-24 18:41:42 +00:00
glm-5.3-flash 68d5be36a0 rfc1928: the keep-or-cut sweep + the honest refusal vocabulary (review-002 N-1, N-4)
- N-1 cut: auth_method_enums! (macro + generated StandardAuthentication/
  StandardAuthenticationStarted/allow_no_auth), skip_auth_this_is_not_
  rfc_compliant, CheckResult's Option/Result impls (bool stays) — the
  producer-replaced machinery; ADR-013's no-speculative-surface posture
- N-1 keep-notes made current: ConnectError (hand-port companion; the
  fired trigger + keep disposition recorded in stream.rs),
  transfer/wait_on_tcp (differential-suite-consumed), Bug (upstream-
  verbatim, display intact)
- N-4: new SocksServerError::Refused(&'static str) — the honest log
  vocabulary for the five in-stream policy refusal sites (the BIND
  command gate + dial/egress/bind-factory/bind-accept seams) and the
  harness's minimal producer; wire bytes untouched (Bug keeps its
  display; AuthenticationRejected stays the typestate's auth-reject)
- Provenance extended, not replaced (convention 17): server.rs module
  doc's owned-changes paragraph + rfc1928.md's owned-code post-fork
  changes list + last_updated
- Differential :103 comment reworded to the RFC's ordering rationale;
  AuthMethod doc updated for the macro cut
- Tests: refusal-site session-error asserts moved to Refused, the
  mapping-table loop grew the variant, a display/shape test pins it

Verified: cargo test (356 green incl. --all-features), clippy/fmt/doc
clean, both wasm checks clean.
2026-09-24 18:20:31 +00:00
glm-5.3-flash ff81f2d27b producer: the explicit bind-policy gate + the builder-register pin (review-002 C-3, D-2, S-1, N-2)
- C-3: Socks5ProducerBuilder.bind_policy(bool) — the substrate-free
  entry's explicit BIND gate, defaulting to the accept seam's
  presence; seam presence is never the sole gate
- D-2: RegisterMode::ProducerBuilder + an integration test wiring the
  full builder through .register(...) serving all three commands
- S-1: run_datagram_stage's doc names the hot-Ok(None) residual
- N-2: wire.md §UDP ASSOCIATE carries the inline-send backpressure line

Verified: cargo test (352 green), clippy/fmt/doc clean, wasm checks clean.
2026-09-24 18:04:55 +00:00
glm-5.3-flash 53739b20cb consumer: the BIND reply#2 re-entry guard + session hygiene (review-002 C-1, D-1, N-6, S-2)
- C-1: BindSession::await_inbound is take-guarded — the first read
  takes the session's stream; the returned BindDataPlane owns it (the
  TakenInner pairing posture; the session stays the teardown owner),
  so a second call returns the family's spent shape Ok(None) and can
  never re-read the live data plane. A failed read restores the inner
  (the phase is only consumed on success; the producer ends the
  session on every post-reply#1 failure exit, so a re-call EOFs —
  never a live data-plane re-read either way). Pinned by the
  double-await_inbound integration test (the spent shape + the
  data-plane bytes asserted untouched) and the spent-BIND unit test.
- D-1: one normative reply#2 reader (option a) — the session's
  await_inbound; BindReply1::await_inbound is cut and reply1() is
  documented as a view (bind_addr + raw_mut), matching its actual
  usage; the reply1()-twice re-entry path is closed (pinned by the
  view test).
- N-6: the three session constructors' prologues collapsed into one
  private open_and_negotiate helper (teardown-at-birth in one place);
  zero behavior change.
- S-2: the EOF-propagation doc line on all three reap sites (the
  dropped teardown_channel handle is deliberate — the graceful shape;
  clear_all aborts instead).
- BindDataPlane is un-lifetimed (owns the stream); into_inner returns
  the owned Socks5Stream<BiStream>; docs synced (module + session
  docs, consumer.md §The BIND client).

Verification: cargo test 352 green (all-features too), clippy
-D warnings clean, fmt clean, cargo doc clean, both wasm checks clean.
2026-09-24 11:58:55 +00:00
glm-5.3-flash 6d14d35a54 tasks: decompose the review-002 fix round — eight dependency-ordered tasks
The general review (docs/reviews/002-protocol-core-implementation-review.md)
decomposed into the fix-round group, grouped so no session carries
both a code-fix vertical and the test sweep:

- fix-bind-reply2-reentry: C-1 (the BIND reply#2 re-entry guard) +
  D-1 (the reader decision) + N-6 (the constructor prologue
  helper) + S-2 (the reap doc line) — one consumer session
- fix-producer-gate-policy: C-3 (the explicit BIND gate input) +
  D-2 (the register/builder coverage) + S-1/N-2 (the stage doc
  lines) — one producer session
- fix-rfc1928-posture: N-1 (the keep-or-cut pass) + N-4 (the honest
  refusal vocabulary) — one fork posture session
- fix-hygiene-residue: D-3 (the ErrorDefinition declaration) +
  N-3 (the unreachable let-else) + N-9 (the is_mid_frame note)
- fix-coverage-residue: N-8's attributed line list — tests only,
  after the code fixes (final shapes)
- fix-test-helper-consolidation: N-5 — after the coverage round
- architecture/adr-014-idle-timeout-posture: C-2 — the ADR-sized
  decision, independent, before the doors exist
- review-fix-round-002: the closing checkpoint; the batch-2 gate

The review doc's disposition table now names the landed tasks.
N-7 is recorded-only (the review's own recommendation).
2026-09-24 11:18:21 +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 048493fefa producer: the BIND phase model + the socks5:bind command gate (ADR-006/ADR-007)
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)
2026-09-23 19:58:31 +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 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
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 a2483e4a84 tasks: decompose the protocol-core group — thirteen dependency-ordered tasks
Batch 1 of the Phase 1 decomposition: the default, wasm-clean crate
(producer + consumer + wire + seams + params/errors), per the
architecture spec set (ADRs 001-013) and the three POCs' validated
shapes. The assembly layer (local/composed providers, front doors) is
batch 2, decomposed after review-protocol-core opens.

- foundation: crate-deps (alkcall 0.8.0 first consumption), wire-codec
  (the ASSOCIATE frame + the joint bound), seam-types (the three
  ADR-004 seams), params-errors (the one-way-door surface)
- harness: duplex transport + identities + in-process seams (the
  alkcall 0.8.0 establishment surface proven before the producer)
- verticals: producer/consumer splits per command (CONNECT,
  ASSOCIATE, BIND) — each POC's scope, producer tasks test via the
  raw RFC client, consumer tasks e2e through the harness
- closing: integration suite (three-command regression, teardown
  matrix, identity matrix, docs sync) + review-protocol-core (the
  batch gate)

taskgraph: 8 generations, no cycles, risk path 2.55 (no high-risk
tasks). Also records the wire.md/bast.md len=0 residue (payload-level
F-2 is the operative invariant) as a doc-sync deliverable of the
wire-codec task.

Verification: cargo test (76 passed), fmt clean; taskgraph
validate/cycles/parallel/critical clean.
2026-09-23 07:38:27 +00:00
glm-5.3-flash 5b18d4d292 review: vendor extraction — gate opens; F-1 panic arm fixed
The extraction review against vendor.md's cut table, ADR-011
§Amendment, and AGENTS.md conventions. All five file diffs vs the
fast-socks5 v1.0.0 reference checkout read hunk-by-hunk and
categorized (cut / carried changes / adjustments / provenance /
tests); wasm, clippy, fmt, doc all green; RFC 1928 spot-checks
(reply form, method order, UDP zero fallback, domain cap, FRAG
split) independently verified against the RFC text.

F-1 (critical, resolved here): ReplyError::from_u8 kept upstream's
unreachable!("ReplyError code unsupported.") arm while being
wire-reachable — Socks5Stream::read_request_reply feeds the raw
reply byte from the wire into it, and RFC 1928 §6 marks 0x09-0xFF
unassigned, so a misbehaving peer would panic the consumer task.
Unassigned codes now map to GeneralFailure (the RFC's catch-all),
pinned by a new test, and the panic-translation adjustment is
recorded in vendor.md's adjustment list (with the Config-Default
and write_all notes) in the same change.

Findings F-2..F-4 (dead commented code dropped with its region;
Cargo.toml feature-layout comments; the preserved resolve_dns error
string) reviewed and accepted. Review task file carries the full
record; the gate to the downstream task groups is open.

Verified: cargo test (38 + 32), cargo test --all-features, clippy
--all-targets and --target wasm32-unknown-unknown (-D warnings),
cargo check --target wasm32-unknown-unknown, cargo fmt --check,
cargo doc --no-deps.
2026-09-22 11:01:55 +00:00
glm-5.3-flash d6fbd04ef3 vendor: the differential RFC edge-case suite — 32 duplex-only tests
tests/vendor-differential.rs pins the vendored extraction's RFC edge
behavior as explicit bytes, per vendor.md §Maintenance Posture (the
differential-testing contract; ADR-011):

- negotiation: empty/zero method lists -> 0xff, server-order method
  preference, 0x04 greeting refusal before the methods byte, EOF
  mid-handshake typed error, password sub-protocol EmptyUsername/
  EmptyPassword + the 0x01/0xff-then-error reject path
- command reads: unknown command -> 0x07 reply, RSV != 0 tolerance
  (upstream reads it unchecked), ATYP 0x02/0x05 -> 0x08, the
  255-byte domain wire maximum, truncated v4/domain address errors
- reply forms (new_reply regression guard): 10/22-byte shapes,
  constant VER/RSV across codes, zero-addr error replies, caller
  sock_addr verbatim on success
- client session: per-code ReplyError mapping (incl. the 0x06
  double map), domain request encoding, UDP-ASSOCIATE zero-target
  fallback form, skip_auth emits no greeting
- UDP codec: GarbageInReserved, FRAG passthrough (the parser
  returns it; refusing is the caller's job), v6 round-trip,
  payload split
- transfer/wait_on_tcp: pump both directions to completion, EOF on
  clean close, UnexpectedUdpControlGarbage carries the byte

Every non-obvious expectation names the upstream behavior it pins
(file + line in /workspace/fast-socks5, v1.0.0); the reference is
consulted, never linked — no build-time dependency. Duplex pairs
only (no TcpListener/UdpSocket/tokio::net in test code).

Verification: cargo test (37 unit + 32 differential),
cargo test --all-features (identical), cargo clippy --all-targets
-- -D warnings, cargo fmt --check, cargo check --target
wasm32-unknown-unknown — all clean.

Task: tasks/implementation/vendor-differential-tests.md (status ->
completed).
2026-09-21 15:27:20 +00:00
glm-5.3-flash 2ae489a205 vendor: the client session — Socks5Stream<S>::use_stream path
Extract the T-generic client session from fast-socks5 v1.0.0's
client.rs into src/vendor/client.rs (ADR-011 §Amendment extraction,
vendor.md cut table row 2): Socks5Stream<S> with use_stream (the
greeting, method-choice read, password sub-handshake, request
encoder, reply reader, socket accessors), the AsyncRead/AsyncWrite
impls, and the pruned Config (skip_auth only).

- typed MissingTargetAddr variant replaces upstream's
  anyhow::Error::msg(...).into() at client.rs:285 (the one SocksError
  addition; the client.rs:528 Other(anyhow!) site went with the cut
  Socks5Datagram)
- use_password_auth's unreachable!() is an error return (upstream's
  None-arm message; convention 2), and the sub-negotiation reply's
  version byte is now checked (was only a dropped debug!)
- write -> write_all in request_header (clippy unused_io_amount;
  byte-identical on a healthy stream)
- cut (not copied): Socks5Datagram, the Socks5Stream<TcpStream>
  convenience impl (connect*/connect_raw), Config::connect_timeout
- 14 first-party duplex tests vs raw-byte mock servers (uncorrelated
  from the vendored server typestate): both handshakes, 0xff
  refusal, version mismatch, domain/IP request forms, the full
  failure-code table, UDP-ASSOCIATE zero fallback, skip_auth,
  io-impl copy, socket accessors
- mod.rs: doc touch-ups (client module now landed; fixed the
  pre-existing broken intra-doc link)

Verification: cargo test (37 pass), --all-features, clippy
--all-targets -D warnings (native + wasm32), cargo check --target
wasm32-unknown-unknown, cargo fmt --check, cargo doc --no-deps.
2026-09-21 14:15:59 +00:00
glm-5.3-flash 9ba63fd239 vendor: the server typestate — Socks5ServerProtocol + new_reply publication
Extract the explicit typestate from fast-socks5 v1.0.0's server.rs
into src/vendor/server.rs (ADR-011 §Amendment extraction, vendor.md
cut table row 1): the states module, Socks5ServerProtocol<T, S>,
the auth machinery (AuthMethod/AuthMethodSuccessState, the
NoAuthentication/PasswordAuthentication impls, auth_method_enums! +
StandardAuthentication), negotiate_auth/read_command/reply_success/
reply_error, transfer/wait_on_tcp, try_notify!, ErrorContext<T>,
SocksServerError (landed early by the wire-vocabulary task).

- carried change #2: new_reply is pub (byte-identity tested — v4
  10-byte / v6 22-byte forms + the reply-code table)
- extraction adjustments: log calls dropped (unused bindings
  renamed), reply_error's parse().unwrap() replaced with a
  compile-time const, auth_method_enums! de-exported to
  pub(crate) use, no anyhow/async-trait
- cut (not copied): the legacy Socks5Server/Incoming/Socks5Socket,
  Config<A>/Authentication layer, DnsResolveHelper, the run_* +
  udp kernel-net handlers, the net-only test module
- 12 first-party duplex tests: full no-auth round-trip, version
  mismatch, 0xff method refusal, 0x07 unknown-command reply, both
  reply forms byte-exact, password accept/reject

Verification: cargo test (25 pass), --all-features, clippy
--all-targets -D warnings (native + wasm32), cargo check --target
wasm32-unknown-unknown, cargo fmt --check, cargo doc.
2026-09-21 14:01:06 +00:00
glm-5.3-flash 7497b79c05 vendor: the wire vocabulary — consts, commands, codecs, errors, macros
Extract fast-socks5 v1.0.0's non-net lib.rs region into
src/vendor/mod.rs (scaffolding-pinned root; the task's lib.rs target
name corrected — a second root file would conflict, see task Notes):
consts, Socks5Command (as_u8/from_u8 made pub), AuthenticationMethod,
SocksError pruned to the extracted region's consumers (no anyhow/
Redaction/InvalidHeader/ReplySocks4Error/ArgumentInputError), the
Result alias, ReplyError codec, UdpHeaderError + new_udp_header/
parse_udp_request. util/target_addr.rs gains TargetAddr/AddrError
(minus resolve_dns + its two variants)/ToTargetAddr/Addr/read_address;
util/stream.rs gains the read_exact!/ready! macros (de-exported to
pub(crate) use) + ConnectError + to_reply_error. SocksServerError
lands verbatim in server.rs early — SocksError's #[from] needs it
before the typestate task. 16 first-party codec tests (round-trips,
mapping tables, garbage-RSV/unknown-ATYP); no sockets, no env_logger.
Newer-clippy style lints allowed at module level in vendored files
(verbatim diff posture, rationale recorded).

Verification: cargo test (16 pass) + --all-features; clippy
--all-targets -D warnings (native + wasm32); cargo check
--target wasm32-unknown-unknown; cargo fmt --check; cargo doc.
Negative sweeps: no anyhow/log/tokio::net/socket2/tokio-stream/
async-trait under src/vendor/; no #[macro_export]; resolve_dns and
the pruned error variants absent.
2026-09-21 13:13:56 +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
glm-5.3-flash 2cc010cf2b tasks: decompose the vendor group — six dependency-ordered tasks
The inline vendor (vendor.md, ADR-011 §Amendment) is the root of the
crate's dependency graph; this decomposes it before any downstream
group (params/wire/producer/consumer/doors).

- vendor-crate-scaffolding: Cargo.toml (wasm-clean tokio subset, no
  alkcall yet), lib.rs, vendor/ skeleton, bundled MIT notice
- vendor-wire-vocabulary: consts, codecs, errors, macros — with the
  extraction-boundary pins (error-variant pruning, pub command
  codecs, macro de-exporting)
- vendor-server-typestate: Socks5ServerProtocol + the new_reply
  publication (carried change #2); BIND's driving is producer-group
  work, the vendor carries only the surface
- vendor-client-session: Socks5Stream::use_stream path + the
  AsyncRead/AsyncWrite impls; Config pruned (connect_timeout cut);
  tests against a raw-byte mock server so it runs parallel with the
  typestate task
- vendor-differential-tests: RFC edge-case suite over duplex streams,
  pinning upstream behavior per vendor.md's differential posture
- review-vendor-extraction: the gate before downstream groups —
  file-by-file diff vs /workspace/fast-socks5 must contain only
  cut/carried-change/adjustment hunks

Graph validated: all dependency ids resolve, no cycles; topological
order scaffolding → wire → (typestate ∥ client) → tests → review.
2026-09-21 11:39:12 +00:00
glm-5.3-flash 9587670138 docs: Phase 1 architecture — specs, ADRs 001-012, open-questions tracker
- docs/architecture/: README index, overview, wire, producer,
  consumer, vendor, bast specs + open-questions.md (the OQ-SK-01..09
  ledger promoted; new questions as OQ-SK2-06..)
- ADRs 001-012: ALPN/op/params, protocol base, the handle swap,
  the dial-callback shape, auth split by the door, access control
  (open gate + BIND command gate), BIND in base, provider defaults,
  feature gates, channel capacity, the inline vendor, target policy
- deferred OQs (SK2-06, SK2-07) with tracker tasks in
  tasks/architecture/ per the sdd_process deferred-OQ protocol
- review pass applied: frame-length joint bound (65766 corner),
  accept_no_auth vs skip_auth corrected against fast-socks5 source,
  composed-feature wasm posture, cross-reference fixes

Verified: cross-references (all ADR/OQ refs resolve), doc sizes
under split threshold, Phase 0 fidelity spot-checks
2026-09-20 18:41:56 +00:00