docs: three-component split; fork-first (vendor-and-vet) posture; consumer-side bind

- phase-0 vision: components split — (1) producer half (expose the
  SOCKS5 service over channels), (2) consumer half (consume it,
  optionally bind it locally — the ssh -D front door + tun2proxy
  path), (3) standalone SOCKS client wrapper for quinn/noq that must
  work with any RFC 1928 server (iroh relay/peer IP-leak motivation,
  alknet ADR-090 generalized); the earlier docs conflated the
  consumer-side bind with the producer-side local backend
- principle 6: the vpn-like endgame — tunnel a produced SOCKS5
  resource to a local port, point tun2proxy (--proxy socks5://
  natively) at it; verified tun2proxy src/args.rs
- OQ-SK-04 resolved as fork-first: 'fork' = vendor-and-vet inline in
  the crate (minimal diff, feature-gate native-net), PR upstream as
  courtesy, never wait on approval; wasm-drop (alkhttp precedent) is
  the escape hatch, not the plan
- AGENTS.md conventions 4/9/17 aligned (fork-first, binds on either
  side, wasm posture)
This commit is contained in:
2026-09-12 10:21:29 +00:00
parent 216a5e965e
commit 766e489f99
2 changed files with 136 additions and 52 deletions
+29 -20
View File
@@ -90,10 +90,11 @@ implementation agents.
(`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;
whether it compiles wasm-clean, needs a fork, or the wrapper
reimplements the SOCKS5 state machine over `tokio::io` generics is an
open question (see `docs/research/phase-0.md` OQ-SK-04) — do not
assume either way until it is resolved.
the resolved posture (OQ-SK-04) is fork-first: vendor the needed
subset and feature-gate native-net pieces (the alkhttp crate shows a
native-only crate is possible, but wasm-clean remains the preferred
posture here). 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
@@ -145,13 +146,17 @@ implementation agents.
The SOCKS5 server must run without binding any port: the RFC 1928
conversation is carried inside a channels data channel, and target
dials happen on the producing side (or hop further through
alktunnels/alksocks). A local bind (a genuine `socks5://host:port`
endpoint) is an optional assembly-layer/feature-gated capability.
UDP ASSOCIATE is the hard case: RFC 1928 replies with a UDP relay
address and the client sends datagrams to it, which seems to demand a
bind — how the relay address is virtualized (or the associate shape
adapted) is a Phase 0 question (OQ-SK-03). Binding decisions belong
to the caller (assembly layer), never the protocol crate.
alktunnels/alksocks). Local binds exist only as explicit, optional
assembly-layer shapes on either side: the producer may serve from a
real listener (a feature-gated local backend), and the consumer may
expose the resource on a local port (the ssh `-D` front door that
vanilla clients — curl, browsers, tun2proxy — point at). The
protocol itself never binds. UDP ASSOCIATE is the hard case: RFC
1928 replies with a UDP relay address and the client sends
datagrams to it, which seems to demand a bind — how the relay
address is virtualized (or the associate shape adapted) is a Phase 0
question (OQ-SK-03). Binding decisions belong to the caller
(assembly layer), never the protocol crate.
10. **Backpressure and limits are inherited, not redefined** — bounded
per-channel buffers, the 256-channel per-connection cap, monotonic
@@ -222,15 +227,19 @@ 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 — make asks early.** We own `fast-socks5`
(`/workspace/fast-socks5`, v1.0.0, MIT) and alkcall. If the wrapper
needs a change upstream (a typestate hook, a generic split, a new
event), file it and land it there rather than working around it
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 upstream
diverges from what we publish, note the fork point in the research
docs.
17. **Upstream is ours — fork-first, PR as courtesy.** We own
`fast-socks5` (`/workspace/fast-socks5`, v1.0.0, MIT) and alkcall.
For changes this crate needs upstream, the preferred posture is:
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 (see `docs/research/phase-0.md` OQ-SK-04's resolved
posture). 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.
## Verification Commands