status(redfix): record the b5f2b10 MERGE PRECONDITION; widen B-redfix-5 to both post-undeploy sites
Acting on the Adversary's wake-#41 verdict (3131e39), which CONFIRMED the merge guidance but left a merge precondition only in REVIEW-redfix.md — Adversary-owned, and not what an operator reads before merging. Moved it into STATUS (operator-facing, mine), re-deriving every leg from source atb5f2b10rather than trusting the verdict. - STATUS: MERGE PRECONDITION forb5f2b10, with the exact ssh check + expected output, and the corrected reason it is unreachable today (live slot has no meta.json — NOT "F-redfix-4 is closed"). - Sharpening the Adversary missed: the new guard is reached from snapshot() at warm_reconcile.py:514 as well as restore() at :536. Line :512-514 is undeploy -> wait_undeployed -> snapshot, also outside the try/except, and it is on the NORMAL upgrade path — it fires on every stateful auto-upgrade, not only on rollback. B-redfix-5 as filed named only the rollback site. - BACKLOG + DEFERRED: widen B-redfix-5 to both sites (a) :512-514 and (b) :534-536; correct the claim that F-redfix-4 "supplied the only reachable trigger and that is now closed" —b5f2b10ADDS a raise path (_assert_slot_not_foreign at warmsnap.py:158 and :209). Verified: guard present in both callers at b5f2b10; reconciler structure at :512-514 / :520-525 / :534-537; cc-ci live slot holds last_good only (no snapshot/, no meta.json, no canon-* slot). Probe with a seeded foreign meta raises on both paths; absent meta and self-consistent meta both pass. No DoD item touched. M1+M2 PASS stand, ## DONE stands, no VETO. Docs-only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YZmH4rVNue3irZ6EsZzavb
This commit is contained in:
@ -430,15 +430,24 @@ reachable via the operator/dev STAGES escape — production drone runs always ru
|
||||
|
||||
## B-redfix-5 — warm reconciler's rollback `restore()` is outside the upgrade's `try/except`
|
||||
|
||||
- **What:** in `runner/warm_reconcile.py`, the unhealthy-rollback path is `abra.undeploy(domain)` →
|
||||
`wait_undeployed` → `warmsnap.restore(...)` → `deploy_version(last_good)`. `restore()` sits OUTSIDE the
|
||||
`try/except` guarding the upgrade, so if it raises for any reason (absent/corrupt snapshot, docker error)
|
||||
the exception propagates and `deploy_version(last_good)` never runs — live keycloak is left **undeployed**,
|
||||
taking down the shared OIDC provider `lasuite-*`/`drone` depend on.
|
||||
- **What:** in `runner/warm_reconcile.py`, **two** post-`abra.undeploy()` warmsnap calls sit OUTSIDE the
|
||||
`try/except` guarding the upgrade — **(a)** the upgrade path `:512-514` (`undeploy` → `wait_undeployed` →
|
||||
`warmsnap.snapshot(...)`) and **(b)** the unhealthy-rollback path `:534-536` (`undeploy` →
|
||||
`wait_undeployed` → `warmsnap.restore(...)` → `deploy_version(last_good)` at `:537`). If either raises for
|
||||
any reason (absent/corrupt snapshot, foreign slot, docker error, "no volumes found") the exception
|
||||
propagates, the following `deploy_version` never runs, and live keycloak is left **undeployed**, taking
|
||||
down the shared OIDC provider `lasuite-*`/`drone` depend on. Site (a) fires on the *normal* upgrade path —
|
||||
no rollback required.
|
||||
- **Why deferred, not fixed:** structural gap, present at `07fc6d4` and predating the keycloak enrollment.
|
||||
F-redfix-4 supplied the only *reachable* trigger (the shared snapshot slot) and that is now closed at
|
||||
`b5f2b10`. Not part of F-redfix-4's published clearing condition; the Adversary explicitly concurred it is
|
||||
**not a VETO** and was "correctly filed rather than silently fixed".
|
||||
Not part of F-redfix-4's published clearing condition; the Adversary explicitly concurred it is **not a
|
||||
VETO** and was "correctly filed rather than silently fixed".
|
||||
- **Reachability, corrected (wake #42).** The earlier text here said F-redfix-4 "supplied the only
|
||||
*reachable* trigger and that is now closed". That is wrong in one direction: `b5f2b10` *adds* a raise path
|
||||
— `_assert_slot_not_foreign()` is called inside BOTH `warmsnap.snapshot()` (`:158`) and `warmsnap.restore()`
|
||||
(`:209`). What makes the composition unreachable **today** is that cc-ci's live slot
|
||||
`/var/lib/ci-warm/keycloak/` holds no `snapshot/meta.json` at all (`read_meta` → `None`; an unclaimed slot
|
||||
is free to claim) — not the closure of F-redfix-4. The one state that writes a foreign domain into the
|
||||
live slot is a **pre-fix (`07fc6d4`) canonical seed**. Recorded as a MERGE PRECONDITION in STATUS-redfix.md.
|
||||
- **Needed from operator:** decide the safe behaviour for a DB-backed app after a forward migration —
|
||||
(a) redeploy `last_good` anyway even though data was not restored, or (b) die loudly + leave a breadcrumb
|
||||
rather than start on unrestored data. That trade-off is a real safety call, not a mechanical fix, which is
|
||||
|
||||
Reference in New Issue
Block a user