diff --git a/DECISIONS-LOG.md b/DECISIONS-LOG.md index a254d9e..98b3100 100644 --- a/DECISIONS-LOG.md +++ b/DECISIONS-LOG.md @@ -309,6 +309,39 @@ deferred rather than best-effort them: to run with the operator present (or confirm it's fine to exercise autonomously with guaranteed cleanup). +## Phase-2 CONFORMANCE EXIT ACHIEVED (2026-08-17, main @ 1762206 + cluster-vars re-apply) + +Operator decided: TLS trust = **A** (chain to LE-staging root); DNS test = **OK** to run live. +Authored both Phase-0 scaffolds into real tests against the deployed platform; **all 4 Phase-2 L2 +tests PASS**: R-NET-01 (default-deny), R-NET-02 (deny-undeclared), R-TLS-01/03 (trusted-tls), +R-DNS-02 (dns-exposure). This covers the roadmap Phase-2 exit demonstrables (default-deny holds, +trusted cert served at *.home.keithjackson.dev, auto DNS record appears). + +- **trusted-tls (R-TLS-01/03):** in-cluster curl probe dials the gateway Service (env-agnostic via + `--connect-to`, no hardcoded VIP) with wildcard SNI and requires the served chain to verify against + the embedded **LE-staging root** ("(STAGING) Pretend Pear X1", fixtures/le-staging-root-ca.yaml). + Probes a public + an internal-only hostname (R-TLS-03). Empirically validated: correct root → rc 0; + system trust → rc 60. +- **dns-exposure (R-DNS-02):** a LoadBalancer Service + external-dns hostname annotation; polls public + DNS (1.1.1.1) until ExternalDNS publishes the A record into the cluster LB range; chainsaw teardown + + `policy=sync` removes it. Verified the full CREATE→DELETE lifecycle in ExternalDNS logs; the live + keithjackson.dev zone is left clean (back to the pre-existing wildcard). + +### FINDING F-DNS1 — ExternalDNS domain-filter must be the ZONE, not the subdomain (FIXED) +The DNS test first failed: ExternalDNS generated the record but skipped it — "no hosted zone matching +record DNS Name". `--domain-filter=home.keithjackson.dev` filtered OUT the real Cloudflare zone +`keithjackson.dev` (a subdomain filter drops the parent zone). Added a `DNS_ZONE` cluster-var +(keithjackson.dev) and set `domainFilters: [${DNS_ZONE}]`. Scope stays effectively home.keithjackson.dev +(only suffix services request) and `policy=sync`+txt-registry never touch non-owned records. + +### FINDING F-OPS1 — cluster-vars changes need a manual `kubectl apply -k clusters/dev` (gap) +Adding `DNS_ZONE` didn't take effect until I re-ran `kubectl apply -k clusters/dev` (the on-cluster +`cluster-vars` ConfigMap isn't reconciled by Flux — this bootstrap model has NO self-managing root +Kustomization that watches `clusters/dev`). Then a `platform` Kustomization reconcile re-ran the +postBuild substitution. **RECOMMEND: add a self-managing root Flux Kustomization** (path ./clusters/dev) +so cluster-vars / graph changes auto-apply — otherwise every overlay change is a manual re-apply +(and, transiently, ${DNS_ZONE} substituted empty → `--domain-filter=` = all-zones, before re-apply). + ## KNOWN ISSUES to fix before Phase-2 un-suspend (logged, not yet fixed) | # | Issue | Impact | Fix | |---|---|---|---|