c85262111c
gates / gates (push) Successful in 23s
Part 0 — floor raised to 0.260.0, MinAgent 0.131.0 declared. 3 boxes below, all down or blocked; both demo boxes SERVED. Part 1 (R-610) — the DANGEROUS power cut, measured three times with three apps and two cut mechanisms. All ended honest: resumed, completed, and pinned/installed/live compose/docker inspect all agreed. vikunja's 2.6.0 migration had ALREADY run 0.64 s after the cut decision and the seeded data read back intact — so the branch that is one step from old-binary-on-migrated-database is now evidence, not argument. Instrument limit stated: `starting` lasts under a second; all three landed in `verifying`, which RecoverUpdates handles in the same branch. Part 3 (R-611) — the night the previous session skipped without saying so. An app updated with nobody pressing anything; a terminally-refused app was pressed exactly once and never again over three passes. The unattended HOLD was NOT produced: the within-a-major rule correctly refused the broken edge before it was attempted, so Q4 still rests on the attended hold from slice 4. Said plainly rather than implied. Rows: closed R-608/609/610/611; opened R-612 (P1 wishlist unusable on a fresh install, and its error is a lie), R-613 (uptime-kuma healthy on its setup wizard), R-614 (stale update phase survives a redeploy). R-520's pointer corrected. Catalog: two drill pairs, both reverted; every image line byte-identical to ff9717d3. The alpine:3.20 negative control a security review flagged is cleared. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
49 lines
3.0 KiB
Plaintext
49 lines
3.0 KiB
Plaintext
# 08 — THE v0.261.0 LOCK, PROVEN LIVE (R-608), with a positive AND a negative control
|
|
#
|
|
# Guest 9202, controller v0.261.0, 2026-09-21. The question is not "is the callback wired" but
|
|
# "does the swap actually refuse, and is it OUR refusal doing it".
|
|
|
|
== WHY A CONTROL WAS NEEDED, AND WHY THIS ONE IS THE RIGHT ONE ==
|
|
Guest 9202 has NO host agent wired, so `TriggerUpdate` refuses anyway — with the AGENT's sentence.
|
|
That makes it the perfect negative control: in `TriggerUpdate` the new app-update check sits BEFORE
|
|
the agent check, so if the lock fires we see OUR sentence and if it does not we see the AGENT's.
|
|
Two different sentences, one probe. It also makes the probe SAFE: no swap can reach a machine.
|
|
|
|
(Self-update is `enabled: false` on this guest by design. It was turned on for this probe and
|
|
turned back OFF immediately afterwards — the original file was copied to
|
|
/root/controller.yaml.pre-lock-probe first and restored from it. Verified reverted below.)
|
|
|
|
== CONTROL A — self-update status, no app update running ==
|
|
GET /api/selfupdate/status -> {"ok":true,"data":{"running":false}}
|
|
|
|
== CONTROL B (NEGATIVE) — the MANUAL trigger with NO app update running ==
|
|
12:39:55.917 POST /api/selfupdate/update
|
|
-> {"ok":false,"error":"A frissites nem erheto el (nincs gazda-ugynok)"}
|
|
i.e. the AGENT refusal. The lock is NOT firing, because nothing is in flight. Correct.
|
|
|
|
== THE PROBE (POSITIVE) — the MANUAL trigger WHILE an app update is in flight ==
|
|
12:39:55.941 POST /api/stacks/uptime-kuma/update -> 202 "Frissites elindult"
|
|
12:39:56.241 app update IN FLIGHT, phase = safety-dump
|
|
12:39:56.244 POST /api/selfupdate/update
|
|
-> {"ok":false,"error":"Egy alkalmazas frissitese eppen folyamatban van. A vezerlo frissitese utana inditható."}
|
|
THE SENTENCE CHANGED. That is the v0.261.0 gate firing, and firing BEFORE the agent check.
|
|
12:39:56.270 GET /api/selfupdate/status -> {"running":false} — nothing was started.
|
|
|
|
(accents transliterated here only to keep this file ASCII-searchable; intact on the wire)
|
|
|
|
== WHAT THE PHASE TELLS US, and it is worth stating ==
|
|
The probe landed in `safety-dump`. That phase is NOT covered by the pre-existing `backupRunning`
|
|
gate — only `backing-up` is, because that one takes the backup single-flight. So the probe hit
|
|
exactly the window the new lock exists for, rather than a window that was already protected.
|
|
|
|
== THE REVERSE DIRECTION — NOT staged live, and why ==
|
|
`UpdatePreflight` refusing an app update with reason `self_updating` while the controller swaps is
|
|
covered by `TestR608_PreflightRefusesWhileTheControllerSwaps` (a consequence test, red-proofed by
|
|
deleting the block). Staging it LIVE would need a real controller swap in flight, which needs a host
|
|
agent this guest does not have and a genuine image swap mid-measurement. **Not measured live. Stated
|
|
as a gap rather than implied.**
|
|
|
|
== CONFIG RESTORED ==
|
|
self_update.enabled is back to `false` on guest 9202, verified by re-reading the file after the
|
|
restore, and the controller was restarted on the restored config.
|