Six exposure:internal services published A records into the public Cloudflare zone answering 192.168.2.20, disclosing the internal subnet, the Gateway VIP and a full service inventory, and forming a DNS-rebind primitive that is why the SOHO router strips these answers in the first place. The renderer now stamps external-dns.alpha.kubernetes.io/controller: none on every HTTPRoute it renders for an internal service, derived from the exposure field alone — so a service that omits exposure defaults to internal and is likewise unpublishable. Established against the deployed v0.21.0's own source, where the controller check runs before hostname resolution in both configured sources, then proven live on a throwaway hostname including that adding the annotation to an existing record triggers the DELETE. Deletes exactly 12 records: the A and TXT pair for jackett, pihole, qbittorrent, radarr, semaphore and sonarr. A 39-record recovery baseline is committed alongside. Safe to land before the DHCP change, contrary to my earlier caution: the router returns NOTHING for all six names today, so these records serve nobody on the LAN, while Pi-hole at 192.168.2.23 already answers for anyone pointed at it. The five exposure:public services are untouched. They remain unreachable publicly, which is a separate problem: the legacy edge at 136.51.115.252 returns HTTP 403 for our hostnames and serves a placeholder certificate, so nothing is reverse-proxying them today.
apps
App-tier manifests, rendered from catalog/*.yaml ServiceDefinitions by catalog/render.py
and split into dependency-ordered waves (wave-<N>/).
- Each
wave-<N>/is reconciled by its own Flux Kustomizationapps-wave-<N>(clusters/base/apps-wave-<N>.yaml), whichdependsOnwave N-1 (wave 0 dependsOnplatform-config) and health-gates (wait: true) ONLY that wave. A crashlooping workload in a later wave can no longer stall an earlier wave or block new revisions. wave-<N>/kustomization.yamlandclusters/base/apps-wave-<N>.yamlare generated — runpython3 catalog/render.py --emit-wavesafter onboarding a service; do not hand-edit them.- Wave assignment = longest dependency-path depth over the catalog
dependencies:graph; a co-located CNPG database<svc>-dbis a leaf and always lands strictly below its consumer.
See ../DESIGN-waves.md for the wave table, Flux topology, and the
cutover runbook.