diff --git a/DECISIONS-LOG.md b/DECISIONS-LOG.md index 4cb2ea9..a1956ce 100644 --- a/DECISIONS-LOG.md +++ b/DECISIONS-LOG.md @@ -1352,3 +1352,58 @@ Consequences, adopted: `fix/act-runner-dind-readiness`) — the DNS one now matters for prod too. 5. Resolve the task-board escalation above. 6. Nodes 2 and 3 through `infra/PROD-PROVISIONING.md` §1–§5 as they arrive. + +--- + +## 2026-08-31 — CI is the enforcement point; the LOCAL gate produced a FALSE GREEN + +**Operator directive: "Conformance and gates are enforced at the gitea runner and CI/CD level. +Use it."** Adopted. The authority on whether a change is mergeable is the Gitea Actions run, not a +local `make -C ci gate`. Local runs are a fast pre-check only. + +This was proven immediately and expensively. Branch `docs/phase-7-open-prod-node-1`: + +- **Local** `make -C ci gate` → `no changed files vs base; empty touched-requirement set` → + **MERGE GATE: PASS**. +- **CI**, same commit (`a1fb31a`, task 200) → 17 touched requirements correctly computed → + `REQUIRE: FAILED — required requirement(s) uncovered: ['R-SEC-01','R-SEC-02','R-TEST-06']` → + **MERGE GATE: BLOCKED**. + +The local run resolved an empty diff base and therefore checked nothing, reporting green. **A local +false green is the most dangerous failure mode this project has** — it hid real coverage debt from +the PM and would have hidden it from any future agent. `ci/touched-requirements.sh` base-ref +resolution is being fixed so local agrees with CI, or announces loudly that it cannot determine a +base. An honest noisy skip beats a quiet false pass (`ci/README.md` exit-code contract). + +The gate itself was RIGHT: we authored a vaulted-secret flow (R-SEC-01) and status tooling that +reasons about spec immutability (R-TEST-06) while those requirements had **no covering test at +all**. Tests are being authored rather than the rule being narrowed. + +**How to read CI from a workstation** (the API paths are non-obvious, so recording them): +```bash +CRED=$(printf 'protocol=https\nhost=gitea.home.keithjackson.dev\n\n' | git credential fill) +# list recent runs (id | workflow | branch | status | sha): +curl -sk -u "$U:$P" "$B/api/v1/repos/Home-Network/home-network-k3s-impl/actions/tasks?limit=10" +# fetch a task's log — NOTE the job-id/task-id OFFSET: task N is at jobs/(N+5)/logs on this instance +curl -sk -u "$U:$P" "$B/api/v1/repos/Home-Network/home-network-k3s-impl/actions/jobs/205/logs" +``` +`.../actions/runs//jobs` is 404 on this Gitea version; use `actions/tasks` + `actions/jobs//logs`. + +### OPERATOR ATTESTATIONS (2026-08-31) — capability vs. automated proof + +The operator states, and this log records as fact: + +1. **DR is PROVEN** — Velero backups to the Proxmox server, restore demonstrated. R-STATE-03's + capability is delivered and in operational use. +2. **Cluster resilience is PROVEN at the dev-cluster level** — node loss / rebuild demonstrated. + It is slow because Longhorn storage is on HDD (etcd is the exception, on its dedicated SSD), + which is a performance property, not a correctness gap. + +**Distinguish capability from automated proof.** The new repo-derived status report flags +`R-STATE-03` as a safety-critical requirement whose L3 test body asserts nothing. That finding +stands and is NOT contradicted by the attestation above — it is **test debt, not capability debt**. +The system does the thing; the suite does not yet assert that it does. Per the project's own +definition of done, only a green requirement-tagged test is acceptance — so the remaining work is +to make `dr-restore/chainsaw-test.yaml` and the node-loss test actually assert the behaviour the +operator has already demonstrated, and let the runner enforce it. Recording the attestation here +does not close the requirement, and the gate must not be softened to make it appear closed.