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
This commit is contained in:
glm-5.3-flash committed 2026-10-30 19:29:23 +00:00
1 parent d37cbc0c8a
commit ab5236ebbb
9 files changed
+634 -53

No files matched your search

+143 -27
View File
@@ -4,33 +4,149 @@ 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/).
## [Unreleased]
## [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
- Initialized: docs-only phase 0 base — SDD process (`docs/sdd_process.md`),
opencode agent definitions, rust crate manifest (lib only, no
dependencies yet), MIT OR Apache-2.0 licensing. The russh pin, the
capability feature graph, and the channel-type mapping table are
phase 0 research output (family ADR-003, OQ-08 remaining scope).
- Phase 0 research set under `docs/research/`: `vision.md` (scope
questions), `russh.md` (0.64.1-era inventory + pin considerations),
`auth-bridge.md` (fingerprint → identity server path; vault-backed
at-rest client key storage — the vault as secret store, not key
derivation), `mapping-table.md` (channel type/request → family seam
+ feature), `pocs.md` (POC-1..3 plan).
- Phase 0 completed — all three POCs passed against the current
published russh with vanilla tooling (121 checks total); findings
in `poc-1-auth-bridge.md` (31), `poc-2-vault-keys.md` (39),
`poc-3-mapping-bakeoff.md` (51, three mapping-table corrections
recorded), plus the reverse-runner client-direction extraction
(`reverse-runner.md`). POC source is disposable, never merged.
- Phase 1 architecture under `docs/architecture/`: the index +
open-questions tracker (OQ-01…13), the spec docs
(`overview.md`, `mapping.md`, `client.md`, `auth.md`), 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 (flat, two-direction, `dynamic-forward` retired); auth
dispositions; vault-key custody; and the mapping/dispatch
decisions (route-1 bridge, exec-only git, parse-only session
dispatch).
**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).