Renames the written-usage rule into practice across the contract surface: docs/ (architecture, research, plans, sdd), tasks/ (all 43 task files, taskgraph validate passes), AGENTS.md, README.md, CHANGELOG.md, and the .opencode/agents/ prompts. Every replacement is a sense-preserving rewrite (colons, semicolons, commas, parentheses, sentence splits, varied), never a mechanical swap; no spaced hyphens were substituted. Enum fields, frontmatter, tables, wire data, and cited identifiers survive verbatim; en dashes inside numeric ranges keep their meaning. Verification: taskgraph validate (43 tasks), repo grep clean (single exempt hit: the verification command's own search pattern in AGENTS.md), cargo test, clippy --all-targets -D warnings, fmt --check, doc all green.
113 lines
5.3 KiB
Markdown
113 lines
5.3 KiB
Markdown
---
|
||
status: reviewed
|
||
last_updated: 2026-10-28
|
||
---
|
||
|
||
# Overview: alkssh
|
||
|
||
## What this crate is
|
||
|
||
alkssh is the alk family's SSH adapter (family ADR-003): a thin
|
||
wrapper around **russh** that terminates the vanilla-SSH wire and
|
||
bridges to/from family protocols. It is **a door in both directions,
|
||
vanilla on the outside** (vision principle 2; ADR framing in
|
||
`mapping.md` / `client.md`):
|
||
|
||
- **Server direction**: a door *for vanilla clients*. Vanilla `ssh`,
|
||
`git`, and (never for us, by design) sftp tooling connect as they
|
||
would to any sshd; each accepted SSH channel/request is mapped onto
|
||
exactly one family protocol seam and exactly one cargo feature.
|
||
Primary current purpose: the alkforge git door.
|
||
- **Client direction**: a door *to vanilla servers*. A family app
|
||
(the reverse-runner hub) dials vanilla `sshd` (rented fleets,
|
||
runpod/vast.ai-style boxes) and the ops map family-side onto
|
||
alktty/alktunnels/alkgit types; the runner stays vanilla by design.
|
||
|
||
The crate's substance is glue and mapping; no SSH framing is authored
|
||
in-family (family ADR-003 decision 1); russh owns the wire, and the
|
||
pin is ADR-002.
|
||
|
||
## Position in the family
|
||
|
||
| Concern | Owner |
|
||
|---|---|
|
||
| SSH wire protocol (KEX, ciphers, channel mux, userauth state machines) | russh (pinned, ADR-002) |
|
||
| SSH channel-type → family-protocol mapping | **this crate** (the spine, `mapping.md` / `client.md`) |
|
||
| Identity (fingerprint → `Identity`) | alkcall `IdentityProvider`, assembly-implemented; never the vault (vault = secrets *we* hold) |
|
||
| Secrets we hold (client dial keys, host keys) | alkvault-backed sources (ADR-005) |
|
||
| The `alk/ssh` ALPN | ADR-001 (edge-termination contract; relay/browser legs have no consumer in scope, OQ-01 resolved) |
|
||
| Deployment policy (which features, which ACLs) | the embedding assembly (alkforge) |
|
||
|
||
Composability boundary: alkssh is a door, not a backend. It depends
|
||
on alkcall types at the wire layer and the mapped crates' session or
|
||
client surfaces, and carries no deployment policy. A downstream app
|
||
embeds it, enables features (ADR-003), brings identity/ACL config.
|
||
|
||
## Public surface (categories)
|
||
|
||
The crate is a library (`[lib]`, no binary, a stated non-goal); the surface
|
||
categories the phase-1 specs define:
|
||
|
||
- **Server stack** (`mapping.md`): serve configuration (feature-gated
|
||
seam wiring, bounded-resource limits, honest-advertisement auth
|
||
config) + the serving loop that accepts vanilla connections and
|
||
dispatches per the mapping table.
|
||
- **Client stack** (`client.md`): dial surface (address, key source,
|
||
host-key policy, keepalive/timeout config), the op-row consumers
|
||
(session exec/pty, tunnel dial, `-R` listen + acceptor), and
|
||
lifecycle primitives (bound-port handles, cancel; OQ-12: no
|
||
reconnect policy is owned).
|
||
- **Key sources** (`auth.md`): vault-backed source construction per
|
||
ADR-005 for both directions (client keys *and* host keys).
|
||
- **Identity plumbing** (`auth.md`): the fingerprint→identity bridge
|
||
at the server; the identity→seam propagation for mapped channels.
|
||
|
||
Feature graph (ADR-003): `session`, `git`, `tunnel`, `sftp`
|
||
(placeholder); flat, independent, `default = []` (no capabilities),
|
||
two-direction symmetry, fail-closed declines contract-tested on every
|
||
side of every feature.
|
||
|
||
## Bounded-resources policy (family convention)
|
||
|
||
Every session is bounded by wall clock, size, and channel count
|
||
(AGENTS.md convention 9; the knobs are russh's `Config` per ADR-002's
|
||
surface notes):
|
||
|
||
| Resource | Knob | Default posture |
|
||
|---|---|---|
|
||
| Session wall clock | `inactivity_timeout` | set (assembly-tunable) |
|
||
| Rekey volume/time | `Limits` | russh-enforced (post-0.64-full-enforcement) |
|
||
| Per-channel memory | `window_size`, `maximum_packet_size`, `channel_buffer_size` | set |
|
||
| Auth attempts | `max_auth_attempts` | 10 default (ADR-004: the counting `none` probe) |
|
||
| Keepalives (client direction, cloud fleets) | `keepalive_interval`/`keepalive_max` | 15 s / 3 (reverse-runner evidence: NAT'd runners) |
|
||
| Concurrent channels per session | ours (in-crate) + per-identity policy when bridged | ours to cap |
|
||
|
||
No unbounded loops, no unbounded buffers; the fail-closed declines
|
||
plus the knobs above are the whole posture.
|
||
|
||
## Non-goals
|
||
|
||
Per `vision.md`: no in-family SSH protocol machinery (ever); not an
|
||
sshd (no local accounts, no OpenSSH `authorized_keys` semantics, no
|
||
PAM); no sftp serving until alkfs lands (OQ-13 resolved; the feature
|
||
exists as a tested declining placeholder); no binary/CLI; no password
|
||
or keyboard-interactive auth in either direction; no x11 or agent
|
||
forwarding at all (not even feature-gated, ADR-003 §5).
|
||
|
||
## Lifecycle note
|
||
|
||
This crate follows the family crate template (alktty root pattern):
|
||
`src/` modules re-exported from `lib.rs`, one module per file, public
|
||
API = crate-root re-exports. The dependency set (russh per ADR-002,
|
||
alkcall types, per-feature sibling deps: alktty/alktunnels/alkgit) and
|
||
the manifest (`rust-version` 1.89, edition 2024) land at
|
||
implementation start; ADR-002 records the manifest decisions.
|
||
|
||
## References
|
||
|
||
- [README.md](README.md) (index), [open-questions.md](open-questions.md) (OQ-01…13)
|
||
- ADRs 001–006 in [decisions/](decisions/)
|
||
- `docs/research/`: vision, POC findings (1/2/3), russh inventory,
|
||
auth bridge, mapping table (validated), reverse-runner extraction
|
||
- Family ADR-003 (the structural decision), family ADR-002 (alkforge;
|
||
why exclusion matters) |