Files
alkssh/CHANGELOG.md
T
glm-5.3-flash ab5236ebbb docs(release): wave 5 release readiness — crate docs, README, CHANGELOG, matrix, dry-run (w5-release-readiness)
- resolve the rustdoc warning set (9 incl. private-link class in
  client_ops.rs + redundant explicit links + a duplicated tty_map
  paragraph): cargo doc warning-free on default and --all-features
- docs honesty: the five recorded limits ride the published
  crate-root rustdoc (§Known limits: write_all no-deadline, PTY
  rule-5, port-0-only mint echo, no-reconnect policy, no-accept-all);
  crate docs state the feature graph + the fail-closed invariant
- two no_run usage doctests (server mount + dial) — the README
  examples stay compile-checked in every matrix build
- README.md lands (the door, feature graph, examples, custody
  posture, license); CHANGELOG.md carries the 0.1.0 founding entry
- feature matrix green (6 test builds, clippy x2 -D warnings, fmt,
  doc) + the fuzz corpus gate (11 invariants)
- cargo publish --dry-run --allow-dirty clean (76 files packaged +
  verified; file list checked against the package policy; manifest
  sanity recorded); the freeze inventory recorded for the gate

Verification: scripts/matrix.sh (all builds), fuzz corpus gate,
taskgraph validate
2026-10-30 19:29:23 +00:00

