Files
alksocks/CHANGELOG.md
T
glm-5.3-flash e196ed43e3 docs: remove em dashes from repo prose and forbid them going forward
- Rewrote em dash prose across the whole tree outside docs/reviews/
  (the historical reviews stay verbatim, matching the alktunnels and
  alktty precedent): src doc comments and inline comments (587),
  docs/architecture (319), docs/research + sdd_process (484), tests
  (361), tasks (899), fuzz (28), README/CHANGELOG/Cargo.toml (77),
  AGENTS.md (85), and the .opencode/agents prompts (109)
- Fenced content follows the precedent: comments, ASCII-diagram label
  separators, and template placeholders rewritten; wire data, JSON/BAST
  documents, byte diagrams, and transcripts survive verbatim; assert,
  expect, panic, error-display, and format message literals rewritten
  as prose; no code, fixture, or test data change
- src/rfc1928/LICENSE: the two dashes in alksocks' own provenance
  header rewritten; the MIT legal text untouched
- AGENTS.md adds Project Convention 18: no em dashes in prose; varied
  restructure, no spaced-hyphen substitutes, fenced prose rule, en
  dash numeric ranges exempt, docs/reviews/ exempt from the greps
- tasks/*.md frontmatter: the name values rewritten by the sweep are
  now quoted (a raw colon inside an unquoted YAML scalar parsed as
  null); taskgraph validate reports 37 tasks, no issues

Verification: cargo test; cargo clippy --all-targets -D warnings;
cargo fmt --check; cargo doc --no-deps; fuzz corpus replay
(cargo test --manifest-path fuzz/shared/Cargo.toml); wasm check and
clippy for wasm32-unknown-unknown with -D warnings; em dash grep over
the repo returns matches only in docs/reviews/ and the bast.md BAST
JSON data fence
2026-11-03 19:31:53 +00:00

14 KiB

Changelog

All notable changes to this crate are documented here. The format is based on Keep a Changelog, and this crate adheres to Semantic Versioning.

Unreleased

[0.3.2] - 2026-11-03

The dependency-patch release: the alktunnels sibling bumped 0.4.1 → 0.5.0 (the correlation-gate release). No alkcall bump (0.10.1 rides on), no alksocks API change, no wire change, and no change on this crate's paths: the composed accept stays on the base register_tunnel_forwarded_openable (kept byte-for-byte upstream), so the new serving-side establishment phase is an adoption question, not a bump requirement. Patch rather than minor: the dependency bump is semver-compatible (additive API only), matching the 0.3.1 precedent.

Changed

  • alktunnels 0.4.1 → 0.5.0 (crates.io). The correlation-gate release (routed from alkssh's downstream experience): the forwarded op's serving half gains an establishment phase: register_tunnel_forwarded_openable_with_establisher + ForwardedGate
    • ForwardedPlan, so a stale/missing listen token fails the open as a typed channel:open_failed with details.reason == "unknown_resource" BEFORE any channel is born (extending alkcall ADR-049's posture to the forwarded op's serving side). Additive public API only; the wire delta is empty and the base register_tunnel_forwarded_openable stays byte-for-byte. Adoption in this crate: available to the composed accept's register_forwarded_serving (the correlation registry is assembly side, so a ForwardedGate over the token map is the adoption shape), but not taken in this bump; the base registration remains the compiled path and the residual-race fallback posture.

0.3.1 - 2026-10-22

The dependency-patch release: the alkcall substrate bumped 0.10.0 → 0.10.1 (the adoption-window ordering fix) and the alktunnels sibling bumped 0.4.0 → 0.4.1 (its dependency-patch ride). No alksocks API change, no wire change; the fix surface is private upstream, so there is no change on this crate's paths. Patch rather than minor: both dependency bumps are semver-compatible (0.10.x → 0.10.1, 0.4.x → 0.4.1), matching the alktunnels 0.4.0 → 0.4.1 ride.

Changed

  • alkcall 0.10.0 → 0.10.1 (crates.io). The adoption-window ordering fix (review 013, routed from alkgit's wave-2 gate): a chunk routed by the channels demux inside the adopt_channel install→drain window was delivered ahead of earlier-parked early arrivals, inverting the channel's byte-stream order (observed downstream as pkt-line desync in alkgit under multi-process load), and a related loss variant (a chunk parked after the drain had removed the queue, parked forever) is closed. The install and its park-drain are one atomic section; no await runs inside it. Relevant in principle to this crate's reverse-path adopt flow (the bind-first establisher surfaces channels through the same adopt path), though no change in this crate's own surfaces was needed: the fix surface is private (ChannelState), the behavior only strengthens. No API, wire-format, or documented-cap behavior change upstream.
  • alktunnels 0.4.0 → 0.4.1 (the dependency-patch ride on alkcall 0.10.1). No alktunnels API/wire change; the composed providers see none of it.
  • fuzz/shared harness pin (the only file-level contacts are the Cargo.tomls/Cargo.lock, plus the doc pins): the harness declares its own alkcall pin (it constructs ChannelOpenError values for the invariant functions), so the two pins must stay in lockstep: bumped 0.10.0 → 0.10.1 with the substrate (a drifting pin produces a duplicate-type compile failure, not silent drift).

0.3.0 - 2026-10-19

The dependency-major release: the alkcall substrate bumped 0.9.0 → 0.10.0 (the gateway ownership-seam release) and the alktunnels sibling bumped 0.3.0 → 0.4.0 (its dependency-major ride on alkcall 0.10.0). No alksocks API change, no wire change; zero code contact with the 0.10.0 breaking surface (compile + suite green unchanged), which is why this is a minor bump rather than a patch: the semver-incompatible dependency bumps plus this crate's public re-exports of alkcall types (SocksOpenError::Open/open_ref carry ChannelOpenError) make it semver-visible to downstream consumers (matching the alktunnels 0.3.0 → 0.4.0 ride).

Changed

  • alkcall 0.9.0 → 0.10.0 (crates.io). The gateway ownership-seam release (review 012): GatewayDispatch gains with_ownership_provider / with_static_ownership_fallback, and the previously-silent static fallback becomes loud: an unwired spine refuses (an error envelope, FORBIDDEN, pre-dispatch) an op whose spec carries access_control.resource_type. None of it is on this crate's paths: alksocks does not use the gateway module; SOCKS5 opens serve via ChannelCore::register_openable/ register_openable_with_establisher registry dispatch on the native wire, which 0.10.0 leaves untouched. All of this crate's alkcall contact points (ChannelClient::open_channel*, ChannelOpenError, Establishment::default(), register_openable*, pump_bidi, the core types) are unchanged between 0.9.0 and 0.10.0. 145 default / 171 all-features tests pass; wasm-clean verified.
  • alktunnels 0.3.0 → 0.4.0 (the dependency-major ride on alkcall 0.10.0). No alktunnels API/wire change; the composed providers see none of it.
  • fuzz/shared harness pin (the only bump contact): the harness declares its own alkcall pin (it constructs ChannelOpenError values for the invariant functions), so the two pins must stay in lockstep, bumped 0.9.0 → 0.10.0 with the substrate (a drifting pin produces a duplicate-type compile failure, not silent drift).

0.2.0 - 2026-10-14

The dependency-major release: the alkcall substrate bumped 0.8.1 → 0.9.0 (the stub-sweep release) and the alktunnels sibling bumped 0.2.1 → 0.3.0. No alksocks API change, no wire change; no code contact with the 0.9.0 breaking surface at all (compile + suite green unchanged), which is why this is a minor bump rather than a patch: the semver-incompatible dependency bumps plus this crate's public re-exports of alkcall types make it semver-visible to downstream consumers (matching the alktunnels 0.2.1 → 0.3.0 ride).

Changed

  • alkcall 0.8.1 → 0.9.0 (crates.io). The stub-sweep release: the marked-pub open contract (S-01), channel/control (S-02), channel/resources/subscribe (S-03), and op/register forward-through (S-04) replace the four always-failing stubs. None of the four stubs were on this crate's paths (no marked-pub registration, no control-handle subscription, no resource enumerator use, no generic op/register announcements). The 0.9.0 breaking list (ManagerError::InvalidAdopt additive, RelayError::PubTypedOpen removal, the register_imported/register_imported_all return change, Establishment dropping its Debug derive) is untouched by this crate's API use: Establishment::default() is the only Establishment contact, in the session gate. 145 default / 171 all-features tests pass; wasm-clean verified.
  • alktunnels 0.2.1 → 0.3.0 (the dependency-major ride on alkcall 0.9.0). No alktunnels API/wire change; the composed providers see none of it.

0.1.0 - 2026-09-27

The initial release: SOCKS5 (RFC 1928) as a produced resource on alkcall channels, the -D flavor as a first-class protocol crate, over alkcall 0.8.1. The defining posture: the protocol never binds a port; kernel binds exist only as explicit, feature-gated assembly shapes. Composed against by the alktunnels 0.2.1 graduation (the direct op + the bind-first/forwarded flow power the composed providers). Fuzzing adopted (the fuzz/ workspace, excluded from the published package) over the crate's two attacker-reachable parsers: the ASSOCIATE datagram codec and the RFC 1928 handshake; campaigns clean, no crate bugs.

Added

  • The RFC 1928 core (src/rfc1928/, ADR-013): the targeted fork of fast-socks5 v1.0.0's T-generic subset, extracted in-tree as fully owned code (MIT notice bundled; extraction per ADR-011): the wire consts, codecs, errors, the explicit typestate server API (Socks5ServerProtocol<T, states::*>, generic over T: AsyncRead + AsyncWrite + Unpin), and the client use_stream path. Two deliberate changes carried from the fork point: BIND support in the base (ADR-007) and the new_reply publication. No kernel-net code; the default crate is wasm-clean by construction.
  • The wire codec (wire, ADR-003): the ASSOCIATE datagram frame ([len: u16 BE][addr + data]), framing applied exactly once at this layer; the DatagramReader incremental parser; the MAX_INNER_LEN oversize guard.
  • The wire-stable open-op surface (params, ADR-001/006): the alk/socks5 ALPN, the channels/socks5/sub op id, the trivial {} params (the RFC conversation is the data plane; nothing to negotiate at open time), and the two scope constants (socks5:open, socks5:bind; two grants, never implied). The typed open-error vocabulary rides error (the ADR-049 reasons).
  • The three seams (egress, ADR-004): DialFn / EgressFactory / BindAcceptFactory: functions, not traits, at the three I/O planes; ownership rides the handle structurally (TargetHandle / BindTargetHandle / BindAccept); the egress readiness contract (next_reply Pending when nothing is ready) is load-bearing API.
  • The producer half (producer): the session-gate establisher (validates the opener identity; the target is unknown at open time), the command-dispatch pump handler (CONNECT pass-through / ASSOCIATE datagram stage / BIND phase model: reply#1 → quiet wait → exactly one accept → reply#2 → pass-through), the command gate (socks5:bind at BIND dispatch), the identity witness, and both wiring shapes: the free functions (register_socks5_openable / socks5_session_establisher / make_socks5_pump_handler / serve_socks5_over) and the builder (Socks5Producer::builder(): dial/egress/accept/bind_policy). Data planes ride alkcall::channels::pump_bidi (ADR-050).
  • The consumer half (consumer): the typed channels-native sessions, each owning its channel's teardown (Drop aborts + reaps; no Clone): Socks5ChannelSession (CONNECT: raw pass-through, the split/into_inner postures), AssociateSession (the framed datagram stage: send_datagram/recv_datagram/split), BindSession (the reply#1/reply#2 reader + the BindDataPlane pass-through), and the token-carrying surface (TokenClient + the *_with_token constructor twins: the cred-bearing front door's re-origination).
  • The local feature (ADR-008/009): the socket-backed seam providers (tcp_dial / udp_egress / bind_accept: the explicit bind decisions, resolving via the non-blocking tokio::net::lookup_host resolver), plus both doors: the consumer-side front doors (FrontDoor: the NoAuth raw pipe + the RFC 1929 cred-bearing door with the credential→identity mapping, ADR-005; UdpFrontDoor: one association per bound relay socket, the RFC codec at the door boundary only, the peer-pin posture: the client's source IP pins on the first parsed datagram, replies follow the latest-seen port from that IP, foreign-IP datagrams are dropped per RFC 1928's MUST; OQ-SK2-09) and the producer-side listener (ProducerDoor: vanilla clients dial it, each accepted connection is served via serve_socks5_over; the ADR-014 idle-first-byte window + max-sessions cap knobs).
  • The composed feature (ADR-008/009): the alktunnels 0.2.1 composed providers: direct_egress (the direct-op egress: a lazy destination→tunnel table, DEFAULT_MAX_TUNNELS bounded), and bindfirst_accept + register_forwarded_serving (the BIND accept whose listener lives on a bind-first listen resource; the CorrelationRegistry correlates the forwarded op's peer metadata into ForwardedSessions).
  • The idle-timeout posture (ADR-014): every phase teardown-governed, no protocol-layer idle bound; the doors own the accept-path defense.
  • The suites: the differential suite against the upstream reference checkout (tests/rfc1928-differential.rs), the protocol-core integration suite (tests/core-integration.rs), and the assembly-layer integration suite (tests/assembly-integration.rs).
  • Fuzzing (fuzz/ workspace, docs/research/fuzzing.md): the alkcall §5 pattern adopted for this crate's two attacker-reachable parser classes: datagram_codec (the wire codec: no-panic, infallible decode, size bound, re-frame round-trip, the retained_bytes bound) and rfc1928_codec (the RFC 1928 handshake state machine, fed attacker bytes from both protocol directions), plus params_parse. Invariant logic lives in fuzz/shared/: a stable-toolchain crate replayed as plain cargo test (the corpus replay is the fuzz gate). 129 committed seeds; detached campaigns clean (oom/timeout/crash: 0/0/0, coverage saturated). The one diagnostic added: DatagramReader::retained_bytes(). fuzz/ is excluded from the workspace and from the published package.