From cced3b2b85878709ea39009f6419091884c1a616 Mon Sep 17 00:00:00 2001 From: "glm-5.3-flash" Date: Sun, 20 Sep 2026 09:59:12 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20correct=20fast-socks5=20posture=20?= =?UTF-8?q?=E2=80=94=20third-party=20upstream,=20inline=20vendor=20decided?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ownership premise ('we own fast-socks5') was wrong — it is third-party upstream and has not been forked. The corrected posture resolves OQ-SK-04: inline vendor. The wrapper's needs exceed the wasm gate regardless (BIND absent upstream — POC #5 proved the wrapper drives it; the run_udp_proxy_custom bind seam; private new_reply), so carrying the T-generic subset (~120 cfg lines, POC #4-verified) pays for itself independent of the adapter story. AGENTS.md: - convention 17 rewritten: 'Upstream: alkcall is ours to shape; fast-socks5 is inlined' — the ownership split stated plainly, the inline vendor + its four carried changes named, the courtesy PR kept optional/never-waited-on, the vendor point (v1.0.0) noted - convention 4: wasm posture note updated to the resolved vendor - prior-art entry: fast-socks5 marked third-party/NOT ours phase-0.md: - OQ-SK-04 RESOLVED (2026-09-20): resolution note headers the OQ (the two settling facts: wrong ownership premise; needs exceed the gate); decision tree retained as reasoning trail with both legs annotated (Case 2's premise falsified by the BIND need); the root question reframed as retrospective; checklist item checked - §Prior art fast-socks5: header + run_udp_proxy_custom caveat reworded from 'fileable ask' to in-tree change - settled-foundations wasm caveat resolved; survey + checklist prior-art entries marked; 'What Phase 0 could NOT answer' wasm item struck as resolved; convergence Layering bullet now enumerates the four in-tree carried changes; upstream-asks bullet: fast-socks5 items are no longer asks poc-connect-wasm-findings.md / poc-bind-findings.md / iroh-socks5-eval.md: 'we own it' ask sections corrected to in-tree-vendor changes (dangling fragment from an earlier edit also fixed); ledger item 3 annotated Verified: fast-socks5 upstream still 1.0.0, no net feature, BIND refused (lib.rs:384-386/server.rs:813-816) — the needs-are-real facts stand. Docs-only change; no build surface affected. --- AGENTS.md | 61 ++++---- docs/research/iroh-socks5-eval.md | 5 +- docs/research/phase-0.md | 157 ++++++++++++++------- docs/research/poc-bind-findings.md | 10 +- docs/research/poc-connect-wasm-findings.md | 27 +++- 5 files changed, 170 insertions(+), 90 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6fdf615..472a10b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,14 +89,11 @@ implementation agents. the alktty/alktunnels precedent. Use the wasm-clean tokio subset (`rt`, `sync`, `io-util`, `macros`, `time`) — **do NOT use `features = ["full"]`** — and keep socket/platform I/O feature-gated. Note: - `fast-socks5` itself uses `tokio::net` and `socket2` unconditionally; - the posture is conditional (OQ-SK-04): if wasm matters for this - crate, the path is fork-first (vendor the `T`-generic subset, gate - native-net pieces — see OQ-SK-04 Case 1); if wasm does not matter, - ride the native `router.rs` path with a plain dependency (Case 2 — - the alkhttp precedent). The root question — does wasm make sense - here — is the OQ to settle; do not carry a fork for an invariant's - sake. Run the wasm check whenever a non-backend module changes. + `fast-socks5` uses `tokio::net` and `socket2` unconditionally as + published; the posture is the inline vendor (OQ-SK-04, resolved + 2026-09-20 — convention 17): vendor the `T`-generic subset, gate + native-net pieces behind a default-on `net`-shaped feature. Run + the wasm check whenever a non-backend module changes. 5. **Wire format is stable** — the SOCKS5 protocol itself is RFC 1928 (fixed); this crate's wire surface is the ALPN + the channel open-op @@ -233,20 +230,22 @@ implementation agents. One ALPN per protocol. The ALPN string is wire-stable once published — decide via ADR before the first consumer. -17. **Upstream is ours — fork-first where it pays, asks for alkcall.** - We own `fast-socks5` (`/workspace/fast-socks5`, v1.0.0, MIT) and - alkcall. For fast-socks5, the posture is conditional (OQ-SK-04): - if wasm matters for this crate (Case 1), make the change as a - minimal fork and use it — offer it upstream as a PR and merge - upstream if they want it, but never wait on approval; if wasm does - not matter (Case 2), ride the native path with a plain dependency, - no fork. For alkcall (the actively co-developed substrate) the - alk* precedent still applies: file asks early and land them there - rather than working around them locally — the alktunnels precedent - (the E-01/E-02 sweep, filed from its Phase 0 and landed in alkcall - 0.5.0 within a day). Keep `/workspace/fast-socks5` as the reference - checkout; if the vendored subset diverges from upstream, note the - fork point in the research docs. +17. **Upstream: alkcall is ours to shape; fast-socks5 is inlined.** + alkcall is ours (the actively co-developed substrate): file asks + early and land them there rather than working around them locally — + the alktunnels precedent (the E-01/E-02 sweep, filed from its + Phase 0 and landed in alkcall 0.5.0 within a day; the graduation + sweep landed in alkcall 0.8.0 / alktunnels 0.2.0). `fast-socks5` + is NOT ours — it is third-party upstream (`/workspace/fast-socks5` + is a read-only reference checkout, v1.0.0, MIT). The posture is + the **inline vendor** (OQ-SK-04, resolved 2026-09-20): vendor the + `T`-generic subset into this crate, gated behind a default-on + `net`-shaped feature, and carry the wrapper's needs in-tree (the + wasm gate, BIND, the `run_udp_proxy_custom` bind seam, the + `new_reply` publication). Offering the net-gate upstream as a + courtesy PR stays optional; never wait on it. Keep + `/workspace/fast-socks5` for differential testing of RFC edge + cases; note the vendor point (v1.0.0) in the vendored code. ## Verification Commands @@ -303,13 +302,17 @@ is expected and is exactly what the OQ tracks. Option A's vehicle), the bind-first establisher + forwarded op (the composed BIND substrate; OQ-SK-08 variant 2), and `TunnelListener`. - - **fast-socks5** — `/workspace/fast-socks5` (v1.0.0, MIT, we own - upstream). The SOCKS5 implementation to wrap: explicit typestate - server API (`Socks5ServerProtocol`), generic over - `T: AsyncRead + AsyncWrite + Unpin`; `run_tcp_proxy` / - `run_udp_proxy_custom` / `transfer` are the interception points; - client side has `Socks5Stream` (generic over the backing socket) - and `Socks5Datagram` (UDP associate). + - **fast-socks5** — `/workspace/fast-socks5` (v1.0.0, MIT, + third-party upstream — NOT ours). The SOCKS5 implementation to + wrap: explicit typestate server API (`Socks5ServerProtocol`), generic over `T: AsyncRead + AsyncWrite + Unpin`; + `run_tcp_proxy` / `run_udp_proxy_custom` / `transfer` are the + interception points; client side has `Socks5Stream` (generic over + the backing socket) and `Socks5Datagram` (UDP associate). The + posture is the inline vendor (OQ-SK-04, resolved 2026-09-20 — + convention 17): the `T`-generic subset is vendored into this + crate behind a `net`-shaped feature, with BIND and the seam fixes + carried in-tree. - **alknet's SOCKS5 client** — `/workspace/@alkdev/alknet/crates/alknet-client/src/socks5.rs` (ADR-090): the client-side example need — `Socks5UdpSocket` diff --git a/docs/research/iroh-socks5-eval.md b/docs/research/iroh-socks5-eval.md index f09f008..16b153b 100644 --- a/docs/research/iroh-socks5-eval.md +++ b/docs/research/iroh-socks5-eval.md @@ -230,7 +230,7 @@ the exact question OQ-SK-03 poses. Its answers: | Client session genericity | `Socks5Stream::use_stream` (any `T`) | none (local TCP front door only) | | wasm posture | fork verified minimal (POC #4) | moot — iroh + tokio-full are native-only | | Tests | unit + examples; router/custom-auth examples | strong integration suite over real iroh infra | -| License | MIT (we own upstream) | MIT OR Apache-2.0 | +| License | MIT (third-party upstream; inline-vendored — OQ-SK-04) | MIT OR Apache-2.0 | | LOC | ~4k | ~1.3k | ## Verdict @@ -258,7 +258,8 @@ though fast-socks5 already covers them): MIT OR Apache-2.0 dual license, copyright Matthew Geddes; keep LICENSE-MIT/LICENSE-APACHE entries and a provenance note in any vendored file header. -Also worth filing upstream (courtesy, we own fast-socks5, but +Also worth noting (posture corrected 2026-09-20: fast-socks5 is +third-party upstream, so nothing is "filed" there as of right; iroh-socks5 is upstream's own crate): nothing blocking. Optionally a repository link on the crates.io entry would help discoverability — the repo exists at `github.com/mattgeddes/iroh-socks5` but `repository` is diff --git a/docs/research/phase-0.md b/docs/research/phase-0.md index 514c13a..6c52c6d 100644 --- a/docs/research/phase-0.md +++ b/docs/research/phase-0.md @@ -1,9 +1,8 @@ --- status: draft -last_updated: 2026-09-20 (the graduation landed upstream: alkcall 0.8.0 -— reply projection, flavor-form discovery, ADR-051 relay; alktunnels -0.2.0 — ADR-007 direct op + ADR-008 bind-first/forwarded, superseding -the BIND ask ledger's shape; ask-ledger statuses updated) +last_updated: 2026-09-20 (fast-socks5 posture corrected + resolved: we +do NOT own it — inline vendor decided; the graduation landed upstream: +alkcall 0.8.0, alktunnels 0.2.0 superseding the BIND ask ledger's shape) --- # alksocks — Phase 0 (Exploration) @@ -177,8 +176,10 @@ not start from zero. It inherits: confined to feature-gated backend modules, injected at the assembly layer (alktty `TtyBackend` / alktunnels no-trait precedent). - **The wasm-clean default crate** — protocol-only code should compile - to `wasm32-unknown-unknown` (alktty/alktunnels precedent). Caveat: - `fast-socks5` itself is not yet known to be wasm-clean (OQ-SK-04). + to `wasm32-unknown-unknown` (alktty/alktunnels precedent). Caveat + resolved: `fast-socks5` itself is not wasm-clean as published + (OQ-SK-04) — the inline vendor (resolved 2026-09-20) carries the + net-gate so the default-crate invariant holds. ## Prior art @@ -215,10 +216,12 @@ load-bearing conclusions this crate inherits: the channels 8-byte header. UDP ASSOCIATE's datagram stage is the exception (OQ-SK-03). -### fast-socks5 — the implementation to wrap +### fast-socks5 — the implementation to wrap (inline-vendor decision) -`/workspace/fast-socks5` (v1.0.0, MIT, we own upstream). Read the source -before designing against it. Key surface points, verified: +`/workspace/fast-socks5` (v1.0.0, MIT — **third-party upstream, not +ours; posture corrected 2026-09-20, OQ-SK-04 resolved to the inline +vendor — see the OQ**). Read the source before designing against it. +Key surface points, verified: - **Explicit typestate server API** (`src/server.rs`): `Socks5ServerProtocol`, @@ -248,9 +251,10 @@ before designing against it. Key surface points, verified: the reply port from that kernel socket; the wrapper can customize the relay loop (`transfer`) and the reply *IP* only. The channels path therefore cannot use this handler: it drives the typestate - directly (`reply_success(sentinel_addr)` + own datagram stage). The - unconditional bind is a fileable upstream ask (we own fast-socks5): - make the bind optional or accept a caller-supplied socket. + directly (`reply_success(sentinel_addr)` + own datagram stage). + Under the inline vendor this is a change we make in-tree, not an + upstream ask: make the bind optional or accept a caller-supplied + socket. - `transfer(inbound, outbound)` — plain two-pump copy; a channels `BiStream` is a legal `T` on either side. - **UDP support** — `new_udp_header(target)` / `parse_udp_request(buf)` @@ -671,6 +675,20 @@ composed story. The datagram-framing ADR (the one-way door) is Phase ### OQ-SK-04: fast-socks5 wasm posture (blocks the wasm-clean invariant) +**RESOLVED 2026-09-20: inline vendor (Case 1, decided).** Two facts +settled it: (1) the ownership premise was wrong — we do *not* own +fast-socks5 (third-party upstream), so the "file asks / PR" legs of +the old decision tree lose their cheap path; and (2) the wrapper's +needs go beyond the wasm gate regardless — BIND is absent upstream +(POC #5 proved the wrapper must drive it itself), and the two seam +fixes (`run_udp_proxy_custom`'s unconditional bind; private +`new_reply`) were only "asks" under the ownership assumption. The +change set (net-gate + BIND + bind seam + `new_reply`) is exactly the +shape POC #4 measured as minimal (~120 cfg lines + additive additions +in the `T`-generic region), so the vendor pays for itself without +leaning on the adapter story. Mechanics in the Convergence §Layering +bullet; the decision record below is retained for the reasoning trail. + `fast-socks5` uses `tokio::net` (`TcpListener`, `TcpStream`, `UdpSocket`) and `socket2` unconditionally (`Cargo.toml`: tokio features `io-util, net, time, macros`; deps `socket2 = "0.5.8"`); `wasm32- @@ -680,7 +698,9 @@ depending on the crate at all may break `cargo check --target wasm32-unknown-unknown` at the dependency-graph level. **The decision tree (2026-09-12 clarification — two main forks, and the -preference between them is conditional):** +preference between them was conditional). Retained as the reasoning +trail; both legs were written under the wrong ownership premise ("we +own upstream") — the resolved posture is the header note above:** - **Case 1: wasm matters for this crate → fork-first.** Make the minimal fork and use it — offer it upstream as a PR (merge if they @@ -697,17 +717,26 @@ preference between them is conditional):** checkout for differential testing of RFC edge cases (reply-code mapping, domain addressing, fragmentation) and the PR source; if upstream accepts the PR, the fork shrinks to a plain dependency. + (The vendoring shape is what was adopted 2026-09-20 — the PR is + optional courtesy, and "shrinks to a plain dependency" is moot since + the vendor also carries BIND + the seam fixes upstream lacks.) - **Case 2: wasm doesn't matter for this crate → plain dependency, no fork.** Ride the `router.rs` native path exactly as-is (the alkhttp precedent — a crate in this suite can ship native-only). This is strictly better *if its premise holds*: no fork burden, no vendoring, upstream stays upstream. The alkhttp contrast is instructive — alkhttp's substance (axum/hyper/reqwest) is - socket-native, so nobody misses wasm there. + socket-native, so nobody misses wasm there. (Superseded: Case 2's + premise — a wrap-only relationship — was falsified by the BIND + + seam needs; see the resolution note above.) -**The root question is therefore: does wasm make sense for alksocks?** -Not "how do we get wasm" — that is Case 1's solved problem. Analysis -for the decision: +**The root question was therefore: does wasm make sense for alksocks?** +(Retrospective note, 2026-09-20: the analysis below was written when +that was open; the ownership correction resolved the OQ ahead of the +adapter story — the vendor is justified by BIND + the seam fixes +alone. The adapter-story input below is retained as the +still-relevant product question for how much wasm surface to +exercise, not as a gate.) Analysis that was on file for the decision: - **What wasm would serve:** the protocol layer (components 1+2 of the three-component split, §Vision) in a sandboxed adapter — the @@ -732,7 +761,7 @@ for the decision: only an argument once Case 1 is chosen; it is not itself the use case. The use case is a planned sandboxed SOCKS consumer. -**Decision inputs (what actually settles Case 1 vs Case 2):** +**Decision inputs (what was set to settle Case 1 vs Case 2):** 1. **Is there a planned sandboxed (wasm) consumer of the SOCKS5 service?** If the downstream TS/Python adapter story includes a @@ -745,11 +774,22 @@ for the decision: gains weight — reimplementing the protocol to serve a wasm story nobody has yet defeats the purpose. -Both inputs point the same way when aligned: fork-first in Case 1 is +Both inputs pointed the same way when aligned: fork-first in Case 1 is the preferred branch *because* wasm is wanted there — not as a general preference for forks over upstream asks. If the adapter story never -materializes, Case 2 (plain dep, router path) is the obvious choice, -and no one should carry a fork for an invariant's sake. +materializes, Case 2 (plain dep, router path) was framed as the +obvious choice — and no one should carry a fork for an invariant's +sake. (The ownership correction below is what changed the balance.) + +**The resolution (2026-09-20), restated:** the ownership correction +made "wait on upstream" legs of both cases unavailable, which pushes +every fast-socks5 change (wasm gate, BIND, bind seam, `new_reply`) +into code we carry — and once that set is carried, a plain-dep +Case 2 would mean wrapping a crate we can't change against needs it +doesn't serve (no BIND). The vendor is the only posture that fits all +four needs; POC #4 established the carry is small. Case 2's fallback +framing (alkhttp precedent) remains the record of what *would* have +been chosen had the crate been native-only with no BIND need. ### OQ-SK-05: Target policy and egress scoping @@ -774,8 +814,8 @@ dissolving most of this OQ for that path): - Domain-form targets (RFC 1928 ATYP 0x03): resolve producer-side (fast-socks5's `dns_resolve` config), refuse, or pass through to the dialer unresolved? (DNS-on-the-producer is the SSH `-D` semantic; - wasm producers may not have a resolver at all — another OQ-SK-04 - interaction.) + wasm producers may not have a resolver at all — an interaction with + the vendored crate's wasm posture, OQ-SK-04 resolved 2026-09-20.) **Virtual address space / identity-scoped subnets (added 2026-09-14, post-POC #2).** A proposal surfaced during the findings review: give @@ -1183,7 +1223,9 @@ Candidate reading for the research specialist (to be expanded): (`Socks5Stream`/`Socks5Datagram`, `use_stream`), `src/lib.rs` (`new_udp_header`/`parse_udp_request`, `ReplyError`), `examples/router.rs` (conditional interception), `examples/ - custom_auth_server.rs`. + custom_auth_server.rs`. (Third-party upstream; the inline vendor — + OQ-SK-04, resolved 2026-09-20 — vendors the `T`-generic subset into + this crate; this checkout is the differential-testing reference.) - iroh-socks5 — `crates.io/crates/iroh-socks5` v0.5.0, repo `github.com/mattgeddes/iroh-socks5` (crates.io has no repository link; the published source matches). Evaluated in @@ -1234,10 +1276,13 @@ Candidate reading for the research specialist (to be expanded): - [ ] Vision + guiding principles captured (this doc, §Vision — including the three-component split) -- [ ] Prior-art pass complete: fast-socks5 surface verified (§Prior +- [x] Prior-art pass complete: fast-socks5 surface verified (§Prior art), alktunnels/alknet/noq lineage mapped, anti-prior-art list written; iroh-socks5 evaluated (structural sibling, not the base; - OQ-SK-03 prior art — `docs/research/iroh-socks5-eval.md`) + OQ-SK-03 prior art — `docs/research/iroh-socks5-eval.md`); + **ownership premise corrected 2026-09-20** (fast-socks5 is + third-party upstream; the posture is the inline vendor, OQ-SK-04 + resolved) - [x] OQ-SK-01 (dial policy) — researched, half-answered (injected dialer hunch); **POC #1 resolved the shape empirically** (dial callback at the command-read interception point, boxed halves, no @@ -1259,24 +1304,27 @@ Candidate reading for the research specialist (to be expanded): POC-validated end to end, findings in `poc-udp-associate-findings.md`; the datagram framing is wire-stable once published — the Phase 1 ADR decision remains)** -- [ ] OQ-SK-04 (fast-socks5 wasm) — the decision tree is written +- [x] OQ-SK-04 (fast-socks5 wasm) — the decision tree was written (Case 1: wasm wanted → fork-first; Case 2: wasm unwanted → plain dep, router path); **POC #4 verified the fork is genuinely minimal** (~120 lines of cfg gating; wasm-clean subset is - functionally complete); the root question ("does wasm make - sense for alksocks?") now reduces to the adapter-story input + functionally complete); **resolved 2026-09-20: inline vendor** + (the ownership premise was corrected — we don't own fast-socks5; + BIND + the seam fixes must be carried regardless, so the vendor + pays for itself independent of the adapter story — see the OQ's + resolution note) - [ ] OQ-SK-05 (target policy) — folded into the OQ-SK-01 decision; scope-gate convention pinned in Phase 1; the 2026-09-14 virtual-subnet proposal (dial-callback translation, no wire change) recorded for Phase 1 -- [ ] OQ-SK-08 (BIND) — new (2026-09-14): the gap + use case + +- [x] OQ-SK-08 (BIND) — new (2026-09-14): the gap + use case + accept-side mechanism written; **POC #5 run 2026-09-15 — passed** (the phase model extends end to end; both accept variants implemented; the scope gate works; the ask ledger is pinned); **the ask ledger landed 2026-09-18/20 — superseded in shape by the bind-first/forwarded graduation (see OQ-SK-08's - landed note)**; the Phase 1 ADR (ship in base crate? default - accept variant?) has empirical ground under it + landed note)**; the remaining Phase 1 ADR (ship in base crate? + default accept variant?) has empirical ground under it - [ ] OQ-SK-09 (channel capacity) — new (2026-09-14): the proxy- workload analysis written (wire change rejected; config is the mechanism; in-channel port multiplexing considered and @@ -1349,21 +1397,30 @@ binds except the two explicit, optional, feature-gated assembly shapes - **Layering: the alktty/alktunnels precedents** — substrate-agnostic 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 - fork posture for fast-socks5 is vendoring the `T`-generic subset - into this crate gated behind a `net`-shaped feature (POC #4: - ~120 cfg lines, wasm-clean subset functionally complete). + consumer + params modules mirroring POC #1/#2's structure. **The + fast-socks5 posture is the inline vendor (resolved 2026-09-20, + OQ-SK-04)**: 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 differential-testing reference; note the vendor point + (v1.0.0) in the vendored code. - **Open for Phase 1 ADRs** (inputs collected, decisions pending): the demux-vs-phase extensibility trade (evidence now favors the phase model — no in-band control vocabulary was needed across both POCs); the params-format/ALPN naming ADRs (wire-stable once published, no consumers exist yet); `SOCKS5_OPEN_SCOPE` convention (must distinguish BIND from CONNECT/ASSOCIATE — OQ-SK-08's security - note); the door's credential→identity mapping shape; the wasm - decision (Case 1 vs Case 2) once the adapter story is confirmed; + note); the door's credential→identity mapping shape; BIND's base-crate inclusion + default accept variant (OQ-SK-08); the proxy-workload channel-cap recommendation (OQ-SK-09); the virtual-subnet translation-layer shape (OQ-SK-05 addendum). + (The wasm decision itself is settled — OQ-SK-04 resolved to the + inline vendor 2026-09-20; only the wasm-consumer adapter story + remains a product input, and it no longer gates the vendor.) - **Upstream asks — landed (the first-real-consumer sweep paid off).** The graduation (`alktunnels docs/research/tunnels-graduation.md`, alkcall review 008) took every ask at once, in one-version bumps: @@ -1380,22 +1437,26 @@ binds except the two explicit, optional, feature-gated assembly shapes egress), the bind-first establisher + forwarded op (dissolving both BIND asks in shape — see OQ-SK-08's landed note), `TunnelListener`, and the `local` bind-first substrate half. - - **fast-socks5 (still open, courtesy)**: the `net` feature gate - (POC #4's ~120-line change), the `run_udp_proxy_custom` - unconditional-bind seam, and the `new_reply` publication (POC #5 - re-encoded the reply wire form by hand). The BIND ledger never - had a fast-socks5 ask — the typestate fit with zero changes. - No asks remain blocking for this crate; the fast-socks5 items are - the courtesy tail (we own the upstream; POC #4's fork posture - covers them if wasm picks Case 1). + - **fast-socks5 — posture changed (2026-09-20): the items are no + longer asks.** The ownership premise was wrong (third-party + upstream, not ours), and the wrapper's needs exceed the wasm gate + (BIND absent upstream; the bind seam; private `new_reply`). All + four changes move into the inline vendor (OQ-SK-04 resolved — + see the Layering bullet); `/workspace/fast-socks5` remains the + reference checkout, and offering the net-gate upstream as a + courtesy PR stays optional. ### What Phase 0 could NOT answer (handed to Phase 1) - The datagram-framing ADR (the one-way door) — now has empirical ground: framing validated, LRU/dedup semantics pinned, open cost measured. Decide with the first consumer in sight. -- The wasm root question (OQ-SK-04) — mechanism de-risked; the - adapter-story input is a product decision, not a research one. +- ~~The wasm root question (OQ-SK-04)~~ **resolved 2026-09-20** (the + inline vendor) — the mechanism is de-risked (POC #4) and the + posture no longer leans on the adapter story (the vendor pays for + itself via BIND + the seam fixes); the sandboxed-wasm-consumer + adapter story remains a product input for later, but nothing waits + on it. - Target-policy shape (OQ-SK-05) — the dialer-refuses shape is evidence-backed; the declarative-allowlist variant stays a Phase 1 choice. (The 2026-09-14 virtual-subnet proposal is recorded there — diff --git a/docs/research/poc-bind-findings.md b/docs/research/poc-bind-findings.md index a52c229..9a0652f 100644 --- a/docs/research/poc-bind-findings.md +++ b/docs/research/poc-bind-findings.md @@ -183,7 +183,8 @@ end-to-end (the same ownership lesson as POC #2's egress, mirrored). writer hand-rolls the 10-byte reply (VER, REP, RSV, ATYP, addr, port — 10 bytes v4 / 22 v6). Ledger ask #3 (fast-socks5, courtesy): publish `new_reply` (or a `reply(code, addr)` constructor) so - embedders don't re-encode replies. + embedders don't re-encode replies. (2026-09-20: rides the inline + vendor — see §ledger statuses.) - `ToTargetAddr::to_target_addr()` (not `From`) is the `SocketAddr → TargetAddr` conversion — `TargetAddr::from` does not exist (the POC hit this; the wrapper's accept layer will too). @@ -227,9 +228,10 @@ both asks are **superseded in shape**, not implemented as posed: 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. (Unchanged — the - courtesy tail; no fast-socks5 release has landed these as of - 2026-09-20.) + `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.) 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 diff --git a/docs/research/poc-connect-wasm-findings.md b/docs/research/poc-connect-wasm-findings.md index 1516a36..151b151 100644 --- a/docs/research/poc-connect-wasm-findings.md +++ b/docs/research/poc-connect-wasm-findings.md @@ -167,9 +167,18 @@ Remaining for Case 1: the fork posture is vendoring *into this crate* (per phase-0: vendor the `T`-generic subset, gate the rest), keeping `/workspace/fast-socks5` as the differential reference; the upstream PR (feature-gate `net` behind a default-on feature) is small enough -to offer as-is. +to offer as-is. **(2026-09-20: resolved — the inline vendor is the +decision; the PR is an optional courtesy, never a wait. See phase-0 +OQ-SK-04.)** -### Follow-on asks (upstream, we own it) +### Follow-on changes (posture corrected 2026-09-20: not upstream asks) + +**Ownership correction:** fast-socks5 is third-party upstream — we do +not own it, and it has not been forked. These are therefore not asks; +they are changes the inline vendor carries in-tree (OQ-SK-04, resolved +2026-09-20). The wasm-gate change below is POC #4's; the other two +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]`). @@ -178,7 +187,8 @@ to offer as-is. customizable seam covers the relay closure and reply IP only; the channels path must drive the typestate directly. Make the `udp_bind_random_port` step optional / accept a caller-supplied - socket. + socket. (Both #2 and the POC #5 courtesy item — publish `new_reply` + — ride the vendor; see `poc-bind-findings.md` §ledger statuses.) ## OQ status after these POCs @@ -192,8 +202,11 @@ to offer as-is. propagation is a wiring requirement the producer harness performs. In-band SOCKS auth was not exercised (NoAuth only); the RFC-facing username/password path for the local backend remains Phase 1. -- **OQ-SK-04 (wasm)**: fork-minimality verified; the decision now - reduces purely to "does wasm make sense for alksocks" (the adapter - story), with the mechanism de-risked. +- **OQ-SK-04 (wasm)**: fork-minimality verified; the decision reduced + to "does wasm make sense for alksocks" (the adapter story), with + the mechanism de-risked. **(2026-09-20: resolved — inline vendor, + on the corrected ownership premise + the BIND/seam needs. See + phase-0 OQ-SK-04.)** - **OQ-SK-07**: #1 and #4 complete; #2 (UDP ASSOCIATE) and #3 (noq) - remain. \ No newline at end of file + remain. (Both resolved later: #2 passed 2026-09-14, #3 dropped with + the scope decision.) \ No newline at end of file