152 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
All notable changes to this crate are documented here. The format is
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
this crate adheres to [Semantic Versioning](https://semver.org/).
## [0.1.0] - 2026-10-30
The founding entry — the crate's first release. `alkssh` is the alk
family's SSH adapter (family ADR-003): a thin wrapper around russh
0.65 terminating the vanilla-ssh wire and bridging to/from alkcall
channels — the two-direction door for vanilla clients. The wire is
russh's; the crate's substance is the channel-type mappings
(session/pty → alktty, direct/forwarded-tcpip → alktunnels, git exec →
alkgit), each behind its cargo feature in a flat, independent graph
(ADR-003): **a default build has no capabilities and serves nothing
but clean declines** — every unfeatured or unimplemented request is
declined fail-closed, never half-served or silently fallen back, and
never advertised. Identity is the family's: a verified key's
fingerprint → alkcall `IdentityProvider`; keys the crate holds come
from alkvault-backed sources, encrypted at rest, decrypted at use,
never env vars (ADR-005). The crate is a door, not a backend — no
binary, no deployment policy; a downstream app embeds it, enables
features, and brings identity/ACL configuration.
### Added
**Phase 0/1 — research and architecture** (the contract the
implementation lands):
- SDD process, phase 0 research set (`docs/research/`), and the three
passed POCs (auth bridge, vault keys, mapping bake-off; findings in
`poc-1..3` + `reverse-runner.md`; POC source never merged).
- Phase 1 architecture under `docs/architecture/`: the spec docs and
ADRs 001–006 (Accepted) — the `alk/ssh` ALPN pin; the russh 0.65.0
pin (aws-lc-rs, no compression, rsa off); the capability feature
graph; auth dispositions; vault-key custody; the mapping/bridge/
dispatch decisions.
**Wave 1 — foundations:**
- The manifest: the russh 0.65 pin (`aws-lc-rs`, default features
off), the flat feature graph (`session` / `git` / `tunnel` /
`sftp`, `default = []`).
- The fail-closed error taxonomy (`thiserror`): `AdapterError`,
`DialError`, `KeySourceError`, `OpError`, `OpenDeclineReason` —
declines are dispositions, never panics; no `unwrap` outside tests.
- Vault-backed key custody in code: the `KeySource` /
`HostKeySource` seams and the ADR-005 implementations
(`VaultKeySource`, `VaultHostKeySource`) — decrypt-at-use /
decrypt-at-construction, the `Zeroizing` seam, one
`decode_secret_key` conversion.
- The `HostKeyPolicy` seam (OQ-05, policy-blind) with the fail-closed
default `RejectAll` — no accept-all built-in exists in the crate.
- The contract-invariant fingerprint computation (the crate's single
fingerprint path, the `SHA256:` format both the auth bridge and the
host-key policy consume).
- The config surface: `ServeConfig`, `DialConfig`, `Limits` (the
bounded-resources budget model — wall clock always set, channel
caps, keepalive posture) — unset fields decline at request time
(OQ-08), construction never validates.
**Wave 2 — the server stack:**
- `SshAdapter` — the mount point: `SshAdapter::new(serve)` builds the
russh server from the config (fail-closed on key-source failure);
`adapter.handle(stream)` serves one connection.
- The auth bridge: russh auth hooks → ADR-004 dispositions —
verified-key fingerprint → `IdentityProvider::resolve_from_fingerprint`,
fail-closed on every path; bounded auth attempts.
- Parse-only dispatch + the fail-closed decline core: every unroutable
or unfeatured request answers a clean, channel-scoped decline; the
spawned serving-path shapes (`channel_failure` then close).
- Spawn-and-return plumbing (ADR-006 decision 4): serving paths run
spawned (russh handlers return fast at this pin), with the
exit-status-before-close mechanics.
- Bounded resources at the handler surface: per-connection channel
caps (refuse-never-queue) and listener caps.
- The in-process loopback harness (the contract-test vehicle).
**Wave 3 — the server mappings (the spine):**
- Per-feature seam handles (`SessionSeam`, `GitSeam`,
`TunnelListenSeam`): unset seam → decline even with the feature on.
- Decline-path tracing (`tracing` events on every decline class).
- The git mapping (exec-only, ADR-006): the full exec grammar —
`git-{upload,receive}-pack '/<repo>'` parsed and dispatched to
alkgit; a subsystem request can never carry the repository and
declines; `1` is honestly reported for push `ng`.
- The session mapping: pty/shell/exec through the alktty seam over a
translation bridge (chunk-framed both directions), OQ-44's reserved
ttymodes JSON, the exit-chunk → SSH exit derivation (rules 1–6),
control rows (window-change, signal) on a bounded per-channel
surface.
- Tunnel leg 1: the route-1 bridge — `direct-tcpip` /
`direct-streamlocal` opens ride the assembly's `TunnelSession` over
the family fabric; fabric failure is a clean `ConnectFailed` reject.
- Tunnel leg 2: the `-R` listen flow — `tcpip_forward` /
`streamlocal_forward` dial the fabric, arrivals correlate through
the token router (miss → teardown-at-birth), the data leg opens
`forwarded-tcpip`/`forwarded-streamlocal` back toward the client,
port-0 mints echo the actually-bound port.
**Wave 4 — the client direction:**
- The dial surface: `dial(DialConfig)` — key load (decrypt-at-dial),
bounded russh client config, the host-key policy call, exactly one
publickey attempt; `SshConnection` the handle.
- The op rows: `exec` / `pty_exec` / `shell` (the alktty chunk plane),
`tunnel_direct` / `tunnel_direct_unix` (byte duplex),
`git_service` (pack duplex + consumed exit) — plus the `sftp`
decline row (always declines, every build).
- The `-R` leg: `reverse_listen` / `reverse_listen_unix` + the
`AcceptorRegistry` (refuse-never-replace) and the acceptor traits —
the hub asks the vanilla server to listen and serves the accepted
channels.
- Lifecycle primitives (OQ-12): explicitly cancellable listener
handles, clean `close()` (`Disconnect::ByApplication`) — drop is
never the clean path at this pin; no reconnect/restore policy (the
crate ships primitives, the assembly composes).
- Hardening riders: the git row's status-before-close by construction,
the channel-not-held guard wire rows, tty control-row coverage, the
`ListenRouter` token-collision pre-check.
**Wave 5 — validation and release:**
- The decline-matrix contract suite: every mapping-decline row × every
build it can appear in × both directions (the matrix runner
`scripts/matrix.sh` — one command over all feature builds).
- Real-tool e2e both directions: OpenSSH (pty/shell/exec, `-L`, `-R`,
`-D` + curl), git clone and push through the door, and a real
`sshd` against the client direction (exec, direct-tcpip dial, `-R`
listen + acceptor) — check-gated, skipped rows carry reasons.
- The `fuzz/` sidecar: the ingress surfaces (exec parse grammar,
fingerprint format, key decode, `TerminalParamsWire`) with the
committed-seed corpus gate (`cargo test --manifest-path
fuzz/shared/Cargo.toml`).
- Release readiness: warning-free crate docs with the known-limits
records riding the published rustdoc, this README, and the publish
dry-run posture.
### Notes
- `sftp` is a feature of decline: enabling it adds no capability —
the `sftp` subsystem request still declines in every build until
the alkfs mapping lands (OQ-13; the decline stays contract
territory).
- The `env` request declines unconditionally (OQ-09): session cwd/env
are assembly-supplied, never wire-derived.
- The russh pin (0.65, `aws-lc-rs`, `des`/`dsa` never enabled) is a
wire-relevant one-way door: bumps are deliberate, tested, and
recorded (ADR-002).