# Changelog All notable changes to this crate are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this crate adheres to [Semantic Versioning](https://semver.org/). ## [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.toml`s/`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`, 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 `ForwardedSession`s). - **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. [`Socks5ChannelSession`]: https://docs.rs/alksocks/latest/alksocks/consumer/struct.Socks5ChannelSession.html [`AssociateSession`]: https://docs.rs/alksocks/latest/alksocks/consumer/struct.AssociateSession.html [`BindSession`]: https://docs.rs/alksocks/latest/alksocks/consumer/struct.BindSession.html [Unreleased]: https://git.alk.dev/alkdev/alksocks/compare/v0.3.0...HEAD [0.3.1]: https://git.alk.dev/alkdev/alksocks/compare/v0.3.0...v0.3.1 [0.3.0]: https://git.alk.dev/alkdev/alksocks/compare/v0.2.0...v0.3.0 [0.2.0]: https://git.alk.dev/alkdev/alksocks/compare/v0.1.0...v0.2.0 [0.1.0]: https://git.alk.dev/alkdev/alksocks/releases/tag/v0.1.0