docs: pin the vendor scope as extraction — the net gate dissolves
Complete the ADR-011 §Amendment (extraction, not wholesale-copy-plus- gate) across every doc that stated the pre-amendment posture: - ADR-011: add the two extraction-recipe exclusions the amendment missed (the socks4 module — upstream's separate default-off cargo feature, out of RFC 1928 scope; the legacy Config/Authentication auth layer — ungated but consumed only by the cut region) and the dependency-surface adjustments (log -> tracing, anyhow dropped, async-trait dropped with its legacy-layer uses) - ADR-009: amend — the vendor's net gate dissolves; features collapse to local + composed; local carries tokio/net + socket2 itself - vendor.md: replace the contradictory old "four carried changes" section with the two-change reading + extraction-time adjustments; extend the cut table (socks4 row, legacy auth layer) - overview.md: dependency diagram + feature table drop the net feature; module map reflects two carried changes - README.md: principles 7/8 + doc/ADR tables updated - ADR-002/012, open-questions.md (OQ-SK-04), phase-0.md current-state sections, AGENTS.md conventions 4/17 + stale wasm-caveat sentence, POC findings posture notes: aligned with the extraction Verification: repo-wide grep for stale "four carried"/default-on net/ implies-net statements returns only amendment-context matches; extraction recipe re-verified against POC #4's gate map and the fast-socks5 v1.0.0 source (async-trait usage confined to the cut legacy layer; AuthMethod<T> traits are native async-fn-in-trait).
This commit is contained in:
1 parent
9587670138
commit
b0cfc26065
12 files changed
+367
-178
No files matched your search
+14
-12
@@ -1,7 +1,8 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-09-20 (Phase 1 initial draft — the OQ-SK ledger
|
||||
promoted into ADRs 001-012 and open-questions.md)
|
||||
last_updated: 2026-09-21 (the vendor extraction amendment — ADR-011
|
||||
§Amendment, ADR-009 §Amendment; Phase 1 initial draft 2026-09-20 —
|
||||
the OQ-SK ledger promoted into ADRs 001-012 and open-questions.md)
|
||||
---
|
||||
|
||||
# alksocks — Architecture
|
||||
@@ -34,7 +35,7 @@ decomposition phase.
|
||||
| [wire.md](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](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](consumer.md) | draft | The consumer half: the channels-native sessions (connect/associate/bind), the front doors, door auth (ADR-005), teardown ownership |
|
||||
| [vendor.md](vendor.md) | draft | The inline vendor: the vendored fast-socks5 subset's scope, the four carried changes, the maintenance posture |
|
||||
| [vendor.md](vendor.md) | draft | The inline vendor: the extracted fast-socks5 subset's scope (extraction, not wholesale copy), the two carried changes, the maintenance posture |
|
||||
| [bast.md](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](open-questions.md) | draft | Centralized OQ tracker (OQ-SK-01..09 promoted; new questions as OQ-SK2-06.. — the SK2 numbering is not contiguous from 01, working-draft numbers were consumed) |
|
||||
|
||||
@@ -50,9 +51,9 @@ decomposition phase.
|
||||
| [006](decisions/006-access-control.md) | Access-Control Posture — the Open Gate Plus the Command Gate | Accepted |
|
||||
| [007](decisions/007-bind-in-base.md) | BIND in the Base Crate — the Phase Model Extended | Accepted |
|
||||
| [008](decisions/008-provider-defaults.md) | Egress/Accept Provider Defaults — Local Socket and Composed (Direct Op) | Accepted |
|
||||
| [009](decisions/009-feature-gates.md) | Feature-Gate Layout — `net`, `local`, and the Composition Boundary | Accepted |
|
||||
| [009](decisions/009-feature-gates.md) | Feature-Gate Layout — `local` and the Composition Boundary | Accepted (amended 2026-09-21) |
|
||||
| [010](decisions/010-channel-capacity.md) | Channel Capacity — Proxy-Workload Recommendation, Not a Wire Change | Accepted |
|
||||
| [011](decisions/011-inline-vendor.md) | the Inline Vendor — fast-socks5's `T`-Generic Subset, In-Tree | Accepted |
|
||||
| [011](decisions/011-inline-vendor.md) | the Inline Vendor — fast-socks5's `T`-Generic Subset, In-Tree | Accepted (amended 2026-09-21) |
|
||||
| [012](decisions/012-target-policy.md) | Target Policy and the Virtual-Subnet Translation Layer | Accepted |
|
||||
|
||||
Upstream ADRs (alkcall/alktunnels/alknet) are referenced by their own
|
||||
@@ -90,14 +91,15 @@ format, `pump_bidi`, identity seam, the channel caps).
|
||||
convention holds for all three commands; the proxy-workload cap
|
||||
posture is ADR-010 (config, not wire).
|
||||
7. **Wasm-clean default crate** (ADR-009): the default crate is
|
||||
protocol-only; the vendored subset rides the default-on `net`
|
||||
gate (ADR-011); `local` is opt-in and non-wasm; `composed` rides
|
||||
alktunnels' wasm-clean default (verified with the wasm check at
|
||||
implementation).
|
||||
protocol-only; the vendor is an extraction with zero kernel-net
|
||||
code — there is no `net` feature (ADR-011 §Amendment); `local` is
|
||||
opt-in and non-wasm; `composed` rides alktunnels' wasm-clean
|
||||
default (verified with the wasm check at implementation).
|
||||
8. **The vendor is first-class** (ADR-011): the `T`-generic subset
|
||||
in-tree with the four carried changes; `/workspace/fast-socks5`
|
||||
stays the differential-testing reference; nothing waits on
|
||||
upstream.
|
||||
extracted in-tree with two carried changes (BIND, `new_reply`);
|
||||
`/workspace/fast-socks5` stays the differential-testing reference
|
||||
and the only place the full upstream surface (the kernel-net
|
||||
region) exists; nothing waits on upstream.
|
||||
|
||||
## Document Lifecycle
|
||||
|
||||
|
||||
@@ -30,10 +30,11 @@ functionally complete (a full RFC 1928 CONNECT conversation passes
|
||||
`Socks5Server`/`Socks5Socket`/`Incoming` bind-based API is
|
||||
deprecated upstream and is out — never vendored into the default
|
||||
path.
|
||||
- **Base = v1.0.0, inline-vendored** (see ADR-011 for the vendor
|
||||
mechanics and the four carried changes). `/workspace/fast-socks5`
|
||||
remains the read-only reference for differential testing of RFC
|
||||
edge cases; the vendor point is noted in the vendored code.
|
||||
- **Base = v1.0.0, inline-vendored as an extraction** (see ADR-011
|
||||
for the vendor mechanics and the two carried changes).
|
||||
`/workspace/fast-socks5` remains the read-only reference for
|
||||
differential testing of RFC edge cases; the vendor point is noted
|
||||
in the vendored code.
|
||||
- **Refusals map faithfully per RFC 1928** — `ReplyError` codes
|
||||
(`as_u8`/`from_u8`) are the error vocabulary at the command plane;
|
||||
refusals are never collapsed into generic errors (AGENTS.md
|
||||
@@ -41,9 +42,8 @@ functionally complete (a full RFC 1928 CONNECT conversation passes
|
||||
|
||||
## Consequences
|
||||
|
||||
- The crate owns its protocol code in-tree (the vendor), so the
|
||||
wasm gate, BIND, and the seam fixes ride the same tree — no
|
||||
upstream waits.
|
||||
- The crate owns its protocol code in-tree (the vendor), so BIND and
|
||||
the `new_reply` publication ride the same tree — no upstream waits.
|
||||
- The typestate's interception points are the layering seams:
|
||||
command-read (the dial/accept dispatch), `transfer` (the raw
|
||||
two-pump), and — where the default handlers are unusable (UDP
|
||||
|
||||
@@ -1,35 +1,34 @@
|
||||
# ADR-009: Feature-Gate Layout — `net` (the Vendor's Gate), `local`, and the Composition Boundary
|
||||
# ADR-009: Feature-Gate Layout — `local` and the Composition Boundary
|
||||
|
||||
## Status
|
||||
|
||||
Accepted (2026-09-20, Phase 1; the wasm-clean default-crate invariant
|
||||
is the alk* family posture — AGENTS.md convention 4)
|
||||
is the alk* family posture — AGENTS.md convention 4). Amended
|
||||
2026-09-21 (pre-decomposition): the vendor's `net` gate dissolves
|
||||
under ADR-011's extraction amendment — the vendor is
|
||||
wasm-clean by construction; features collapse to `local` +
|
||||
`composed`; see §Amendment.
|
||||
|
||||
## Context
|
||||
|
||||
The default crate must compile to `wasm32-unknown-unknown` (the
|
||||
alktty/alktunnels precedent; the wasm shape is a sandboxed
|
||||
SOCKS5 consumer — pure byte framing, no local sockets needed
|
||||
client-side; phase-0 OQ-SK-04's analysis). Three groups of
|
||||
client-side; phase-0 OQ-SK-04's analysis). Two groups of
|
||||
platform-specific or sibling-dependent code need gating:
|
||||
|
||||
1. **The vendored fast-socks5 subset's kernel-net touches** — POC #4
|
||||
measured the gate at ~120 cfg lines across 5 files, keyed on one
|
||||
feature (`net = ["tokio/net", "dep:socket2", "dep:tokio-stream"]`,
|
||||
default-on for native; wasm users build with
|
||||
`default-features = false`).
|
||||
2. **The crate's own local backends** (dial/listen/egress providers
|
||||
1. **The crate's own local backends** (dial/listen/egress providers
|
||||
touching real sockets — ADR-008's local variants).
|
||||
3. **The composed providers** (the alktunnels-composed egress/accept
|
||||
2. **The composed providers** (the alktunnels-composed egress/accept
|
||||
helpers — ADR-008's composed variants), which need the
|
||||
alktunnels dependency.
|
||||
|
||||
One design constraint from OQ-SK-04's resolution: the vendored
|
||||
subset's `net` gate and the crate's own backend gate are
|
||||
*mechanically the same boundary* (tokio::net + socket2), but their
|
||||
*ownership* differs — the vendor's gate ships with the vendored
|
||||
code (v1.0.0-faithful + carried changes), the crate's local backends
|
||||
are first-party code.
|
||||
The vendor originally contributed a third gate: its kernel-net
|
||||
region was to ride a default-on `net` feature (POC #4's measured
|
||||
shape, ~120 cfg lines across 5 files). ADR-011's 2026-09-21
|
||||
amendment pins the vendor as *extraction* — the kernel-net region is
|
||||
not copied, so that gate no longer exists (see §Amendment). POC #4's
|
||||
gate map survives as the extraction recipe, not as in-tree cfg.
|
||||
|
||||
## Decision
|
||||
|
||||
@@ -37,15 +36,15 @@ are first-party code.
|
||||
placement per [overview.md](../overview.md): protocol, wire,
|
||||
producer, consumer, vendor modules at the core; backend modules
|
||||
feature-gated, never imported by the protocol layer.
|
||||
- **`net` (default-on)**: the vendored subset's kernel-net gate
|
||||
(POC #4's shape, carried into the vendor). Turning it off yields
|
||||
the wasm-clean functional protocol subset (a full RFC 1928
|
||||
conversation passes — POC #4's verification).
|
||||
- **The default build has no `net` feature**: the extracted vendor
|
||||
contains zero kernel-net code, so the wasm-clean subset is the
|
||||
whole crate — there is nothing to gate (ADR-011 §Amendment).
|
||||
- **`local` (default-off)**: the crate's first-party local backends
|
||||
— the TCP dial, the UDP egress socket, the BIND listener, and the
|
||||
front doors (the consumer's ssh `-D` local exposure; the
|
||||
producer's local backend). Implies `net`. Non-wasm by design
|
||||
(enabling it on wasm is a build error, the alktty posture).
|
||||
producer's local backend). Brings `tokio/net` + `socket2` into the
|
||||
graph. Non-wasm by design (enabling it on wasm is a build error,
|
||||
the alktty posture).
|
||||
- **`composed` (default-off)**: the composed providers over
|
||||
alktunnels 0.2.0 (direct-op egress, bind-first listen accept) —
|
||||
the only feature that adds the alktunnels dependency. The
|
||||
@@ -53,8 +52,32 @@ are first-party code.
|
||||
module does, injected at the assembly layer (ADR-004/ADR-008).
|
||||
- **tokio stays `default-features = false`** with the wasm-clean
|
||||
subset (`rt`, `sync`, `io-util`, `macros`, `time`) — **never
|
||||
`features = ["full"]`** (AGENTS.md convention 4); `net` and
|
||||
`process`-shaped additions ride the features above.
|
||||
`features = ["full"]`** (AGENTS.md convention 4); `net`-shaped
|
||||
additions ride `local` alone.
|
||||
|
||||
## Amendment (2026-09-21, pre-decomposition — the vendor's `net` gate dissolves)
|
||||
|
||||
The original decision carried a third feature — `net`
|
||||
(default-on), the vendored subset's kernel-net gate, with `local`
|
||||
implying it. ADR-011's extraction amendment dissolves it:
|
||||
|
||||
- The vendor is an extraction of the `T`-generic inventory only; the
|
||||
kernel-net region (`run_tcp_proxy`, `run_udp_proxy*`, the legacy
|
||||
`Socks5Server`/`Incoming` API, `Socks5Datagram`'s kernel path, the
|
||||
DNS-resolve helper, the net-only tests), the `socks4` module, and
|
||||
the legacy `Config`/`Authentication` layer are not copied into the
|
||||
tree — the extraction is wasm-clean by construction, with no
|
||||
in-tree cfg gate.
|
||||
- Features collapse to two: **`local`** (first-party socket
|
||||
providers + front doors, ADR-008; brings `tokio/net` + `socket2`
|
||||
into the graph itself) and **`composed`** (the alktunnels
|
||||
providers). `local` no longer implies a separate `net` feature —
|
||||
it is the sole gate for socket/platform I/O.
|
||||
- POC #4's gate map survives as the *extraction recipe* (its
|
||||
ungated inventory is what to copy), not as in-tree cfg.
|
||||
- The wasm verification is a hard gate with no feature toggles:
|
||||
`cargo check --target wasm32-unknown-unknown` and native
|
||||
`--no-default-features` both compile the same complete crate.
|
||||
|
||||
## Consequences
|
||||
|
||||
@@ -65,17 +88,16 @@ are first-party code.
|
||||
`cargo test --all-features`, and both wasm checks
|
||||
(`cargo check/clippy --target wasm32-unknown-unknown`) — the
|
||||
structural guard for the invariant.
|
||||
- The vendor's carried changes (BIND, the `run_udp_proxy_custom`
|
||||
bind seam, `new_reply` publication) live inside the `net`-gated
|
||||
region where they touch kernel sockets and in the ungated
|
||||
`T`-generic region where they don't (the BIND typestate driving
|
||||
is `T`-generic; only the local-socket accept variant is
|
||||
`net`-gated).
|
||||
- The vendor's carried changes (BIND, `new_reply` publication) live
|
||||
in the extracted region where they touch codecs/typestate; nothing
|
||||
vendored is gated — the only feature-gated socket code is the
|
||||
crate's own first-party `local` module.
|
||||
|
||||
## References
|
||||
|
||||
- OQ-SK-04 (resolved: inline vendor — see ADR-011), OQ-SK-01/03/08
|
||||
(the providers the features gate)
|
||||
- POC #4 `poc-connect-wasm-findings.md` (the measured gate),
|
||||
- POC #4 `poc-connect-wasm-findings.md` (the measured gate — now the
|
||||
extraction recipe),
|
||||
alktty's `local` feature (the posture precedent), alktunnels
|
||||
ADR-004 + overview.md (the same three-way split)
|
||||
ADR-004 + overview.md (the same feature split)
|
||||
@@ -3,7 +3,9 @@
|
||||
## Status
|
||||
|
||||
Accepted (2026-09-20, Phase 1; OQ-SK-04's resolution — the ownership
|
||||
premise corrected the same day)
|
||||
premise corrected the same day). Amended 2026-09-21 (pre-decomposition):
|
||||
the vendor scope is pinned as **extraction** — the kernel-net handlers
|
||||
are not copied; see §Amendment.
|
||||
|
||||
## Context
|
||||
|
||||
@@ -35,18 +37,21 @@ Two facts settled the posture: the ownership premise was wrong
|
||||
(no cheap "file asks / PR" path), and the carried needs (2–4) exist
|
||||
regardless of the wasm question — so the vendor pays for itself
|
||||
without leaning on the adapter story. The change set is exactly the
|
||||
shape POC #4 measured as minimal.
|
||||
shape POC #4 measured as minimal. (Need 1 later dissolves —
|
||||
§Amendment; needs 3's handler is not extracted with it.)
|
||||
|
||||
## Decision
|
||||
|
||||
- **Vendor the `T`-generic subset into this crate** (the codecs, the
|
||||
typestate machinery, the client `use_stream` path — the parts
|
||||
already generic over `T: AsyncRead + AsyncWrite + Unpin`), gated
|
||||
behind the default-on `net` feature (ADR-009; POC #4's gate
|
||||
shape).
|
||||
- **Extract the `T`-generic subset into this crate** (see §Amendment
|
||||
for the mechanical reading of "extract"): the codecs, the typestate
|
||||
machinery, the client `use_stream` path — the parts already generic
|
||||
over `T: AsyncRead + AsyncWrite + Unpin`. The extraction contains
|
||||
zero kernel-net code and is wasm-clean by construction.
|
||||
- **Carry the four needs in the same vendor**: the net gate, BIND
|
||||
(the typestate-driven shape, ADR-007), the `run_udp_proxy_custom`
|
||||
seam fix, and the `new_reply` publication.
|
||||
seam fix, and the `new_reply` publication. (Post-Amendment: the
|
||||
net gate dissolves — see §Amendment; BIND and `new_reply` are the
|
||||
two that touch extracted code.)
|
||||
- **Note the vendor point (v1.0.0) in the vendored code**; keep the
|
||||
MIT license obligations (upstream is MIT; preserve the license
|
||||
header per file or a bundled notice).
|
||||
@@ -63,12 +68,84 @@ shape POC #4 measured as minimal.
|
||||
- The crate owns its protocol code in-tree: no upstream release
|
||||
cadence, no feature waits, and the vendored code co-evolves with
|
||||
the wrapper (the carried changes are first-class, not patches).
|
||||
- The cost is maintenance of the vendored subset (~4k LoC upstream;
|
||||
the vendored subset is the smaller `T`-generic region + codecs).
|
||||
The vendor's diff vs upstream is deliberate and bounded: the four
|
||||
carried changes + the license/provenance notes.
|
||||
- The cost is maintenance of the extracted subset (the `T`-generic
|
||||
region + codecs — a fraction of upstream's ~4k LoC; POC #4's
|
||||
ungated inventory is the shopping list). The diff vs upstream is
|
||||
deliberate and bounded: the extraction cut + the carried changes +
|
||||
the license/provenance notes.
|
||||
- **Nothing in the crate routes through the kernel-net handlers**;
|
||||
if a future need surfaces (e.g. a standalone vanilla-server
|
||||
example), the fix is re-vendor that piece then, as an additive
|
||||
decision.
|
||||
- Differential testing against `/workspace/fast-socks5` guards the
|
||||
RFC edge cases the vendored code must keep passing.
|
||||
RFC edge cases the extracted code must keep passing.
|
||||
|
||||
## Amendment (2026-09-21, pre-decomposition — "extract" pinned, the `net` gate dissolves)
|
||||
|
||||
The decision's wording ("vendor the `T`-generic subset") supported
|
||||
two mechanical readings; this amendment pins the intent so the
|
||||
decomposition task is unambiguous:
|
||||
|
||||
- **Extraction, not wholesale-copy-plus-gate.** Copy *only* the
|
||||
`T`-generic inventory into `src/vendor/`; the kernel-net handlers
|
||||
(`run_tcp_proxy`, `run_udp_proxy*`, `udp_bind_random_port`, the
|
||||
legacy `Socks5Server`/`Incoming` API, `Socks5Datagram`'s kernel
|
||||
socket path, the DNS-resolve helper, the net-only tests), the
|
||||
`socks4` module (upstream's separate default-off `socks4` cargo
|
||||
feature, which POC #4 never compiled; out of this crate's RFC 1928
|
||||
scope), and the legacy `Config<A>`/`Authentication` auth layer
|
||||
(ungated upstream, but consumed only by the cut legacy/net region)
|
||||
are **not copied into the crate**; they remain available in
|
||||
`/workspace/fast-socks5`, the differential-testing reference.
|
||||
The kernel-net region is carried only as the cfg *map* (POC #4's
|
||||
five-file inventory), recorded in `vendor.md` so a future
|
||||
re-vendor knows the cut.
|
||||
- **Why**: convention 17's letter ("vendor the `T`-generic subset");
|
||||
no crate consumer routes through the kernel-net region (the
|
||||
producer/consumer/doors drive the typestate and the pure codecs;
|
||||
the local backends are first-party tokio code — ADR-004/ADR-008);
|
||||
and the BIND + `new_reply` needs touch only the extracted region
|
||||
(BIND's driving is wrapper-side code per POC #5 — "zero upstream
|
||||
ask for BIND itself").
|
||||
- **The `net` feature gate dissolves.** With no kernel-net code
|
||||
in-tree, the extraction is wasm-clean by construction — no
|
||||
`#[cfg]` gate needed inside the vendored files. Features collapse
|
||||
to two: `local` (the crate's first-party socket providers and
|
||||
front doors, ADR-008) and `composed` (the alktunnels providers).
|
||||
POC #4's gate map survives as the *extraction recipe* (its ungated
|
||||
inventory is exactly what to copy), not as in-tree cfg. tokio
|
||||
stays `default-features = false` with the wasm-clean subset
|
||||
(AGENTS.md convention 4); `tokio/net` rides `local` alone.
|
||||
- **The carried-changes list re-reads under extraction**: (1) the
|
||||
net gate — dissolves (no net code); (2) BIND — stays (the typestate
|
||||
driving + reply#2 writer are in-tree; ADR-007); (3) the
|
||||
`run_udp_proxy_custom` bind seam — dissolves (the handler isn't
|
||||
extracted; the typestate-driving shape POC #2 validated is the
|
||||
crate's ASSOCIATE path); (4) `new_reply` publication — stays
|
||||
(it is inside the extracted codec region). Net: **two carried
|
||||
changes** touch extracted code.
|
||||
- **Extraction completeness is compiler-checked**: a missed
|
||||
transitive dependency is a build error, and the wasm check
|
||||
(`cargo check --target wasm32-unknown-unknown`, plus
|
||||
`--no-default-features` native) is the structural guard. The
|
||||
extracted crate must compile clean with no `net`-shaped feature.
|
||||
- **The extraction's dependency surface is adjusted, not absorbed**:
|
||||
upstream's `log` calls in the extracted region are dropped or
|
||||
re-pointed at the crate's `tracing` (the alk* convention); the
|
||||
extracted region's `anyhow::Context` error wrapping is dropped
|
||||
(error surface is the crate's `thiserror` types — the vendored
|
||||
`SocksError`/`SocksServerError` stay the wire-level vocabulary);
|
||||
`async-trait` is dropped (its four upstream uses are all on the
|
||||
legacy `Authentication` layer, which is cut — the typestate's
|
||||
`AuthMethod<T>` traits are native async-fn-in-trait); the
|
||||
`socks4` module and the legacy `Config`/`Authentication` layer are
|
||||
out (above). These are extraction-time mechanical adjustments to
|
||||
the copied code, not new carried changes.
|
||||
|
||||
The verification commands in AGENTS.md that mention the wasm check
|
||||
failing on the dependency graph are stale for this crate (that
|
||||
caveat predated OQ-SK-04's resolution); the extraction makes the
|
||||
wasm check a hard gate as in alktty/alktunnels.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -39,7 +39,9 @@ against a per-identity resource table).
|
||||
have no resolver at all, and the composed variant's targets ride
|
||||
the alktunnels direct op (producer-side resolution there, per
|
||||
alktunnels ADR-007's own posture). fast-socks5's `dns_resolve`
|
||||
config stays off — it is a kernel-net concern, gated with `net`.
|
||||
config (and its `resolve_dns` step) is not part of the extracted
|
||||
vendor region at all — the crate's producer never resolves
|
||||
(ADR-006/ADR-012), so the extraction drops both.
|
||||
- **The virtual-subnet translation layer is assembly-layer policy,
|
||||
not a crate feature.** The crate ships no translation-table
|
||||
helper in v1: the dial callback is the seam, and a deployment
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-09-20 (Phase 1 initial draft — the OQ-SK ledger
|
||||
OQ-SK-01..09 promoted; new questions continue as OQ-SK2-06..)
|
||||
last_updated: 2026-09-21 (OQ-SK-04's resolution updated to the
|
||||
extraction posture; the OQ-SK ledger OQ-SK-01..09 promoted 2026-09-20;
|
||||
new questions continue as OQ-SK2-06..)
|
||||
---
|
||||
|
||||
# alksocks — Open Questions
|
||||
@@ -84,10 +85,11 @@ sequence starts at the numbers in use. Format per
|
||||
- **Origin**: [phase-0.md](../research/phase-0.md) (OQ-SK-04)
|
||||
- **Status**: resolved — [ADR-011](decisions/011-inline-vendor.md)
|
||||
- **Priority**: high
|
||||
- **Resolution**: 2026-09-20 (Phase 0's final resolution, promoted).
|
||||
The inline vendor: the `T`-generic subset in-tree behind the
|
||||
default-on `net` feature; the four carried changes (net gate,
|
||||
BIND, the udp-bind seam, `new_reply` publication); v1.0.0 noted;
|
||||
- **Resolution**: 2026-09-20 (Phase 0's final resolution, promoted;
|
||||
amended 2026-09-21 by ADR-011 §Amendment). The inline vendor as
|
||||
**extraction**: the `T`-generic subset in-tree with zero kernel-net
|
||||
code (wasm-clean by construction, no `net` feature); two carried
|
||||
changes (BIND, `new_reply` publication); v1.0.0 noted;
|
||||
differential testing against `/workspace/fast-socks5`.
|
||||
- **Cross-references**: ADR-002, ADR-009, ADR-011
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-09-20 (Phase 1 initial draft — the OQ-SK ledger promoted
|
||||
last_updated: 2026-09-21 (the vendor extraction amendment — no `net`
|
||||
feature; Phase 1 initial draft 2026-09-20 — the OQ-SK ledger promoted
|
||||
into ADRs 001-012 and open-questions.md)
|
||||
---
|
||||
|
||||
@@ -126,12 +127,9 @@ alksocks (default — wasm-clean)
|
||||
├── serde/serde_json (params schema), thiserror (error surface), tracing
|
||||
└── (no backend deps — sockets live in feature-gated modules)
|
||||
|
||||
alksocks (net feature, default-on) — non-wasm
|
||||
└── adds: tokio/net, socket2, tokio-stream (the vendored subset's
|
||||
kernel-net gate; ADR-009)
|
||||
|
||||
alksocks (local feature) — non-wasm by design
|
||||
└── adds: the first-party local backends + front doors (implies net)
|
||||
└── adds: tokio/net + socket2 (the feature's own socket providers) and
|
||||
the first-party local backends + front doors
|
||||
|
||||
alksocks (composed feature)
|
||||
└── adds: alktunnels 0.2.0 (the direct op egress; the bind-first
|
||||
@@ -141,18 +139,19 @@ alksocks (composed feature)
|
||||
```
|
||||
|
||||
Same posture as alktty/alktunnels: the default crate is
|
||||
protocol-only and wasm-clean; the vendored fast-socks5 subset rides
|
||||
the `net` gate (ADR-011); substrate I/O is feature-gated
|
||||
(ADR-009). `fast-socks5` is NOT a Cargo dependency — it is vendored
|
||||
in-tree (ADR-011).
|
||||
protocol-only and wasm-clean — the vendor is an *extraction* of
|
||||
fast-socks5's `T`-generic subset, containing zero kernel-net code,
|
||||
so there is no `net` feature at all (ADR-011 §Amendment);
|
||||
substrate I/O rides `local` alone (ADR-009 §Amendment).
|
||||
`fast-socks5` is NOT a Cargo dependency — it is extracted in-tree
|
||||
(ADR-011).
|
||||
|
||||
## Feature Gates
|
||||
|
||||
| Feature | Contents | Wasm |
|
||||
|---------|----------|------|
|
||||
| *(default)* | the vendored `T`-generic subset (codecs, typestate), wire codec, open-op spec, the three seams' traits/types, producer + consumer session types — protocol only | yes |
|
||||
| `net` *(default-on)* | the vendored subset's kernel-net pieces (`tokio/net`, `socket2`): the local-socket default handlers, DNS resolve helper, `Socks5Datagram` kernel socket path | no (wasm builds use `default-features = false`) |
|
||||
| `local` | the crate's first-party local backends: TCP dial, UDP egress socket, BIND `TcpListener` accept, the front doors (consumer + producer local shapes) — implies `net` | no (build error on wasm, the alktty posture) |
|
||||
| *(default)* | the extracted `T`-generic subset (codecs, typestate), wire codec, open-op spec, the three seams' traits/types, producer + consumer session types — protocol only; zero kernel-net code, wasm-clean by construction | yes |
|
||||
| `local` | the crate's first-party local backends: TCP dial, UDP egress socket, BIND `TcpListener` accept, the front doors (consumer + producer local shapes); brings `tokio/net` + `socket2` into the graph | no (build error on wasm, the alktty posture) |
|
||||
| `composed` | the composed providers over alktunnels 0.2.0: direct-op egress (lazy destination→tunnel table), bind-first listen accept — adds the alktunnels dep | yes (alktunnels' default crate is wasm-clean; the composed providers use only its ungated channels surface — verify with the wasm check at implementation) |
|
||||
|
||||
## Module Map
|
||||
@@ -160,10 +159,10 @@ in-tree (ADR-011).
|
||||
```
|
||||
src/
|
||||
lib.rs — re-exports; crate docs
|
||||
vendor/ — the vendored fast-socks5 T-generic subset (ADR-011;
|
||||
vendor/ — the extracted fast-socks5 T-generic subset (ADR-011;
|
||||
vendor point v1.0.0 noted in-tree): codecs, typestate,
|
||||
client use_stream path, carried changes (BIND reply
|
||||
writer, new_reply publication, the udp-bind seam)
|
||||
client use_stream path; two carried changes (BIND reply
|
||||
writer, new_reply publication); no kernel-net code
|
||||
params.rs — the trivial params schema + SOCKS5_OPEN_SCOPE/
|
||||
SOCKS5_BIND_SCOPE constants (ADR-001/006)
|
||||
wire.rs — the ASSOCIATE datagram frame codec, re-implemented
|
||||
@@ -207,9 +206,9 @@ All design decisions are documented as ADRs in [decisions/](decisions/).
|
||||
| [006](decisions/006-access-control.md) | Access-control posture | `socks5:open` gate + `socks5:bind` command gate; target policy = the dialer |
|
||||
| [007](decisions/007-bind-in-base.md) | BIND in the base crate | phase model extended (reply#1 → quiet wait → accept → reply#2 → pass-through); additive |
|
||||
| [008](decisions/008-provider-defaults.md) | Provider defaults | local-socket + composed (direct op) providers, both feature-gated; no implicit dialer |
|
||||
| [009](decisions/009-feature-gates.md) | Feature gates | `net` (default-on, the vendor's gate), `local`, `composed`; default crate wasm-clean |
|
||||
| [009](decisions/009-feature-gates.md) | Feature gates | `local` + `composed`; no `net` feature (the vendor is wasm-clean by construction — ADR-011 §Amendment); default crate wasm-clean |
|
||||
| [010](decisions/010-channel-capacity.md) | Channel capacity | no wire change; assembly-layer config + the documented proxy-workload recommendation |
|
||||
| [011](decisions/011-inline-vendor.md) | The inline vendor | the `T`-generic subset vendored in-tree; the four carried changes; v1.0.0 noted |
|
||||
| [011](decisions/011-inline-vendor.md) | The inline vendor | the `T`-generic subset extracted in-tree; two carried changes (BIND, `new_reply`); v1.0.0 noted |
|
||||
| [012](decisions/012-target-policy.md) | Target policy | dialer-refuses; domain targets pass through unresolved; virtual subnets = assembly policy |
|
||||
|
||||
## Open Questions
|
||||
|
||||
+103
-41
@@ -1,6 +1,8 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-09-20 (Phase 1 initial draft)
|
||||
last_updated: 2026-09-21 (the extraction amendment — ADR-011 §Amendment:
|
||||
extraction not wholesale copy, the net gate dissolves, two carried
|
||||
changes; Phase 1 initial draft 2026-09-20)
|
||||
---
|
||||
|
||||
# alksocks — The Inline Vendor (fast-socks5 subset)
|
||||
@@ -12,71 +14,131 @@ vendor's scope, the carried changes, and the maintenance posture.
|
||||
The protocol base decision is ADR-002; the feature gating is
|
||||
ADR-009.
|
||||
|
||||
## What is Vendored
|
||||
## The Mechanism: Extraction, Not Wholesale Copy (ADR-011 §Amendment)
|
||||
|
||||
The vendor is an **extraction**: copy *only* the `T`-generic
|
||||
inventory from fast-socks5 v1.0.0 into `src/vendor/`; the kernel-net
|
||||
handlers are **not copied** — they stay in `/workspace/fast-socks5`
|
||||
(the read-only reference checkout). Concretely: POC #4's cfg map
|
||||
(its five-file inventory of what is kernel-net-gated) is the base of
|
||||
the extraction recipe — copy what POC #4 left *ungated*, minus the
|
||||
two recorded exclusions (the `socks4` module and the legacy
|
||||
`Config`/`Authentication` layer — see the cut table). The extraction
|
||||
contains zero kernel-net code, so it is wasm-clean by construction;
|
||||
there is no in-tree `net`-shaped feature gate (that part of POC #4's
|
||||
change dissolves — ADR-011 §Amendment).
|
||||
|
||||
## What is Extracted
|
||||
|
||||
From fast-socks5 **v1.0.0** (MIT, third-party upstream —
|
||||
`/workspace/fast-socks5` is the read-only reference checkout; the
|
||||
vendor point is noted in the vendored code):
|
||||
vendor point is noted in the extracted code):
|
||||
|
||||
| Piece | Why it rides | Gating |
|
||||
|-------|--------------|--------|
|
||||
| The server typestate (`Socks5ServerProtocol<T, states::*>`, negotiate/auth/command-read/reply) | the producer's conversation driver (ADR-002) | `T`-generic — ungated |
|
||||
| The auth traits (`AuthMethod<T>`/`AuthMethodSuccessState<T>`) | the negotiation machinery (the crate uses NoAuth in-band; the traits stay for fidelity) | ungated |
|
||||
| `transfer` (the generic two-pump) | the interception-point shape (the crate's data plane is `pump_bidi`, but `transfer` is the typestate's own seam) | ungated |
|
||||
| The codecs: `new_udp_header`/`parse_udp_request`, `TargetAddr`/`to_be_bytes`/`read_address`, `new_reply` (published — carried change #4), `ReplyError`/`SocksError`/`SocksServerError` | the RFC wire vocabulary everywhere (front doors, associate frames, reply#2 reader) | ungated |
|
||||
| The client types: `Socks5Stream<S>::use_stream` + the `AsyncRead/AsyncWrite` impls | the consumer half's stream session (ADR-002; POC #1's fit) — the first-party associate session in `consumer.rs` was informed by this shape (upstream's `Socks5Datagram` kernel path is the net-gated row) | ungated |
|
||||
| Kernel-net pieces (the local-socket default handlers, `Socks5Datagram`'s kernel socket path, the DNS resolve helper, the legacy `Socks5Server`/`Incoming`) | upstream surface kept for fidelity where `net` is on | **`net`-gated** |
|
||||
| Piece | Why it rides | Notes |
|
||||
|-------|--------------|-------|
|
||||
| The server typestate (`Socks5ServerProtocol<T, states::*>`, negotiate/auth/command-read/reply, `accept_no_auth`/`finish_auth`/`accept_password_auth`) | the producer's conversation driver (ADR-002) | `T`-generic |
|
||||
| The auth traits (`AuthMethod<T>`/`AuthMethodSuccessState<T>`) | the negotiation machinery (the crate uses `accept_no_auth` in-band; the traits stay for fidelity) | `T`-generic |
|
||||
| `transfer` + `wait_on_tcp` | the typestate's own two-pump seam (the crate's data plane is `pump_bidi`; `transfer` is the interception-point shape) | `T`-generic |
|
||||
| The codecs: `new_udp_header`/`parse_udp_request`, `TargetAddr`/`to_be_bytes`/`read_address`, `ReplyError`/`SocksError`/`SocksServerError` | the RFC wire vocabulary everywhere (front doors, associate frames, reply#2 reader) | pure; `new_reply` published in-tree (carried change) |
|
||||
| The client types: `Socks5Stream<S>::use_stream` + the `AsyncRead/AsyncWrite` impls | the consumer half's stream session (ADR-002; POC #1's fit) — the first-party associate session in `consumer.rs` was informed by this shape | `T`-generic |
|
||||
| The non-net test modules (where extractable as unit tests) | RFC edge-case coverage rides in-tree | adjusted to the crate's test layout |
|
||||
|
||||
Not vendored: the deprecated `Socks5Server`/`Socks5Socket`/`Incoming`
|
||||
bind-based API as a *default path* (it exists upstream and stays
|
||||
behind `net`; the crate never routes through it). The vendored subset
|
||||
is functionally complete without `net` (POC #4: a full RFC 1928
|
||||
CONNECT conversation passes `--no-default-features`).
|
||||
## What is NOT Extracted (the cut — POC #4's gated inventory + two recipe additions)
|
||||
|
||||
## The Four Carried Changes (ADR-011)
|
||||
These stay in `/workspace/fast-socks5` (the differential-testing
|
||||
reference); the cut table below records the boundary, so a future
|
||||
re-vendor knows the cut. Rows 1–5 are POC #4's five-file cfg map
|
||||
(what POC #4 gated is what is not extracted); the socks4 row and the
|
||||
legacy `Config`/`Authentication` layer are this recipe's two
|
||||
additions — the socks4 module is out of RFC 1928 scope, and the
|
||||
legacy auth layer was left ungated by POC #4 (it compiles without
|
||||
net) but no extraction consumer reaches it. None of it is copied:
|
||||
|
||||
The vendor's diff vs upstream v1.0.0 is deliberate and bounded:
|
||||
| Upstream file | Region NOT in `src/vendor/` |
|
||||
|---|---|
|
||||
| `src/server.rs` | `run_tcp_proxy`, `run_udp_proxy`/`run_udp_proxy_custom`, `udp_bind_random_port`, the legacy `Socks5Server`/`Incoming`/`Socks5Socket` (struct + impls), `DnsResolveHelper` trait + impl, `handle_udp_*`/`transfer_udp`, the net-only test module — plus the legacy `Config<A>` + `Authentication` trait + impls (`SimpleUserPassword`/`DenyAuthentication`/`AcceptAuthentication`, `authenticate_callback`), which POC #4 left ungated but which only this cut region consumes (rows 1–5 are POC #4's gate map; the `Config`/`Authentication` layer and the socks4 row are this recipe's two additions) |
|
||||
| `src/client.rs` | `Socks5Datagram` (struct + impl), the `Socks5Stream<TcpStream>` convenience impl (`connect`/`connect_with_password`/`connect_raw`) |
|
||||
| `src/util/stream.rs` | `tcp_connect*` fns (the `read_exact!`/`ready!` macros + `ConnectError` stay) |
|
||||
| `src/util/target_addr.rs` | the `resolve_dns` method (the codec stays) |
|
||||
| `src/lib.rs` | the net-heavy test module (consts/errors/UDP-header codec stay) |
|
||||
| `src/socks4/` | the whole module (upstream's separate default-off `socks4` cargo feature; out of RFC 1928 scope) |
|
||||
|
||||
1. **The `net` feature gate** — ~120 `#[cfg]` insertions across 5
|
||||
files, exactly POC #4's measured shape
|
||||
(`poc-connect-wasm-findings.md` §The gating change: server.rs
|
||||
~8 insertions; client.rs 87 diff lines (whitespace-inflated);
|
||||
util/stream.rs, util/target_addr.rs, lib.rs ≤3; Cargo.toml's
|
||||
`net = ["tokio/net", "dep:socket2", "dep:tokio-stream"]`).
|
||||
2. **BIND** — absent upstream (every handler refuses
|
||||
**Why none of it is needed in-tree** (ADR-011 §Amendment): no crate
|
||||
consumer routes through the kernel-net region — the producer drives
|
||||
the typestate directly (the ASSOCIATE path is the POC #2
|
||||
typestate-driving shape; `run_udp_proxy_custom` is unusable on
|
||||
channels regardless), the consumer sessions use `use_stream` plus
|
||||
the first-party associate session, the doors are pure codecs +
|
||||
first-party bridges, and the local backends are first-party tokio
|
||||
code (ADR-008). The "producer-side local backend" is a bridge *onto
|
||||
the channels-served service* (POC #1's door shape), not a standalone
|
||||
vanilla server. If a future need surfaces (e.g. a standalone
|
||||
vanilla-server example), the fix is re-vendor that piece then, as an
|
||||
additive decision.
|
||||
|
||||
## The Carried Changes (ADR-011, re-read under extraction)
|
||||
|
||||
The extraction's diff vs upstream v1.0.0 is deliberate and bounded —
|
||||
**two changes touch extracted code**; the other two of the original
|
||||
four dissolve with the kernel-net region:
|
||||
|
||||
1. **BIND** — absent upstream (every handler refuses
|
||||
`Socks5Command::TCPBind`). The crate drives the typestate itself
|
||||
for the BIND shape (ADR-007); the vendor carries the shape
|
||||
in-tree (`reply_success`'s `sock_addr` as the reply#1 carrier;
|
||||
the reply#2 writer using the published `new_reply`).
|
||||
3. **The `run_udp_proxy_custom` bind seam** — the seam is narrower
|
||||
than it looks (`udp_bind_random_port` unconditionally; the reply
|
||||
port derives from that kernel socket). In-tree fix: make the bind
|
||||
optional / accept a caller-supplied socket. (The channels path
|
||||
drives the typestate directly regardless; the fix serves the
|
||||
`net`-gated path's embedders.)
|
||||
4. **`new_reply` publication** — the reply encoder becomes public
|
||||
2. **`new_reply` publication** — the reply encoder becomes public
|
||||
(a `reply(code, addr)`-shaped constructor) so the BIND reply#2
|
||||
writer doesn't re-encode the 10/22-byte reply form.
|
||||
|
||||
Dissolved: the `net` feature gate (no net code in-tree) and the
|
||||
`run_udp_proxy_custom` bind seam (the handler isn't extracted).
|
||||
|
||||
Plus the provenance notes: the vendor point (v1.0.0) and the license
|
||||
headers (MIT; preserve per-file headers or a bundled notice —
|
||||
ADR-011's license obligation).
|
||||
|
||||
Plus the **extraction-time adjustments** (not carried changes —
|
||||
mechanical edits to the copied code, ADR-011 §Amendment):
|
||||
|
||||
- The `socks4` module is out entirely (upstream's separate
|
||||
default-off `socks4` cargo feature, which POC #4 never compiled;
|
||||
out of RFC 1928 scope). `SocksError`'s `ReplySocks4Error` variant
|
||||
(also `#[cfg(feature = "socks4")]` upstream) goes with it.
|
||||
- The legacy `Config<A>`/`Authentication` auth layer is out
|
||||
(ungated upstream, but consumed only by the cut legacy/net region
|
||||
— `Socks5Server`/`Socks5Socket`/the `run_*` handlers; the
|
||||
typestate's own `accept_no_auth`/`accept_password_auth` are the
|
||||
crate's in-band auth surface). With it go `async-trait` (its four
|
||||
upstream uses are all on this layer), the example auth impls
|
||||
(`SimpleUserPassword`/`DenyAuthentication`/`AcceptAuthentication`),
|
||||
and `SocksError`'s `AuthenticationRejected`-consuming legacy
|
||||
plumbing that only they exercise.
|
||||
- Upstream `log` calls in the extracted region are dropped or
|
||||
re-pointed at the crate's `tracing`.
|
||||
- Upstream `anyhow` error wrapping (`Context` / `Other(#[from]
|
||||
anyhow::Error)`) is dropped — the crate's error surface is
|
||||
`thiserror`-typed; the vendored `SocksError`/`SocksServerError`
|
||||
stay the wire-level vocabulary.
|
||||
|
||||
## Maintenance Posture
|
||||
|
||||
- **The vendor is first-class code, not a patch stack**: the carried
|
||||
changes live in-tree and co-evolve with the wrapper; the vendored
|
||||
changes live in-tree and co-evolve with the wrapper; the extracted
|
||||
subset's RFC fidelity is the crate's own test suite's job.
|
||||
- **Differential testing**: `/workspace/fast-socks5` stays the
|
||||
reference for RFC edge cases (reply-code mapping, domain
|
||||
addressing, fragmentation). The crate's test suite covers the
|
||||
edge cases the vendored code must keep passing; when in doubt,
|
||||
diff behavior against the reference checkout.
|
||||
edge cases the extracted code must keep passing; when in doubt,
|
||||
diff behavior against the reference checkout. The kernel-net
|
||||
region lives there too — the reference checkout is the only place
|
||||
the full upstream surface exists.
|
||||
- **Upstream posture**: fast-socks5 is third-party; nothing waits on
|
||||
it. Offering the `net` gate upstream as a courtesy PR is optional
|
||||
(POC #4: small enough to offer as-is); a future upstream release
|
||||
may be re-based against deliberately, never absorbed silently
|
||||
(the carried changes would need re-verification).
|
||||
it. Offering a net-gate PR upstream is optional courtesy (POC #4:
|
||||
small enough to offer as-is) and unrelated to this crate's build —
|
||||
the extraction doesn't need it. A future upstream release may be
|
||||
re-based against deliberately, never absorbed silently (the
|
||||
extraction cut + carried changes would need re-verification).
|
||||
- **No second codec, ever**: the vendored codecs are the only RFC
|
||||
wire vocabulary in the crate (ADR-011's rationale; the alknet
|
||||
anti-prior-art record is in phase-0 §Anti-prior-art).
|
||||
@@ -86,8 +148,8 @@ ADR-011's license obligation).
|
||||
| ADR | Decision | Summary |
|
||||
|-----|----------|---------|
|
||||
| [002](decisions/002-protocol-base.md) | Protocol base | the explicit typestate API only |
|
||||
| [009](decisions/009-feature-gates.md) | Feature gates | `net` default-on; wasm builds use `default-features = false` |
|
||||
| [011](decisions/011-inline-vendor.md) | The inline vendor | the subset in-tree; the four carried changes; v1.0.0 noted |
|
||||
| [009](decisions/009-feature-gates.md) | Feature gates | `local`, `composed`; the default crate is wasm-clean with no `net` feature (ADR-011 §Amendment) |
|
||||
| [011](decisions/011-inline-vendor.md) | The inline vendor | the extraction in-tree; two carried changes (BIND, `new_reply`); v1.0.0 noted |
|
||||
|
||||
## Open Questions
|
||||
|
||||
|
||||
+35
-28
@@ -168,9 +168,11 @@ not start from zero. It inherits:
|
||||
layer (alktty `TtyBackend` / alktunnels no-trait precedent).
|
||||
- **The wasm-clean default crate** — protocol-only code should compile
|
||||
to `wasm32-unknown-unknown` (alktty/alktunnels precedent). The
|
||||
vendored fast-socks5 subset is wasm-clean: the inline vendor gates
|
||||
kernel-net behind a default-on `net`-shaped feature (OQ-SK-04
|
||||
resolved; POC #4 verified the subset is functionally complete).
|
||||
extracted fast-socks5 subset is wasm-clean by construction: the
|
||||
inline vendor is an extraction (the `T`-generic subset only; the
|
||||
kernel-net handlers are not copied — OQ-SK-04 resolved; ADR-011
|
||||
§Amendment, 2026-09-21; POC #4 verified the subset is functionally
|
||||
complete).
|
||||
- **The upstream substrate this crate composes against** — alkcall
|
||||
0.8.0 (reply projection; `ChannelRelay`/`HubLegTemplate` per ADR-051;
|
||||
flavor-form open-op ids in discovery per ADR-047 amendment 3) and
|
||||
@@ -219,13 +221,15 @@ load-bearing conclusions this crate inherits:
|
||||
### fast-socks5 — the vendored implementation
|
||||
|
||||
`/workspace/fast-socks5` (v1.0.0, MIT — third-party upstream, not ours;
|
||||
read-only reference checkout). **The posture is the inline vendor
|
||||
(OQ-SK-04, resolved 2026-09-20): vendor the `T`-generic subset into this
|
||||
crate behind a default-on `net`-shaped feature, carrying the wrapper's
|
||||
needs in-tree.** `/workspace/fast-socks5` remains the differential-testing
|
||||
reference for RFC edge cases (reply-code mapping, domain addressing,
|
||||
fragmentation); note the vendor point (v1.0.0) in the vendored code. Key
|
||||
surface points, verified:
|
||||
read-only reference checkout). **The posture is the inline vendor as an
|
||||
extraction (OQ-SK-04, resolved 2026-09-20; extraction pinned
|
||||
2026-09-21, ADR-011 §Amendment): extract the `T`-generic subset into
|
||||
this crate — the kernel-net handlers and the `socks4` module are not
|
||||
copied — carrying the wrapper's needs in-tree.**
|
||||
`/workspace/fast-socks5` remains the differential-testing reference
|
||||
for RFC edge cases (reply-code mapping, domain addressing,
|
||||
fragmentation); note the vendor point (v1.0.0) in the vendored code.
|
||||
Key surface points, verified:
|
||||
|
||||
- **Explicit typestate server API** (`src/server.rs`):
|
||||
`Socks5ServerProtocol<T, states::Opened|Authenticated|CommandRead>`,
|
||||
@@ -284,15 +288,17 @@ surface points, verified:
|
||||
proxy, refuse, or handle in-process. Structurally the shape of the
|
||||
channels open handler (inspect params → dial or refuse) and of the
|
||||
alknet ADR-090 client (hand the established stream to quinn).
|
||||
- **What the vendor must add (the four carried needs):** the
|
||||
kernel-net feature gate (POC #4: ~120 cfg lines, wasm-clean subset
|
||||
functionally complete); **BIND** (absent upstream — fast-socks5
|
||||
parses `Socks5Command::TCPBind` but every handler refuses it,
|
||||
`lib.rs:384-386` / `server.rs:813-816`; the wrapper drives the
|
||||
typestate itself); the `run_udp_proxy_custom` bind seam (above); and
|
||||
the publication of `new_reply` (the reply encoder is private; the
|
||||
BIND reply#2 writer otherwise hand-rolls the 10-byte reply —
|
||||
`poc-bind-findings.md`).
|
||||
- **What the vendor must add (the carried needs; re-read under the
|
||||
2026-09-21 extraction amendment — ADR-011 §Amendment):** **BIND**
|
||||
(absent upstream — fast-socks5 parses `Socks5Command::TCPBind` but
|
||||
every handler refuses it, `lib.rs:384-386` / `server.rs:813-816`;
|
||||
the wrapper drives the typestate itself) and the publication of
|
||||
`new_reply` (the reply encoder is private; the BIND reply#2 writer
|
||||
otherwise hand-rolls the 10-byte reply — `poc-bind-findings.md`).
|
||||
The other two of the original four needs — the kernel-net feature
|
||||
gate (POC #4: ~120 cfg lines, wasm-clean subset functionally
|
||||
complete) and the `run_udp_proxy_custom` bind seam — dissolve with
|
||||
the kernel-net region, which the extraction does not copy.
|
||||
|
||||
### iroh-socks5 — the structural sibling (evaluated, not the base)
|
||||
|
||||
@@ -783,7 +789,7 @@ drives the command dispatch itself — implementing BIND is wrapper-side
|
||||
code, carried in the vendor (no upstream ask). POC-confirmed:
|
||||
`reply_success`'s `sock_addr` parameter carries reply#1's `BND.ADDR`
|
||||
verbatim; the courtesy item is publishing `new_reply` (rides the
|
||||
vendor — see §Prior art's four carried needs).
|
||||
vendor — see §Prior art's carried needs).
|
||||
|
||||
**The shape (convergent precedent: iroh-socks5's channels-native BIND —
|
||||
server relays raw bytes post-reply for CONNECT/BIND, `docs/research/
|
||||
@@ -1102,14 +1108,15 @@ except the two explicit, optional, feature-gated assembly shapes
|
||||
protocol modules at the crate core; feature-gated backend modules
|
||||
(local binds) never imported by the protocol layer; producer +
|
||||
consumer + params modules mirroring POC #1/#2's structure. **The
|
||||
fast-socks5 posture is the inline vendor (OQ-SK-04, resolved
|
||||
2026-09-20)**: vendor the `T`-generic subset into this crate (the
|
||||
codecs, typestate machinery, client `use_stream` path), gated behind
|
||||
a default-on `net`-shaped feature (POC #4: ~120 cfg lines, wasm-clean
|
||||
subset functionally complete) — and carry the four wrapper needs in
|
||||
the same vendor: BIND (absent upstream; POC #5's typestate-driven
|
||||
shape), the `run_udp_proxy_custom` bind seam, the `new_reply`
|
||||
publication, and the wasm gate. `/workspace/fast-socks5` stays the
|
||||
fast-socks5 posture is the inline vendor as an extraction (OQ-SK-04,
|
||||
resolved 2026-09-20; extraction pinned 2026-09-21, ADR-011
|
||||
§Amendment)**: extract the `T`-generic subset into this crate (the
|
||||
codecs, typestate machinery, client `use_stream` path; the
|
||||
kernel-net handlers and `socks4` are not copied, so there is no
|
||||
`net` feature — POC #4's gate map survives as the extraction
|
||||
recipe) — and carry the two extracted-region needs in the same
|
||||
vendor: BIND (absent upstream; POC #5's typestate-driven shape) and
|
||||
the `new_reply` publication. `/workspace/fast-socks5` stays the
|
||||
differential-testing reference; note the vendor point (v1.0.0) in
|
||||
the vendored code.
|
||||
- **Open for Phase 1 ADRs** (inputs collected, decisions pending): the
|
||||
|
||||
@@ -231,7 +231,10 @@ both asks are **superseded in shape**, not implemented as posed:
|
||||
`run_udp_proxy_custom` unconditional-bind seam. (Posture note,
|
||||
2026-09-20: fast-socks5 is third-party upstream and these are no
|
||||
longer asks — all three move into the inline vendor, OQ-SK-04
|
||||
resolved.)
|
||||
resolved. 2026-09-21: under the extraction — ADR-011 §Amendment —
|
||||
`new_reply` is the one that rides in-tree; the `net` gate and the
|
||||
bind seam dissolve with the kernel-net region, which is not
|
||||
copied.)
|
||||
|
||||
The POC's evidence stands as the record of what was validated against
|
||||
alktunnels 0.1.0; the Phase 1 shape composes variant 2 against 0.2.0
|
||||
@@ -261,7 +264,10 @@ are additive surface, discovered in priority order:
|
||||
3. **(fast-socks5, courtesy)** `new_reply` is private — publish it
|
||||
(or a constructor) so embedders don't re-encode the reply wire
|
||||
form. Also still open from POC #4: the `net` feature gate and the
|
||||
`run_udp_proxy_custom` unconditional-bind seam.
|
||||
`run_udp_proxy_custom` unconditional-bind seam. (2026-09-21: under
|
||||
the extraction — ADR-011 §Amendment — `new_reply` is the one that
|
||||
rides in-tree; the `net` gate and the bind seam dissolve with the
|
||||
kernel-net region, which is not copied.)
|
||||
|
||||
No asks block the POC's conclusions; 1–2 shape variant 2's *full*
|
||||
fidelity, and the POC's stand-ins (carried `bind_addr`; sentinel
|
||||
|
||||
@@ -181,7 +181,10 @@ were recorded as "asks" under the wrong ownership premise and move
|
||||
into the vendor with it.
|
||||
|
||||
1. **Feature-gate kernel-net behind a default-on `net` feature**
|
||||
(POC #4's change, ~120 lines of `#[cfg]`).
|
||||
(POC #4's change, ~120 lines of `#[cfg]`). (2026-09-21: dissolved
|
||||
under the extraction — ADR-011 §Amendment; the kernel-net region
|
||||
is not copied, and POC #4's gate map survives as the extraction
|
||||
recipe, not in-tree cfg.)
|
||||
2. **`run_udp_proxy_custom` binds a kernel socket unconditionally**
|
||||
(noted in phase-0 §Prior art, verified again here): the
|
||||
customizable seam covers the relay closure and reply IP only; the
|
||||
|
||||
Reference in new issue
Block a user