review(redfix): wake #45186b0ba rewrite VERIFIED cold; A-redfix-2/3/4 CLOSED; A-redfix-1 = same live credential as B-redfix-8 (sentinel 3fcea789…, still unrotated)

This commit is contained in:
autonomic-bot
2026-07-09 09:02:52 +00:00
parent 186b0ba46b
commit cf807321e1
2 changed files with 89 additions and 3 deletions
+35 -3
View File
@@ -534,7 +534,7 @@ a sha alone is not durable evidence. Record the *content assertion* (file → ex
or push a tag. The other three redfix fixes pinned exactly (`4ca7f418`, `a0f2db88`, `4987ba91`), as did cc-ci or push a tag. The other three redfix fixes pinned exactly (`4ca7f418`, `a0f2db88`, `4987ba91`), as did cc-ci
`redfix-m2-harness`@`07fc6d4a` — discourse drifted only because a later phase reused its branch. `redfix-m2-harness`@`07fc6d4a` — discourse drifted only because a later phase reused its branch.
### A-redfix-2 [adversary] — STATUS's "no code path redeploys it / recovery is manual" is REFUTED: the B-redfix-5 wedge **does** self-heal on the next unit activation, which makes it look intermittent ### A-redfix-2 [adversary] — **CLOSED 2026-07-09T08:59Z** (accepted at `f64d102`; false half superseded by A-redfix-4 at `e356698`) — STATUS's "no code path redeploys it / recovery is manual" is REFUTED: the B-redfix-5 wedge **does** self-heal on the next unit activation, which makes it look intermittent
> **⚠ PARTIALLY WITHDRAWN by me at wake #44 (2026-07-09T08:5xZ) — see A-redfix-4.** > **⚠ PARTIALLY WITHDRAWN by me at wake #44 (2026-07-09T08:5xZ) — see A-redfix-4.**
> The *first* half (a code path redeploys it → the "recovery is manual" wording is wrong) **stands**. > The *first* half (a code path redeploys it → the "recovery is manual" wording is wrong) **stands**.
@@ -596,7 +596,7 @@ does restore live keycloak — but the foreign meta remains, so it re-wedges on
is to remove the foreign `snapshot/`, not to redeploy."* The **precondition itself is unchanged and still is to remove the foreign `snapshot/`, not to redeploy."* The **precondition itself is unchanged and still
correct**; only the mechanism/remediation sentences are wrong. correct**; only the mechanism/remediation sentences are wrong.
### A-redfix-3 [adversary] — STATUS's `main.go` "present in both clones ⇒ written outside git" evidence is void: `/srv/cc-ci` is a **symlink** to `/srv/cc-ci-orch`, so there is one file, not two ### A-redfix-3 [adversary] — **CLOSED 2026-07-09T08:59Z** (accepted + evidence retracted at `f64d102`; STATUS:28-29,564-572 re-read and correct) — STATUS's `main.go` "present in both clones ⇒ written outside git" evidence is void: `/srv/cc-ci` is a **symlink** to `/srv/cc-ci-orch`, so there is one file, not two
Severity **INFO**. No VETO, no gate impact, no DoD impact. The *conclusion* (untracked, not from this phase, Severity **INFO**. No VETO, no gate impact, no DoD impact. The *conclusion* (untracked, not from this phase,
leave it alone) is fine; the supporting evidence is an artifact. leave it alone) is fine; the supporting evidence is an artifact.
@@ -627,7 +627,7 @@ on not deleting it: neither of us created it.
--- ---
### A-redfix-4 [adversary] — the B-redfix-5 wedge has a **weekly autonomous re-trigger** (`nightly-sweep.timer`) and fails **silently**: post-arming, keycloak oscillates down-a-week / up-a-week with `nightly-sweep.service` reporting `Result=success` ### A-redfix-4 [adversary] — **CLOSED 2026-07-09T08:59Z** — all three asks applied at `e356698` and cold-re-verified by me at wake #45 (probes deleted; oscillation + silence recorded; precondition re-anchored to "never deploy `07fc6d4`"). The underlying *behaviour* remains open under **B-redfix-5**, which is deferred, not fixed. — the B-redfix-5 wedge has a **weekly autonomous re-trigger** (`nightly-sweep.timer`) and fails **silently**: post-arming, keycloak oscillates down-a-week / up-a-week with `nightly-sweep.service` reporting `Result=success`
Severity **MED** (operator-facing; describes a *deferred* item's blast profile, **not** a DoD item). Severity **MED** (operator-facing; describes a *deferred* item's blast profile, **not** a DoD item).
**No VETO. Does not reopen the phase.** M1 + M2 PASS stand. Merge target `b5f2b10` unchanged and still correct. **No VETO. Does not reopen the phase.** M1 + M2 PASS stand. Merge target `b5f2b10` unchanged and still correct.
@@ -722,3 +722,35 @@ means **the merge's own activation switch is itself a reconcile trigger**, along
Remediation if ever armed is unchanged and still correct: **delete the foreign `snapshot/` from the slot**; Remediation if ever armed is unchanged and still correct: **delete the foreign `snapshot/` from the slot**;
do not redeploy keycloak (the sweep does that for you, and it is what masks the fault). do not redeploy keycloak (the sweep does that for you, and it is what masks the fault).
---
### A-redfix-1 — ADDENDUM (wake #45, 2026-07-09T08:59Z): the embedded value is the **same live credential as B-redfix-8**, confirmed at value level; and rotation will **not** clean this file
Still **OPEN**. Re-verified cold on cc-ci this wake, without printing the secret:
ssh cc-ci 'stat -c "%a %U:%G" /etc/cc-ci/.git/config' # → 644 root:root
ssh cc-ci 'grep -oE "https://[^/@]+:[^/@]+@" /etc/cc-ci/.git/config \
| sed -E "s#https://[^:]+:##; s#@$##" | tr -d "\n" | sha256sum | cut -c1-16'
**EXPECTED / observed: `3fcea78925015fc9`** — byte-identical to the B-redfix-8 rotation sentinel
(`sha256(GITEA_PASSWORD)[:16]`, re-confirmed this wake from `/srv/cc-ci/.testenv` on the **orchestrator**).
So A-redfix-1 and B-redfix-8 are **two exposures of one still-unrotated, push-capable credential**, and the
sentinel matching proves it is **still not rotated**. (Extract-then-hash, never echo. `python3` is absent on
cc-ci — do not run the orchestrator's python probe over `ssh`; that is the `e3b0c44298fc1c14` empty-input tell.)
**New, and operator-relevant: rotation does not fix this file, and may recreate the exposure.**
`/etc/cc-ci` is a **manual `git clone`**, not nix-generated — `nix/hosts/cc-ci-hetzner/configuration.nix:7`
documents `git clone --recursive https://git.autonomic.zone/recipe-maintainers/cc-ci.git /etc/cc-ci`. Nothing
regenerates `.git/config` on `nixos-rebuild switch`. Therefore:
- After rotating `GITEA_PASSWORD`, the **old** value persists verbatim in this 0644 file (inert, but it should
still be scrubbed — it is the value published at `14c7dee`).
- If the operator re-clones or re-embeds the **new** password in the remote URL, the 0644 exposure **returns**.
**Recommendation (operator, alongside the B-redfix-8 rotation):** point the remote at a credential-less URL
(`https://git.autonomic.zone/recipe-maintainers/cc-ci.git`) and authenticate via a `credential.helper` /
token file with `0600`, or at minimum `chmod 0600 /etc/cc-ci/.git/config`. Do not carry userinfo in the URL.
**Rotation blast radius is small** (checked, so this is not a reason to delay): `GITEA_PASSWORD` is consumed
only by `scripts/bootstrap-drone-oauth.sh` (a one-off bootstrap). `scripts/recipe-mirror-sync.sh` pushes with
an **OAuth token**, not the password, so the weekly sweep's mirror sync does **not** depend on it.
+54
View File
@@ -1433,3 +1433,57 @@ deferred/open. B-redfix-8 unchanged (OPEN/HIGH/operator-rotation-only; not re-pr
Three asks of the Builder in A-redfix-4 — all STATUS text, no code, nothing reopens. Three asks of the Builder in A-redfix-4 — all STATUS text, no code, nothing reopens.
Did not read JOURNAL-redfix.md before forming this verdict. Did not read JOURNAL-redfix.md before forming this verdict.
---
## Wake #45 — 2026-07-09T09:02:52Z — Builder's A-redfix-4 rewrite (`e356698`) **VERIFIED**; A-redfix-2/3/4 CLOSED; A-redfix-1 re-confirmed live and linked to B-redfix-8 at value level. Still no VETO.
Autonomous tick. `BUILDER-INBOX.md` consumed by the Builder (deleted); no `ADVERSARY-INBOX.md`; no gate
CLAIMED (STATUS:433 is the historical M2 claim, superseded by `## DONE` at :10). **M1 + M2 PASS stand,
`## DONE` stands, no VETO, merge target `b5f2b10` unchanged.**
**All three A-redfix-4 asks applied — and I re-verified the rewrite rather than accepting it.** The lone
surviving `grep -i keycloak` string in STATUS (:152) is prose *warning against* the probe, not prescribing it;
the prescribed probe is now `git grep -n warm_reconcile -- runner/ nix/`, which is falsifiable and does find
both invokers. Deleted, not fixed — correct.
**Every new claim in the rewrite checked cold; all hold:**
- `write_alert()` call sites `:493,500,503,539` ✓; `write_last_good()` `:478,484,491,527` ✓, all inside
`reconcile()` (`:448``:551`, `main()` at `:552`) ✓.
- "on `main` the same sites sit two lines earlier" ✓ exactly: `514→512`, `523→521`, `552→550`.
- `abra.undeploy` = single `_run(["app","undeploy",domain,"-n"], …, check=False)`, no `.env` handling ✓.
- fresh-deploy branch `:472 if not deployed` → `:479 return deployed-fresh:{target}`, no `warmsnap` ✓.
- `_assert_slot_not_foreign`: raises iff `meta and meta["domain"] != domain`; "a slot with no snapshot yet is
free to claim" ✓ (verbatim in the docstring).
- **"`python3` is absent there"** — I expected this to be the Builder's own unfalsifiable-probe slip. It is
**true**: `command -v python3` on cc-ci → not found. Claim survives.
- Trap not armed: slot holds `last_good` only, no `snapshot/meta.json`, no `/var/lib/ci-warm/canon-keycloak` ✓.
Live `https://warm-keycloak…/realms/master` → **200** ✓.
- Sound probe also surfaces a **third** invoker the Builder's EXPECTED text omits: `nix/modules/proxy.nix:27`
→ `warm_reconcile.py traefik`. Not a defect — traefik is `stateful: False`, never snapshots, so blast radius
is unchanged. Noted, not filed.
**I hardened my own wake-#44 evidence.** My mtime proof rests on "`write_last_good()` is reachable only from
`reconcile()`" — but I had verified that against `b5f2b10`, when the tree that actually ran on 2026-07-05 is
the **deployed** one. Re-checked repo-wide at `origin/main`: no caller outside `warm_reconcile.py`, all four
sites inside `reconcile()` (`:476,482,489,525`; `reconcile` `:446`, `main` `:550`). The proof holds **on the
correct tree**. Closing that gap is the same discipline that caught A-redfix-2.
**A-redfix-2, A-redfix-3, A-redfix-4 → CLOSED** (I own closing them). A-redfix-4's *behaviour* remains open
under **B-redfix-5**, which stays deferred — the text is fixed, the wedge is not.
**A-redfix-1: re-probed, STILL OPEN, and now pinned to B-redfix-8 at value level.** `/etc/cc-ci/.git/config`
is `644 root:root` and carries userinfo in the remote URL; extracting that password and hashing it (never
echoing it) yields **`3fcea78925015fc9`** — byte-identical to the B-redfix-8 rotation sentinel, re-confirmed
this wake from `/srv/cc-ci/.testenv` on the **orchestrator**. Two exposures, one credential, **still
unrotated**. New: `/etc/cc-ci` is a **manual `git clone`** (`nix/hosts/cc-ci-hetzner/configuration.nix:7`),
not nix-generated — so rotation neither scrubs this file nor regenerates it, and re-embedding the new password
recreates the exposure. Rotation blast radius is small (`GITEA_PASSWORD` is used only by
`scripts/bootstrap-drone-oauth.sh`; `recipe-mirror-sync.sh` pushes with an OAuth **token**), so there is no
operational reason to delay it. Addendum + recommendation filed under A-redfix-1.
**B-redfix-8 remains OPEN/HIGH/operator-rotation-only** — the sentinel check above is the sanctioned
non-republishing probe, and it says: not yet rotated.
**Verdict: no VETO. `## DONE` stands. M1 + M2 PASS stand. Merge target `b5f2b10` unchanged.**
Did not read JOURNAL-redfix.md before forming this verdict.