The operator ruled the implementation repo's main (50c8719) the latest and accepted state. Sync the spec to it. Accepted changes are reflected: one bare-metal environment, TrueNAS bulk storage, R2 off-cluster backup, CloudNativePG, single-node VPN gateway with Cilium fail-closed, inbound WireGuard, per-app auth sidecars, Renovate, the CI gate as approver, and the pm-agent. New ADR-0017..0025; ADR-0016 corrected and accepted; R-* IDs unchanged, eight amended. Where the implementation has simply not met a requirement, the requirement stands and the shortfall is recorded in docs/16-known-gaps.md. Co-Authored-By: Claude Opus 5.5 <[email protected]>
5.3 KiB
Definition of Done
A change is done only when an automated, reproducible, behavior-based test for each relevant
gate below passes green, the test is committed with the change and tagged with the
requirement IDs it verifies, and the change is traced to those IDs. A manual demonstration, a
screenshot, or "it reconciles" is not done (R-TEST-01..04, ../docs/14-testing-and-conformance.md).
Governance (R-TEST-06): you may not change the specifications to reach done. If the spec can't be met, that is an escalation to the human, not a spec/requirement/test-intent edit. Weakening a test so it passes is a defect, not a completion.
Universal checklist (every change)
- Traced to one or more requirement IDs (
R-*) and the spec/ADR it implements. - An automated behavior test (Given/When/Then) exists, is committed with the change, tagged
with its
R-*IDs, and passes; it appears in the coverage report. - The test is reproducible: single-command, hermetic (self-provisioning + self-cleaning), deterministic, and yields identical results on re-run.
- Expressed as GitOps (in git, reconciled by Flux) — no click-ops except ADR-sanctioned bootstrap.
- No plaintext secrets anywhere; secrets are SOPS-encrypted (and no secret printed in output).
- Authored once with environment-scoped overrides (no per-env base fork).
- Observability wired (metrics/logs) and at least the relevant alert exists.
- No specification/ADR/requirement was modified to achieve this (R-TEST-06); any spec problem was escalated, not edited.
- Result recorded in the PR and a handoff entry, with a link to or ledger row for the passing run.
Requirement-class gates (apply those relevant to the change)
Each checkbox below is the intent of an automated behavior test — implement it as a reproducible, requirement-tagged test (see the behavior catalog in
../docs/14-testing-and-conformance.md), not a manual check. Safety-critical gates (marked fault-injection) must break the system and assert fail-closed / no-data-loss (R-TEST-05).
State & rebuild (R-STATE-*)
- Destroy the workload entirely and re-apply from git; data survives.
- Stateful data is on
longhorn(replicated) or thebulktier — never ephemeral/hostPath. - DR-critical data restores from an off-cluster backup (drill for at least one service/phase).
Network isolation & egress (R-NET-*)
- With no explicit allows, the workload can reach only DNS (default-deny proven via Hubble + probe).
- Declared
dependencieswork; an undeclared destination is blocked (negative test). egress: internetleaves via the home/WAN IP;egress: vpnleaves via the VPN IP.- VPN kill-switch: tunnel forced down ⇒ the
vpnworkload leaks nothing;internetworkloads unaffected. - Changing
egressclass in git re-routes with no workload rewrite.
TLS (R-TLS-*)
- Endpoint serves a valid, non-self-signed, unexpired cert (external check), including for
internalservices. - Renewal is automatic (observed or verified via cert-manager) with no manual step.
DNS & ingress (R-DNS-*)
<service>.home.keithjackson.devrecord appears automatically and routes correctly.internalis unreachable publicly;publicis reachable + TLS-valid.- Internal clients resolving via Pi-hole reach the internal Gateway; via a public resolver, a
publicservice still works through the tunnel (R-DNS-04). - LAN/VPN-only hostnames get 404 at the tunnel;
internalservices have no public record, except non-HTTP L4 names, which may hold DNS-only records at LAN addresses (R-DNS-05); the Kubernetes API is not publicly reachable (R-SEC-04).
Automated updates (R-UPD-*)
- Advances to a newer stable version automatically on schedule with no human/AI edit, as a machine-authored change through the merge gate (allowed update classes).
- A deliberately bad update is health-gated: auto-rollback + alert.
- A pinned service does not advance.
Observability & alerting (R-OBS-*)
- Metrics + logs flow; a meaningful alert fires in a fault test and is delivered by email.
- Dashboard renders and is linked from the C2 UI.
VM/IaaS (R-PLAT-03)
- VM created/started/stopped/destroyed via
kubectl/virtctl(same K8s surface). - VM disk is Longhorn-backed; rebuild preserves data; default-deny + egress class apply; guest auto-updates.
Security & auditability (R-SEC-*)
- Least-privilege RBAC (no broad cluster rights for workloads).
- The auditability proofs (isolation / egress path / kill-switch / TLS / backup) are producible.
Per-service onboarding (WS-APPS)
- The service is fully wired from its ServiceDefinition alone (compute/storage/policy/egress/ TLS/DNS/monitoring/update) — no manual steps beyond merge.
Phase exit
A phase is done when the full conformance suite for that phase's requirements passes green
(R-TEST-03) and the exit criteria in ../roadmap/phases.md are recorded with
links to the passing runs. Prod (Phase 7) additionally requires a successful automated prod DR
drill.