- 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
9.4 KiB
status: draft last_updated: 2026-09-25 (the assembly layer landed + the cross-cutting assembly integration suite; the protocol core landed + the cross-cutting integration suite 2026-09-24; the rfc1928 doc's targeted fork 2026-09-22; the vendor extraction amendment ADR-011 §Amendment 2026-09-21; Phase 1 initial draft 2026-09-20; the OQ-SK ledger promoted into ADRs 001-012 and open-questions.md)
alksocks: Architecture
A SOCKS5 (RFC 1928) producer/consumer protocol crate on alkcall
channels: an arbitrary-egress proxy service that never binds a port
unless explicitly configured to. It is the alk/socks5-family
producer/consumer protocol crate, the sibling of alktty
(alk/tty) and alktunnels (alk/tunnel). Where alktunnels
realizes the -L/-R forwarding flavors, alksocks realizes the
-D flavor (dynamic / SOCKS5 proxy). This directory holds the
architecture spec docs and the ADRs.
Current State
Phase 1 (Architecture): the protocol core and the assembly layer
are implemented. Phase
0 (docs/research/phase-0.md) is converged (2026-09-14) and
POC-complete (all numbered POCs passed or were dropped with the scope
decision); the OQ-SK ledger's Phase 1 inputs are collected and
promoted into ADRs 001–014. All docs are draft; they transition
to reviewed when their open questions resolve and the architecture
review passes.
The landed surface: the RFC 1928 core in src/rfc1928/ (the targeted
fork, ADR-013; the vendor group's six tasks landed and passed the
extraction review), the ASSOCIATE datagram frame codec (src/wire.rs,
ADR-003), the open-op params + typed error surface (src/params.rs /
src/error.rs, ADR-001), the three seam types (src/egress.rs,
ADR-004), the producer half (src/producer.rs: the session-gate
establisher, the command-dispatch pump, the three commands, the scope
gates), and the consumer half (src/consumer.rs: the
connect/associate/bind session types with teardown ownership). The
assembly layer (batch 2) landed with it: the local providers in
src/local/ (tcp_dial / udp_egress / bind_accept, the producer-side
ProducerDoor, ADR-008/009), the front doors in src/door.rs (the
NoAuth raw-pipe + RFC 1929 cred-bearing TCP door, the BIND door, the
UDP door, ADR-005/003/014), and the composed providers in
src/composed/ (the direct-op egress + the bind-first accept over
alktunnels 0.2.0, ADR-007/008). Both cross-cutting integration suites
pin the behavior end to end: tests/core-integration.rs (the
protocol core) and tests/assembly-integration.rs (the assembly
layer: the full -D story through the doors, the composed variant
set, mixed assembly, the assembly teardown matrix).
Documents
| Document | Status | Description |
|---|---|---|
| overview.md | draft | Crate purpose, the resource model in brief, dependencies, feature gates, module map |
| wire.md | draft | The wire format: the open op (trivial params, ADR-001), the phase model, the data planes (CONNECT pass-through / ASSOCIATE frames / BIND phases), sentinels |
| producer.md | draft | The producer half: the session-gate establisher, command dispatch, the three seams (dial/egress/accept), scope gates, the local backend |
| consumer.md | draft | The consumer half: the channels-native sessions (connect/associate/bind), the front doors, door auth (ADR-005), teardown ownership |
| vendor.md | draft | The RFC 1928 core: the targeted fork of fast-socks5's T-generic subset (ADR-013; the extraction mechanics in ADR-011), covering the fork's scope, the deliberate modifications, the maintenance posture |
| bast.md | draft | The BAST document for the ASSOCIATE datagram frame (ADR-003); pass-through stages have no binary framing to describe |
| open-questions.md | draft | Centralized OQ tracker (OQ-SK-01..09 promoted; new questions as OQ-SK2-06.., where the SK2 numbering is not contiguous from 01 because working-draft numbers were consumed) |
ADR Table
| ADR | Title | Status |
|---|---|---|
| 001 | ALPN, Open Op, and Trivial Params | Accepted |
| 002 | Protocol Base: the Vendored fast-socks5 Typestate Subset | Accepted |
| 003 | The Handle Swap: one Channel per Association, Frames In-Band | Accepted |
| 004 | The Dial-Callback Shape: Function, not Trait, at Three Seams | Accepted |
| 005 | Auth Mapping: "Both," Split by the Door | Accepted |
| 006 | Access-Control Posture: the Open Gate Plus the Command Gate | Accepted |
| 007 | BIND in the Base Crate: the Phase Model Extended | Accepted |
| 008 | Egress/Accept Provider Defaults: Local Socket and Composed (Direct Op) | Accepted |
| 009 | Feature-Gate Layout: local and the Composition Boundary |
Accepted (amended 2026-09-21) |
| 010 | Channel Capacity: Proxy-Workload Recommendation, Not a Wire Change | Accepted |
| 011 | the Inline Vendor: fast-socks5's T-Generic Subset, In-Tree |
Superseded by ADR-013 (extraction mechanics remain authoritative) |
| 012 | Target Policy and the Virtual-Subnet Translation Layer | Accepted |
| 013 | The Targeted Fork: the Extracted Subset Is Owned, Not Vendored | Accepted |
Upstream ADRs (alkcall/alktunnels/alknet) are referenced by their own
numbers and are NOT ported; the alkcall originals at
/workspace/@alkdev/alkcall/docs/architecture/decisions/ remain
authoritative for the shared surfaces (establishment, channels wire
format, pump_bidi, identity seam, the channel caps).
Key Design Principles
- The protocol never binds. The SOCKS5 service is a produced, ACL-scoped resource on a channels connection ("ALPN as a service"); kernel binds exist only as the two explicit, optional, feature-gated assembly shapes (the producer's local backend; the consumer's front door). The binding decision belongs to the caller. The UDP ASSOCIATE "bind" is virtualized as the channel (the handle swap, ADR-003).
- The RFC conversation is the data plane. One ALPN, one open op, trivial params (ADR-001); the phase model needs no mode byte (the reply synchronizes the switch); no in-band control vocabulary (the escape hatch is a new ALPN, never a framing change).
- The seams are functions, not traits (ADR-004): DialFn / EgressFactory / BindAcceptFactory at the three I/O planes; the protocol layer never names a substrate type; ownership rides the handle structurally.
- Auth is split by the door (ADR-005): producer = the identity seam; the front door = RFC 1929 + the credential→identity static mapping.
- Two grants, clean separation (ADR-006):
socks5:open(egress) andsocks5:bind(ingress listeners), never implied by each other; target policy = the dialer. - Backpressure and limits are inherited, not redefined (the alkcall channels invariants); the one-channel-per-session convention holds for all three commands; the proxy-workload cap posture is ADR-010 (config, not wire).
- Wasm-clean default crate (ADR-009): the default crate is
protocol-only; the RFC 1928 core is an extraction with zero
kernel-net code; there is no
netfeature (ADR-011 §Amendment);localis opt-in and non-wasm;composedrides alktunnels' wasm-clean default (verified with the wasm check at implementation). - The RFC 1928 core is owned (ADR-013, superseding ADR-011's
vendor posture): the extracted
T-generic subset is a targeted fork (src/rfc1928/, fork point5b18d4d); project conventions apply unconditionally, and the lint-allow/verbatim apparatus is dissolved;/workspace/fast-socks5stays the differential-testing behavioral reference and the only place the full upstream surface (the kernel-net region) exists; nothing waits on upstream and nothing is absorbed from it (a future upstream fix is a hand-port, guarded by the differential suite).
Document Lifecycle
| Status | Meaning | Transitions |
|---|---|---|
draft |
Under active development; may change significantly | → reviewed when the doc's open questions resolve |
reviewed |
Architecture is final; implementation may begin | → stable when implementation is complete and verified |
stable |
Locked; changes require review, may warrant an ADR | → deprecated when superseded |
deprecated |
Superseded; kept for reference | Removed when no longer referenced |
References
- Phase 0:
docs/research/phase-0.md(the OQ ledger + convergence), the POC findings files,docs/research/iroh-socks5-eval.md - The SDD process:
docs/sdd_process.md(Phase 1's process; the task format; the deferred-OQ blocker-task half) - Upstream: alkcall ADR-037/039/047/049/050/040/041/051, ledger CF-005/CF-006; alktunnels ADR-003/004/006/007/008 + the graduation research; alknet ADR-078/090
- Siblings: alktty (
/workspace/@alkdev/alktty), alktunnels (/workspace/@alkdev/alktunnels) - Reference checkout:
/workspace/fast-socks5(v1.0.0, MIT, third-party; the differential-testing reference) - RFC 1928, RFC 1929; tun2proxy (
/workspace/tun2proxy)