claim(2w): W0.10a traefik WC1.1 migrated onto shared health-gated reconciler — no-op converge proven; destructive rollback = Adversary cold proof

warm_reconcile.py: per-spec setup hook + health_domain; SPECS[traefik]
(stateful=False, version-rollback-only, _traefik_setup preserves wildcard-cert/
file-provider config, health on routed dashboard host). keycloak path unchanged.
proxy.nix: deploy-proxy.service now execs warm_reconcile.py traefik. ZERO-disruption
migration (traefik already at latest 5.1.1+v3.6.15; pre-seeded TYPE+last_good →
clean no-op converge; traefik 200 + keycloak-through-traefik 200 + 0 failed).
65 unit pass. Per operator out: code+converge delivered; destructive rollback
(brief TLS blip) = Adversary's required cold proof. Closes the W0.10a tracked-open.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 03:50:32 +01:00
parent aec6911c68
commit e678d2e006
5 changed files with 145 additions and 45 deletions

View File

@ -308,3 +308,24 @@ Plan for next: (a) W0.10a traefik health-gated reconciler migration (quiet windo
serves all TLS); (b) W3 WC5 promote-on-green-cold (extend cold-run teardown to re-seed the canonical
on green-latest, reusing seed_canonical); (c) W3 WC6 nightly sweep (systemd timer: rebuild-then-cold-
sweep). traefik first (use the window) or interleave; W0.10b alert-relay is a small loop step.
## 2026-05-29 — W0.10a traefik WC1.1 migrated (quiet window) — code + no-op converge; rollback = Adversary proof
Used the post-W2 quiet window (Adversary idle) for the tracked traefik WC1.1 migration. Generalized
warm_reconcile.py: per-spec `setup` hook + `health_domain`; added SPECS["traefik"] (stateful=False →
stateless version-rollback-only, NO snapshot; setup=_traefik_setup preserving the wildcard-cert/
file-provider config EXACTLY via the proven newline-safe abra.env_set; health on the routed dashboard
host). keycloak's path is unchanged (no `setup` key → default). proxy.nix migrated:
deploy-proxy.service now execs `warm_reconcile.py traefik` (runner/ packaged in the store, D8-clean).
ZERO-DISRUPTION migration: traefik was already at the latest tag (5.1.1+v3.6.15, image v3.6.15, chaos
commit 005f023 = the tag commit). I pre-seeded the .env TYPE + last_good to 5.1.1+v3.6.15 (accurate —
traefik IS at that version), so the health-gated reconcile is a clean no-op (current==latest==healthy)
→ NO redeploy, NO TLS blip. Verified via nixos-rebuild switch: deploy-proxy.service → "no-op",
traefik 200 + keycloak-through-traefik 200 + 0 failed units. 65 unit pass.
Per the operator's explicit out (a destructive traefik test risks ALL TLS), I delivered the code +
safe no-op converge and left the DESTRUCTIVE rollback as the Adversary's required cold proof (staged
broken traefik tag → reconcile → rollback to last-good, brief TLS blip + manual recovery ready). The
rollback logic is the proven keycloak pattern, stateless variant. Claiming W0.10a so the Adversary
runs that cold proof. After this clears, WC1.1 is fully closed (keycloak + traefik).