Files
alksocks/tasks/implementation/vendor-wire-vocabulary.md
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

12 KiB
Raw Permalink Blame History

id, name, status, depends_on, scope, risk, impact, level
id name status depends_on scope risk impact level
implementation/vendor-wire-vocabulary Vendor (the wire vocabulary, i.e. consts, commands, codecs, errors, macros) completed
implementation/vendor-crate-scaffolding
narrow low component implementation

Description

Extract the pure wire vocabulary from fast-socks5 v1.0.0 into src/vendor/, holding the RFC 1928 codecs and error enums that everything else (typestate, client sessions, producer/consumer layers) consumes. This is the "codecs" row of vendor.md's extraction table plus the lib.rs non-net region. Copy from /workspace/fast-socks5 (read-only reference checkout) and apply the extraction-time adjustments; the result must be wasm-clean by construction (no tokio::net, no anyhow, no log).

What is extracted (upstream file → in-tree target):

  1. src/lib.rs → src/vendor/lib.rs (new file: upstream's lib.rs content minus the cut regions):
    • consts module verbatim (all SOCKS5_* constants).
    • Socks5Command enum + as_u8/from_u8 (make both pub: the producer's command dispatch and the consumer's request writer both need them; upstream keeps them private with #[allow(dead_code)]).
    • AuthenticationMethod enum + impls (consumed by the client session's use_stream path; keep as-is).
    • ReplyError enum + as_u8/from_u8 verbatim.
    • UdpHeaderError enum, new_udp_header, parse_udp_request verbatim (the ASSOCIATE datagram codec per vendor.md's codecs row).
    • Result<T, E = SocksError> type alias.
    • NOT extracted: the net-heavy test module (upstream lib.rs lines 345–520, which binds real sockets; the crate's own test task covers these edge cases), the socks4 module declaration.
  2. src/util/target_addr.rs → src/vendor/util/target_addr.rs:
    • AddrError, TargetAddr (+ is_ip/is_domain/to_be_bytes/ into_string_and_port), ToSocketAddrs impl, Display impl, ToTargetAddr trait + all impls, Addr enum, read_address, all verbatim.
    • NOT extracted: the resolve_dns method (POC #4's gate map, since it is the one net-touching member; tokio::net::lookup_host is not in the wasm-clean graph). Delete the method; AddrError:: DNSResolutionFailed/NoDNSRecords go with it (see adjustments).
    • Drop the debug! log calls (upstream log, to be dropped or re-pointed at tracing; these are per-octet debug traces, so drop them).
  3. src/util/stream.rs → src/vendor/util/stream.rs:
    • read_exact! and ready! macros verbatim. Adjustment: they are #[macro_export] upstream (crate-root exported, which would pollute the alksocks public API); convert to plain macro_rules! with pub(crate) use scoping inside the vendor module so they stay internal (the wrapper's own code gets its own macros; the vendor's are implementation detail).
    • ConnectError enum + to_reply_error verbatim (the reply-code mapping vocabulary consumed by the dial seam's error mapping).
    • NOT extracted: tcp_connect/tcp_connect_with_timeout (the tokio::net::TcpStream dialers per POC #4's gate map; the crate's local backend is first-party tokio code, ADR-008).
  4. SocksError (in src/vendor/lib.rs), meaning the error vocabulary, pruned to what the extracted region + the crate's error surface actually consumes (vendor.md: "the vendored SocksError/ SocksServerError stay the wire-level vocabulary"):
    • Keep: Io, AuthMethodUnacceptable, UnsupportedSocksVersion, ExceededMaxDomainLen, AuthenticationRejected(String), ServerError(#[from] SocksServerError), UdpHeaderError(#[from] UdpHeaderError), AddrError(#[from] AddrError), ReplyError(#[from] ReplyError).
    • Drop: Redaction, InvalidHeader (dead upstream, with no consumer in the extracted region), ConnectError(#[from] ConnectError) (its only producer was the cut tcp_connect*; ConnectError itself stays, as the dial seam maps it), ReplySocks4Error (socks4 is cut), ArgumentInputError (no consumer), Other(#[from] anyhow::Error) (anyhow is dropped per vendor.md's adjustments).
    • Note: AuthenticationRejected(String) on SocksError is the client-side variant (client.rs uses it with a message); SocksServerError::AuthenticationRejected (unit) is the server-side one; both stay, each in its own enum.

Extraction-time adjustments (mechanical, per ADR-011 §Amendment + vendor.md): drop anyhow wrapping, drop log calls, prune error variants whose only producers/consumers were cut, keep thiserror derives. No behavior change: every kept codec's wire behavior is byte-identical to upstream v1.0.0.

Acceptance Criteria

  • src/vendor/lib.rs, src/vendor/util/{mod,stream,target_addr}.rs exist with the inventory above; cargo test compiles (boundary note: the vocabulary lives in src/vendor/mod.rs, not a second root file src/vendor/lib.rs, because the completed scaffolding task pinned the vendor root as mod.rs with upstream file names preserved; a second root file would be an E0758 conflict. Upstream's lib.rs content minus the cut regions is what mod.rs now carries.)
  • cargo check --target wasm32-unknown-unknown clean
  • cargo check (native, default features) clean
  • No anyhow, log, tokio::net, socket2, tokio-stream, async-trait anywhere under src/vendor/
  • Socks5Command::as_u8/from_u8 are pub (the wrapper needs them; upstream had them private)
  • read_exact!/ready! are not exported at the crate root (no #[macro_export]); they resolve inside the vendor module
  • TargetAddr has no resolve_dns method; AddrError has no DNSResolutionFailed/NoDNSRecords variants
  • SocksError has no Other(anyhow::Error), no Redaction, no InvalidHeader, no ReplySocks4Error, no ArgumentInputError variants
  • cargo clippy --all-targets -- -D warnings and cargo fmt --check clean
  • Unit tests for the codecs pass: to_be_bytes/read_address round-trip (v4/v6/domain), new_udp_header/parse_udp_request round-trip, ReplyError::as_u8/from_u8 mapping table, ported from upstream's non-net test regions where extractable (vendor.md's "non-net test modules" row), adjusted to the crate's test layout (no env_logger, no real sockets)

References

  • docs/architecture/vendor.md (the extraction table + the cut table)
  • docs/architecture/decisions/011-inline-vendor.md §Amendment (the mechanical adjustments)
  • docs/architecture/decisions/002-protocol-base.md (the codecs are the wire vocabulary; "no second codec, ever")
  • Upstream: /workspace/fast-socks5/src/lib.rs, /workspace/fast-socks5/src/util/target_addr.rs, /workspace/fast-socks5/src/util/stream.rs
  • POC #4 gate map: docs/research/poc-connect-wasm-findings.md (lib.rs/util rows)

Notes

  • Module placement correction: the task text says src/vendor/lib.rs, but the completed scaffolding task pinned the vendor root as src/vendor/mod.rs (skeleton with mod + submodule declarations already committed, 57b107b). A second root file (lib.rs alongside mod.rs) is an E0758 conflict, so the vocabulary landed in mod.rs as upstream's lib.rs content minus the cut regions, appended after the scaffolding module doc. The review task's file-by-file diff vs upstream is unaffected (the upstream lib.rs region maps to mod.rs; noted here for the reviewer).
  • SocksServerError lands early: SocksError keeps ServerError(#[from] server::SocksServerError) per the task's keep-list, but server.rs was a stub and a #[from] needs the type now. Upstream defines SocksServerError at the top of server.rs; it landed there verbatim (enum + to_reply_error, including UnexpectedUdpControlGarbage) as the first item of the server-typestate task's inventory, with a module doc noting the early landing. The server task's remaining inventory is unchanged.
  • Verbatim-code lint posture: the copied upstream regions trip newer-clippy style lints (match_like_matches_macro, legacy_numeric_constants for u8::max_value(), io_other_error for io::Error::new(Other), needless_lifetimes, redundant_closure). Churning vendored code to satisfy a newer clippy would break the mechanical per-file diff posture (vendor.md §Maintenance Posture; review task criterion 1), so the lints are allowed at module level with the rationale recorded. Behavior is untouched.
  • AuthenticationMethod::as_u8/from_u8 stay private with upstream's #[allow(dead_code)]: the client session task's send_version_and_methods consumes them when it lands. Making them pub now would be ahead of need (the task pins pub only for Socks5Command).
  • ready! macro: upstream's server typestate consumes it (the transfer/wait_on_tcp region); nothing in the vocabulary region does. It rides with #[allow(unused_macros)]/#[allow(unused_imports)] until the typestate lands, and it is kept verbatim now so the util diff stays complete.
  • Tests: the vocabulary region's unit tests are first-party (upstream's lib.rs test module is the cut net-heavy region, so none of its tests are extractable); the codec tests here follow the crate's test layout (tokio duplex for read_address, plain slice parsing for parse_udp_request, no env_logger, no sockets). ConnectError::to_reply_error and AddrError:: to_reply_error mappings are pinned too (the dial seam + the address-type reply mapping are wire-adjacent behavior). Vendored enums keep upstream's derives (no PartialEq was added), so tests compare via as_u8()/matches! rather than adding derives.
  • The ToSocketAddrs impl's error string still names TargetAddr::resolve_dns() (upstream text preserved verbatim) even though the method is cut, and note it in the module doc; a future consumer hitting that path gets the explicit-resolution message exactly as upstream produced it.

Summary

Extracted the wire vocabulary from fast-socks5 v1.0.0 per ADR-011 §Amendment + vendor.md: upstream lib.rs's non-net region (consts, Socks5Command with pub as_u8/from_u8, AuthenticationMethod, the pruned SocksError (no anyhow/Redaction/InvalidHeader/ ConnectError-from/ReplySocks4Error/ArgumentInputError), the Result alias, ReplyError codec, UdpHeaderError + new_udp_header/parse_udp_request) into src/vendor/mod.rs (the scaffolding-pinned root; the task's lib.rs target name was corrected (see Notes), AddrError/TargetAddr/ToTargetAddr/Addr/ read_address minus resolve_dns into util/target_addr.rs, and the read_exact!/ready! macros (de-exported to pub(crate) use)

  • ConnectError + to_reply_error into util/stream.rs. SocksServerError (enum + to_reply_error) landed verbatim in server.rs early, since SocksError's #[from] needs it before the typestate task lands. 16 first-party unit tests cover the codecs (v4/v6/domain round-trips, UDP header/parse incl. frag/payload/garbage RSV/unknown ATYP, reply-code mapping table, command mapping, to_reply_error mappings, ToTargetAddr conversions, domain-length cap). Verified: cargo test (16 pass), --all-features, clippy --all-targets -- -D warnings native + wasm32, cargo check --target wasm32-unknown-unknown, cargo fmt --check, cargo doc, and the negative sweeps (no anyhow/log/tokio::net/socket2/ tokio-stream/async-trait in vendor code; no #[macro_export]; resolve_dns + the five pruned error variants absent).