docs: Phase-2 conformance exit achieved (R-NET/R-TLS/R-DNS green) + findings

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
jakman85andClaude Opus 4.8 committed 2026-08-17 08:33:24 -05:00
1 parent 17622069fc
commit f78ce4ebe7
1 file changed
+33
+33
View File
@@ -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 to run with the operator present (or confirm it's fine to exercise autonomously with guaranteed
cleanup). 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) ## KNOWN ISSUES to fix before Phase-2 un-suspend (logged, not yet fixed)
| # | Issue | Impact | Fix | | # | Issue | Impact | Fix |
|---|---|---|---| |---|---|---|---|