docs: reverse-flow POC summary — -R shape validated end-to-end
POC at /workspace/alktunnels-reverse-poc (14 tests, clippy/fmt clean, repeat-run stable) over alkcall 0.6.0: - The review 007 non-finding trace confirmed by execution: the hub (accept side) opens tunnel channels toward a connect-side worker serving its own open op (from_connection_with_serving + ChannelOperations::register_on + post-hoc openable registration) - ADR-047 §5 exercised in the Pub-like orientation: the worker (connect side) allocates odd IDs; the hub adopts - R-01 plan flow under concurrency: two same-resource opens, distinct channels, distinct dialed handles — the forward POC's handoff race is structurally gone - OQ-TN-03's last open thread closed: no advertisement op needed — the listener is the initiator's own local resource; a far-side listener is a producer-side listen establisher over the same open op - W4 EOF sentinel propagation validated (half-close semantics); W3 adopter self-reaping pinned as a TunnelSession spec requirement; W2 post-hoc registration viable Findings: - F-1: ChannelPlan's Send+Sync bound constrains plan payloads (socket halves carry + Sync; spec should pin the constraint) - F-2: empty UDP datagrams collide with the EOF sentinel in raw pass-through (pinned by an executable test) — the length-framed codec is mandatory for UDP; raw pass-through stays stream-substrate-only. Second validation of the codec decision; OQ-TN-02 mandate strengthened W1 (connect-side serving path resolves caller identity only via payload auth_token) filed upstream as alkcall consumer-findings ledger CF-005 (alkcall 0d287a9). Verification: cargo test 14/14, clippy --all-targets -D warnings, fmt --check — all clean, repeat-run stable
This commit is contained in:
@@ -416,6 +416,19 @@ re-chunked arbitrarily)?
|
||||
(OQ-TN-10 #1) remains +EV for the channels-layer fit
|
||||
(chunk-size vs datagram-size, MTU vs bounded buffers, idle expiry).
|
||||
|
||||
**Mandate strengthened 2026-09-07 (reverse POC finding F-2):** the
|
||||
length-framed codec is not just boundary preservation — it is
|
||||
*mandatory for correctness* on UDP. In the raw pass-through pump
|
||||
shape, an empty datagram is a zero-byte read from the substrate
|
||||
adapter — indistinguishable from EOF (`tokio::io::copy` treats `Ok(0)`
|
||||
as end-of-stream and shuts the pump down). An empty datagram and the
|
||||
zero-length EOF sentinel are the same wire shape at the pump level;
|
||||
the `[len: u16 BE]` prefix makes an empty datagram two bytes,
|
||||
unambiguous. UDP rides the codec, never raw pass-through; raw
|
||||
pass-through stays stream-substrate-only (where a zero-byte read is
|
||||
genuinely EOF). Validated from a second angle by the reverse-flow POC
|
||||
(`reverse-poc-summary.md` §F-2, pinned by an executable test).
|
||||
|
||||
### OQ-TN-03: Direction semantics (`-L` / `-R` / dynamic)
|
||||
|
||||
**Status: resolved 2026-09-05** by the hub-owns-the-connection model
|
||||
@@ -460,9 +473,17 @@ connection. The open questions:
|
||||
"SOCKS5 server implemented over alktunnels dial primitives" in a
|
||||
separate crate. Keep or cut for v1?
|
||||
|
||||
**Status:** open — needs architecture decision. Half-answer (hunch): `-L`
|
||||
is the channel/open handler; `-R` needs a small advertisement/lifecycle
|
||||
surface; `-D` composes on top and is out of scope for the base crate.
|
||||
**Status:** resolved 2026-09-05 by the hub-owns-the-connection model;
|
||||
the last open thread (the `-R` advertisement/lifecycle surface) closed
|
||||
2026-09-07 by the reverse-flow POC (`reverse-poc-summary.md`): **no
|
||||
advertisement op is needed.** The listener is the initiating side's
|
||||
own local resource — it binds (assembly layer, OQ-TN-04) and opens
|
||||
tunnel channels toward the serving side per accept; a far-side
|
||||
listener ("expose a port on your end") is a producer-side listen
|
||||
establisher over the same open op, not a new mechanism. The hunch
|
||||
above is superseded: `-L` and `-R` are the same open op with the
|
||||
entry point on different machines; `-D` composes on top and stays out
|
||||
of scope for the base crate.
|
||||
|
||||
### OQ-TN-04: No forced local binding
|
||||
|
||||
@@ -744,6 +765,19 @@ Phase 0 may need (in rough priority order, per the SDD process's
|
||||
Template available: SSH's `tcpip-forward` global-request
|
||||
registration → per-accept `forwarded-tcpip` opens → cancel
|
||||
(`ssh-socks5-survey.md` §RFC 4254 §7.1).
|
||||
|
||||
**Done 2026-09-07** — see `reverse-poc-summary.md`. 14 tests pass
|
||||
over alkcall 0.6.0; the review 007 non-finding trace confirmed by
|
||||
execution (`from_connection_with_serving` + `register_on` +
|
||||
serving-side allocation). The advertisement thread of OQ-TN-03
|
||||
closes: no advertisement op needed — the listener is the hub's own
|
||||
local resource; a far-side listener is a producer-side listen
|
||||
establisher over the same open op. Findings: F-1 (plan payloads
|
||||
must be `Send + Sync`), F-2 (UDP raw pass-through cannot carry
|
||||
empty datagrams — the length-framed codec is mandatory, second
|
||||
validation of the codec decision). W1 (connect-side serving path
|
||||
resolves identity only via payload `auth_token`) filed for the
|
||||
alkcall ledger.
|
||||
3. **Unix socket + stdio bridge POC** — cheap; validates "substrate
|
||||
agnostic" beyond IP substrates.
|
||||
4. **Two-pump helper extraction spike** — OQ-TN-06, only after 1–3.
|
||||
@@ -834,13 +868,23 @@ Candidate reading for the research specialist (to be expanded):
|
||||
`[len:u16 BE]` per datagram for UDP (2 B); no 5-byte header (a
|
||||
tunnel has one data stream per direction — no sub-demux key
|
||||
needed). Residual for the Phase 1 ADR: empty-datagram
|
||||
(`len=0`) semantics. Feeds OQ-TN-07 (option A strengthened:
|
||||
(`len=0`) semantics — **strengthened 2026-09-07 (F-2): the
|
||||
codec is mandatory for UDP** (empty datagram = zero-byte read
|
||||
= EOF collision in raw pass-through); the empty-datagram
|
||||
semantic under the codec is `len=0` = a legal empty datagram
|
||||
(forward POC validated). Feeds OQ-TN-07 (option A strengthened:
|
||||
substrate discriminator in params selects the framing) and the
|
||||
OQ-TN-05 trait shape
|
||||
- [ ] Decision input: backend trait vs no-trait (OQ-TN-05), now
|
||||
including the hub re-produce composition question
|
||||
- [ ] Targeted POC(s) run + summary (OQ-TN-10) — UDP POC DONE
|
||||
(2026-09-06, `poc-summary.md`); reverse-flow POC remains
|
||||
- [x] Targeted POC(s) run + summary (OQ-TN-10) — UDP POC DONE
|
||||
(2026-09-06, `poc-summary.md`); reverse-flow POC DONE
|
||||
(2026-09-07, `reverse-poc-summary.md` — the `-R` shape validated
|
||||
end-to-end over alkcall 0.6.0; findings F-1/F-2; W1 filed for
|
||||
the upstream ledger). Remaining items (#3 unix/stdio, #4 helper
|
||||
spike) are spec-scope: #3 folds into the real crate's tests
|
||||
(pump agnosticism confirmed twice), #4 resolved by alkcall 0.6.0
|
||||
(ADR-050)
|
||||
- [x] Two-pump helper convergence input gathered (OQ-TN-06) — the POC
|
||||
gives both shapes (producer `pump_halves`, consumer
|
||||
`take_halves` + copy): same shape modulo channel side; the
|
||||
|
||||
Reference in New Issue
Block a user