Split the last open substrate-placement question: - Unix: ships with the local feature v1 (dial_unix — same halves shape as TCP; the wire enum already carried unix per ADR-001; the params task's schema list includes all three values) - Stdio: OUT of scope — a spawned process's stdin/stdout/stderr IS alktty's pipe mode (LocalTtyBackend + tokio::process + Stdio::piped, alktty tty-local.md): three multiplexed logical streams + the exit-code control chunk (alktty ADR-004) + signal forwarding (REQ-TTY-02). A stdio bridge here would be alktty's runner mode with the terminal stripped out — a strictly worse duplicate that also drops the semantics that matter (a byte tunnel has neither exit codes nor signals). Remote command execution composes via alktty on the same channels substrate. Updated: open-questions.md OQ-TN-14 (resolved), overview.md feature gate + deps + OQ summary, producer.md OQ ref, OQ-TN-10 promotion (#3 split), phase-0-findings + both POC summaries' resolution notes, params task (schema enum includes unix), local-socket-halves task (unix ships, stdio does NOT — with the composition rationale), oq-tn-14-tracker task repurposed (boundary-maintenance: re-opens only if a consumer needs stdio-without-process-semantics — which would need its own ADR, or if the alktty/alktunnels boundary needs sharpening). Verified: taskgraph valid (12 tasks, no cycles)
242 lines
12 KiB
Markdown
242 lines
12 KiB
Markdown
---
|
|
status: draft
|
|
last_updated: 2026-09-07
|
|
---
|
|
|
|
# alktunnels — Open Questions
|
|
|
|
Centralized tracker. The Phase 0 OQ ledger (`docs/research/
|
|
phase-0-findings.md`, OQ-TN-01..10) is promoted here with statuses
|
|
current as of the Phase 1 spec; new Phase 1 questions continue the
|
|
OQ-TN numbering. Format per `docs/sdd_process.md`.
|
|
|
|
## Theme 1: Wire format and addressing
|
|
|
|
### OQ-TN-01: Target addressing format (open-op `params` shape)
|
|
|
|
- **Origin**: [phase-0-findings.md](../research/phase-0-findings.md) (OQ-TN-01)
|
|
- **Status**: resolved — [ADR-001](decisions/001-open-params-layout.md)
|
|
- **Priority**: high
|
|
- **Resolution**: 2026-09-07 (Phase 1). `params` = self-contained
|
|
JSON object: `{ "resource": <string>, "substrate": <string> }`.
|
|
The resource identifier is the producer's stable name (a registered
|
|
resource id, not an address); substrate is the extensible
|
|
discriminator (`tcp` | `udp` | `unix` extensible, additive). The
|
|
producer owns the backing; no URL-style general addressing. Reframe
|
|
+ survey input (ssh-socks5-survey §OQ-TN-01 residue) + both POCs.
|
|
- **Cross-references**: OQ-TN-02, OQ-TN-03, ADR-001, ADR-002
|
|
|
|
### OQ-TN-02: Datagram substrates (UDP) — boundary preservation
|
|
|
|
- **Origin**: [phase-0-findings.md](../research/phase-0-findings.md) (OQ-TN-02)
|
|
- **Status**: resolved — [ADR-003](decisions/003-codec-and-udp-framing.md)
|
|
- **Priority**: high
|
|
- **Resolution**: split by path (2026-09-06 survey) + F-2 mandate
|
|
(2026-09-07 reverse POC). Base open-op UDP resources:
|
|
endpoint-at-open (one channel = one flow). Dynamic/`-D` UDP:
|
|
per-datagram addressing inside the tunnel payload, assembly-layer.
|
|
Boundary preservation: mandatory `[len: u16 BE]` per-datagram
|
|
framing — mandatory for correctness, not cosmetics (F-2; the full
|
|
rationale and the executable pin live in ADR-003). Under the codec,
|
|
`len=0` is a legal empty datagram (forward POC validated); EOF is
|
|
the channels-level sentinel; the layers never collide.
|
|
- **Cross-references**: OQ-TN-01, OQ-TN-07, ADR-003
|
|
|
|
### OQ-TN-03: Direction semantics (`-L` / `-R` / dynamic)
|
|
|
|
- **Origin**: [phase-0-findings.md](../research/phase-0-findings.md) (OQ-TN-03)
|
|
- **Priority**: high
|
|
- **Status**: resolved — hub-owns-the-connection model (2026-09-05) +
|
|
the reverse-flow POC (2026-09-07, `reverse-poc-summary.md`).
|
|
No protocol-level direction: role follows the resource. `-L`/`-R`
|
|
are the same open op with the entry point on different machines;
|
|
no advertisement op is 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). `-D` composes at the assembly
|
|
layer ("tunnel a socks5 connection"), out of base-crate scope.
|
|
- **Cross-references**: OQ-TN-04, OQ-TN-08, ADR-004, ADR-005
|
|
|
|
### OQ-TN-04: No forced local binding
|
|
|
|
- **Origin**: [phase-0-findings.md](../research/phase-0-findings.md) (OQ-TN-04)
|
|
- **Priority**: medium
|
|
- **Status**: resolved — binding is always assembly-layer and
|
|
optional, on either side; the protocol never binds. API surface:
|
|
dial flows with no local bind (both POCs), listen flows where the
|
|
binding is the producer's establisher (listen variant, ADR-004),
|
|
unbound/abstract flows (in-process pipes — the pump is generic over
|
|
boxed halves). The concrete produce/consume surface is spec'd in
|
|
producer.md / consumer.md (ADR-005).
|
|
- **Cross-references**: OQ-TN-03, ADR-004, ADR-005
|
|
|
|
## Theme 2: Crate architecture
|
|
|
|
### OQ-TN-05: Backend inversion point — `TunnelBackend` trait?
|
|
|
|
- **Origin**: [phase-0-findings.md](../research/phase-0-findings.md) (OQ-TN-05)
|
|
- **Status**: resolved — [ADR-004](decisions/004-no-backend-trait.md)
|
|
- **Priority**: medium
|
|
- **Resolution**: 2026-09-07 (Phase 1). No trait for substrate access:
|
|
"produce boxed halves for a resource" is a function (UDP POC,
|
|
OQ-TN-05 executable input). The only remaining thread — the hub
|
|
re-produce composition — resolves the same way: a hub proxy is a
|
|
consumer + producer composed at the assembly layer (the reverse
|
|
POC's hub is exactly this shape minus re-export); a composition
|
|
helper is deferred(scope) until a concrete hub-proxy consumer
|
|
exists (OQ-TN-12).
|
|
- **Cross-references**: OQ-TN-12, ADR-004
|
|
|
|
### OQ-TN-06: The two-pump helper — extract now?
|
|
|
|
- **Origin**: [phase-0-findings.md](../research/phase-0-findings.md) (OQ-TN-06)
|
|
- **Priority**: medium
|
|
- **Status**: resolved (upstream) — `alkcall::channels::pump_bidi`
|
|
landed in alkcall 0.6.0 (ADR-050, review 007 R-03), shape as this
|
|
OQ sketched it; this crate is cited as convergence input. alktunnels
|
|
consumes the helper; hand-rolling is out.
|
|
- **Cross-references**: ADR-005 (consumer pump), ADR-050 (upstream)
|
|
|
|
## Theme 3: Protocol surfaces
|
|
|
|
### OQ-TN-07: ALPN strategy
|
|
|
|
- **Origin**: [phase-0-findings.md](../research/phase-0-findings.md) (OQ-TN-07)
|
|
- **Status**: resolved — [ADR-002](decisions/002-alpn-strategy.md)
|
|
- **Priority**: high
|
|
- **Resolution**: 2026-09-07 (Phase 1). Option A: single `alk/tunnel`
|
|
ALPN; the substrate discriminator in `params` selects the framing.
|
|
Prior art (SSH one channel mechanism; SOCKS5 one control
|
|
connection; udpgw self-describing framing) gives no reason for the
|
|
split; option B's consumer-side API bifurcation buys nothing.
|
|
- **Cross-references**: OQ-TN-01, OQ-TN-02, ADR-001, ADR-002
|
|
|
|
### OQ-TN-08: Access control and ownership scope
|
|
|
|
- **Origin**: [phase-0-findings.md](../research/phase-0-findings.md) (OQ-TN-08)
|
|
- **Status**: resolved — [ADR-006](decisions/006-access-control-posture.md)
|
|
(2026-09-07 — the posture promoted to a decision). The resource is
|
|
owned by the far side (alkcall op-level ACL applies as-is; no
|
|
tunnel-specific policy layer, no allowlists in v1; the ownership
|
|
seam is the establisher seeing the per-call opener identity).
|
|
Discovery = the ACL-filtered ops listing (openable channels are
|
|
operations, ADR-047); `OperationSpec.description` round-trips
|
|
through discovery (review 006 E-02). The live resource-enumeration
|
|
half (alkcall OQ-40) stays deferred upstream. Identity: 0.7.0's
|
|
precedence chain (token > `ServingConfig.identity` > transport),
|
|
per-call opener identity on the open-op hooks (CF-005/CF-006).
|
|
The `tunnel:open` scope constant is stable once published (ADR-006
|
|
§2). `-D` = "tunnel a socks5 connection" (target selection in the
|
|
socks5 protocol).
|
|
- **Cross-references**: OQ-TN-03, ADR-006, producer.md (scope gating)
|
|
|
|
### OQ-TN-09: Lifecycle, teardown, and error reporting
|
|
|
|
- **Origin**: [phase-0-findings.md](../research/phase-0-findings.md) (OQ-TN-09)
|
|
- **Priority**: high
|
|
- **Status**: resolved (superseded by alkcall ADR-049, 0.5.0; narrowed
|
|
through 0.6.0/0.7.0) — establishment is the open op's awaited phase;
|
|
dial failure is a typed `channel:open_failed` call error (reason ∈
|
|
`dial_failed` / `unknown_resource` / `resource_shortage` /
|
|
`handler_error` / `timeout`), never a phantom channel. Residual
|
|
resolved by the POCs: half-open semantics = the two-pump contract
|
|
(W4 validated); the consumer session owns teardown (W3, ADR-005);
|
|
v1 needs no mid-stream control frame (pump-phase failures are
|
|
EOF-shaped by design, ADR-049 §6).
|
|
- **Cross-references**: ADR-003 (sentinels), ADR-005, alkcall ADR-049
|
|
|
|
### OQ-TN-10: POC scope (Phase 0 closure)
|
|
|
|
- **Origin**: [phase-0-findings.md](../research/phase-0-findings.md) (OQ-TN-10)
|
|
- **Priority**: low
|
|
- **Status**: resolved — UDP POC DONE (2026-09-06, 17 tests),
|
|
reverse-flow POC DONE (2026-09-07, 14 tests; re-validated over
|
|
alkcall 0.7.0, 16 tests). #3 split (OQ-TN-14): unix ships with the
|
|
`local` feature; stdio is OUT — alktty's pipe mode owns process
|
|
stdio (exit codes + signals are tty semantics). #4 (helper spike)
|
|
resolved by alkcall ADR-050. Findings F-1 (plan payloads
|
|
`Send + Sync` — documented upstream) and F-2 (UDP codec mandatory)
|
|
recorded; W1 filed upstream and RESOLVED (CF-005/CF-006).
|
|
- **Cross-references**: ADR-003, OQ-TN-05, OQ-TN-06
|
|
|
|
## Theme 4: Phase 1 residues (new)
|
|
|
|
### OQ-TN-11: Resource naming — collision domain and lifecycle of a resource id
|
|
|
|
- **Origin**: OQ-TN-01's residue (stable resource name vs target
|
|
address), carried into Phase 1
|
|
- **Status**: partially resolved — the collision-domain half is
|
|
**resolved by [ADR-001](decisions/001-open-params-layout.md)**: the
|
|
domain is the producer's registry (per-producer; two producers on
|
|
the same connection may expose the same resource name independently
|
|
— the open op resolves against the SERVING side's registry). The
|
|
lifecycle half stays open: is a resource registry a producer-side
|
|
assembly construct (the POCs' `HashMap` — the leading candidate),
|
|
or does it need protocol-level register/rename/retire ops?
|
|
- **Priority**: medium
|
|
- **Impacts**: producer.md's `ResourceRegistry` shape and the
|
|
discovery story (OQ-TN-08); a protocol-level registry op would be a
|
|
new wire surface (one-way door).
|
|
- **Resolution**: lifecycle half pending — no prior-art pressure
|
|
(SSH lists no forwards in-band; discovery is the ops listing);
|
|
decide when a consumer needs shared/lifecycle-managed resources.
|
|
- **Cross-references**: ADR-001, OQ-TN-08
|
|
|
|
### OQ-TN-12: Hub re-produce composition helper
|
|
|
|
- **Origin**: OQ-TN-05's remaining thread (2026-09-05 hub model)
|
|
- **Status**: deferred(scope)
|
|
- **Priority**: low
|
|
- **Blocked on**: a concrete hub-proxy consumer (a crate that
|
|
re-produces a consumed tunnel resource) — the reverse POC's hub is
|
|
the seed shape (consumer + `register_openable` on the same
|
|
connection) but does not exercise re-export; if one materializes,
|
|
decide whether a composition helper belongs in this crate or is
|
|
assembly-layer wiring of the existing surface.
|
|
- **Cross-references**: OQ-TN-05, ADR-004, alkcall ADR-042 (relay)
|
|
|
|
### OQ-TN-13: UDP truncation semantics at the codec boundary
|
|
|
|
- **Origin**: forward POC Issues Surfaced #3
|
|
- **Status**: resolved — [ADR-003](decisions/003-codec-and-udp-framing.md)
|
|
(2026-09-07): **fail-loud at the adapter level.** A receive buffer
|
|
smaller than the datagram is an error, never a silent truncation —
|
|
a truncated datagram would corrupt the length-framed stream's
|
|
framing invariants (the reverse POC's F-2 rationale: the codec's
|
|
wire discipline is what keeps empty datagrams unambiguous; silent
|
|
truncation is the same class of invariant break). The codec's MTU
|
|
bound (65535) makes truncation unreachable for well-formed peers;
|
|
failing loud turns a spec violation into a typed error.
|
|
- **Priority**: medium
|
|
- **Impacts**: the `local` feature's UDP adapter and
|
|
`TunnelSession::recv_datagram`'s error surface; consumer-visible
|
|
(an error vs silent truncation is a behavioral difference), so the
|
|
decision rides an Accepted ADR before the first consumer.
|
|
- **Cross-references**: ADR-003, wire.md
|
|
|
|
### OQ-TN-14: Unix-socket and stdio substrate placement
|
|
|
|
- **Origin**: OQ-TN-10 #3 (the cheap un-POC'd item)
|
|
- **Priority**: low
|
|
- **Status**: **resolved 2026-09-07 (split by substrate):**
|
|
- **Unix: in scope for the `local` feature v1** — same halves shape
|
|
as TCP (`dial_unix`), cheap, wire enum already carries `unix`
|
|
(ADR-001). Implemented by `tunnels/local-socket-halves`.
|
|
- **Stdio: OUT of scope — alktty owns it.** A spawned process's
|
|
stdin/stdout/stderr IS a terminal session in alktty's model:
|
|
`LocalTtyBackend`'s pipe mode (`tokio::process::Command` +
|
|
`Stdio::piped()`, alktty `tty-local.md`) is exactly the stdio
|
|
case — three multiplexed logical streams + the exit-code
|
|
control chunk (alktty ADR-004) + signal forwarding (REQ-TTY-02).
|
|
A "stdio bridge" here would be alktty's runner mode with the
|
|
terminal stripped out: a strictly worse duplicate that also
|
|
drops the semantics that matter (exit code, signals — a byte
|
|
tunnel has neither). Consumers needing to run commands remotely
|
|
compose: alkcall dial → alktty session (pipe mode) — the two
|
|
crates are siblings on the same channels substrate, not
|
|
competitors. (The OQ-TN-10 #3 "cheap item" was scoped before the
|
|
sibling relationship was this clear.)
|
|
- **Impacts**: `tunnels/local-socket-halves` (unix yes, stdio no);
|
|
the wire enum's `unix` value now has a v1 implementation path.
|
|
- **Cross-references**: ADR-003, ADR-004, overview.md; alktty
|
|
`tty-local.md` §pipe mode, alktty ADR-004 (exit code on a control
|
|
chunk) |