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:
2026-09-07 10:06:42 +00:00
parent b3b00f37bd
commit 603f398f6d
3 changed files with 296 additions and 7 deletions
+50 -6
View File
@@ -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 13.
@@ -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