diff --git a/docs/plans/implementation.md b/docs/plans/implementation.md index c10efc8..91fa60d 100644 --- a/docs/plans/implementation.md +++ b/docs/plans/implementation.md @@ -1,8 +1,8 @@ --- status: draft -last_updated: 2026-10-29 (wave 4 decomposed after the wave-3 gate - closed green — absorbing the gate's four booked findings; waves 1–3 - decomposed + implemented + gated 2026-10-28/29) +last_updated: 2026-10-30 (wave 5 decomposed after the wave-4 gate + closed green — nothing to absorb beyond the wave's own plan; waves + 1–4 decomposed + implemented + gated 2026-10-28/29) --- # alkssh — Implementation plan @@ -48,7 +48,7 @@ mappings ∥ client direction) → validation & release. | [2](#wave-2--the-server-stack) | `SshAdapter::handle` mount + `Config` construction; the auth bridge; parse-only dispatch + fail-closed decline core; spawn-and-return plumbing; bounded resources; loopback harness | wave 1 | decomposed | | [3](#wave-3--server-mappings) | session → alktty (translation bridge + exit derivation); git → alkgit (exec grammar + dispatch); tunnel → alktunnels route 1; sftp placeholder declines | wave 2 | decomposed | | [4](#wave-4--client-direction) | Dial surface; op rows (exec/pty, direct-tcpip, git exec); the `-R` leg (listen + acceptor registry); lifecycle primitives | wave 1 | decomposed | -| [5](#wave-5--validation--release) | Decline-matrix contract suite; real-tool e2e; fuzzing; docs; **the publish** | waves 3 + 4 | pending | +| [5](#wave-5--validation--release) | Decline-matrix contract suite; real-tool e2e; fuzzing; docs; **the publish** | waves 3 + 4 | decomposed | ## Wave 1 — Foundations @@ -467,6 +467,65 @@ Interpretations recorded (flagged for the wave-4 gate): dry-run, then **the publish of `alkssh 0.1`** — the gate review that closes the plan. +**Decomposition record** (2026-10-30, after the wave-4 gate closed +green — the gate's verdict: "wave 5 decomposition is unblocked and +should absorb nothing beyond its own plan"; the wave-3 gate's item-5 +upstream asks verified still booked with their owners, no task): wave +5 decomposed into seven task files under `tasks/implementation/`. +Shape: four independent implementation tasks over the landed waves — +`w5-decline-matrix` (the coverage audit of `mapping.md`'s matrix +table cell by cell + the gap rows in the existing per-build binaries ++ the matrix runner joining the verification list), `w5-e2e-server` +(OpenSSH pty/shell/exec/`-L`/`-R`/`-D`+curl, decline observability, +git clone **and** push — a dedicated new e2e binary, the wave-3 +smokes re-landed/extended), `w5-e2e-client` (the reverse-runner shape +against a spawned real `sshd` — the sshd fixture, exec/direct-tcpip/ +`-R`+acceptor, the decline rows), and `w5-fuzz-harness` (the `fuzz/` +sidecar per the alkgit convention: four targets — exec_parse, +fingerprint, key_decode, terminal_params — the shared-library corpus +gate joining the verification list, the detached runner, the root +workspace `exclude`); then `w5-release-readiness` (rustdoc +warning-free × builds, README lands, the CHANGELOG 0.1.0 entry, the +feature matrix, the publish dry-run + package-policy file-list check, +the freeze inventory recorded for the gate) over all four; +`review-wave-5` (the release gate — a **pure review**) over all five; +and `w5-publish` (the publish checklist: manifest sanity, the full +verification set, the dry-run, the crate-qualified `alkssh-v0.1.0` +tag, `cargo publish`, the plan's closure recorded) over the gate. +The four implementation tasks are mutually independent by +construction (disjoint files: the matrix task owns the existing +per-build binaries, the e2e tasks own new binaries + their own +fixture modules, the fuzz task owns `fuzz/` + at most +`#[doc(hidden)]` exposures) — parallel *conceptually*; any src/ +fix either finds is fixed in-task, with the gate as the merge point. + +Interpretations recorded (flagged for the wave-5 gate): + +- **The gate-then-publish split** — the plan's release-readiness + bullet folds the publish into release readiness, but the + decomposition follows the alkgit pattern: `review-wave-5` stays a + pure review and `w5-publish` is its own task (the publish is a + one-way door; it executes only over a green gate). +- **The e2e vehicle/placement** — dedicated new test binaries + (`tests/e2e_server.rs` / `tests/e2e_client.rs`, reusing + `tests/common`) rather than extensions of the wave-3/4 mapping + binaries, keeping those single-writer for the matrix task; the + check-gated skipped-with-reason posture (the wave-3 smoke + convention) holds for every row. Flagged for the gate. +- **The matrix runner vehicle** (script vs documented command list) + is decided + recorded in `w5-decline-matrix`; the corpus gate + joins the verification list alongside it (the alkgit posture). +- **The fuzz exposure shape** (public API vs `#[doc(hidden)]` + fuzz-visible exposures per target) is decided + recorded in + `w5-fuzz-harness` (the alkgit pattern); the sidecar is excluded + from the root single-member workspace and never a root dep. +- **The tag convention** — crate-qualified `alkssh-v0.1.0` (the + alkgit convention; a bare `v0.1.0` would be ambiguous across the + family's multi-crate repos). Pinned in `w5-publish`; flagged for + the gate to confirm. +- **No version bump** — the manifest already carries 0.1.0; the + publish task verifies rather than bumps. + ## References - `docs/architecture/` — overview, mapping, client, auth, diff --git a/tasks/implementation/review-wave-5.md b/tasks/implementation/review-wave-5.md new file mode 100644 index 0000000..3fb03cc --- /dev/null +++ b/tasks/implementation/review-wave-5.md @@ -0,0 +1,86 @@ +--- +id: review-wave-5 +name: Wave 5 gate — the release review +status: pending +depends_on: [w5-decline-matrix, w5-e2e-server, w5-e2e-client, w5-fuzz-harness, w5-release-readiness] +scope: narrow +risk: low +impact: phase +level: review +--- + +## Description + +The wave-5 review gate — the release review that closes the plan +(`docs/plans/implementation.md` §Wave 5: "then **the publish of +`alkssh 0.1`** — the gate review that closes the plan"). The gate +stays a **pure review**; the publish is its own task (`w5-publish`) +executing only over a green verdict. The gate reads: + +- **The decline-matrix suite** — the coverage-audit table read + against `mapping.md`'s matrix table cell by cell: every row × + every build it can appear in × both directions pinned; the sftp + placeholder rows and the never-features explicit in every build; + the matrix runner in the verification list. +- **The e2e postures** — both directions' real-tool rows read: + nothing silently green (every skip reasoned with the tool/version + cause), every e2e finding discharged or explicitly booked with an + owner (never absorbed); the real-`sshd` client-direction rows + verified against the reverse-runner shape. +- **The fuzz corpus gate** — the sidecar's layout read against the + alkgit convention (detached runner, committed seeds + no-op-diff + generator, the shared-library corpus replay in the verification + list); the campaign logs read (no unresolved crash/OOM/timeout); + the exposure shape read (no non-`doc(hidden)` surface growth). +- **Release readiness** — rustdoc warning-free × builds; README/ + CHANGELOG read for honesty; the packaged file list against the + package policy; the manifest sanity; **the freeze inventory read + against the landed code** — the list of surfaces the publish makes + one-way (the mapping contracts, the honest-advertisement posture, + the decline-matrix behavior, the fingerprint format, the russh + pin's wire posture) confirmed accurate, because `w5-publish` + executes immediately after this gate. +- **The plan's closure conditions** — the scope-authority checklist + (the complete two-direction door shipped; the assembly out; no + binary; single crate) verified against the landed state; the + upstream asks (the wave-3 gate's item 5 lineage) verified still + booked with their owners — nothing absorbed silently through the + release. + +Verdict: green (`w5-publish` unblocked) or findings booked +(remediation; the publish waits). + +## Acceptance Criteria + +- [ ] The matrix audit table verified cell by cell against + `mapping.md`; the runner in the verification list +- [ ] Both e2e postures verified (nothing silently green; findings + discharged or booked) +- [ ] The fuzz corpus gate + campaign logs read clean; the sidecar + convention held +- [ ] Release readiness verified (docs × builds, README/CHANGELOG, + package policy, manifest, dry-run) +- [ ] The freeze inventory verified accurate against the landed code +- [ ] Full verification set green (`cargo test` per build + + `--all-features`, clippy ×2 `-D warnings`, fmt, + `cargo doc --no-deps`, the fuzz corpus gate) +- [ ] `taskgraph validate` clean +- [ ] Verdict recorded; `w5-publish` unblocked or findings booked + +## References + +- docs/plans/implementation.md §Wave 5 (the bullets this gate reads) +- docs/architecture/mapping.md §Decline matrix, + docs/architecture/client.md (the two-direction contract the + publish freezes) +- tasks/implementation/w5-*.md (the wave's tasks + their records) +- /workspace/@alkdev/alkgit/docs/plans/implementation.md §Wave 5 + (the release-gate pattern: pure review, publish as its own task) + +## Notes + +> To be filled by the reviewing agent + +## Summary + +> To be filled on completion \ No newline at end of file diff --git a/tasks/implementation/w5-decline-matrix.md b/tasks/implementation/w5-decline-matrix.md new file mode 100644 index 0000000..c9c43ac --- /dev/null +++ b/tasks/implementation/w5-decline-matrix.md @@ -0,0 +1,86 @@ +--- +id: w5-decline-matrix +name: Wave 5 — the decline-matrix contract suite (every build × every row × both directions) +status: pending +depends_on: [review-wave-4] +scope: moderate +risk: low +impact: phase +level: implementation +--- + +## Description + +The complete decline-matrix contract suite (`mapping.md` §Decline +matrix — the fail-closed invariant is contract territory on both +sides of every feature, AGENTS.md conventions 5–6): **every build** +(none / `git` / `session` / `tunnel` / `--all-features`) **× every +row it can appear in × both directions**, including the sftp +placeholder rows (server subsystem + client-side, OQ-13) and the +never-features (x11, `auth-agent` — never feature-gated, ADR-003 §5). + +Waves 2–4 already landed per-build rows incrementally +(`tests/dispatch_core.rs`, `tests/client_dial.rs`'s decline-all row, +the mapping binaries' per-feature matrices); this task makes the +matrix **complete and systematic** rather than accreted: + +- **The coverage audit** — every row of `mapping.md`'s tables + (channel-type rows, session-request rows, the global-request `-R` + rows, the sftp placeholder rows both directions, the + never-features) × every build it can appear in × both directions → + where it is pinned today (binary + test name). Recorded as a table + in this task's Notes; the audit is the gate's checklist. +- **Gap rows landed** — every cell the audit finds unpinned gets its + row in the existing per-build binaries (the single-writer map + recorded: which binaries this task edits, so the e2e tasks' new + binaries stay disjoint). +- **The matrix runner** — the per-build verification set (cargo test + per build + `--all-features`, clippy ×2 `-D warnings`) as one + command (a script under `scripts/` or the documented command list — + decide + record the vehicle), joining the verification list so the + full matrix is one invocation from here on (the corpus gate's + sibling posture). +- **The sftp rows explicit in every build** — the feature gates + nothing (no dep, no behavior change); the decline-with-reason rows + (server subsystem + client-side placeholder) are pinned in every + build, and the `sftp`-only build compiles + declines identically + (the no-op-feature fact itself verified, not assumed). +- **The never-features in every build, both directions** — x11 / + `auth-agent` decline rows server-side (open + any request shape) + and client-side (the decline-all skeleton's server-initiated-open + rows), never advertised, never feature-gated. + +## Acceptance Criteria + +- [ ] The coverage-audit table recorded (every row × build × + direction → the test that pins it); every gap identified +- [ ] Every gap row landed; `mapping.md`'s matrix table green in + every cell, in every build it can appear in, both directions +- [ ] The sftp placeholder rows pinned in every build (both + directions); the `sftp`-only build verified no-op + declining +- [ ] The never-feature rows (x11, `auth-agent`) pinned in every + build, both directions +- [ ] The matrix runner lands and joins the verification list + (vehicle decided + recorded) +- [ ] `cargo test` per build + `--all-features`, clippy ×2 + (`-D warnings`), fmt, `cargo doc --no-deps` green + +## References + +- docs/architecture/mapping.md §Decline matrix (the contract this + suite completes), §Channel-type rows, §Request-level rows, §Global- + request rows +- docs/architecture/decisions/003-feature-graph.md (§4–5: the + fail-closed rule + the never-features) +- docs/plans/implementation.md §Wave 5 (the matrix bullet) +- tests/dispatch_core.rs, tests/client_dial.rs, tests/git_mapping.rs, + tests/tty_mapping.rs, tests/tunnel_mapping.rs (the accreted rows + this task audits and completes) + +## Notes + +> To be filled by implementation agent + +## Summary + +> To be filled on completion \ No newline at end of file diff --git a/tasks/implementation/w5-e2e-client.md b/tasks/implementation/w5-e2e-client.md new file mode 100644 index 0000000..f6abc5e --- /dev/null +++ b/tasks/implementation/w5-e2e-client.md @@ -0,0 +1,87 @@ +--- +id: w5-e2e-client +name: Wave 5 — real-tool e2e, client direction (the door against a real sshd) +status: pending +depends_on: [review-wave-4] +scope: moderate +risk: medium +impact: phase +level: implementation +--- + +## Description + +The client-direction real-tool e2e — the reverse-runner shape +re-landed against a **real `sshd`** (`docs/plans/implementation.md` +§Wave 5, the real-tool e2e bullet's client half; the wave-4 client +rows ran against the in-process fake `sshd` double, and the wave-4 +gate named real-`sshd` e2e wave-5 territory explicitly). A dedicated +new binary (decide + record the placement — `tests/e2e_client.rs` +reusing `tests/common` is the recommended posture, disjoint from the +matrix task's binaries), under the check-gated +**skipped-with-reason** posture: + +- **The sshd fixture** — a spawned real OpenSSH server the dial + targets: host key generated (ed25519), a listen port picked, the + `HostKeyPolicy` accepting the fixture's known fingerprint (the + case-1 pin posture — the policy seam consumed against a real + presented key), a generated ed25519 user key authorized in the + fixture's `authorized_keys` (the decrypt-at-dial path over the + in-memory vault double). The fixture's exact shape (spawned + per-test vs a shared per-binary instance; the sshd_config knobs — + publickey-only, no password) decided + recorded. +- **The op rows against real sshd** — exec (exit-status parity + through a real server's reaping), the direct-tcpip dial (a real + TCP connection through the server's forwarding — `-L`-shaped), + **the `-R` leg**: `tcpip_forward` with the port-0 mint against a + real server's actually-bound reply, the server-initiated + `forwarded-tcpip` open served through the acceptor registry (the + reverse-runner consumer pattern end to end), the cancel form + tearing the real listen down. +- **The decline rows against a real server** — the sftp client-side + placeholder decline (`subsystem` sftp → the typed decline), the + unfeatured direct-tcpip decline (the connection stays usable — + the typed-open decline mirror's real-server row), the host-key + policy mismatch hard-decline (a wrong-fingerprint fixture → no + dial, the case-1 posture against a real presented key). +- **Every skip reasoned** (no `sshd` in the environment / fixture + constraints), every finding fixed in-task or booked for the gate — + never absorbed silently. + +## Acceptance Criteria + +- [ ] The sshd fixture lands (spawned real server, ed25519 host + + user keys, the policy pin posture); its shape decided + + recorded +- [ ] Exec, direct-tcpip, and the `-R` leg (port-0 mint + accepted + arrival + cancel) green against real sshd (or reasoned-skipped) +- [ ] The decline rows green: sftp placeholder, unfeatured + direct-tcpip (connection stays usable), host-key mismatch + hard-decline +- [ ] Every finding fixed in-task or booked for the gate (recorded) +- [ ] `cargo test` (+ the builds the new binary rides), clippy ×2 + (`-D warnings`), fmt, `cargo doc --no-deps` green + +## References + +- docs/plans/implementation.md §Wave 5 (the real-tool e2e bullet), + §Wave 4 (the fake-`sshd` posture this task's real server replaces + for e2e) +- docs/architecture/client.md (the dial surface, op rows, the + acceptor), docs/research/reverse-runner.md (the consumer pattern + the client direction serves) +- docs/research/poc-2*.md / the reverse-runner extraction (the + real-`sshd` client-direction evidence this re-lands against the + shipped crate) +- tests/client_dial.rs, tests/client_ops.rs, + tests/client_reverse_listen.rs (the double-driven rows this task + mirrors against the real server), tests/common/sshd_double.rs (the + double's semantics — what the real fixture must match) + +## Notes + +> To be filled by implementation agent + +## Summary + +> To be filled on completion \ No newline at end of file diff --git a/tasks/implementation/w5-e2e-server.md b/tasks/implementation/w5-e2e-server.md new file mode 100644 index 0000000..0d8dfab --- /dev/null +++ b/tasks/implementation/w5-e2e-server.md @@ -0,0 +1,83 @@ +--- +id: w5-e2e-server +name: Wave 5 — real-tool e2e, server direction (OpenSSH / git / curl against the door) +status: pending +depends_on: [review-wave-4] +scope: moderate +risk: medium +impact: phase +level: implementation +--- + +## Description + +The server-direction real-tool e2e — the POC-3 gates re-landed +against the shipped crate (`docs/plans/implementation.md` §Wave 5, +the real-tool e2e bullet's server half). The wave-3 smokes proved one +clone, one `-L`, one pty session; this task lands the **full** +server-direction e2e set in a dedicated home (decide + record the +placement — a new `tests/e2e_server.rs` binary reusing `tests/common` +is the recommended posture, keeping the wave-3/4 mapping binaries +single-writer for `w5-decline-matrix`), under the established +check-gated **skipped-with-reason** posture (never silently green): + +- **OpenSSH against the door** — pty/shell interactive session + (the wave-3 smoke's composition, re-homed or extended per the + placement decision), plain exec (`ssh host "cmd"` through the exec + wrapper), `-L` local forward through the tunnel mapping, + **`-R` remote forward** (the `w3-tunnel-listen` flow — listen + request, bound port, the server-initiated `forwarded-tcpip` + arrival pumped through the fabric — the leg the in-process smokes + covered only through the alkcall fabric double), and **`-D`**: + curl through the SOCKS proxy with the door as the server (the + `direct-tcpip` leg end to end — POC-3 correction 2's posture). +- **Decline observability** — a declined open/session surfaces a + clean diagnostic to the real client (POC-1 §5 posture: + channel-scoped decline, auth intact, no hangs): an unfeatured + channel type from real `ssh -L`/`-R`/pty attempts in a + feature-limited build, the sftp subsystem decline from a real + `sftp`/`ssh -s` attempt, the unknown-repo collapsed generic denial + from a real `git clone` of a nonexistent repo. +- **git 2.43+ through the git mapping** — clone (re-land) **and + push** (the wave-3 smoke was clone-only; receive-pack through the + real client is the POC-3 §B gate re-landed). +- **The harness posture** — real processes (`ssh`/`git`/`curl`), the + adapter mounted on a real TCP listener over the in-memory doubles + (the existing smoke composition); every skip reasoned (tool + absent / version short), every finding fixed in-task or booked for + the gate — never absorbed silently. + +## Acceptance Criteria + +- [ ] The e2e home decided + recorded (new binary recommended); the + check-gated skipped-with-reason posture held for every row +- [ ] OpenSSH rows green (or reasoned-skipped): pty/shell, exec, + `-L`, `-R` (listen + arrival + data leg), `-D` + curl through + the proxy +- [ ] Decline-observability rows green: unfeatured declines from a + real client (clean diagnostic, no hang), the sftp decline, the + unknown-repo generic denial +- [ ] git clone **and** push through the git mapping green (or + reasoned-skipped) +- [ ] Every finding fixed in-task or booked for the gate (recorded) +- [ ] `cargo test` (+ the builds the new binary rides), clippy ×2 + (`-D warnings`), fmt, `cargo doc --no-deps` green + +## References + +- docs/plans/implementation.md §Wave 5 (the real-tool e2e bullet) +- docs/architecture/mapping.md (the rows the real tools exercise), + docs/research/poc-3-mapping-bakeoff.md (stages A–D — the gates + re-landed), docs/research/poc-1-auth-bridge.md §5 (decline + observability) +- tests/git_mapping.rs / tests/tty_mapping.rs / + tests/tunnel_mapping.rs (the wave-3 smoke compositions this task + re-lands/extends), tests/common/ (the doubles + harness) + +## Notes + +> To be filled by implementation agent + +## Summary + +> To be filled on completion \ No newline at end of file diff --git a/tasks/implementation/w5-fuzz-harness.md b/tasks/implementation/w5-fuzz-harness.md new file mode 100644 index 0000000..451a451 --- /dev/null +++ b/tasks/implementation/w5-fuzz-harness.md @@ -0,0 +1,99 @@ +--- +id: w5-fuzz-harness +name: Wave 5 — the fuzz sidecar (the crate's ingress surfaces) +status: pending +depends_on: [review-wave-4] +scope: moderate +risk: medium +impact: phase +level: implementation +--- + +## Description + +The family standing rule — anything worth fuzzing gets fuzzed — on +the crate's ingress surfaces (`docs/plans/implementation.md` §Wave 5, +the fuzzing bullet): the `fuzz/` sidecar per the alkgit convention +(`fuzz/README.md` there — the layout, the detached runner, the corpus +gate). Four targets over the plan's ingress inventory: + +- **`exec_parse`** — the git-parseable exec grammar + the dispatch + parse path (`src/git_map.rs`'s parse + `src/dispatch.rs`'s + parse-only routing): no-panic on any command string; the typed + decline classes (git-parseable → the git row, non-git → the + session pipe path, service-only → decline-with-reason) stable per + input; the per-length caps enforced before any allocation (the + decline-first-alloc-never invariant under hostile lengths). +- **`fingerprint`** — the `SHA256:` + unpadded base64 format path + (`src/fingerprint.rs`): no-panic on arbitrary key blobs; the + format invariant holds for every accepted input; determinism; the + committed `ssh-keygen -lf` parity vectors still agree. +- **`key_decode`** — the `decode_secret_key` ingress + (`src/key_source.rs`'s decrypt-at-use seam): no-panic on arbitrary + plaintext bytes and passphrase shapes; every failure a typed + `KeySourceError` class (decode failure — never a catch-all, never + a panic); no secret material retained past the one-time decode + (the `Zeroizing` posture's shape asserted where assertable). +- **`terminal_params`** — the `pty_request` args → + `TerminalParamsWire` conversion (`src/tty_map.rs`, the SSH modes → + reserved-modes JSON): no-panic on arbitrary term strings, sizes, + pixel dims, and mode blobs; oversize/overflow fail-closed (typed, + not clamped-silent); the reserved-modes JSON shape stable. + +Shape (the alkgit convention, adapted): + +- `fuzz_targets/` thin `fuzz_target!` wrappers; `shared/` the + invariant logic as a plain stable-clean library so `cargo test + --manifest-path fuzz/shared/Cargo.toml` replays the committed + corpora through the same invariants — **the corpus gate joins the + verification list**; the sidecar consumes the crate's public API + only (plus `#[doc(hidden)]` fuzz-visible exposures where the + ingress is private — the exposure shape decided + recorded, the + alkgit pattern; never a dependency of the root crate). +- `corpus//` committed hand-made seeds + the deterministic + generator (`gen_fuzz_seeds.py`, no-op-diff check); grown + corpora/artifacts/coverage gitignored, never merged back. +- `run-detached.sh` — the mandatory detached runner (agent sessions + never foreground a campaign); `rust-toolchain.toml` nightly pin + inside `fuzz/`; the root `Cargo.toml` gains `exclude = ["fuzz"]` + (the root is a single-member workspace — the sidecar is its own). +- Campaigns run detached per target (the runner's default budget); + any finding fixed in-task or booked for the gate — never absorbed + silently. + +## Acceptance Criteria + +- [ ] The `fuzz/` sidecar lands with all four targets; the sidecar + is excluded from the root workspace and never a root dep +- [ ] The exposure shape decided + recorded (public API vs + `#[doc(hidden)]` per target) +- [ ] Committed seeds + the deterministic generator (no-op diff); + the corpus gate (`cargo test --manifest-path + fuzz/shared/Cargo.toml`) green and joining the verification + list +- [ ] Detached campaigns run per target; findings fixed or booked + (recorded) +- [ ] `fuzz/README.md` documents the layout + commands (the alkgit + shape); the root crate's verification set stays green (the + sidecar changes no root behavior) + +## References + +- docs/plans/implementation.md §Wave 5 (the fuzzing bullet — the + four-surface inventory) +- /workspace/@alkdev/alkgit/fuzz/ (the convention's reference + implementation: README, run-detached.sh, gen_fuzz_seeds.py, + shared/), docs/plans/implementation.md (alkgit) §Wave 5 (the + fuzz-harness task's shape) +- src/git_map.rs, src/dispatch.rs, src/fingerprint.rs, + src/key_source.rs, src/tty_map.rs (the ingress surfaces) +- docs/architecture/mapping.md §Session-channel dispatch (the + decline-first-alloc-never invariant the exec_parse target pins) + +## Notes + +> To be filled by implementation agent + +## Summary + +> To be filled on completion \ No newline at end of file diff --git a/tasks/implementation/w5-publish.md b/tasks/implementation/w5-publish.md new file mode 100644 index 0000000..c2c05bd --- /dev/null +++ b/tasks/implementation/w5-publish.md @@ -0,0 +1,78 @@ +--- +id: w5-publish +name: Wave 5 — the publish of alkssh 0.1 +status: pending +depends_on: [review-wave-5] +scope: narrow +risk: medium +impact: project +level: implementation +--- + +## Description + +The publish — the plan's closing act (`docs/plans/implementation.md` +§Wave 5: "then **the publish of `alkssh 0.1`** — the gate review that +closes the plan"; the alkgit pattern: the gate stays a pure review, +the publish is its own task executing only over a green verdict). +The checklist: + +- **Manifest sanity** — version 0.1.0 (already the manifest value — + verify, no bump needed), `rust-version` 1.89, edition 2024, the + license files present, the dependency pins as ADR-002 records them + (russh 0.65 / aws-lc-rs, alkcall 0.10, alkvault 0.1, the + per-feature siblings), the package-policy `exclude` list, the + feature graph exactly ADR-003's. +- **The full verification set** — `cargo test` per build + + `--all-features`, clippy ×2 `-D warnings`, fmt, + `cargo doc --no-deps`, the fuzz corpus gate, the matrix runner — + all green at the publish commit. +- **The dry-run** — `cargo publish --dry-run --allow-dirty` clean at + the publish commit (the packaged file list spot-checked once more). +- **The tag** — the crate-qualified `alkssh-v0.1.0` (the alkgit + convention: crate-qualified tags, a bare `v0.1.0` would be + ambiguous across the family's multi-crate repos). +- **The publish** — `cargo publish`; the published version verified + resolvable on crates.io after (a fresh `cargo add`/`cargo search` + or the index check). **If the publish credential is unavailable, + the task stops and books it — never a silent skip**; everything + before the credential step still lands (tag + records). +- **The plan's closure recorded** — `docs/plans/implementation.md` + updated (the wave-5 row + the closure note: the plan closed at the + publish commit; the freeze inventory's surfaces are one-way from + here — the mapping contracts, the honest-advertisement posture, + the decline-matrix behavior, the fingerprint format, the russh + pin's wire posture; further wire-relevant change is a new ADR + a + semver event). + +## Acceptance Criteria + +- [ ] Manifest sanity verified + recorded (no version bump needed — + 0.1.0 is the manifest value) +- [ ] The full verification set green at the publish commit +- [ ] The dry-run clean at the publish commit +- [ ] The `alkssh-v0.1.0` tag on the publish commit +- [ ] `cargo publish` executed; the published 0.1.0 verified + resolvable on crates.io (or the credential absence booked — + never a silent skip) +- [ ] The plan's closure recorded in + `docs/plans/implementation.md` + +## References + +- docs/plans/implementation.md §Wave 5 (the publish bullet), §Scope + authority (v0.1.0 publishes the crate) +- docs/architecture/decisions/002-russh-pin.md (the pin the manifest + records), docs/architecture/decisions/001-alkssh-alpn-pin.md (the + ledger entry the publish makes load-bearing) +- /workspace/@alkdev/alkgit tasks (the `core/w5-publish` shape this + mirrors: manifest sanity, verification, dry-run, the + crate-qualified tag, `cargo publish`) + +## Notes + +> To be filled by implementation agent + +## Summary + +> To be filled on completion \ No newline at end of file diff --git a/tasks/implementation/w5-release-readiness.md b/tasks/implementation/w5-release-readiness.md new file mode 100644 index 0000000..9bd4c36 --- /dev/null +++ b/tasks/implementation/w5-release-readiness.md @@ -0,0 +1,86 @@ +--- +id: w5-release-readiness +name: Wave 5 — release readiness (docs, feature matrix, CHANGELOG/README, dry-run) +status: pending +depends_on: [w5-decline-matrix, w5-e2e-server, w5-e2e-client, w5-fuzz-harness] +scope: moderate +risk: low +impact: phase +level: implementation +--- + +## Description + +Everything the publish needs except the publish itself +(`docs/plans/implementation.md` §Wave 5, the release-readiness +bullet; the alkgit `w5-release-readiness` shape): + +- **Crate docs** — public-API rustdoc warning-free (default build + + `--all-features`; the pre-existing `client_ops.rs` private-link + warnings resolved or explicitly dispositioned); the docs-honesty + pass: module docs name each surface's postures and known limits + (the recorded limits ride the published docs — the `write_all` + no-deadline record, the PTY rule-5 fidelity limit, the port-0-only + mint wire fact, the no-reconnect-policy boundary, the no-accept-all + policy posture); crate-level docs state the feature graph and the + fail-closed invariant. +- **README.md** — lands (none exists): what the crate is (the + two-direction door), the feature graph + the fail-closed posture + (a default build has no capabilities), minimal compile-checked + usage examples (a server mount + a dial), the custody/security + posture summary (vault-backed keys, no env vars, no secret + material on the wire), the license note. +- **CHANGELOG.md** — the 0.1.0 entry summarizing the plan's landing + per wave (the file exists; the entry lands). +- **The feature matrix** — `default` / each feature over it / + `--all-features`: test + clippy + doc green (the matrix runner + from `w5-decline-matrix` if it landed the vehicle — one command). +- **The publish dry-run** — `cargo publish --dry-run --allow-dirty`; + the packaged file list verified against the package policy (the + `exclude` list: the architecture docs ship as the authoritative + contract; the process surface — plans/research/reviews/tasks/ + AGENTS.md/`.opencode` — does not); the manifest sanity (version + 0.1.0, `rust-version` 1.89, edition 2024, license files present, + the pins as ADR-002 records them). +- **The freeze inventory** — the list of what the publish makes + one-way (the wire-relevant surfaces: the mapping contracts, the + honest-advertisement posture, the decline-matrix behavior, the + fingerprint string format, the russh pin's wire posture) recorded + for the gate's read — the semver-relevant surface is frozen at the + publish, so the gate reads this list against the landed code + before `w5-publish` executes. + +## Acceptance Criteria + +- [ ] `cargo doc --no-deps` (+ `--all-features`) warning-free or + every residual dispositioned; the docs-honesty pass complete + (the known-limits records ride the published docs) +- [ ] README.md landed (what/why, feature graph + fail-closed, + compile-checked examples, custody posture, license) +- [ ] CHANGELOG.md's 0.1.0 entry landed +- [ ] The feature matrix green (default / each feature / + `--all-features`: test + clippy + doc) +- [ ] `cargo publish --dry-run --allow-dirty` clean; the packaged + file list verified against the package policy; manifest sanity + recorded +- [ ] The freeze inventory recorded for the gate + +## References + +- docs/plans/implementation.md §Wave 5 (the release-readiness + bullet), §Scope authority (v0.1.0 publishes the crate) +- Cargo.toml (the package policy exclude list; the manifest ADR-002 + landed), CHANGELOG.md, LICENSE-MIT / LICENSE-APACHE (present) +- docs/architecture/ (what ships as the authoritative contract), + docs/architecture/decisions/002-russh-pin.md (the pin the manifest + records) +- /workspace/@alkdev/alkgit (the sibling release shape: README, + CHANGELOG, the publish checklist's dry-run posture) + +## Notes + +> To be filled by implementation agent + +## Summary + +> To be filled on completion \ No newline at end of file