Compare commits

...

1 Commits

Author SHA1 Message Date
Jon Chery 8b19c9ab68 docs(milestone): complete coverage-trust-hardening — v0.8 milestone release
Mark REQ-057..060 Complete in REQUIREMENTS.md, mark v0.8 COMPLETE in
ROADMAP.md, advance config.json phase to 4.

P0 (v0.7.0): pre-execution — specify/clarify/research/plan/grill.
P1 (v0.7.1): coverage round 2 — 9 packages hit tiered floor.
P2 (v0.7.2): SSH trust hardening — --host-key-fingerprint + key-reset
             + v0.6 TOFU ship-defect bugfix + doctor parity.
P3 (v0.7.3): requirements-hygiene gate — make verify-reqs + CI hook.
P4 (v0.7.4): final review + audit + milestone release (this commit).

Review: PASS-WITH-FOLLOWUPS (0 P0, 3 P1+ deferred to v0.9).
Audit: PASS (1 P1 stale-branch-hygiene, pre-existing, post-ship cleanup).
GRILL: 4/4 binding conditions satisfied.

---ci---
project: orca
phase: 4
milestone: v0.8
status: complete
requirements:
  covered: [REQ-057, REQ-058, REQ-059, REQ-060]
  partial: []
---/ci---
2026-08-04 12:25:58 +00:00
6 changed files with 397 additions and 16 deletions
+60
View File
@@ -0,0 +1,60 @@
# Phase 4 Audit — v0.8 Coverage & Trust Hardening (Final Phase)
**Milestone**: v0.8 — Coverage & Trust Hardening
**Date**: 2026-08-04
**Branch**: `phase/04-final-review-ship`
**Result**: ✅ PASS (with P1 branch-hygiene finding — pre-existing, non-blocking for v0.8)
## Step 1 — Reconstruction Test ✅
- Latest `---ci---` block (HEAD of milestone/v0.8): `project: orca, phase: 3, milestone: v0.8, status: verify, requirements: covered: [REQ-060]` — matches CHECKPOINT.json (`phase: 2, stage: verify` — note: checkpoint is one phase behind because the P03 verify commit didn't update it to phase 3; the git log `---ci---` block is authoritative and correct).
- config.json `milestone: v0.8` — matches.
- `make verify-reqs``✓ 60 requirements consistent with roadmap` — ROADMAP ↔ REQUIREMENTS consistent.
- All 35 v0.8 commits have `---ci---` blocks (100% commit discipline).
## Step 2 — .ciagent/ File Discipline ✅
- `config.json`: valid JSON, `milestone: v0.8`, `phase: 0` (stale — should be 3 post-P03; minor, will be corrected at milestone-complete), `milestone_type: nfr`, `active_projects: ["orca"]` — all required fields present.
- `PROJECT.md`: has v0.8 scope summary + D-043..D-047 + the vision/constraints/decisions sections — complete.
- `ROADMAP.md`: v0.8 milestone section present with 4 phases (P0-P4), phases P0-P3 marked `[x]` (shipped tags v0.7.0..v0.7.3), P4 pending — matches git branches + tags. v0.8 milestone header NOT yet marked COMPLETE (milestone ship step will add this).
- `REQUIREMENTS.md`: REQ-057..060 present, status `Pending` (milestone ship step will mark `Complete`). All 56 prior REQs (REQ-001..056) `Complete`. Traceability matrix complete.
- `ARCHITECTURE.md`: not updated for v0.8 (no new components — verify-reqs is a `cmd/` program, not an architecture component; the trust-surface changes refine existing proxmox/doctor/cli packages). Acceptable — v0.8 is NFR, no architecture changes.
- `PERSONAS.md`: v0.8 roster at top (lead/backend/data active; frontend/security/cli-engineer deactivated with reasons), v0.7 baseline preserved — complete.
- `RESEARCH_v0.8.md`, `PLAN_v0.8.md`, `GRILL_v0.8.md`, `REVIEW_v0.8.md`, `PHASE1..3_VERIFICATION_v0.8.md` — all present.
## Step 3 — Branch Hygiene ⚠️ P1 (pre-existing, non-blocking)
**Stale merged local branches** (should have been deleted by prior ship workflows — v0.6 + v0.7 milestones):
- `milestone/v0.6-node-bootstrap-proxmox` (merged to main via v0.6 ship)
- `milestone/v0.7-hardening-completion` (merged to main via v0.7 ship)
- `phase/01-cert-register`, `phase/02-config-parser`, `phase/03-coverage-uplift`, `phase/04-pprof-daemon`, `phase/05-final-review-ship` (all v0.7 phase branches, merged to v0.7 milestone)
**Stale remote branches** (same set + older v0.6-era branches): `origin/milestone/v0.6-*`, `origin/milestone/v0.7-*`, `origin/phase/01-init-bootstrap`, `origin/phase/02-proxmox-join`, `origin/phase/03-doctor-extensions`, `origin/phase/04-final-review-ship`, etc.
**v0.8 branches** (`phase/01-coverage-round2`, `phase/02-ssh-trust-hardening`, `phase/03-requirements-hygiene-gate`, `phase/04-final-review-ship`, `milestone/v0.8-coverage-trust-hardening`) are all active or just-merged — NOT stale.
**Finding**: The ship workflow's branch-cleanup step (audit.md:46-49 "Step 6.5") is not running for prior milestones. This is a P1 process gap (recurring across v0.6 + v0.7) but does NOT block v0.8 ship. **Recommendation**: after v0.8 milestone ship, delete the stale v0.6/v0.7 local + remote branches (tags preserve the history). Defer to post-ship cleanup; do NOT block the milestone release.
## Step 4 — Commit Discipline ✅
- All 35 v0.8 commits have `---ci---` blocks (100%).
- No stale decisions: D-043..D-047 are all reflected in code (T02.3 flag per D-044, T02.5 callback per D-045, T02.8 local-only per D-046, T01.6 tiered floor per D-047, T02.6 bugfix per D-043 chore classification).
- No unresolved escalations (the only escalation was P0's `release_pending` from GITEA_TOKEN unset — auto-resolved, local-only fallback, pipeline not halted).
- All 4 GRILL binding conditions satisfied (verified in REVIEW_v0.8.md).
## Step 5 — Run Audit Checks ✅
- `go build ./...` PASS
- `go vet ./...` PASS
- `go test ./...` PASS (16 packages)
- `make verify-reqs` PASS (60 consistent)
- `make build` PASS
- `gofmt -l .` clean
## Overall Verdict
**PASS** — v0.8 is shippable. The P1 branch-hygiene finding (stale v0.6/v0.7 branches) is pre-existing, non-blocking, and recommended for post-ship cleanup. The checkpoint phase-staleness (config.json `phase: 0` vs actual phase 3) is a minor bookkeeping gap corrected at milestone-complete.
## Recommendation
Proceed to milestone ship: mark REQ-057..060 `Complete` in REQUIREMENTS.md, mark v0.8 `COMPLETE` in ROADMAP.md, update config.json `phase: 4`, merge `phase/04-final-review-ship``milestone/v0.8``main`, tag `v0.7.4` (= milestone release), push, then delete stale v0.6/v0.7 branches as post-ship cleanup.
+5 -5
View File
@@ -1,11 +1,11 @@
{
"phase": 3,
"stage": "verify",
"phase": 4,
"stage": "complete",
"milestone": "v0.8",
"milestone_slug": "coverage-trust-hardening",
"phase_role": "execution",
"phase_role": "final",
"attempts": 0,
"updated_at": "2026-08-04T01:20:00Z",
"milestone_complete": false,
"updated_at": "2026-08-04T01:30:00Z",
"milestone_complete": true,
"next_milestone": null
}
+4 -4
View File
@@ -136,7 +136,7 @@ REQ-047..052 all complete.
| ID | Requirement | Priority | Phase | Status |
|----|-------------|----------|-------|--------|
| REQ-057 | Test coverage uplift round 2: raise `internal/engine` (8.3%), `internal/proxmox` (5.1%), `internal/cli` (27.6%), `internal/transport` (26.3%), `internal/store` (46.7%), `internal/jobspec` (47.6%) to ≥ 70%; add first tests for `internal/audit`, `internal/certpaths`, `cmd/orca` (currently 0%) to ≥ 50% (D-047 tiered floor) | High | **v0.8 P1** | Pending |
| REQ-058 | `--host-key-fingerprint <SHA256:base64>` pre-pin flag on `orca node join` (validated when `--type proxmox`): when supplied, join fails fast if the SSH host key's OpenSSH SHA-256 fingerprint does not match; supersedes TOFU (D-035) for pre-pinned deployments (D-044, D-045) | Medium | **v0.8 P2** | Pending |
| REQ-059 | `orca node key-reset <node>` command: clears the persisted SSH host key entry for the node from `~/.orca/known_hosts` only (local, not remote authorized_keys — D-046); audit-logs `event=node.key_reset`; next `doctor proxmox`/dispatch re-pins via TOFU or `--host-key-fingerprint` | Low | **v0.8 P2** | Pending |
| REQ-060 | Requirement-status hygiene sweep: REQUIREMENTS.md v0.7 rows were stale ("Pending" after ship); add a verify-stage assertion that every REQ listed as `Complete` in ROADMAP.md has a matching `Complete` row in REQUIREMENTS.md, enforced by `make verify-reqs` | Medium | **v0.8 P3** | Pending |
| REQ-057 | Test coverage uplift round 2: raise `internal/engine` (8.3%), `internal/proxmox` (5.1%), `internal/cli` (27.6%), `internal/transport` (26.3%), `internal/store` (46.7%), `internal/jobspec` (47.6%) to ≥ 70%; add first tests for `internal/audit`, `internal/certpaths`, `cmd/orca` (currently 0%) to ≥ 50% (D-047 tiered floor) | High | **v0.8 P1** | **Complete** (P1 shipped v0.7.1; all 9 packages exceeded floor) |
| REQ-058 | `--host-key-fingerprint <SHA256:base64>` pre-pin flag on `orca node join` (validated when `--type proxmox`): when supplied, join fails fast if the SSH host key's OpenSSH SHA-256 fingerprint does not match; supersedes TOFU (D-035) for pre-pinned deployments (D-044, D-045) | Medium | **v0.8 P2** | **Complete** (P2 shipped v0.7.2) |
| REQ-059 | `orca node key-reset <node>` command: clears the persisted SSH host key entry for the node from `~/.orca/known_hosts` only (local, not remote authorized_keys — D-046); audit-logs `event=node.key_reset`; next `doctor proxmox`/dispatch re-pins via TOFU or `--host-key-fingerprint` | Low | **v0.8 P2** | **Complete** (P2 shipped v0.7.2) |
| REQ-060 | Requirement-status hygiene sweep: REQUIREMENTS.md v0.7 rows were stale ("Pending" after ship); add a verify-stage assertion that every REQ listed as `Complete` in ROADMAP.md has a matching `Complete` row in REQUIREMENTS.md, enforced by `make verify-reqs` | Medium | **v0.8 P3** | **Complete** (P3 shipped v0.7.3) |
+321
View File
@@ -0,0 +1,321 @@
# Review: Orca v0.8 — Coverage & Trust Hardening (final-phase)
**Reviewer**: ci-code-reviewer (multi-persona: correctness, testing, security, performance, maintainability, adversarial)
**Branch**: `phase/04-final-review-ship` (review HEAD = P03 ship `70c5718`)
**Diff scope**: `main...milestone/v0.8-coverage-trust-hardening` (all v0.8 work, 59 files, +6550/-173)
**Date**: 2026-08-04
**Verdict**: **PASS-WITH-FOLLOWUPS** (0 P0, 2 P1, 2 P2)
## Methodology
Read the full diff (`internal/`, `cmd/`, `Makefile`, `.coreci.yml`), all 3 phase
verification reports, PLAN/RESEARCH/GRILL/PERSONAS, and the critical production
files directly (`internal/proxmox/bootstrap.go`, `internal/security/ca.go`,
`internal/security/sshkey.go`, `internal/doctor/doctor.go:400-454`,
`cmd/verify-reqs/main.go`). Re-ran `go build ./...`, `go vet ./...`,
`go test -race` on proxmox/security/doctor/cli/verify-reqs/cmd-orca, and
`make verify-reqs` (all PASS). Re-verified the verify-reqs regex against the
real ROADMAP.md (matches v0.1..v0.7 COMPLETE incl. v0.2 parenthetical; v0.8
correctly not matched). Confirmed all 7 T02.10 e2e cases are present and
exercised through a real in-process SSH server.
---
## Per-Axis Findings
### 1. Correctness (lead-developer)
**C1 — `sessionRunner` seam backward-compat** ✅
`internal/proxmox/bootstrap.go:170-172,322-339`. The seam is a package-level
`var sessionRunner sessionRunnerType` (line 326) initialized lazily inside
`BootstrapProxmox` from the dialed `*ssh.Client` (`if sessionRunner == nil {
sessionRunner = &sshSessionRunner{client: conn} }`). Existing callers are
unchanged — the default `sshSessionRunner` wraps the real
`conn.NewSession().CombinedOutput(...)`. Tests reset `sessionRunner = nil`
between runs (bootstrap_test.go:910, 1010, 1035) to avoid cross-test leakage.
Backward compatible as required by P01 verification. No issue.
**C2 — `verify-reqs` parser correctness** ✅
`cmd/verify-reqs/main.go:18-26`. The `reqRowRe` uses a greedy `.*` for the
Requirement+Priority cells and anchors the Phase+Status match at the END of
the line, where those two columns always live. This correctly handles
escaped pipes inside the Requirement cell (e.g. REQ-049
`localhost\|linux\|proxmox` — verified by the passing `make verify-reqs`
which reports 60 consistent rows, matching the 60 REQ rows in
REQUIREMENTS.md). The status token is optionally bold-wrapped
(`\*{0,2}(Complete|Pending)\*{0,2}`) with `[^|]*` for trailing notes —
handles `**Complete** (P01 shipped v0.2.1)`. The milestone-complete regex
`^##\s*Milestone\s+(v0\.\d+):.*—\s*\*\*[^*]*\bCOMPLETE\b[^*]*\*\*` is
substring-tolerant (GRILL #4) — verified against the real ROADMAP: matches
v0.1..v0.7 incl. v0.2's `**COMPLETE (merged to main via v0.3)**` and v0.6's
duplicate header (line 94 matched; line 92 without COMPLETE ignored). v0.8
(line 136, not yet COMPLETE) correctly not matched — so the v0.8 REQ rows
being `Pending` is NOT flagged as drift (correct: milestone not shipped
yet). No issue.
**C3 — TOFU capture-fix logic** ✅
`internal/proxmox/bootstrap.go:275-310`. On `*knownhosts.KeyError` with
empty `Want` (host unknown), captures the key, reads existing known_hosts
(create-if-missing), ensures trailing newline, appends
`knownhosts.Line([]string{knownhosts.Normalize(addr)}, key)`, writes via
`security.WriteAtomic`, returns nil (dial proceeds). On non-empty `Want`
(mismatch) returns the error (MITM detection preserved). On `nil` (match)
records key + returns nil. Correct against x/crypto v0.54.0 `checkAddr`
semantics. No issue.
**C4 — `ResetHostKey` line matching** ✅
`internal/proxmox/bootstrap.go:479-523`. Matches a line when its first
whitespace-delimited field, normalized via `knownhosts.Normalize`, equals
the normalized target. Handles `[host]:22` vs bare `host` (Normalize
brackets ports). Preserves comments/blanks. Atomic rewrite via
`security.WriteAtomic`. Edge cases handled: empty host errors, missing
file is a no-op, no matching lines is a no-op. Test
`TestResetHostKey_RemovesTargetLines` (bootstrap_test.go:718) seeds 2 lines
for target + 1 for another host, asserts target's 2 removed + other
intact. No issue.
**C5 — `--host-key-fingerprint` non-proxmox validation** ✅
`internal/cli/node.go:79-81`. `RunE` checks `joinHostKeyFP != "" &&
joinType != "proxmox"` → clear error. Test
`TestNodeJoinHostKeyFingerprintRequiresProxmox` (node_test.go:445) asserts
the error; `TestNodeJoinHostKeyFingerprintProxmoxAccepted` (node_test.go:477)
asserts the negative-space (proxmox type accepts the flag). No issue.
### 2. Testing (all personas)
**T1 — Coverage held post-P02** ✅
PHASE2 verification: proxmox 86.5% (was 87.1%), cli 76.7% (was 76.2%),
doctor 70.4%. Marginal changes from new code paths — no coverage regression.
Re-ran `go test -race ./internal/proxmox/... ./internal/cli/...` PASS.
**T2 — Race tests pass** ✅
`go test -race -count=1 ./internal/proxmox/... ./internal/security/...
./internal/doctor/... ./cmd/verify-reqs/... ./cmd/orca/...` all PASS.
`./internal/cli/...` PASS (77s, dominated by watch tests). No races.
**T3 — 7 T02.10 integration cases** ✅
All 7 present in `internal/proxmox/bootstrap_test.go`, exercised
end-to-end through `BootstrapProxmox` with a real in-process SSH server
(`bootstrapE2ESetup`):
- Case 1: `TestBootstrapE2E_PinnedFingerprintCorrect` (815)
- Case 2: `TestBootstrapE2E_PinnedFingerprintWrong` (842)
- Case 3: `TestBootstrapE2E_TOFUFirstConnectCapturesKey` (865)
- Case 4: `TestBootstrapE2E_TOFUSecondConnectMatches` (905)
- Case 5: `TestBootstrapE2E_TOFUMismatchFails` (925)
- Case 6: `TestBootstrapE2E_KeyResetThenRePin` (1002)
- Case 7: `TestBootstrapE2E_PrePopulatedKnownHostsMatches` (966, v0.6→v0.8 migration)
**T4 — Golden tests for verify-reqs** ✅
`cmd/verify-reqs/main_test.go` has 7 tests covering: clean pair, multi-drift
(both directions), default-args subprocess, malformed (no REQ rows → error),
missing file → error, v0.2 substring-tolerant header regression guard
(`TestVerify_v02SubstringTolerantHeader`), and real-repo regression guard.
The substring-tolerant regex is explicitly exercised — the drift fixture's
ROADMAP uses `**COMPLETE (merged to main via v0.3)**` on v0.2 and the test
asserts REQ-002 (v0.2 P1, Pending) is flagged forward-drift (would be
silently skipped if the regex regressed). No issue.
**T5 — Doctor parity test** ✅
`internal/doctor/doctor_test.go` extended with 94 LOC covering
`probeProxmoxPVEVersion` paths. The doctor callback now uses the shared
`proxmox.TOFUHostKeyCallback` (doctor.go:424) — GRILL #2 parity verified by
reading both call sites. No issue.
### 3. Security (backend-engineer)
**S1 — `--host-key-fingerprint` fails closed** ✅
`internal/proxmox/bootstrap.go:141-153,245-258`. The pinned/TOFU branch is
mutually exclusive (`if opts.HostKeyFingerprint != "" { ... } else { ... }`).
The pinned callback (245-258) validates `SHA256:` prefix up front (rejects
raw hex per D-045), computes `ssh.FingerprintSHA256(key)`, returns an error
on any mismatch — no fallback to TOFU. The dial (164) aborts on callback
error before any SSH session command runs. Cannot be bypassed: the pin is
compared as a full string against the canonical fingerprint of the
server-presented key; a mismatch returns before `*capturedKey` is set. No
issue.
**S2 — `key-reset` is local-only (D-046)** ✅
`internal/proxmox/bootstrap.go:479-523` + `internal/cli/node.go:348-407`.
`ResetHostKey` only reads/writes `certpaths.KnownHostsPath()`. No SSH dial,
no remote authorized_keys touch. Audit-logs `node.key_reset` with
actor+node+host (node.go:396-400). Verified by `TestNodeKeyReset`
(node_test.go:326) which asserts the audit row. No issue.
**S3 — TOFU capture-fix doesn't weaken MITM detection** ✅
See C3 — the fix ONLY captures on `KeyError{Want:[]}` (host unknown); a
non-empty `Want` (key mismatch / MITM) returns the error. The capture path
writes the server-presented key, so a subsequent different key fails. No
issue.
**S4 — `WriteAtomic` is actually atomic** ✅
`internal/security/ca.go:308-337`. Temp file in same dir
(`os.CreateTemp(dir, ".tmp-*")`), `Write`, `Chmod`, `Sync`, `Close`, then
`os.Rename` (atomic on POSIX same-filesystem). `defer os.Remove(tmpName)`
cleans up on failure. Genuine atomic-write pattern. No issue.
### 4. Performance (all)
**P1 — ResetHostKey is O(n) in file size** ✅
`internal/proxmox/bootstrap.go:479-523`: one `os.ReadFile` (O(n)), one
`strings.Split` + linear filter loop (O(n)), one `security.WriteAtomic`
(O(n)). No nested loops, no O(n²). For a known_hosts file (typically tens
of lines), this is negligible. No issue.
**P2 — Unnecessary allocations** (P2 — nit)
`bootstrap.go:494-510`: `strings.Split(string(existing), "\n")` allocates a
slice of all lines + `append(kept, []byte(line+"\n")...)` reallocates the
kept buffer. For known_hosts (small file) this is fine; a `bufio.Scanner`
over `bytes.NewReader(existing)` with a `strings.Builder` would be leaner,
but the current shape is clear and the file is tiny. Not worth changing.
Flagged P2 (nit, no action).
### 5. Maintainability (lead-developer)
**M1 — `TOFUHostKeyCallback` extraction** ✅
`internal/proxmox/bootstrap.go:261-310` is exported and shared by bootstrap
(148) and doctor (doctor.go:424) via
`proxmox.TOFUHostKeyCallback(sshAddr, &capturedHostKey)`. Clean coupling:
doctor imports proxmox (one-way), no duplication, no circular dep. The
GRILL #2 parity requirement (both call sites use the same wrapper) is
satisfied by construction. No issue.
**M2 — `verify()` testable** ✅
`cmd/verify-reqs/main.go:98-148`: the core logic is a pure function
`verify(roadmapPath, reqsPath string) (diff []string, count int, err error)`
with `main()` as a thin wrapper. Golden-file tests call `verify()` directly
(no subprocess). Mirrors the T01.11 `main()→run()` pattern. No issue.
**M3 — cli tests follow conventions** ✅
`internal/cli/namespace_test.go:21-35` adds `resetCommandFlags()` to zero
the package-level flag-bound vars between subtests (cobra parses into
globals; without reset a prior test's value persists). Called from
`resetRootFlags`. This is a sound convention — the test isolation is
correct. No issue.
**M4 — `resetCommandFlags` completeness** (P2 — nit)
`namespace_test.go:28-34` resets the join/leave/cap/audit/run/stop flags but
NOT `joinHostKeyFP`. A test that sets `--host-key-fingerprint` without
calling `resetRootFlags` could leak the value to a later test. In practice
all node tests call `resetRootFlags` which calls `resetCommandFlags`, so
this is a latent risk only. Recommend adding `joinHostKeyFP = ""` to
`resetCommandFlags` for completeness. Flagged P2 (nit).
### 6. Adversarial (backend-engineer)
**A1 — Can `--host-key-fingerprint` be bypassed?** ✅
No. The pinned callback (bootstrap.go:249-258) returns an error before
recording the key or allowing the dial to proceed on any mismatch. There is
no code path where a supplied pin is ignored — the branch at 141-153 is
`if opts.HostKeyFingerprint != ""` (pinned) `else` (TOFU); once pinned is
chosen, TOFU is not consulted. No bypass.
**A2 — Can `key-reset` corrupt known_hosts under concurrent write?** (P1 — important, low likelihood)
`proxmox.ResetHostKey` (bootstrap.go:479-523) and `TOFUHostKeyCallback`
(bootstrap.go:290-302) both do read-modify-write on
`certpaths.KnownHostsPath()` WITHOUT a lock. Two concurrent operations
(e.g. `orca node join --type proxmox hostA` + `orca node key-reset hostB`,
or two simultaneous joins to different hosts) could interleave:
- T1 reads known_hosts (empty), T2 reads known_hosts (empty)
- T1 writes hostA line, T2 writes hostB line
- Last rename wins → one line lost.
The `security.WriteAtomic` (temp+rename) prevents corruption (the file is
always valid OpenSSH format), but a captured line can be silently lost. This
is a **last-writer-wins race on a flat file with no lock**. Severity is low
because orca is a single-operator CLI (concurrent joins are unusual) and
the lost line is recoverable (re-connect re-pins via TOFU). But it is a
real correctness gap for the trust surface. Recommend either (a) a
file-lock around the read-modify-write, or (b) documenting the
single-operator assumption explicitly. Flagged P1 (important, post-hoc).
**A3 — Can verify-reqs be fooled by a crafted markdown table?** ✅
No. The `reqRowRe` anchors on `^\|\s*(REQ-\d+)\s*\|` and the status column
at end-of-line. A crafted row with a fake status would have to match the
regex exactly. The "malformed" fixture (`requirements_malformed.md`)
exercises the no-REQ-rows path → clear error. A row like
`| REQ-999 | missing status cell | High | v0.1 |` (no final `|...|`) does
NOT match `reqRowRe` (the trailing `\|\s*$` requires the status cell) — it
is silently skipped, which `verify` reports as "no REQ rows" only if ALL
rows are malformed. If some rows are valid + one malformed, the malformed
row is skipped without error — a minor blind spot, but acceptable (the
gate catches drift, not typos). No blocking issue.
---
## GRILL Conditions Verification
### #1 — T02.6 labeled as v0.6 ship-defect bugfix ✅
Commit `8b0cbe1` summary: "fix(proxmox): TOFU capture bug — **v0.6
ship-defect** first-connect join always failed (T02.6)". The commit message
explicitly labels it as a v0.6 ship-defect bugfix, not a v0.8 feature.
PHASE2 verification report records it as "TOFU bugfix (T02.6, v0.6
ship-defect)". **Satisfied.**
### #2 — T02.9 doctor parity (bootstrap + doctor use capture-fix wrapper) ✅
- Bootstrap: `internal/proxmox/bootstrap.go:148` calls
`TOFUHostKeyCallback(sshAddr, &capturedHostKey)`.
- Doctor: `internal/doctor/doctor.go:424` calls
`proxmox.TOFUHostKeyCallback(sshAddr, nil)`.
Both use the SAME exported wrapper (`proxmox.TOFUHostKeyCallback`,
bootstrap.go:275). No duplication. The doctor diff
(`internal/doctor/doctor.go`) removes the direct `knownhosts.New` call and
replaces it with the shared wrapper. **Satisfied.**
### #3 — T01.6 cli escape valve (was it needed?) ✅
PHASE1 verification: cli hit **76.2%** (above the 70% floor, excluding
daemon.go). The escape valve (ship at 65% if 70% not reached) was **NOT
needed**. The plan's conditional was correctly conservative; the actual
result exceeded the floor. **Satisfied (not invoked).**
### #4 — T03.1 verify-reqs regex substring-tolerant + reverse direction ✅
- **Substring-tolerant**: `cmd/verify-reqs/main.go:30`:
`^##\s*Milestone\s+(v0\.\d+):.*—\s*\*\*[^*]*\bCOMPLETE\b[^*]*\*\*`.
Verified against the real ROADMAP: matches v0.2's
`**COMPLETE (merged to main via v0.3)**` and all other COMPLETE
milestones. Golden test `TestVerify_v02SubstringTolerantHeader`
(main_test.go:140) guards against regression.
- **Reverse direction**: `cmd/verify-reqs/main.go:135-139`: a REQ marked
`Complete` whose referenced milestones are ALL not-C_COMPLETE in ROADMAP
is flagged as `direction=reverse` drift. Golden test `TestVerify_drift`
asserts REQ-003 is reverse-drift.
- **Scope note**: PLAN + commit `fc2b020` document that REQ-060 catches
doc-vs-doc drift only (code-vs-doc like the REQ-053 cert_repo_test.go
case is out of scope; P04 audit is the backstop). **Satisfied.**
---
## P0 Fixes Applied
**None.** No P0 issues (correctness bugs, security holes, broken build/test)
were found. `go build ./...`, `go vet ./...`, `go test -race` (all key
packages), and `make verify-reqs` all PASS. The milestone is shippable as-is.
---
## P1+ Issues Flagged (post-hoc review)
| ID | Severity | File:line | Issue | Recommendation |
|----|----------|-----------|-------|----------------|
| A2 | P1 (important, low likelihood) | `internal/proxmox/bootstrap.go:290-302, 479-523` | `TOFUHostKeyCallback` capture path and `ResetHostKey` both do read-modify-write on `known_hosts` with no lock; concurrent operations can lose a captured line (last-writer-wins via atomic rename — no corruption, but data loss). | Add a file-lock (`flock` on a `.known_hosts.lock` sibling, or `github.com/gofrs/flock` if a dep is acceptable) around the RMW in both paths; OR document the single-operator assumption in the key-reset help text. Defer to v0.9. |
| M4 | P2 (nit) | `internal/cli/namespace_test.go:28-34` | `resetCommandFlags()` does not reset `joinHostKeyFP`; a test setting `--host-key-fingerprint` without `resetRootFlags` could leak the value. | Add `joinHostKeyFP = ""` to `resetCommandFlags`. Trivial. |
| P2 | P2 (nit) | `internal/proxmox/bootstrap.go:494-510` | `ResetHostKey` uses `strings.Split` + repeated `append` (minor allocation churn). | Optional: use `bufio.Scanner` + `strings.Builder`. Not worth changing for a small file. |
---
## Overall Verdict
**PASS-WITH-FOLLOWUPS**
The v0.8 milestone is correct, secure, tested, and shippable. All 4 GRILL
binding conditions are satisfied. Zero P0 issues. The single P1 (concurrent
`known_hosts` write race, A2) is a real but low-likelihood gap appropriate
for post-hoc follow-up — it does not block the milestone ship because orca
is a single-operator CLI and the atomic-rename guarantees the file is never
corrupted (only a captured line can be lost, recoverable on re-connect).
The 2 P2 nits are cosmetic. Coverage held post-P02 (86.5%/76.7%/70.4% for
proxmox/cli/doctor), race tests pass, all 7 T02.10 e2e cases are present and
exercised through a real in-process SSH server, and `make verify-reqs`
passes on the current repo (60 consistent rows).
Recommend proceeding to P04 ship (T04.7/T04.8: mark REQ-057..060 Complete +
ROADMAP v0.8 COMPLETE, then tag v0.7.4).
+6 -6
View File
@@ -133,7 +133,7 @@ Tags run on the previous minor's patch line (v0.6.x) per
branch-strategy.md. The milestone branch label uses the milestone
number (`milestone/v0.7-hardening-completion`); no separate minor tag.
## Milestone v0.8: Coverage & Trust Hardening
## Milestone v0.8: Coverage & Trust Hardening — **COMPLETE**
Scope: continue the v0.7 hardening theme. v0.7 P03's ≥ 50% floor left
six packages still under 50% (engine 8.3%, proxmox 5.1%, cli 27.6%,
@@ -144,11 +144,11 @@ in v0.6 (D-035 `--host-key-fingerprint` pre-pin, RESEARCH_v0.6 §80
`orca node key-reset`) and adds a requirements-hygiene gate to prevent
the stale-REQ-status drift seen after v0.7 ship.
- [ ] Phase 0: Pre-execution (specify → clarify → research → plan → grill) — tag `v0.7.0`
- [ ] Phase 1: Test coverage uplift round 2 — 6 packages to ≥ 70%, 3 zero-test packages to first tests (REQ-057) — tag `v0.7.1`
- [ ] Phase 2: SSH trust hardening — `--host-key-fingerprint` pre-pin + `orca node key-reset` + TOFU bugfix + `HostKeyFingerprint` population (REQ-058, REQ-059) — tag `v0.7.2`
- [ ] Phase 3: Requirements-hygiene gate — `make verify-reqs` + verify assertion (REQ-060) — tag `v0.7.3`
- [ ] Phase 4: Final review + ship + audit (milestone release) — tag `v0.7.4`
- [x] Phase 0: Pre-execution (specify → clarify → research → plan → grill) — tag `v0.7.0` (shipped)
- [x] Phase 1: Test coverage uplift round 2 — 6 packages to ≥ 70%, 3 zero-test packages to first tests (REQ-057) — tag `v0.7.1` (shipped)
- [x] Phase 2: SSH trust hardening — `--host-key-fingerprint` pre-pin + `orca node key-reset` + TOFU bugfix + `HostKeyFingerprint` population (REQ-058, REQ-059) — tag `v0.7.2` (shipped)
- [x] Phase 3: Requirements-hygiene gate — `make verify-reqs` + verify assertion (REQ-060) — tag `v0.7.3` (shipped)
- [x] Phase 4: Final review + ship + audit (milestone release) — tag `v0.7.4` (shipped)
**Milestone type**: NFR (P01 test, P02 chore on trust surface per
D-043, P03 chore, P04 docs/review). Final phase patch IS the milestone
+1 -1
View File
@@ -6,7 +6,7 @@
"name": "Orca",
"description": "Offline/CLI-first orchestration engine (Orca) — Nomad-inspired, far simpler than Kubernetes",
"milestone": "v0.8",
"phase": 0,
"phase": 4,
"milestone_type": "nfr",
"default_branch": "main",
"tech_stack": {