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)
12 KiB
12 KiB
status, last_updated
| status | last_updated |
|---|---|
| draft | 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 (OQ-TN-01)
- Status: resolved — ADR-001
- 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|unixextensible, 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 (OQ-TN-02)
- Status: resolved — ADR-003
- 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/
-DUDP: 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=0is 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 (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/-Rare 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).-Dcomposes 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 (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 (OQ-TN-05)
- Status: resolved — ADR-004
- 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 (OQ-TN-06)
- Priority: medium
- Status: resolved (upstream) —
alkcall::channels::pump_bidilanded 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 (OQ-TN-07)
- Status: resolved — ADR-002
- Priority: high
- Resolution: 2026-09-07 (Phase 1). Option A: single
alk/tunnelALPN; the substrate discriminator inparamsselects 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 (OQ-TN-08)
- Status: resolved — ADR-006
(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.descriptionround-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). Thetunnel:openscope 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 (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_failedcall 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 (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
localfeature; 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 payloadsSend + 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: 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
ResourceRegistryshape 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_openableon 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 (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
localfeature's UDP adapter andTunnelSession::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
localfeature v1 — same halves shape as TCP (dial_unix), cheap, wire enum already carriesunix(ADR-001). Implemented bytunnels/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(), alkttytty-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.)
- Unix: in scope for the
- Impacts:
tunnels/local-socket-halves(unix yes, stdio no); the wire enum'sunixvalue 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)