Slice 4 shipped (R-448/R-443/R-439 CLOSED, proven live); R-472..R-476; the floor-between-bakes claim corrected
gates / gates (push) Successful in 19s

Controller v0.237.0-v0.238.1: the Update button is a guarded job — refusals, backup-first when the
proven Tier-2 copy is stale, safety dump, pin, pull (pin back on failure), health, HOLD on failure.
Proven live on demo-hp: A, B, E, F, H and the restore walk (audits/slice4-2026-09-13/).

Correction to this morning's pages: between golden bakes the hub HOLDS a floor above the vouched
golden, so a release does not reach the fleet by floor (R-472, operator decision). Corrected in the
runbook, STATUS, CONTEXT, R-468 and the gate docstring.

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-13 12:30:17 +02:00
parent abe567e14d
commit 5ef0f52bcd
46 changed files with 1029 additions and 285 deletions
@@ -0,0 +1,28 @@
ok gitea.dooplex.hu/admin/felhom-controller/cmd/controller 10.311s
ok gitea.dooplex.hu/admin/felhom-controller/internal/agentapi 0.178s
ok gitea.dooplex.hu/admin/felhom-controller/internal/api 0.316s
ok gitea.dooplex.hu/admin/felhom-controller/internal/appbackup 0.020s
ok gitea.dooplex.hu/admin/felhom-controller/internal/appexport 0.971s
ok gitea.dooplex.hu/admin/felhom-controller/internal/backup 316.772s
ok gitea.dooplex.hu/admin/felhom-controller/internal/backupwindow 0.003s
ok gitea.dooplex.hu/admin/felhom-controller/internal/bootrecon 0.007s
ok gitea.dooplex.hu/admin/felhom-controller/internal/bootstrap 14.023s
ok gitea.dooplex.hu/admin/felhom-controller/internal/channelhealth 0.004s
ok gitea.dooplex.hu/admin/felhom-controller/internal/config 0.005s
ok gitea.dooplex.hu/admin/felhom-controller/internal/fillwatch 0.007s
ok gitea.dooplex.hu/admin/felhom-controller/internal/infra 0.009s
ok gitea.dooplex.hu/admin/felhom-controller/internal/mailrelay 0.015s
ok gitea.dooplex.hu/admin/felhom-controller/internal/metrics 0.008s
ok gitea.dooplex.hu/admin/felhom-controller/internal/monitor 0.004s
ok gitea.dooplex.hu/admin/felhom-controller/internal/notify 0.778s
ok gitea.dooplex.hu/admin/felhom-controller/internal/offsiteapply 0.010s
ok gitea.dooplex.hu/admin/felhom-controller/internal/quiesce 0.076s
ok gitea.dooplex.hu/admin/felhom-controller/internal/report 2.578s
ok gitea.dooplex.hu/admin/felhom-controller/internal/scheduler 0.154s
ok gitea.dooplex.hu/admin/felhom-controller/internal/selfupdate 0.022s
ok gitea.dooplex.hu/admin/felhom-controller/internal/settings 0.009s
ok gitea.dooplex.hu/admin/felhom-controller/internal/setup 0.009s
ok gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.540s
ok gitea.dooplex.hu/admin/felhom-controller/internal/sync 0.015s
ok gitea.dooplex.hu/admin/felhom-controller/internal/system 0.104s
ok gitea.dooplex.hu/admin/felhom-controller/internal/web 29.840s
@@ -0,0 +1,28 @@
ok gitea.dooplex.hu/admin/felhom-controller/cmd/controller 10.293s
ok gitea.dooplex.hu/admin/felhom-controller/internal/agentapi 0.190s
ok gitea.dooplex.hu/admin/felhom-controller/internal/api 0.298s
ok gitea.dooplex.hu/admin/felhom-controller/internal/appbackup 0.020s
ok gitea.dooplex.hu/admin/felhom-controller/internal/appexport 1.023s
ok gitea.dooplex.hu/admin/felhom-controller/internal/backup 318.161s
ok gitea.dooplex.hu/admin/felhom-controller/internal/backupwindow 0.006s
ok gitea.dooplex.hu/admin/felhom-controller/internal/bootrecon 0.008s
ok gitea.dooplex.hu/admin/felhom-controller/internal/bootstrap 14.025s
ok gitea.dooplex.hu/admin/felhom-controller/internal/channelhealth 0.008s
ok gitea.dooplex.hu/admin/felhom-controller/internal/config 0.006s
ok gitea.dooplex.hu/admin/felhom-controller/internal/fillwatch 0.009s
ok gitea.dooplex.hu/admin/felhom-controller/internal/infra 0.009s
ok gitea.dooplex.hu/admin/felhom-controller/internal/mailrelay 0.015s
ok gitea.dooplex.hu/admin/felhom-controller/internal/metrics 0.008s
ok gitea.dooplex.hu/admin/felhom-controller/internal/monitor 0.006s
ok gitea.dooplex.hu/admin/felhom-controller/internal/notify 0.797s
ok gitea.dooplex.hu/admin/felhom-controller/internal/offsiteapply 0.012s
ok gitea.dooplex.hu/admin/felhom-controller/internal/quiesce 0.079s
ok gitea.dooplex.hu/admin/felhom-controller/internal/report 2.578s
ok gitea.dooplex.hu/admin/felhom-controller/internal/scheduler 0.156s
ok gitea.dooplex.hu/admin/felhom-controller/internal/selfupdate 0.025s
ok gitea.dooplex.hu/admin/felhom-controller/internal/settings 0.013s
ok gitea.dooplex.hu/admin/felhom-controller/internal/setup 0.010s
ok gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.544s
ok gitea.dooplex.hu/admin/felhom-controller/internal/sync 0.019s
ok gitea.dooplex.hu/admin/felhom-controller/internal/system 0.094s
ok gitea.dooplex.hu/admin/felhom-controller/internal/web 29.766s
@@ -0,0 +1,28 @@
ok gitea.dooplex.hu/admin/felhom-controller/cmd/controller 10.306s
ok gitea.dooplex.hu/admin/felhom-controller/internal/agentapi 0.190s
ok gitea.dooplex.hu/admin/felhom-controller/internal/api 0.360s
ok gitea.dooplex.hu/admin/felhom-controller/internal/appbackup 0.022s
ok gitea.dooplex.hu/admin/felhom-controller/internal/appexport 1.127s
ok gitea.dooplex.hu/admin/felhom-controller/internal/backup 317.940s
ok gitea.dooplex.hu/admin/felhom-controller/internal/backupwindow 0.006s
ok gitea.dooplex.hu/admin/felhom-controller/internal/bootrecon 0.008s
ok gitea.dooplex.hu/admin/felhom-controller/internal/bootstrap 14.027s
ok gitea.dooplex.hu/admin/felhom-controller/internal/channelhealth 0.005s
ok gitea.dooplex.hu/admin/felhom-controller/internal/config 0.006s
ok gitea.dooplex.hu/admin/felhom-controller/internal/fillwatch 0.009s
ok gitea.dooplex.hu/admin/felhom-controller/internal/infra 0.009s
ok gitea.dooplex.hu/admin/felhom-controller/internal/mailrelay 0.016s
ok gitea.dooplex.hu/admin/felhom-controller/internal/metrics 0.011s
ok gitea.dooplex.hu/admin/felhom-controller/internal/monitor 0.005s
ok gitea.dooplex.hu/admin/felhom-controller/internal/notify 0.817s
ok gitea.dooplex.hu/admin/felhom-controller/internal/offsiteapply 0.012s
ok gitea.dooplex.hu/admin/felhom-controller/internal/quiesce 0.082s
ok gitea.dooplex.hu/admin/felhom-controller/internal/report 2.591s
ok gitea.dooplex.hu/admin/felhom-controller/internal/scheduler 0.156s
ok gitea.dooplex.hu/admin/felhom-controller/internal/selfupdate 0.027s
ok gitea.dooplex.hu/admin/felhom-controller/internal/settings 0.012s
ok gitea.dooplex.hu/admin/felhom-controller/internal/setup 0.010s
ok gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.655s
ok gitea.dooplex.hu/admin/felhom-controller/internal/sync 0.023s
ok gitea.dooplex.hu/admin/felhom-controller/internal/system 0.106s
ok gitea.dooplex.hu/admin/felhom-controller/internal/web 29.955s
@@ -0,0 +1,16 @@
=== floor raise 2026-09-13T09:43:21Z ===
POST http=303
Location: /configuration?flash=floor_set
name="min_controller_version" value="0.237.0"
=== fleet 2026-09-13T09:51:44Z ===
demo-hp: gitea.dooplex.hu/admin/felhom-controller:0.236.0 Up 3 hours (healthy)
demo-felhom: gitea.dooplex.hu/admin/felhom-controller:0.236.0 Up 3 hours (healthy)
=== the hub HELD the 0.237.0 floor on every box (hub log, verbatim) ===
2026/09/13 11:43:21 [INFO] Global controller-version floor set to "0.237.0"
2026/09/13 11:43:23 [INFO] managed floor HELD for demo-felhom: held: floor 0.237.0 is ABOVE the vouched golden 0.236.0, so its agent requirement is unknown — vouch a golden carrying the floor's controller (publish-train rule 1) (controller floor withheld)
2026/09/13 11:43:24 [INFO] managed floor HELD for demo-hp: held: floor 0.237.0 is ABOVE the vouched golden 0.236.0, so its agent requirement is unknown — vouch a golden carrying the floor's controller (publish-train rule 1) (controller floor withheld)
=== floor put back to the vouched golden 0.236.0 2026-09-13T09:52:43Z ===
POST http=303
Location: /configuration?flash=floor_set
name="min_controller_version" value="0.236.0"
@@ -0,0 +1,4 @@
=== hand-deploy 0.237.0 on felhom-pve-lan guest 9201 2026-09-13T09:52:50Z (skill route: pull, write the image file, restart the bootstrap unit) ===
gitea.dooplex.hu/admin/felhom-controller:0.237.0
docker ps: gitea.dooplex.hu/admin/felhom-controller:0.237.0 Up 6 seconds (healthy)
--- startup lines ---
@@ -0,0 +1,6 @@
=== hand-deploy 0.237.0 on hp guest 9201 2026-09-13T09:52:50Z (skill route: pull, write the image file, restart the bootstrap unit) ===
gitea.dooplex.hu/admin/felhom-controller:0.237.0
docker ps: gitea.dooplex.hu/admin/felhom-controller:0.237.0 Up 7 seconds (healthy)
--- startup lines ---
2026/09/13 09:52:55 client.go:67: [DEBUG] [agentapi] agent version seen: 0.130.0 (was "")
2026/09/13 09:52:59 builder.go:40: [DEBUG] [report] BuildReport: starting — version=0.237.0, storagePaths=1
@@ -0,0 +1,29 @@
=== glance abandoned as the test app 2026-09-13T09:59:15Z: its catalog template crash-loops on a fresh install (no glance.yml seeded) ===
restarts=13 status=restarting
parsing config: reading /app/config/glance.yml: open /app/config/glance.yml: no such file or directory
parsing config: reading /app/config/glance.yml: open /app/config/glance.yml: no such file or directory
--- removal through the feature (R-442), data + backups ---
HTTP 409
{"ok":false,"error":"stack \"glance\" is still running — stop it first before removing"}
--- after ---
glance Restarting (1) 44 seconds ago
glance_glance_config
app.yaml
applied-compose.yml
docker-compose.yml
compose
manifest.json
--- stop, then remove (data + backups) 2026-09-13T09:59:42Z ---
HTTP 200
{"ok":true,"message":"Stack glance stop completed"}
HTTP 200
{"ok":true,"data":{"removed":"glance","volumes_removed":null,"hdd_paths_removed":[],"hdd_paths_preserved":[],"hdd_note":"Az alkalmazás nem tárolt saját adatot külső meghajtón, így ott nem volt mit törölni."},"message":"Stack glance removed"}
--- after ---
volumes:
stackdir: applied-compose.yml docker-compose.yml
primary: compose manifest.json
@@ -0,0 +1,32 @@
=== L1 setup 2026-09-13T09:54:46Z: catalog a1f1c38 carries glance v0.8.4 ===
--- sync via POST /api/sync (the dashboard's 'Sablonok frissítése' — the syncer's own entry point) ---
HTTP 200
{"ok":true,"data":{"ok":true,"updated":["glance"],"message":"Sablonok frissítve — frissítve: glance"},"message":"Sablonok frissítve — frissítve: glance"}
image: glanceapp/glance:v0.8.4
--- deploy glance (throwaway) ---
HTTP 202
{"ok":true,"message":"Telepítés elindítva – az állapot a kártyán követhető"}
state after deploy:
glanceapp/glance:v0.8.4 Restarting (1) 35 seconds ago
Traceback (most recent call last):
File "<string>", line 1, in <module>
import json,sys; d=json.load(sys.stdin)["data"]; print("pinned_images:", (d.get("app_config") or {}).get("pinned_images"))
~~~~~~~~~^^^^^^^^^^^
File "/usr/lib/python3.13/json/__init__.py", line 293, in load
return loads(fp.read(),
cls=cls, object_hook=object_hook,
parse_float=parse_float, parse_int=parse_int,
parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
File "/usr/lib/python3.13/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
~~~~~~~~~~~~~~~~~~~~~~~^^^
File "/usr/lib/python3.13/json/decoder.py", line 345, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.13/json/decoder.py", line 363, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)
--- wait for the periodic capture to write glance's primary unit ---
@@ -0,0 +1,30 @@
=== L1 setup 2026-09-13T09:59:55Z: catalog 01c631d carries uptime-kuma 2.3.2 ===
--- sync via POST /api/sync ---
HTTP 200
{"ok":true,"data":{"ok":true,"updated":["glance","uptime-kuma"],"message":"Sablonok frissítve — frissítve: glance, uptime-kuma"},"message":"Sablonok frissítve — frissítve: glance, uptime-kuma"}
image: louislam/uptime-kuma:2.3.2
--- deploy uptime-kuma (throwaway) ---
HTTP 202
{"ok":true,"message":"Telepítés elindítva – az állapot a kártyán követhető"}
state after deploy: running (2026-09-13T10:00:57Z)
louislam/uptime-kuma:2.3.2 Up 13 seconds (healthy)
pinned_images: {'uptime-kuma': 'louislam/uptime-kuma:2.3.2'}
--- wait for the periodic capture to write the primary unit ---
total 8
drwxr-xr-x 2 root root 4096 2026-09-13T10:02:54Z compose
-rw-r--r-- 1 root root 1008 2026-09-13T10:02:54Z manifest.json
--- Tier-2 via POST /api/backup/tier2 2026-09-13T10:03:03Z ---
HTTP 200
{"ok":true,"message":"2. mentés elindítva"}
uptime-kuma cross_drive: 2026-09-13T10:03:07Z ok /mnt/felhom-drives/hdd_1
total 8
drwxr-xr-x 2 root root 4096 2026-09-13T10:02:54Z compose
-rw-r--r-- 1 root root 1008 2026-09-13T10:02:54Z manifest.json
--- the card's view ---
state running catalog_images {'uptime-kuma': 'louislam/uptime-kuma:2.3.2'} installed {'uptime-kuma': {'ref': 'louislam/uptime-kuma:2.3.2', 'digest': 'sha256:9aeb4e51d038047f414309c77a1af553281ca535723cb88907d907269d0a908e', 'at': '2026-09-13T10:00:45Z'}}
=== L1 done 2026-09-13T10:03:16Z ===
@@ -0,0 +1,13 @@
=== Scenario A catalog change 2026-09-13T10:07:28Z: revert 01c631d — uptime-kuma 2.3.2 -> 2.4.0 ===
image: louislam/uptime-kuma:2.4.0
catalog_since: "2026-07-18"
all catalog gates OK
pre-push [app-catalog-felhom.eu]: gates OK - push proceeding.
catalog HEAD=28ce33b
--- sync ---
HTTP 200
{"ok":true,"data":{"ok":true,"updated":["uptime-kuma"],"message":"Sablonok frissítve — frissítve: uptime-kuma"},"message":"Sablonok frissítve — frissítve: uptime-kuma"}
image: louislam/uptime-kuma:2.3.2
(the live file must STILL name 2.3.2 — the app is frozen until Update)
@@ -0,0 +1,78 @@
=== Scenario A — a real upgrade 2.3.2 -> 2.4.0 with a fresh proven copy — 2026-09-13T10:07:31Z ===
--- BEFORE ---
{
"state": "running",
"updating": false,
"update_phase": null,
"update_phase_label": null,
"update_error": null,
"hold_reason": null,
"pinned_images": {
"uptime-kuma": "louislam/uptime-kuma:2.3.2"
},
"installed_images": {
"uptime-kuma": {
"ref": "louislam/uptime-kuma:2.3.2",
"digest": "sha256:9aeb4e51d038047f414309c77a1af553281ca535723cb88907d907269d0a908e",
"at": "2026-09-13T10:00:45Z"
}
},
"catalog_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.0"
}
}
louislam/uptime-kuma:2.3.2 Up 6 minutes (healthy)
--- POST /api/stacks/uptime-kuma/update at 2026-09-13T10:07:32Z ---
HTTP 202
{"ok":true,"data":{"accepted":true,"completed":false},"message":"Frissítés elindult – az állapot a kártyán követhető"}
10:07:32 U safety-dump
10:07:34 U pulling
10:08:01 U starting
10:08:16 U verifying
10:08:20 - done
--- AFTER 2026-09-13T10:08:20Z ---
{
"state": "running",
"updating": false,
"update_phase": "done",
"update_phase_label": "Frissítve",
"update_error": null,
"hold_reason": null,
"pinned_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.0"
},
"installed_images": {
"uptime-kuma": {
"ref": "louislam/uptime-kuma:2.4.0",
"digest": "sha256:91e963bfda569ba115206e843febb446f473ab525add4e08b2b9e3beffa16985",
"at": "2026-09-13T10:08:19Z"
}
},
"catalog_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.0"
}
}
louislam/uptime-kuma:2.4.0 Up 7 seconds (healthy)
--- the controller, verbatim (update + backup lines since 2026-09-13T10:07:32Z) ---
2026/09/13 10:07:32 router.go:567: [INFO] [api] update requested for stack: uptime-kuma
2026/09/13 10:07:32 update.go:278: [INFO] [stacks] update uptime-kuma: accepted — guarded update started
2026/09/13 10:07:32 update.go:701: [INFO] [stacks] update uptime-kuma: phase checking
2026/09/13 10:07:32 update.go:409: [INFO] [stacks] update uptime-kuma: precondition met — proven copy from 2026-09-13T10:03:07Z (4m0s old, limit 24h0m0s)
2026/09/13 10:07:32 update.go:701: [INFO] [stacks] update uptime-kuma: phase safety-dump
2026/09/13 10:07:32 update_guard.go:239: [INFO] [backup] update safety dump for uptime-kuma: the app has no database — nothing to copy (no-op)
2026/09/13 10:07:32 update.go:423: [INFO] [stacks] update uptime-kuma: safety dump done (0 file(s)) []
2026/09/13 10:07:32 update.go:701: [INFO] [stacks] update uptime-kuma: phase pinning
2026/09/13 10:07:32 pin.go:362: [INFO] [stacks] update uptime-kuma: pin advanced to the catalog's current definition (uptime-kuma=louislam/uptime-kuma:2.4.0)
2026/09/13 10:07:32 update.go:701: [INFO] [stacks] update uptime-kuma: phase pulling
2026/09/13 10:08:01 update.go:701: [INFO] [stacks] update uptime-kuma: phase starting
2026/09/13 10:08:14 update.go:701: [INFO] [stacks] update uptime-kuma: phase verifying
2026/09/13 10:08:19 update.go:499: [INFO] [stacks] update uptime-kuma: healthy after 5s (the app's health check passed)
2026/09/13 10:08:19 update.go:505: [INFO] [stacks] update uptime-kuma: DONE in 47s
--- the stacks page card (badge / hold / phase fragments) ---
1 Frissítés
1 Naprakész
1 stackAction(event, 'uptime-kuma', 'restart')
1 stackAction(event, 'uptime-kuma', 'stop')
1 stackAction(event, 'uptime-kuma', 'update')
=== Scenario A — a real upgrade 2.3.2 -> 2.4.0 with a fresh proven copy done ===
@@ -0,0 +1,6 @@
=== Scenario B setup 2026-09-13T10:09:30Z: the operator knob update.backup_max_age set to 2m on demo-hp (a REAL config setting, not a test hook), reverted at the end of this phase ===
042b71a3123d70da
update:
backup_max_age: 2m
controller: gitea.dooplex.hu/admin/felhom-controller:0.237.0 Up 16 seconds (healthy)
@@ -0,0 +1,100 @@
=== Scenario B — the proven copy is older than update.backup_max_age (2m): back up first — 2026-09-13T10:09:48Z ===
--- BEFORE ---
{
"state": "unhealthy",
"updating": false,
"update_phase": null,
"update_phase_label": null,
"update_error": null,
"hold_reason": null,
"pinned_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.0"
},
"installed_images": {
"uptime-kuma": {
"ref": "louislam/uptime-kuma:2.4.0",
"digest": "sha256:91e963bfda569ba115206e843febb446f473ab525add4e08b2b9e3beffa16985",
"at": "2026-09-13T10:08:19Z"
}
},
"catalog_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.0"
}
}
louislam/uptime-kuma:2.4.0 Up About a minute (healthy)
--- POST /api/stacks/uptime-kuma/update at 2026-09-13T10:09:49Z ---
HTTP 202
{"ok":true,"data":{"accepted":true,"completed":false},"message":"Frissítés elindult – az állapot a kártyán követhető"}
10:09:50 U backing-up
10:09:52 U pulling
10:09:54 U verifying
10:09:58 - done
--- AFTER 2026-09-13T10:09:58Z ---
{
"state": "running",
"updating": false,
"update_phase": "done",
"update_phase_label": "Frissítve",
"update_error": null,
"hold_reason": null,
"pinned_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.0"
},
"installed_images": {
"uptime-kuma": {
"ref": "louislam/uptime-kuma:2.4.0",
"digest": "sha256:91e963bfda569ba115206e843febb446f473ab525add4e08b2b9e3beffa16985",
"at": "2026-09-13T10:08:19Z"
}
},
"catalog_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.0"
}
}
louislam/uptime-kuma:2.4.0 Up 8 seconds (healthy)
--- the controller, verbatim (update + backup lines since 2026-09-13T10:09:49Z) ---
2026/09/13 10:09:49 router.go:567: [INFO] [api] update requested for stack: uptime-kuma
2026/09/13 10:09:49 update.go:278: [INFO] [stacks] update uptime-kuma: accepted — guarded update started
2026/09/13 10:09:49 update.go:701: [INFO] [stacks] update uptime-kuma: phase checking
2026/09/13 10:09:49 update.go:394: [INFO] [stacks] update uptime-kuma: the proven copy is 7m0s old (limit 2m0s) — backing up first
2026/09/13 10:09:49 update.go:701: [INFO] [stacks] update uptime-kuma: phase backing-up
2026/09/13 10:09:49 update_guard.go:143: [INFO] [backup] update pre-backup for uptime-kuma: starting (DB dump → volume dump → unit capture → Tier 2)
2026/09/13 10:09:51 update_guard.go:192: [INFO] [backup] update pre-backup for uptime-kuma: volume dump OK
2026/09/13 10:09:51 update_guard.go:198: [INFO] [backup] update pre-backup for uptime-kuma: recovery unit captured (0 database dump(s))
2026/09/13 10:09:51 tier2.go:424: [INFO] [backup] Tier 2 copied uptime-kuma → /mnt/felhom-drives/hdd_1/backups/secondary/uptime-kuma (19.9 KB, 0 leg(s), 0s)
2026/09/13 10:09:51 update_guard.go:214: [INFO] [backup] update pre-backup for uptime-kuma: complete in 1.395s
2026/09/13 10:09:51 update.go:701: [INFO] [stacks] update uptime-kuma: phase safety-dump
2026/09/13 10:09:51 update_guard.go:239: [INFO] [backup] update safety dump for uptime-kuma: the app has no database — nothing to copy (no-op)
2026/09/13 10:09:51 update.go:423: [INFO] [stacks] update uptime-kuma: safety dump done (0 file(s)) []
2026/09/13 10:09:51 update.go:701: [INFO] [stacks] update uptime-kuma: phase pinning
2026/09/13 10:09:51 pin.go:362: [INFO] [stacks] update uptime-kuma: pin advanced to the catalog's current definition (uptime-kuma=louislam/uptime-kuma:2.4.0)
2026/09/13 10:09:51 update.go:701: [INFO] [stacks] update uptime-kuma: phase pulling
2026/09/13 10:09:52 update.go:701: [INFO] [stacks] update uptime-kuma: phase starting
2026/09/13 10:09:53 update.go:701: [INFO] [stacks] update uptime-kuma: phase verifying
2026/09/13 10:09:58 update.go:499: [INFO] [stacks] update uptime-kuma: healthy after 5s (the app's health check passed)
2026/09/13 10:09:58 update.go:505: [INFO] [stacks] update uptime-kuma: DONE in 8s
--- the stacks page card (badge / hold / phase fragments) ---
1 Frissítés
1 Naprakész
1 stackAction(event, 'uptime-kuma', 'restart')
1 stackAction(event, 'uptime-kuma', 'stop')
1 stackAction(event, 'uptime-kuma', 'update')
=== Scenario B — the proven copy is older than update.backup_max_age (2m): back up first done ===
--- the copy after the backup-first leg ---
cross_drive last_success 2026-09-13T10:09:51Z status ok
/mnt/sys_drive/felhom-data/backups/primary/uptime-kuma/:
total 12
drwxr-xr-x 2 root root 4096 2026-09-13T10:09:51Z compose
-rw-r--r-- 1 root root 1048 2026-09-13T10:09:51Z manifest.json
drwxr-xr-x 2 root root 4096 2026-09-13T10:09:50Z volume-dumps
/mnt/sys_drive/felhom-data/backups/primary/uptime-kuma/volume-dumps/:
total 4
-rw-r--r-- 1 root root 3072 2026-09-13T10:09:50Z uptime-kuma_uptime_kuma_data.tar
total 4
-rw-r--r-- 1 root root 3072 2026-09-13T10:09:50Z uptime-kuma_uptime_kuma_data.tar
=== revert the knob 2026-09-13T10:10:04Z ===
042b71a3123d70da
1
controller: gitea.dooplex.hu/admin/felhom-controller:0.237.0 Up 16 seconds (healthy)
@@ -0,0 +1,11 @@
=== Scenario E setup 2026-09-13T10:11:01Z: catalog 29a8cbe names louislam/uptime-kuma:2.4.999 (does not resolve) ===
--- BEFORE ---
container: cb541381d93ef9a7a9d19f06c31e6b75d74cea70f3d11c0da8f9cd5a51cdd4fb louislam/uptime-kuma:2.4.0 started=2026-09-13T10:09:50.950051403Z
live: image: louislam/uptime-kuma:2.4.0
applied: image: louislam/uptime-kuma:2.4.0
pre-update-copies: 0
--- sync ---
HTTP 200
{"ok":true,"data":{"ok":true,"updated":["uptime-kuma"],"message":"Sablonok frissítve — frissítve: uptime-kuma"},"message":"Sablonok frissítve — frissítve: uptime-kuma"}
@@ -0,0 +1,86 @@
=== Scenario E — the pull fails (the catalog names a tag that does not exist) — 2026-09-13T10:11:03Z ===
--- BEFORE ---
{
"state": "running",
"updating": false,
"update_phase": null,
"update_phase_label": null,
"update_error": null,
"hold_reason": null,
"pinned_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.0"
},
"installed_images": {
"uptime-kuma": {
"ref": "louislam/uptime-kuma:2.4.0",
"digest": "sha256:91e963bfda569ba115206e843febb446f473ab525add4e08b2b9e3beffa16985",
"at": "2026-09-13T10:08:19Z"
}
},
"catalog_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.999"
}
}
louislam/uptime-kuma:2.4.0 Up About a minute (healthy)
--- POST /api/stacks/uptime-kuma/update at 2026-09-13T10:11:04Z ---
HTTP 202
{"ok":true,"data":{"accepted":true,"completed":false},"message":"Frissítés elindult – az állapot a kártyán követhető"}
10:11:04 U safety-dump
10:11:06 - failed
--- AFTER 2026-09-13T10:11:06Z ---
{
"state": "running",
"updating": false,
"update_phase": "failed",
"update_phase_label": "A frissítés nem sikerült",
"update_error": "Az új verzió letöltése nem sikerült, ezért a frissítés elmaradt. Az alkalmazás a korábbi verzióval fut tovább.",
"hold_reason": null,
"pinned_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.0"
},
"installed_images": {
"uptime-kuma": {
"ref": "louislam/uptime-kuma:2.4.0",
"digest": "sha256:91e963bfda569ba115206e843febb446f473ab525add4e08b2b9e3beffa16985",
"at": "2026-09-13T10:08:19Z"
}
},
"catalog_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.999"
}
}
louislam/uptime-kuma:2.4.0 Up About a minute (healthy)
--- the controller, verbatim (update + backup lines since 2026-09-13T10:11:04Z) ---
2026/09/13 10:11:04 router.go:567: [INFO] [api] update requested for stack: uptime-kuma
2026/09/13 10:11:04 update.go:278: [INFO] [stacks] update uptime-kuma: accepted — guarded update started
2026/09/13 10:11:04 update.go:701: [INFO] [stacks] update uptime-kuma: phase checking
2026/09/13 10:11:04 update.go:409: [INFO] [stacks] update uptime-kuma: precondition met — proven copy from 2026-09-13T10:09:51Z (1m0s old, limit 24h0m0s)
2026/09/13 10:11:04 update.go:701: [INFO] [stacks] update uptime-kuma: phase safety-dump
2026/09/13 10:11:04 update_guard.go:239: [INFO] [backup] update safety dump for uptime-kuma: the app has no database — nothing to copy (no-op)
2026/09/13 10:11:04 update.go:423: [INFO] [stacks] update uptime-kuma: safety dump done (0 file(s)) []
2026/09/13 10:11:04 update.go:701: [INFO] [stacks] update uptime-kuma: phase pinning
2026/09/13 10:11:04 pin.go:362: [INFO] [stacks] update uptime-kuma: pin advanced to the catalog's current definition (uptime-kuma=louislam/uptime-kuma:2.4.999)
2026/09/13 10:11:04 update.go:701: [INFO] [stacks] update uptime-kuma: phase pulling
2026/09/13 10:11:06 update.go:551: [INFO] [stacks] update uptime-kuma: pin and definition PUT BACK to the pre-update version (uptime-kuma=louislam/uptime-kuma:2.4.0)
2026/09/13 10:11:06 update.go:469: [ERROR] [stacks] update uptime-kuma: pull failed — pin and definition PUT BACK; the app was not touched. Docker said: exit code 1
2026/09/13 10:11:06 update.go:373: [ERROR] [stacks] update uptime-kuma FAILED in phase pulling after 1.411s — nothing was moved: pull failed: exit code 1
--- the stacks page card (badge / hold / phase fragments) ---
1 Frissítés
1 Frissítés gombot.">Frissítés elérhetÅ‘ â
1 stackAction(event, 'uptime-kuma', 'restart')
1 stackAction(event, 'uptime-kuma', 'stop')
1 stackAction(event, 'uptime-kuma', 'update')
=== Scenario E — the pull fails (the catalog names a tag that does not exist) done ===
--- AFTER: the app untouched, the pin and definition put back ---
container: cb541381d93ef9a7a9d19f06c31e6b75d74cea70f3d11c0da8f9cd5a51cdd4fb louislam/uptime-kuma:2.4.0 started=2026-09-13T10:09:50.950051403Z
live: image: louislam/uptime-kuma:2.4.0
applied: image: louislam/uptime-kuma:2.4.0
pre-update-copies: 0
--- the pull's own error, verbatim, from the log ---
2026/09/13 10:11:06 manager.go:1394: [ERROR] [stacks] stderr: Image louislam/uptime-kuma:2.4.999 Pulling
2026/09/13 10:11:06 update.go:551: [INFO] [stacks] update uptime-kuma: pin and definition PUT BACK to the pre-update version (uptime-kuma=louislam/uptime-kuma:2.4.0)
2026/09/13 10:11:06 update.go:469: [ERROR] [stacks] update uptime-kuma: pull failed — pin and definition PUT BACK; the app was not touched. Docker said: exit code 1
stderr: Image louislam/uptime-kuma:2.4.999 Pulling
2026/09/13 10:11:06 update.go:373: [ERROR] [stacks] update uptime-kuma FAILED in phase pulling after 1.411s — nothing was moved: pull failed: exit code 1
stderr: Image louislam/uptime-kuma:2.4.999 Pulling
@@ -0,0 +1,3 @@
=== hand-deploy 0.238.0 on felhom-pve-lan guest 9201 2026-09-13T10:12:05Z (the floor is held above the golden — R-472) ===
gitea.dooplex.hu/admin/felhom-controller:0.238.0
docker ps: gitea.dooplex.hu/admin/felhom-controller:0.238.0 Up 6 seconds (healthy)
@@ -0,0 +1,3 @@
=== hand-deploy 0.238.0 on hp guest 9201 2026-09-13T10:12:05Z (the floor is held above the golden — R-472) ===
gitea.dooplex.hu/admin/felhom-controller:0.238.0
docker ps: gitea.dooplex.hu/admin/felhom-controller:0.238.0 Up 7 seconds (healthy)
@@ -0,0 +1,9 @@
=== Scenario F setup 2026-09-13T10:12:56Z: catalog 6ce3f65 names alpine:3.20 for uptime-kuma; controller 0.238.0 ===
--- units BEFORE ---
primary-unit: image: louislam/uptime-kuma:2.4.0 manifest "created_at": "2026-09-13T10:12:09Z"
tier2-mirror: image: louislam/uptime-kuma:2.4.0 manifest "created_at": "2026-09-13T10:09:51Z"
--- sync ---
HTTP 200
{"ok":true,"data":{"ok":true,"message":"Sablonok naprakészek — nincs változás"},"message":"Sablonok naprakészek — nincs változás"}
@@ -0,0 +1,96 @@
=== Scenario F — the new version never becomes healthy (alpine:3.20 exits at once) — 2026-09-13T10:12:57Z ===
--- BEFORE ---
{
"state": "running",
"updating": false,
"update_phase": null,
"update_phase_label": null,
"update_error": null,
"hold_reason": null,
"pinned_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.0"
},
"installed_images": {
"uptime-kuma": {
"ref": "louislam/uptime-kuma:2.4.0",
"digest": "sha256:91e963bfda569ba115206e843febb446f473ab525add4e08b2b9e3beffa16985",
"at": "2026-09-13T10:08:19Z"
}
},
"catalog_images": {
"uptime-kuma": "louislam/uptime-kuma:2.4.999"
}
}
louislam/uptime-kuma:2.4.0 Up 3 minutes (healthy)
--- POST /api/stacks/uptime-kuma/update at 2026-09-13T10:12:58Z ---
HTTP 202
{"ok":true,"data":{"accepted":true,"completed":false},"message":"Frissítés elindult – az állapot a kártyán követhető"}
10:12:59 U safety-dump
10:13:01 U verifying
10:18:04 - failed
--- AFTER 2026-09-13T10:18:04Z ---
{
"state": "stopped",
"updating": false,
"update_phase": "failed",
"update_phase_label": "A frissítés nem sikerült",
"update_error": "A(z) uptime-kuma frissítése 2026-09-13 12:18-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a(z) 2026-09-13 12:09-i biztonsági mentésből a Mentések oldalon.",
"hold_reason": "A(z) uptime-kuma frissítése 2026-09-13 12:18-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a(z) 2026-09-13 12:09-i biztonsági mentésből a Mentések oldalon.",
"pinned_images": {
"uptime-kuma": "alpine:3.20"
},
"installed_images": {
"uptime-kuma": {
"ref": "louislam/uptime-kuma:2.4.0",
"digest": "sha256:91e963bfda569ba115206e843febb446f473ab525add4e08b2b9e3beffa16985",
"at": "2026-09-13T10:08:19Z"
}
},
"catalog_images": {
"uptime-kuma": "alpine:3.20"
}
}
--- the controller, verbatim (update + backup lines since 2026-09-13T10:12:58Z) ---
2026/09/13 10:12:59 router.go:567: [INFO] [api] update requested for stack: uptime-kuma
2026/09/13 10:12:59 update.go:278: [INFO] [stacks] update uptime-kuma: accepted — guarded update started
2026/09/13 10:12:59 update.go:701: [INFO] [stacks] update uptime-kuma: phase checking
2026/09/13 10:12:59 update.go:409: [INFO] [stacks] update uptime-kuma: precondition met — proven copy from 2026-09-13T10:09:51Z (3m0s old, limit 24h0m0s)
2026/09/13 10:12:59 update.go:701: [INFO] [stacks] update uptime-kuma: phase safety-dump
2026/09/13 10:12:59 update_guard.go:239: [INFO] [backup] update safety dump for uptime-kuma: the app has no database — nothing to copy (no-op)
2026/09/13 10:12:59 update.go:423: [INFO] [stacks] update uptime-kuma: safety dump done (0 file(s)) []
2026/09/13 10:12:59 update.go:701: [INFO] [stacks] update uptime-kuma: phase pinning
2026/09/13 10:12:59 pin.go:362: [INFO] [stacks] update uptime-kuma: pin advanced to the catalog's current definition (uptime-kuma=alpine:3.20)
2026/09/13 10:12:59 update.go:701: [INFO] [stacks] update uptime-kuma: phase pulling
2026/09/13 10:13:00 update.go:701: [INFO] [stacks] update uptime-kuma: phase starting
2026/09/13 10:13:01 update.go:701: [INFO] [stacks] update uptime-kuma: phase verifying
2026/09/13 10:18:02 update.go:510: [ERROR] [stacks] update uptime-kuma FAILED after the new version was started: not healthy: not healthy within 5m0s (last: state restarting) — stopping and HOLDING the app; the pin stays on the new version (its migration may have run)
2026/09/13 10:18:02 settings.go:1618: [WARN] [settings] restore hold SET for uptime-kuma — the app stays stopped until it is cleared
2026/09/13 10:18:02 update_guard.go:294: [WARN] [backup] uptime-kuma is HELD STOPPED after a failed update (restore point: 2026-09-13T10:09:51Z)
--- the stacks page card (badge / hold / phase fragments) ---
1 Frissítés gombot.">Frissítés elérhetÅ‘ â
1 data-held="true"
=== Scenario F — the new version never becomes healthy (alpine:3.20 exits at once) done ===
--- the hold record in settings.json ---
{
"uptime-kuma": {
"stack": "uptime-kuma",
"at": "2026-09-13T10:18:02Z",
"reason": "update_failed",
"copy_date": "2026-09-13T10:09:51Z"
}
}
--- units AFTER (did anything overwrite the restore point during the 5-minute verify window?) ---
primary-unit: image: alpine:3.20 manifest "created_at": "2026-09-13T10:17:09Z"
tier2-mirror: image: louislam/uptime-kuma:2.4.0 manifest "created_at": "2026-09-13T10:09:51Z"
--- containers ---
(none listed = removed by the hold's stop)
--- app_info page fragments (ASCII only; controls included) ---
2 Mentések
2 Visszaáll
1 data-held="true"
3 friss
2 href="/backups/apps"
3 leáll
--- controls: fragments that must be ABSENT on a held card ---
lifecycle buttons on the uptime-kuma card: 0
@@ -0,0 +1,4 @@
2026-09-13T10:16:27Z
primary-unit: image: louislam/uptime-kuma:2.4.0 "created_at": "2026-09-13T10:12:09Z"
tier2-mirror: image: louislam/uptime-kuma:2.4.0 "created_at": "2026-09-13T10:09:51Z"
alpine:3.20 Restarting (0) 41 seconds ago
@@ -0,0 +1,24 @@
=== Scenario H — a held app cannot be started from any path — 2026-09-13T10:18:35Z ===
--- POST /api/stacks/uptime-kuma/start ---
HTTP 409
{"ok":false,"error":"A(z) uptime-kuma frissítése 2026-09-13 12:18-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a(z) 2026-09-13 12:09-i biztonsági mentésből a Mentések oldalon."}
--- POST /api/stacks/uptime-kuma/restart ---
HTTP 409
{"ok":false,"error":"A(z) uptime-kuma frissítése 2026-09-13 12:18-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a(z) 2026-09-13 12:09-i biztonsági mentésből a Mentések oldalon."}
--- POST /api/stacks/uptime-kuma/update ---
HTTP 409
{"ok":false,"error":"A(z) uptime-kuma frissítése 2026-09-13 12:18-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a(z) 2026-09-13 12:09-i biztonsági mentésből a Mentések oldalon."}
--- container after the three presses (must still be absent) ---
(end)
--- controller restart at 2026-09-13T10:18:37Z: the boot reconciler gets its pass ---
--- the boot reconciler, the app-stop recovery and the update recovery, verbatim ---
2026/09/13 10:19:04 bootrecon.go:236: [INFO] [bootrecon] "uptime-kuma" is a boot orphan by intent but is HELD (held after a failed update (2026-09-13T10:18:02Z) — restore it from its backup to start it) — NOT starting it; whatever is holding it owns its recovery
2026/09/13 10:19:04 bootrecon.go:251: [INFO] [bootrecon] Boot reconciliation: nothing to start — 1 app(s) held (absent drive / quiesce / app-data operation): [uptime-kuma]
--- container after the controller restart + boot sweep (must still be absent) ---
(end)
--- the API after the restart ---
state stopped | hold_reason: A(z) uptime-kuma frissítése 2026-09-13 12:18-kor nem sikerült, és az alkalmazás nem indult el az új verzióval. Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek. Visszaállítható a(z) 2026-09-13 12:09-i biztonsági mentésből a Mentések oldalon.
=== Scenario H done ===
@@ -0,0 +1,37 @@
=== the restore walk — 2026-09-13T10:25:02Z ===
--- POST /backup/tier2/unit-restore (form, as the page submits it) ---
HTTP/2 302
location: /backups/apps?flash=Teljes+vissza%C3%A1ll%C3%ADt%C3%A1s+elindult+%E2%80%94+az+%C3%A1llapot+itt+friss%C3%BCl.
--- restore-status at the end ---
{
"running": false,
"op": "tier2-unit-restore",
"stack": "uptime-kuma",
"started_at": "2026-09-13T10:25:02.394608073Z",
"last": {
"op": "tier2-unit-restore",
"stack": "uptime-kuma",
"ok": true,
"message": "A(z) uptime-kuma: 1 adatkötet visszaállítva — az alkalmazás újraindult. A visszaállítás forrása a második meghajtón lévő másolat volt (2026-09-13 12:09).",
"finished_at": "2026-09-13T10:25:11.504258982Z"
},
"last_recent": true
}
--- the app after the restore ---
container: louislam/uptime-kuma:2.4.0 Up 10 seconds (healthy)
state running | pinned {'uptime-kuma': 'louislam/uptime-kuma:2.4.0'} | hold_reason None | installed {'uptime-kuma': 'louislam/uptime-kuma:2.4.0'}
--- the hold store ---
restore_holds: None
--- the controller, verbatim ---
2026/09/13 10:25:02 handlers.go:1881: [WARN] [web] Tier-2 UNIT restore requested (async, OVERWRITES live data): stack=uptime-kuma from 172.18.0.3:42310
2026/09/13 10:25:02 tier2_restore.go:197: [WARN] [backup] Tier-2 UNIT restore for uptime-kuma from the secondary mirror /mnt/felhom-drives/hdd_1/backups/secondary/uptime-kuma/recovery-unit — this OVERWRITES live app data
2026/09/13 10:25:11 restore_unit.go:391: [INFO] [backup] Restore-from-unit completed: uptime-kuma — 1 volume(s) of 1 listed, 0 database(s) of 0 listed
2026/09/13 10:25:11 update_guard.go:324: [INFO] [backup] uptime-kuma: restore completed — the update hold (set 2026-09-13T10:18:02Z) is CLEARED
2026/09/13 10:25:11 handlers.go:1891: [INFO] [web] Tier-2 unit restore completed (async): stack=uptime-kuma in 9.109539298s (volumes 1/1, dbs 0/0)
--- the card ---
1 Frissítés
1 Naprakész
1 stackAction(event, 'uptime-kuma', 'restart')
1 stackAction(event, 'uptime-kuma', 'stop')
1 stackAction(event, 'uptime-kuma', 'update')
=== restore walk done ===
@@ -0,0 +1,26 @@
=== teardown layer 1: uptime-kuma removed through the feature (R-442) 2026-09-13T10:25:53Z ===
HTTP 200
{"ok":true,"message":"Stack uptime-kuma stop completed"}
HTTP 200
{"ok":true,"data":{"removed":"uptime-kuma","volumes_removed":null,"hdd_paths_removed":[],"hdd_paths_preserved":[],"hdd_note":"Az alkalmazás nem tárolt saját adatot külső meghajtón, így ott nem volt mit törölni."},"message":"Stack uptime-kuma removed"}
--- what the removal left (R-474) ---
containers: 0
volumes:
uptime-kuma stackdir: applied-compose.yml docker-compose.yml
uptime-kuma primary: compose manifest.json volume-dumps
uptime-kuma secondary: recovery-unit
glance stackdir: applied-compose.yml docker-compose.yml
glance primary: compose manifest.json
glance secondary:
images: louislam/uptime-kuma:2.4.0 louislam/uptime-kuma:2.3.2 alpine:3.20 glanceapp/glance:v0.8.4
--- residue removed BY HAND (throwaway apps only, named paths, no prune) ---
8
after: 0 dirs
0
journal-absent
--- standing apps untouched ---
bentopdf|Up 6 hours (healthy) bookstack-db|Up 2 hours (healthy) bookstack|Up 6 hours (healthy) calibre-web|Up 6 hours (healthy) cloudflared|Up 11 days docmost-postgres|Up 6 hours (healthy) docmost-redis|Up 6 hours (healthy) docmost|Up 6 hours (healthy) filebrowser|Up 11 days (healthy) kimai-db|Up 6 hours (healthy) kimai|Up 6 hours (healthy) opengist|Up 6 hours (healthy) paperless-postgres|Up 6 hours (healthy) paperless-redis|Up 6 hours (healthy) paperless-webserver|Up 6 hours (healthy) privatebin|Up 6 hours (healthy) romm-db|Up 6 hours (healthy) romm-redis|Up 6 hours (healthy) romm|Up 6 hours (healthy) traefik|Up 11 days
@@ -0,0 +1,6 @@
=== teardown layer 3: the hub 2026-09-13T10:26:04Z ===
host: demo-felhom-8363b5
host: demo-hp-bb76ea
customer configs: 0
floor: name="min_controller_version" value="0.236.0"
(this run created no host, no customer and no appliance record; two app-deployed events from the throwaways reached the hub as ordinary events; the floor is back at the vouched golden)
@@ -0,0 +1,3 @@
=== hand-deploy 0.238.1 on felhom-pve-lan guest 9201 2026-09-13T10:26:31Z (floor held above the golden — R-472) ===
gitea.dooplex.hu/admin/felhom-controller:0.238.1
docker ps: gitea.dooplex.hu/admin/felhom-controller:0.238.1 Up 6 seconds (healthy)
@@ -0,0 +1,3 @@
=== hand-deploy 0.238.1 on hp guest 9201 2026-09-13T10:26:31Z (floor held above the golden — R-472) ===
gitea.dooplex.hu/admin/felhom-controller:0.238.1
docker ps: gitea.dooplex.hu/admin/felhom-controller:0.238.1 Up 7 seconds (healthy)
@@ -0,0 +1,11 @@
MUTATION in internal/stacks/update.go:
- healthy, detail := m.updateHealth(ctx, name, timeout)
+ healthy, detail := true, "RED-PROOF: no health wait"; _ = timeout
=== RUN TestSlice4_A_SuccessIsDeclaredOnlyAfterHealth
update_test.go:180: the health wait was never reached; state: updating=false phase=done err=""
--- FAIL: TestSlice4_A_SuccessIsDeclaredOnlyAfterHealth (5.01s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 5.017s
FAIL
exit=1
@@ -0,0 +1,15 @@
MUTATION in internal/stacks/update.go:
- rp, err := g.RestorePoint(name)
if err != nil || !rp.Restorable || !rp.Proven {
return m.refuseUpdate(
+ rp, err := g.RestorePoint(name)
if err != nil || !rp.Proven {
return m.refuseUpdate(
=== RUN TestSlice4_C_NoRestorableCopyRefusesBeforeAnythingMoves
update_test.go:295: an app with no restorable copy must be REFUSED (no_backup), got <nil>
--- FAIL: TestSlice4_C_NoRestorableCopyRefusesBeforeAnythingMoves (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.007s
FAIL
exit=1
@@ -0,0 +1,11 @@
MUTATION in internal/stacks/update.go:
- } else if err := g.HoldAfterFailedUpdate(name, m.now(), provenAt); err != nil {
+ } else if err := error(nil); err != nil {
=== RUN TestSlice4_F_HealthFailureHoldsTheAppAndKeepsTheNewPin
update_test.go:409: an app that did not come up must be HELD
--- FAIL: TestSlice4_F_HealthFailureHoldsTheAppAndKeepsTheNewPin (0.01s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.012s
FAIL
exit=1
@@ -0,0 +1,11 @@
MUTATION in internal/api/router.go:
- if action == "start" || action == "restart" || action == "update" {
+ if action == "start" || action == "restart" {
=== RUN TestR439_UpdateOfAHeldAppIsRefused
slice4_update_test.go:117: a HELD app's update must be refused with the hold's own sentence: code=409 ok=false error="A(z) app nem frissíthető, mert nincs olyan biztonsági mentése, amelyből vissza lehetne állítani. Kapcsold be a 2. mentést az alkalmazás mentési beállításainál a Mentések oldalon, és várd meg az első sikeres másolatot — utána a frissítés elindítható."
--- FAIL: TestR439_UpdateOfAHeldAppIsRefused (0.06s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/api 0.072s
FAIL
exit=1
@@ -0,0 +1,13 @@
MUTATION in internal/backup/backup.go:
- if m.isHeld(stack.Name) {
m.logger.Printf("[WARN] [backup] Skipping volume dump
+ if false && m.isHeld(stack.Name) {
m.logger.Printf("[WARN] [backup] Skipping volume dump
=== RUN TestSlice4_NightlyLegsLeaveAHeldAppAlone
slice4_update_guard_test.go:145: the nightly volume dump touched a HELD app (dumped=[held free] stopped=[])
--- FAIL: TestSlice4_NightlyLegsLeaveAHeldAppAlone (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.006s
FAIL
exit=1
@@ -0,0 +1,13 @@
MUTATION in internal/web/intermediary.go:
- if s.appHeld(name) {
continue
+ if false && s.appHeld(name) {
continue
=== RUN TestSlice4_DriveReturnGateSkipsAHeldApp
slice4_update_test.go:70: the drive-return gate tried to START a held app: runtime error: invalid memory address or nil pointer dereference
--- FAIL: TestSlice4_DriveReturnGateSkipsAHeldApp (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.009s
FAIL
exit=1
@@ -0,0 +1,16 @@
MUTATION in internal/web/templates/stacks.html:
- {{if .Updating}}
<span class="tag tag-progress"
+ {{if and .Updating (not (isOperational .State))}}
<span class="tag tag-progress"
=== RUN TestSlice4_Page_UpdatingCardShowsThePhaseAndNoLifecycleButton
slice4_page_test.go:34: an updating card must show its phase label
slice4_page_test.go:38: an updating card must offer no lifecycle button, found "stackAction(event, 'bookstack', 'update')"
slice4_page_test.go:38: an updating card must offer no lifecycle button, found "stackAction(event, 'bookstack', 'restart')"
slice4_page_test.go:38: an updating card must offer no lifecycle button, found "stackAction(event, 'bookstack', 'stop')"
--- FAIL: TestSlice4_Page_UpdatingCardShowsThePhaseAndNoLifecycleButton (0.01s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.020s
FAIL
exit=1
@@ -0,0 +1,14 @@
MUTATION in internal/web/templates/stacks.html:
- {{else if .HoldReason}}
+ {{else if and .HoldReason (not (isOperational .State))}}
=== RUN TestSlice4_Page_HeldCardShowsTheHoldAndTheWayBack
slice4_page_test.go:49: a held card must show the hold sentence and link Mentések
slice4_page_test.go:53: a held card must offer nothing that starts or updates it, found "stackAction(event, 'bookstack', 'update')"
slice4_page_test.go:53: a held card must offer nothing that starts or updates it, found "stackAction(event, 'bookstack', 'restart')"
slice4_page_test.go:53: a held card must offer nothing that starts or updates it, found "stackAction(event, 'bookstack', 'stop')"
--- FAIL: TestSlice4_Page_HeldCardShowsTheHoldAndTheWayBack (0.01s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.022s
FAIL
exit=1
@@ -0,0 +1,11 @@
MUTATION in internal/backup/update_guard.go:
- return m.updatingCheck != nil && m.updatingCheck(stackName)
+ return false
=== RUN TestSlice4_NightlyLegsLeaveAnAppMidUpdateAlone
slice4_update_guard_test.go:188: a nightly leg touched an app MID-UPDATE (dumped=[updating free] stopped=[] captured=[updating free] mirrored=[updating free])
--- FAIL: TestSlice4_NightlyLegsLeaveAnAppMidUpdateAlone (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.006s
FAIL
exit=1