- 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
7.5 KiB
ADR-013: The Targeted Fork: fast-socks5's T-Generic Subset Is Owned, Not Vendored
Status
Accepted (2026-09-22, post-extraction-review; supersedes the ADR-011 maintenance posture; ADR-011 stays for the extraction mechanics and the cut table; the ADR-011 §Amendment is subsumed here)
Context
ADR-011 pinned the inline-vendor posture as extraction (the
T-generic subset copied in-tree, kernel-net region not copied; the
net gate dissolving), and the vendor group (five implementation
tasks plus the review gate) landed it in commits 57b107b..5b18d4d,
with the review (tasks/implementation/ review-vendor-extraction.md) as the fidelity gate: the file-by-file
diff vs /workspace/fast-socks5 v1.0.0 categorizes every hunk, and
every review criterion passed.
The review also made the maintenance posture's cost visible. The tree is now permanently diverged from upstream in five categories:
- The extraction cut: the kernel-net region,
socks4, the legacyConfig/Authenticationlayer,Socks5Datagram, the convenience dialers, the DNS helper: gone. - The carried changes: BIND's reply surface, the published
new_reply. - The panic translations:
ReplyError::from_u8(the review's F-1),use_password_auth,reply_error's parse. - The error-pruning adjustments: anyhow/log/async-trait out,
error variants pruned,
MissingTargetAddradded. - The lint-allow posture: module-level
#[allow]s preserving upstream style (u8::max_value(), needless lifetimes,match_like_matches_macro,io_other_error,wrong_self_ convention, the F-4 verbatim string) to keep the diff mechanical.
Category 5 exists solely to keep categories 1–4 reconcilable by a line-based diff. But a future re-base against an upstream release was never going to be a clean mechanical diff again; it was always going to be manual reconciliation across all five categories. The vendor posture's maintenance apparatus (verbatim preservation, the lint allows, the re-vendor/adjustment-list discipline) pays a permanent tax to serve a re-base path that would never be used.
The "vendor" framing also produced a real defect: the review's
F-1 (ReplyError::from_u8's upstream unreachable!() arm kept
verbatim; wire-reachable, a misbehaving peer could panic the
consumer task) escaped precisely because the vendor posture
maintained a second, weaker instruction set ("verbatim + adjustments
list" instead of "project conventions, unconditionally"). The
fidelity-vs-conventions tension is structural to the vendor framing;
the review caught the escape, but the seam itself was the vendor
framing's.
The fork point is now, post-review and post-F-1, the cleanest line
the tree will ever present: the extraction provenance is in git
history (57b107b..5b18d4d), the review is the recorded fidelity
gate, and the five divergence categories are documented in ADR-011,
vendor.md, and the review task. "The tree as of the review commit
(5b18d4d) is the fork point" is a trivially defensible line.
Decision
- The extracted region is a targeted fork, fully owned by this crate. The "vendor" framing is retired: there is no upstream tree to stay reconcilable with, no re-vendor, no adjustment-list apparatus, no second instruction set. Project conventions (the AGENTS.md set) apply unconditionally to the forked code.
- The fork point is the tree as of commit
5b18d4d(the extraction review's gate commit). The extraction provenance is carried in git history (57b107b..5b18d4d), the module docs, and the extended LICENSE notice; the review task is the recorded fidelity gate. - Module naming: the forked core is
src/rfc1928/, re-exported asalksocks::rfc1928. "vendor" names an ownership relation (now gone); "socks5" would stutter with the crate name (alksocks::socks5) and collide with the future module structure (the producer/consumer/adapter layers are also SOCKS5-shaped).rfc1928names what the module is (the RFC 1928 wire vocabulary and the state machines), permanent and collision-free. - The lint-allow posture dissolves. The module-level
#[allow]s and the "verbatim lint posture" module-doc paragraphs are removed; the suppressed smells are fixed per project conventions:u8::max_value()→u8::MAX, needless lifetimes elided,match_like_matches_macroapplied,io::Error::new(Other)→io::Error::other,wrong_self_conventionfixed onAuthMethod:: new(self, ..), the F-4 string re-worded (it no longer names a cut function), and the#[allow(dead_code)]onAuthenticationMethodswept with actual usage. Upstream's commented-out dead code stays dropped (F-2). - The license mechanics: MIT permits sublicensing, so modifications after the fork point are this project's under the crate license (MIT OR Apache-2.0, per Cargo.toml). The bundled notice is extended, not replaced: upstream MIT text + copyright (the notice-preservation obligation, perpetual) + a fork-point statement + the modification note.
- The reference checkout survives as a behavioral reference.
/workspace/fast-socks5stays for differential testing of RFC edge cases; the differential suite (tests/rfc1928-differential.rs) pins bytes, not upstream text, so it survives the rename untouched. Textual-diff discipline is retired; behavioral differential testing is retained. - The cut table is re-read as the not-forked inventory, the map of what to hand-port if a future need surfaces (e.g. the kernel-net region for a standalone vanilla-server example). The hand-port path replaces the re-vendor path: port against the reference checkout, adapt to the crate's conventions, and let the suite guard it.
- The honest cost: the cheap upstream-fix path closes. A future fast-socks5 fix (a reply-code mapping correction, a codec fix) arrives as a hand-port against the reference checkout, not a diff absorb. Risk is assessed low; fast-socks5 is a quiet project, and the extracted surface is the well-trodden RFC 1928 path.
Consequences
- Positive: one instruction set (project conventions, unconditionally); the lint-allow tax and the adjustment-list apparatus dissolve; smells are fixed at the only cost that matters: a one-time cleanup verified by the existing suite. The F-1 seam class (conventions-vs-fidelity gaps) is closed structurally.
- Positive: the module name is stable for the crate's future
(no
alksocks::socks5stutter, nosocks5::producercollision pressure). - Negative (accepted): the cheap upstream-fix path closes; a future upstream fix is a hand-port against the reference checkout, guarded by the differential suite. Assessed low-risk (quiet upstream, well-trodden RFC surface).
- Neutral: the differential suite survives the rename untouched
(it pins bytes, not upstream text).
/workspace/fast-socks5keeps its role as the behavioral reference; the only thing it loses is being the target of a line-based diff. - Neutral: the fork-point line (
5b18d4d) is recorded in git history, the module docs, and the extended LICENSE notice; the extraction provenance (the ADR-011 trail) remains readable.
References
- ADR-011 (the extraction mechanics, the cut table, the carried
changes; the mechanics remain authoritative), ADR-002 (the
protocol base), ADR-009 (feature gates, no
netfeature) tasks/implementation/review-vendor-extraction.md(the fidelity gate + F-1),docs/architecture/rfc1928.md(the owned-core spec)/workspace/fast-socks5(v1.0.0, MIT, the behavioral reference for differential testing)