Files
alkssh/tasks/implementation/review-wave-1.md
T
glm-5.3-flash f4b5f896b4 docs: sweep em dashes from all markdown prose
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.
2026-11-04 20:28:00 +00:00

7.8 KiB

id, name, status, depends_on, scope, risk, impact, level
id name status depends_on scope risk impact level
review-wave-1 Wave 1 gate: the foundations review completed
w1-manifest
w1-error-model
w1-key-sources
w1-host-key-policy
w1-fingerprint
w1-config
w1-test-doubles
narrow low phase review

Description

The wave-1 review gate, the cheap-place gate of the plan. The config types, the error taxonomy, and the key-source seam are one-way doors in practice: every later task implements against them, and the published crate freezes them. A shape error found here costs a task revision; found after the stack and mappings implement against them it costs churn across both directions.

The gate reads the landed surface against the architecture line by line:

  • ADR-002, the pin as declared (russh 0.65, aws-lc-rs only, no flate2/rsa in the tree, edition 2024, MSRV 1.89); the recorded ssh-key RC exception verified in cargo tree.
  • ADR-003, the feature graph shape (flat, independent, default = []); the recorded interpretation (per-feature sibling deps land with their first consuming wave) confirmed or corrected.
  • ADR-004, the fingerprint format invariant (parity vectors green); the max_auth_attempts default posture in Limits.
  • ADR-005, the custody chain (decrypt-at-use, Zeroizing wrap, distinct failure variants, EncryptedData opaque, host-key load path, plaintext never persists).
  • OQ-05, the policy seam (fail-closed default, no accept-all built-in, policy-blind crate).
  • OQ-08/09, the serve-config Option-field semantics (unset → decline, no crate default, no construction-time validation drift).
  • The error model: no catch-alls; auth declines are dispositions, not errors.
  • Docs honesty, or that module docs state what is deliberately not here yet (the stack, the mappings, the client direction).

Verdict: green (wave 2 decomposes, absorbing corrections) or findings booked (remediation before wave 2 decomposes).

Acceptance Criteria

  • Every ADR/OQ surface above read and confirmed (or corrected with the correction landed)
  • The recorded interpretations confirmed or fixed (sibling-dep timing; the vault-double shape; the policy verdict type)
  • Full verification set green (cargo test, --all-features, clippy, fmt)
  • Verdict recorded; wave 2 decomposition unblocked or findings booked

References

  • docs/plans/implementation.md (wave 1 section + this gate's role)
  • docs/architecture/decisions/001…006, open-questions.md

Notes

To be filled by implementation agent

Gate reading (line by line, 2026-10-28)

  • ADR-002 ✓, because Cargo.toml carries russh = { version = "0.65", default-features = false, features = ["aws-lc-rs"] }; edition 2024, rust-version = "1.89"; cargo tree -e normal confirms no rsa, no flate2, no ring, and the recorded ssh-key =0.7.0-rc.11 RC exception riding the russh keys path is present exactly as ADR-002 records it.
  • ADR-003 ✓, since session/git/tunnel/sftp declared, flat, default = [], nothing implied; the per-feature sibling deps (alktty/alktunnels/alkgit) are not in the manifest; the recorded interpretation (they land with their first consuming wave) confirmed as recorded.
  • ADR-004 ✓, since src/fingerprint.rs is the single fingerprint path; both parity suites (tests/fingerprint_parity.rs, tests/doubles.rs fixture rows) are green against the ssh-keygen -lf-recorded manifest; Limits::max_auth_attempts defaults to 10 with the decision-6 rationale in its doc.
  • ADR-005 ✓, as the custody chain is in code: one vault.decrypt → Zeroizing<String> wrap at the adapter seam → one-time decode_secret_key; the vault's taxonomy reshaped to the five distinct variants (no re-export, no collapse); EncryptedData opaque in crate code (tests mutate fields only to tamper); host keys decrypt-at-construction via VaultHostKeySource (empty set → Absent, locked → no key material); rotation-preservation tested; no plaintext persistence anywhere. The known-gap (vault's plain String return) is documented as the ADR-005 decision-3 contract, not silently absorbed.
  • OQ-05 ✓: the HostKeyPolicy seam offers a RejectAll fail-closed default; no accept-all built-in (the permissive posture exists only as the double's explicit with_default(true) choice in tests, which is the correct posture); the crate is policy-blind.
  • OQ-08/09 ✓: shell_argv and exec_wrapper_argv are both Option with unset→decline semantics in the type docs; no construction-time validation, no config-error type (the recorded interpretation confirmed, and none was needed); session_cwd/session_env are assembly-supplied, never wire-derived; channel_client absent → tunnel rows decline even under the feature.
  • Error model ✓: five closed variants, no catch-all; the dispositions-not-errors contract (auth declines, wire declines, config validation) is written into error.rs's module docs.
  • Docs honesty ✓: every module's docs state what is deliberately not here yet (russh Config construction and the dispatch are wave-2; dial wiring is wave-4; the grammar is wave-3).

Interpretations (flagged for this gate), all confirmed

  1. Sibling-dep timing: confirmed (see ADR-003 above).
  2. Vault-double shape, confirmed: TestVault wraps alkvault 0.1's own in-memory construction (VaultServiceHandle::new() + unlock_new) rather than re-implementing behind the source trait, so the real error taxonomy and GCM behavior ride every row (the decision is recorded in tests/common/mod.rs's module docs).
  3. Policy verdict type, confirmed: accept/reject bool, pinned to the russh 0.65 check_server_key → Result<bool, E> hook shape, with the Err channel held for wire/IO failures (recorded in host_key.rs's module docs).

Minor issues found and fixed inline (in this session, same commit set)

Small doc/polish findings; each is a one-to-few-line fix:

  • cargo doc --no-deps emitted 2 rustdoc warnings (ambiguous [async_trait] intra-doc links, since the crate and the attribute-macro share the name) in key_source.rs and host_key.rs → resolved as plain code spans. The crates' verification set does not run rustdoc, so these had gone unnoticed, which is worth remembering at wave 5's "public-API rustdoc warning-free" gate.
  • key_source.rs HostKeySource docs: stray ) typo ("on host pin) trust").
  • lib.rs crate docs: stale line ("the dependency surface and feature graph land with implementation start") is now landed; rewritten to state the landed/future split honestly.
  • Two redundant test lines removed (a discarded pre-probe try_sign in key_source.rs's usability helper; a redundant None re-assignment in config.rs's independent-flip row).

Nothing found rose to the level of a booked finding, and no shape error in the config types, the error taxonomy, or the key-source seam.

Verification (all green)

cargo test 47/47 · cargo test --all-features 47/47 · cargo clippy --all-targets -- -D warnings ✓ · cargo clippy --all-features --all-targets -- -D warnings ✓ · cargo fmt --check ✓ · cargo doc --no-deps 0 warnings.

Summary

To be filled on completion

Verdict: green. The wave-1 foundations read clean against ADR-002/003/004/005 and the OQ-05/08/09 resolutions, line by line; all three recorded interpretations (sibling-dep timing, vault-double shape, policy verdict type) were confirmed as recorded. Only minor doc/polish findings surfaced, and they were fixed inline (rustdoc link disambiguation, a doc typo, a stale crate-doc line, two redundant test lines), recorded above. No shape errors in the one-way-door surfaces. Wave 2 decomposition is unblocked; it should absorb the rustdoc-hygiene lesson (run cargo doc --no-deps on gates), though no fix tasks are needed.