--- status: draft last_updated: 2026-10-26 --- # Open questions Centralized tracker for alkssh. Seeded from the phase 0 POC findings (`docs/research/poc-{1,2,3}-*.md`), the research docs' OQ seeds, and the reverse-runner extraction. Numbers are repo-local (family and alkcall trackers have their own OQ spaces). ## Theme A — wire & family topology ### OQ-01: Does an `alk/ssh` relay/browser-leg consumer emerge? - **Origin**: [mapping-table.md](../research/mapping-table.md) §topology, `vision.md` scope Q1 - **Status**: deferred(scope) - **Door type**: two-way (the pin is one-way; consumer *existence* is not) - **Priority**: medium - **Impacts**: none for the phase 1 scope — ADR-001 pins the contract so relay/browser legs don't foreclose it; the phase 1 docs serve edge termination only. A future relay leg would exercise `docs/architecture/client.md`'s accept surface in a new role. - **Blocked on**: a concrete consumer — either the browser-WASM route (alkcall ADR-009 sketch) materializing in an assembly, or a hub deployment needing SSH-in-relay. No such use case exists yet. - **Resolution**: Not yet decidable — no consumer use case exists. ADR-001 decides everything decidable now: the ALPN pin's raw-stream contract, and its transport-blindness. - **Cross-references**: ADR-001, OQ-13 ## Theme B — session-channel dispatch & mapping details ### OQ-02: ~~What is the session-channel dispatch shape (SOCKS-detect vs parse, and who bounds the window)?~~ — resolved (then simplified) - **Origin**: [poc-3-mapping-bakeoff.md](../research/poc-3-mapping-bakeoff.md) §Stage B.3, `mapping-table.md` §notes - **Status**: resolved — resolved twice over. First by ADR-006 point 3 (dispatch composition: request-driven parse wins, request-less channels get the detect). Then **simplified by the ADR-003 §1a amendment**: the `dynamic-forward` feature retired (no consumer is ever the family-native SOCKS-in-channel client; vanilla `-D` is client-side SOCKS + plain `direct-tcpip`; the family `-D` door is alksocks composed locally at the assembly), so the detect lost its owner. Final shape: **session dispatch is parse-only**; request-less session channels decline. POC-3 stage B survives as the feasibility record for re-adding a remote SOCKS door via explicit ADR. - **Cross-references**: ADR-006, ADR-003 §1a ### OQ-03: ~~Username disposition~~ — resolved - **Origin**: [poc-1-auth-bridge.md](../research/poc-1-auth-bridge.md) §2, `auth-bridge.md` §The mapping - **Status**: resolved - **Resolution**: usernames are never the identity model and carry no routing semantics — the fingerprint is the sole resolution path (POC-1: `ssh anything@host` works with the same identity). Whether a username string appears in logs is deployment policy, outside the crate. Rides as the recorded contract in the `auth.md` spec / ADR-004. ### OQ-04: OpenSSH certificate auth — is there ever a CA-trust use case? - **Origin**: `mapping-table.md` (auth rows), [poc-1-auth-bridge.md](../research/poc-1-auth-bridge.md) OQ seed 4 - **Status**: deferred(scope) - **Door type**: two-way - **Priority**: low - **Impacts**: none — `auth_openssh_certificate` is declined (the ADR-004 disposition), and POC-1 established the decline exists. A revisit only matters if alkforge ever wants CA-issued certificates. - **Blocked on**: a concrete OpenSSH-CA use case arriving in an embedding assembly. - **Resolution**: Not yet decidable — decline initial; no CA-trust story in the family identity model today. ## Theme C — auth, identity & key custody ### OQ-05: ~~What is the client-side host-key pin store?~~ — resolved (policy-seam shape) - **Origin**: [auth-bridge.md](../research/auth-bridge.md) §Host keys, `reverse-runner.md` §5 - **Status**: resolved — the *seam* is decided; where learned pins persist is assembly detail (the crate takes a policy, not a pin store). - **Resolution**: two basic client cases, one seam: 1. **Known beforehand** — trust anchors exist. Family-built runners mint their host key at assembly time, so the expected fingerprint is known before first contact: assembly-supplied pins, **hard decline on mismatch** (no soft failure). 2. **Unknown beforehand** — vanilla `sshd` on container fleets the assembly didn't provision; no anchor exists until first contact. The crate surfaces the presented host key (host, port, fingerprint) to an **assembly-provided `HostKeyPolicy`** that decides: prompt-and-record, provider-metadata match, or learn-and-record. The OpenSSH "add to known_hosts?" moment becomes an assembly policy rather than crate behavior. Crate rules that make this family-shaped: the crate's default policy is **fail-closed** (reject unknown, hard-decline mismatch — russh's own reject-all default, kept); the crate never decides trust itself; accept-all is never a crate option (that collapse is the old-code anti-pattern, and for ephemeral fleets strict pinning is the wrong control anyway — the anchor there is hub-held key material/lifecycle, not host pins). The contract lands in the client-side ADR (written with `client.md`; expected to be ADR-007) and the `auth.md` spec. - **Cross-references**: OQ-07, `reverse-runner.md`, [poc-2-vault-keys.md](../research/poc-2-vault-keys.md) §5 (host keys ride the vault model) ### OQ-06: ~~One vault, many roles?~~ — resolved - **Origin**: [poc-2-vault-keys.md](../research/poc-2-vault-keys.md) OQ seed 3 - **Status**: resolved - **Resolution**: not an alkssh constraint. The crate takes vault handles the assembly injects; whether the assembly runs separate vault instances per role (client keys vs host keys) is assembly policy. ADR-005 records the boundary: vault handle in, key material out, version semantics owned by the vault. ### OQ-07: Is the alkvault `decrypt` plain-`String` zeroization gap closed at the vault or at the adapter? - **Origin**: [poc-2-vault-keys.md](../research/poc-2-vault-keys.md) §2 + OQ seed 1 - **Status**: open - **Priority**: medium - **Impacts**: an in-family cross-crate ask (alkvault API change vs alkssh-side convention). Blocks nothing functionally — POC-2 proves the adapter-side `Zeroizing` wrap correct — but decides where the security convention lives for the whole family (alkhttp secrets ride the same `&str`-out surface). - **Resolution**: pending. Candidates: alkvault returns `Zeroizing` (family-wide fix, touches a published crate), or the adapter-side wrap is the recorded family convention (ADR-005). Bring to alkvault; if upstream accepts, ADR-005 cites the follow-up; if not, ADR-005 records the adapter obligation as the convention. - **Cross-references**: OQ-05, ADR-005 ## Theme D — session-request mapping details ### OQ-08: Shell command convention for `shell_request` - **Origin**: `mapping-table.md` (shell row), [poc-3-mapping-bakeoff.md](../research/poc-3-mapping-bakeoff.md) OQ seed 3 - **Status**: open - **Priority**: medium - **Impacts**: blocks the `mapping.md` session-row detail (what alktty `drives` when a vanilla `ssh host` lands). The POC's stand-in (`bash`/`sh -c`) was explicit assembly policy, not wire-derived. - **Resolution**: pending. Direction known (assembly policy, nothing wire-supplied); the decision is the concrete convention surface: a config field on the assembly vs a crate-level default that the assembly may override. Decide when writing `mapping.md`. ### OQ-09: `env_request` policy — is an allowlist ever wanted? - **Origin**: `mapping-table.md` (env_request row) - **Status**: deferred(scope) - **Door type**: two-way - **Priority**: low - **Impacts**: none — decline-by-default is the fixed posture (wire env is not family config). An allowlist (`LANG`, …) only matters if a consuming assembly has a concrete need. - **Blocked on**: a concrete consumer use case requiring wire-supplied environment variables. - **Resolution**: Not yet decidable — no use case; decline stands. ### OQ-10: The alktty exit chunk carries no signal identity — widen the chunk or map by assembly policy? - **Origin**: [poc-3-mapping-bakeoff.md](../research/poc-3-mapping-bakeoff.md) §D.2, `mapping-table.md` (exit_signal row) - **Status**: open - **Priority**: medium - **Impacts**: blocks the `exit-signal` fidelity detail in `mapping.md`; an in-family upstream ask (alktty wire change, third-party-upstream posture applies family-internally too). - **Resolution**: pending. Candidates (per POC-3): alktty widens the exit chunk with the signal name (filed as an ask — alkssh never silently works around), or alkssh maps negative exit codes via assembly policy (fidelity compromise: name inferred/coarse). Also in scope for the same OQ: pipe-mode signals are pid-only vs PTY process-group scope (backend-semantics fidelity note for the session rows). Decide the *fallback* during `mapping.md`; the upstream ask stays open until alktty answers. - **Cross-references**: OQ-08 ### OQ-11: `direct-streamlocal` platform surface — compile-time or runtime decline shape? - **Origin**: `mapping-table.md` (streamlocal row) - **Status**: open - **Priority**: low - **Impacts**: blocks the `tunnel` feature's platform matrix detail (unix-only compile-out vs universal-compile runtime decline), a small contract test question. - **Resolution**: pending — decide during `mapping.md`; default direction is runtime decline (matches fail-closed and windows-on-ssh portability) unless the unix-only compile split proves simpler. ### OQ-12: ~~Client reconnect: does the crate own forward/session restoration?~~ — resolved - **Origin**: `reverse-runner.md` §4 - **Status**: resolved - **Resolution**: the crate owns lifecycle primitives only — bound-port handles (forward listeners return the actually-bound port, per russh's `tcpip_forward -> u32`), explicit cancellable forward/session handles, and clean disconnects. Reconnect-and-restore policy (rebinding persisted tunnel ports per alkminer's flow) is assembly-owned. Recorded as a constraint in `client.md`; no reconnect policy is baked into the crate. ## Theme E — deferred features ### OQ-13: The `sftp` client+server halves when alkfs lands - **Origin**: `mapping-table.md` (sftp rows), `reverse-runner.md`, POC-2 scope notes - **Status**: deferred(scope) - **Door type**: two-way - **Priority**: low (until alkforge phase 0 resumes) - **Impacts**: the `sftp` feature ships declining from the first build (honest advertisement, decline contract tested on both sides); the alkforge CI deploy path (binary/artifact push, alkminer-precedent evidence) and the alkfs server seam are the eventual consumers. - **Blocked on**: alkfs — family ADR-002, paused so alkforge can land; alkssh's sftp implementation follows alkfs' maturity. - **Resolution**: Not yet decidable — the target protocol is pending. The placeholder contract (decline, tested) is in scope for the first architecture pass. - **Cross-references**: OQ-01 ## Deferred / Blocked (at a glance) | OQ | Blocked on | Priority | |---|---|---| | OQ-01 | concrete relay/browser-leg consumer | medium | | OQ-02 | (deferred(unclear)) investigation during `mapping.md` | high | | OQ-04 | concrete OpenSSH-CA use case | low | | OQ-09 | concrete wire-env use case | low | | OQ-13 | alkfs landing (family ADR-002) | low (for now) |