Runtime fixes 2026-10-28: TABLE of the 20 apps (calibre-web loads Brotli — corrected; file manager does not, 3 boxes), lane batches 1+2 evidence; 09 decisions 277 (D61, operator) + 278 and the lane batch; R-1313/R-1322/R-1327 closed; R-1334..R-1337 opened; app rows updated

This commit is contained in:
admin committed 2026-10-28 10:40:31 +01:00
1 parent 29e9cd36a6
commit 47e1ef062b
33 files changed
+2880 -11

No files matched your search

@@ -0,0 +1,57 @@
# The 20 catalog apps with a bad runtime inside (R-1332) — where each one stands, 2026-10-28
HTTP2Shell (CVE-2026-111497): the Brotli decoder in Node.js (fixed 22.23.4 / 24.22.1 / 26.12.1; 20, 23, 25 get no fix)
and Python `brotli` (fixed 1.0.10 / 1.1.1 / 1.2.1). **Every version below was READ FROM THE IMAGE**
(`scripts/image_runtime.py`: the registry config, then the layers — never release notes); the candidates came from each
registry's tag list in the pinned tag's own shape (`rt-candidates.json`, `rt-candidates.txt`). The main version is the
first number of the tag (the ladder's rule; 0.x moves by the minor were lane steps on 2026-10-27, e.g. Homebox
0.26 → 0.27). „Runs" = what the image starts (its config) and, on a test box, `ps` in the running container
(`ps-test-boxes.txt`). The setup gate covers an app only until its first account exists; the family gate always.
**Fleet (2026-10-28):** three boxes report — demo-hp, Tester 1, demo-felhom; no household. 9202 is scratch.
## State 1 — a fixed release in the same main version: a security-fix step (8)
| App | Pinned → step | Runtime: pinned → step | Runs | Boxes | Walk |
|---|---|---|---|---|---|
| adventurelog | v0.13.0 → v0.13.1 (frontend + backend) | Node 26.3.0 → 26.12.1 | `node start.js` (SvelteKit server; `ps` on demo-hp) | demo-hp | batch 1 |
| ghost | 6.67.0-alpine → 6.73.0-alpine | Node 22.23.3 → 22.23.4 | Node (Ghost) | — | batch 1 |
| metube | 2026.09.29 → 2026.10.27 | py-Brotli 1.2.0 → 1.2.1 | Python (aiohttp) | — | batch 1 |
| papra | 26.6.2-rootless → 26.7.1-rootless | Node 26.4.0 → 26.12.1 | Node | — | batch 1 |
| zipline | 4.8.0 → 4.8.2 | Node 24.21.0 → 24.22.1 (Alpine brotli-libs 1.2.1) | Node | — | batch 1 |
| karakeep | 0.33.2 → 0.34.1 | Node 24.18.1 → 24.22.1 | Node | — | batch 2 |
| tandoor | 2.6.15 → 2.7.2 | Node 24.18.1 → 24.22.1 (Alpine nodejs 24.22.1-r0) | Python (Django) + Node in the image | — | batch 2 |
| dawarich | 1.15.3 → 1.19.0 (app + sidekiq) | Node 20.19.2 → **no Node in the image** (Debian libbrotli1 1.1.0-2+deb13u1) | Ruby (Rails) | — | batch 2 |
(Home Assistant 2026.9.4 → 2026.10.4 and Immich v3.2.4 → v3.3.5 went live this morning — catalog `b5b78f6`, `0158b50`.)
## State 2 — the fix needs a new main version: a row each, no step today (4 apps + 1 box program)
| App | Pinned → fixed in | Runtime | Runs | Gate | Boxes |
|---|---|---|---|---|---|
| homepage | v1.13.2 → v2.x (v2.7.0) | Node 22.22.3 → 24.22.1 | `node server.js` as root | family gate (always) | — |
| termix | 2.8.0 → the new numbering 26.10.x (26.10.5); 2.9.2 still Node 26.10.0 | Node 26.9.0 → 24.22.1 | Node | setup gate | — (D58: waits for its big step, R-1311) |
| wanderer | v0.20.0 → v0.21.2 | Node 22.23.1 → 22.23.4 | `npm run start` | — | none; **hidden since today (D59)** — its big step (R-1313's successor row) |
| seerr | jellyseerr 2.7.3 → upstream moved to `ghcr.io/seerr-team/seerr` (v3.5.1) | Node 22.18.0 → 22.23.4 | `pnpm start` (Node) | setup gate | — |
| filebrowser (a BOX program, not an app) | 1.5.8-stable → 2.0.2-stable | Alpine brotli-libs 1.2.0-r1 → 1.2.1-r0 | a Go binary that does NOT link libbrotli (`ldd`: musl only; no process maps it — all three boxes, `filebrowser-brotli.txt`); brotli-libs is there for libcurl | the controller's own route | all three boxes |
## State 3 — no fixed release exists (the watch keeps flagging them every night) (6)
| App | Pinned (newest) | Runtime | Runs | Gate | Boxes |
|---|---|---|---|---|---|
| actualbudget | 26.9.0 (26.10.0 still Node 24.21.0) | Node 24.20.0 | `node app.js` | setup gate | — |
| calcom | v6.2.0 (newest) | Node 20.20.0 (end of life — no fix on its line) + Debian 12 libbrotli1 1.0.9-2+b6 | Node (`start.sh`) | setup gate | — (R-1329) |
| calibre-web | v4.0.8 (newest) | py-Brotli 1.2.0 (+ Pillow's libbrotlidec 1.2.0, Debian libbrotlidec 1.1.0) | Python `cps.py` **loads all three** (its `/proc/<pid>/maps`, read from the guest — `calibre-web-brotli.txt`; a morning line here said „not loaded" from the process list: wrong, corrected the same day). The Python decoder is urllib3's, for replies to the app's own outbound calls (book metadata) | — | demo-hp |
| paperless-ngx | 2.20.15 (3.3.4 still py-Brotli 1.2.0, and a new main) | py-Brotli 1.1.0 | Python; decodes only replies to its own outbound calls (R-1331, decided) | — | demo-hp, Tester 1 |
| romm | 5.4.1 (newest) | Node 24.18.1 | **no Node process** (gunicorn, rq, nginx — `ps` on demo-hp) | setup gate | demo-hp (D61 = keep offered, R-1330) |
| sparkyfitness | v0.17.3 (v1.9.0 still Node 24.22.0, and a new main) | Node 24.18.0 | `tsx index.ts` (Node) | setup gate | — |
(SparkyFitness has two images; its web image is nginx and carries no Node.)
## Exposure, in plain words
A bad decoder is dangerous when the app unpacks Brotli data that an attacker chose: a request body sent with
`Content-Encoding: br`, or the reply of a server the attacker controls. In every app here the household's login (or the
family gate) stands in front of the app's own pages after setup; a Node server that unpacks request bodies, or that
fetches outside pages for its users (bookmarks, recipes, link previews — Karakeep, Tandoor, Adventurelog), is the
likelier path. No app here has a notice of its own: the watch is the only thing that sees them.
@@ -0,0 +1,48 @@
# 2026-10-28 09:37Z — calibre-web (demo-hp 9201): does any process load Brotli? (R-1332)
== crocodilestick/calibre-web-automated:v4.0.8@sha256:5e00373854247750cc3e4479b492ae09293ff5e06ed10177f226634d97888679 running
--- python brotli in the image:
/lsiopy/bin/python3: 1.2.0 /lsiopy/lib/python3.13/site-packages/brotli.py
/lsiopy/bin/python3: 1.2.0 /lsiopy/lib/python3.13/site-packages/brotli.py
--- processes (pid comm args) and whether their maps name brotli:
1 s6-svscan brotli-maps=0 :: /package/admin/s6/command/s6-svscan -d4 -- /run/service
10315 sleep brotli-maps= :: sleep 600
10520 sleep brotli-maps= :: sleep 5
10527 sh brotli-maps=0 :: sh -s
1322 python3 brotli-maps= :: python3 /app/calibre-web-automated/cps.py
1420 bash brotli-maps= :: bash ./run cwa-ingest-service
1422 bash brotli-maps=0 :: bash ./run metadata-change-detector
1440 bash brotli-maps=0 :: bash ./run metadata-change-detector
1456 bash brotli-maps=0 :: bash ./run metadata-change-detector
1457 inotifywait brotli-maps= :: inotifywait -m -e close_write -e moved_to --exclude ^.*\.(swp)$ /app/calibre-web-automated/metadata_change_logs
1458 bash brotli-maps=0 :: bash ./run metadata-change-detector
1465 bash brotli-maps= :: bash ./run cwa-ingest-service
1467 bash brotli-maps= :: bash ./run cwa-ingest-service
1481 bash brotli-maps= :: bash ./run cwa-ingest-service
1482 bash brotli-maps= :: bash ./run cwa-ingest-service
1484 bash brotli-maps= :: bash ./run cwa-ingest-service
1485 bash brotli-maps= :: bash ./run cwa-ingest-service
1486 inotifywait brotli-maps= :: inotifywait -m -r --format=%e %w%f -e close_write -e moved_to /cwa-book-ingest
17 s6-supervise brotli-maps=0 :: s6-supervise s6-linux-init-shutdownd
19 s6-linux-init-s brotli-maps=0 :: /package/admin/s6-linux-init/command/s6-linux-init-shutdownd -d3 -c /run/s6/basedir -g 3000 -C -B
221 bash brotli-maps=0 :: bash ./run cwa-auto-zipper
283 sleep brotli-maps=0 :: sleep 69059
290 bash brotli-maps=0 :: bash ./run svc-cron
306 sleep brotli-maps=0 :: sleep infinity
34 s6-supervise brotli-maps=0 :: s6-supervise svc-cron
35 s6-supervise brotli-maps=0 :: s6-supervise cwa-auto-zipper
36 s6-supervise brotli-maps=0 :: s6-supervise s6rc-fdholder
37 s6-supervise brotli-maps=0 :: s6-supervise svc-calibre-web-automated
38 s6-supervise brotli-maps=0 :: s6-supervise s6rc-oneshot-runner
39 s6-supervise brotli-maps=0 :: s6-supervise cwa-ingest-service
40 s6-supervise brotli-maps=0 :: s6-supervise metadata-change-detector
48 s6-ipcserverd brotli-maps=0 :: /package/admin/s6/command/s6-ipcserverd -1 -- /package/admin/s6/command/s6-ipcserver-access -v0 -E -l0 -i data/rules --
== CORRECTION, 09:37Z: inside the container the app process's maps were NOT readable (brotli-maps= empty above, pid 1322 = cps.py), so the in-container check proves nothing for it. Read from the guest (pct exec 9201, /proc/<host pid>/maps):
433919 1000 python3 /app/calibre-web-automated/cps.py
pid 433919 maps lines: 871
/lsiopy/lib/python3.13/site-packages/_brotli.cpython-313-x86_64-linux-gnu.so
/lsiopy/lib/python3.13/site-packages/pillow.libs/libbrotlicommon-53534446.so.1.2.0
/lsiopy/lib/python3.13/site-packages/pillow.libs/libbrotlidec-7e5462ba.so.1.2.0
/usr/lib/x86_64-linux-gnu/libbrotlicommon.so.1.1.0
/usr/lib/x86_64-linux-gnu/libbrotlidec.so.1.1.0
Verdict: cps.py LOADS Python Brotli 1.2.0 (_brotli), Pillow's libbrotlidec 1.2.0 and Debian's libbrotlidec 1.1.0. The 2026-10-28 morning TABLE line „Brotli is NOT loaded" was wrong (it came from the process list, not the maps).
@@ -0,0 +1,12 @@
actualbudget/actual-server:26.9.0 EP=["/usr/bin/tini", "-g", "--"] CMD=["node", "app.js"] USER=None
calcom/cal.com:v6.2.0 EP=["docker-entrypoint.sh"] CMD=["/calcom/scripts/start.sh"] USER=None
crocodilestick/calibre-web-automated:v4.0.8 EP=["/init"] CMD=null USER=None
ghcr.io/paperless-ngx/paperless-ngx:2.20.15 EP=["/init"] CMD=null USER=None
rommapp/romm:5.4.1 EP=["/docker-entrypoint.sh"] CMD=["/init"] USER=None
fallenbagel/jellyseerr:2.7.3 EP=["/sbin/tini", "--"] CMD=["pnpm", "start"] USER=None
codewithcj/sparkyfitness_server:v0.17.3 EP=["docker-entrypoint.sh"] CMD=["./node_modules/.bin/tsx", "index.ts"] USER=None
codewithcj/sparkyfitness:v0.17.3 EP=["/docker-entrypoint.sh"] CMD=["/docker-entrypoint.sh"] USER=None
ghcr.io/lukegus/termix:2.8.0 EP=["docker-entrypoint.sh"] CMD=["/entrypoint.sh"] USER=None
ghcr.io/gethomepage/homepage:v1.13.2 EP=["docker-entrypoint.sh"] CMD=["node", "server.js"] USER=root
flomp/wanderer-web:v0.20.0 EP=["docker-entrypoint.sh"] CMD=["npm", "run", "start"] USER=None
gtstef/filebrowser:1.5.8-stable EP=["./filebrowser"] CMD=null USER=filebrowser
@@ -0,0 +1,40 @@
# 2026-10-28 09:36Z — the file manager: does any process load libbrotli? (R-1332; script: the loop below, run with docker exec -i filebrowser sh)
== demo-hp (guest 9201): gtstef/filebrowser:1.5.8-stable running
alpine 3.24.2
brotli-libs-1.2.0-r1
--- ldd /home/filebrowser/filebrowser
/lib/ld-musl-x86_64.so.1 (0x7c7210331000)
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7c7210331000)
--- processes (pid comm) and whether their maps name brotli:
1 filebrowser brotli-maps=0
12902 sh brotli-maps=0
--- installed packages that depend on brotli-libs:
brotli-libs-1.2.0-r1 is required by:
libcurl-8.22.0-r0
== tester-1 (guest 9201): gtstef/filebrowser:1.5.8-stable running
alpine 3.24.2
brotli-libs-1.2.0-r1
--- ldd /home/filebrowser/filebrowser
/lib/ld-musl-x86_64.so.1 (0x739c65453000)
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x739c65453000)
--- processes (pid comm) and whether their maps name brotli:
1 filebrowser brotli-maps=0
12925 sh brotli-maps=0
--- installed packages that depend on brotli-libs:
brotli-libs-1.2.0-r1 is required by:
libcurl-8.22.0-r0
== demo-felhom (guest 9201): gtstef/filebrowser:1.5.8-stable running
alpine 3.24.2
brotli-libs-1.2.0-r1
--- ldd /home/filebrowser/filebrowser
/lib/ld-musl-x86_64.so.1 (0x74a46350c000)
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x74a46350c000)
--- processes (pid comm) and whether their maps name brotli:
1 filebrowser brotli-maps=0
12880 sh brotli-maps=0
--- installed packages that depend on brotli-libs:
brotli-libs-1.2.0-r1 is required by:
libcurl-8.22.0-r0
@@ -0,0 +1,79 @@
== demohp (docker ps: project image)
adventurelog ghcr.io/seanmorley15/adventurelog-backend:v0.13.0
adventurelog ghcr.io/seanmorley15/adventurelog-frontend:v0.13.0
adventurelog postgis/postgis:16-3.5-alpine
bentopdf ghcr.io/alam00000/bentopdf:v2.8.10
bookstack lscr.io/linuxserver/bookstack:26.09.2
bookstack mariadb:12.3
calibre-web crocodilestick/calibre-web-automated:v4.0.8
cloudflared cloudflare/cloudflared:2026.10.4
docmost docmost/docmost:0.97.0
docmost postgres:18-alpine
docmost redis:7-alpine
filebrowser gtstef/filebrowser:1.5.8-stable
gitea.dooplex.hu/admin/felhom-controller:0.346.1
home-assistant ghcr.io/home-assistant/home-assistant:2026.9.4
kimai kimai/kimai2:2.67.0
kimai mariadb:11.8
opengist ghcr.io/thomiceli/opengist:1.15
paperless-ngx ghcr.io/paperless-ngx/paperless-ngx:2.20.15
paperless-ngx postgres:18-alpine
paperless-ngx redis:7-alpine
plex plexinc/pms-docker:1.43.5.11029-6bf8af3f0
privatebin privatebin/pdo:2.1.0
romm mariadb:11.8
romm redis:7-alpine
romm rommapp/romm:5.4.1
traefik traefik:v3.7.16
== tester1 (docker ps: project image)
bookstack lscr.io/linuxserver/bookstack:26.09.2
bookstack mariadb:12.3
cloudflared cloudflare/cloudflared:2026.10.4
filebrowser gtstef/filebrowser:1.5.8-stable
gitea.dooplex.hu/admin/felhom-controller:0.346.1
paperless-ngx ghcr.io/paperless-ngx/paperless-ngx:2.20.15
paperless-ngx postgres:18-alpine
paperless-ngx redis:7-alpine
privatebin privatebin/pdo:2.1.0
traefik traefik:v3.7.16
== n100 (docker ps: project image)
VMID Status Lock Name
9201 running demo-felhom
guest 9201
cloudflared cloudflare/cloudflared:2026.10.4
filebrowser gtstef/filebrowser:1.5.8-stable
gitea.dooplex.hu/admin/felhom-controller:0.346.1
opengist ghcr.io/thomiceli/opengist:1.15
prowlarr lscr.io/linuxserver/prowlarr:version-2.6.5.5623
qbittorrent qbittorrentofficial/qbittorrent-nox:5.2.4-1
radarr lscr.io/linuxserver/radarr:6.4.4
sonarr lscr.io/linuxserver/sonarr:4.0.20
traefik traefik:v3.7.16
== processes in the flagged containers, demo-hp 9201
== adventurelog-frontend (ghcr.io/seanmorley15/adventurelog-frontend:v0.13.0@sha256:51ee22428b4192f4372b54f84c8b90cd710311ad99993c5045f53b51717dd3f7) entrypoint=["/usr/bin/node"] ["start.js"]
1 node-MainThread /usr/bin/node start.js
== calibre-web (crocodilestick/calibre-web-automated:v4.0.8@sha256:5e00373854247750cc3e4479b492ae09293ff5e06ed10177f226634d97888679) entrypoint=["/init"] null
7 bash bash ./run cwa-ingest-service
4 bash bash ./run metadata-change-detector
1 sleep sleep infinity
1 sleep sleep 69059
1 sleep sleep 600
1 sleep sleep 5
1 s6-svscan /package/admin/s6/command/s6-svscan -d4 -- /run/service
1 s6-supervise s6-supervise svc-cron
1 s6-supervise s6-supervise svc-calibre-web-automated
1 s6-supervise s6-supervise s6rc-oneshot-runner
1 s6-supervise s6-supervise s6rc-fdholder
1 s6-supervise s6-supervise s6-linux-init-shutdownd
== romm (rommapp/romm:5.4.1@sha256:8677fb7b81b1d3db20b849e989a1dadc2a11159e51eb34a2acdcb01102274edf) entrypoint=["/bin/sh","-c"] ["if [ ! -f /romm/config/config.yml ]; then\n echo \"Creating default config.yml...\"\n cat > /romm/config/config.yml << 'CONF'\nexclude:\n platforms: []\n roms: []\nsystem:\n log_level: INFO\nCONF\nfi\nexec /docker-entrypoint.sh /init\n"]
7 nginx nginx: worker process
4 rq /src/.venv/bin/python /src/.venv/bin/rq worker --path /backend --worker-class handler.rq_worker.RomMWorker --connection-class handler.redis_handler.RomMRedi
3 gunicorn /src/.venv/bin/python /src/.venv/bin/gunicorn --bind=0.0.0.0:5000 --pid=/tmp/gunicorn.pid --no-control-socket --forwarded-allow-ips=127.0.0.1,::1,10.0
2 rq /src/.venv/bin/python /src/.venv/bin/rq worker --path /backend --worker-class handler.rq_worker.PreloadingWorker --connection-class handler.redis_handler.Ro
1 sleep sleep 5
1 rq /src/.venv/bin/python /src/.venv/bin/rq cron --path /backend --connection-class handler.redis_handler.RomMRedis --logging-level INFO tasks.cron_config
1 nginx nginx: master process nginx -g user romm;
1 bash bash /init
== filebrowser (gtstef/filebrowser:1.5.8-stable) entrypoint=["sh","-c","umask 002; exec /home/filebrowser/filebrowser"] null
1 filebrowser /home/filebrowser/filebrowser
@@ -0,0 +1,514 @@
{
"actualbudget": {
"ref": "actualbudget/actual-server:26.9.0",
"newer": [
"26.10.0"
],
"newest_same_main": "26.10.0",
"newest": "26.10.0",
"reads": {
"26.9.0": {
"node": "24.20.0",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {},
"unchecked": [],
"env": {
"NODE_VERSION": "24.20.0"
}
},
"26.10.0": {
"node": "24.21.0",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {},
"unchecked": [],
"env": {
"NODE_VERSION": "24.21.0"
}
}
}
},
"adventurelog": {
"ref": "ghcr.io/seanmorley15/adventurelog-frontend:v0.13.0",
"newer": [
"v0.13.1"
],
"newest_same_main": "v0.13.1",
"newest": "v0.13.1",
"reads": {
"v0.13.0": {
"node": "26.3.0",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {},
"unchecked": [],
"env": {}
},
"v0.13.1": {
"node": "26.12.1",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {},
"unchecked": [],
"env": {}
}
}
},
"calcom": {
"ref": "calcom/cal.com:v6.2.0",
"newer": [],
"newest_same_main": null,
"newest": null,
"reads": {
"v6.2.0": {
"node": "20.20.0",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {
"libbrotli1": "1.0.9-2+b6",
"python3": "3.11.2-1+b1",
"python3.11": "3.11.2-6+deb12u6"
},
"unchecked": [],
"env": {
"NODE_VERSION": "20.20.0"
}
}
}
},
"calibre-web": {
"ref": "crocodilestick/calibre-web-automated:v4.0.8",
"newer": [],
"newest_same_main": null,
"newest": null,
"reads": {
"v4.0.8": {
"node": null,
"brotli": "1.2.0",
"brotlicffi": null,
"apk": {},
"dpkg": {
"libbrotli1": "1.1.0-2build2",
"python3": "3.12.3-0ubuntu2.1",
"python3.13": "3.13.15-1+noble1"
},
"unchecked": [],
"env": {}
}
}
},
"homepage": {
"ref": "ghcr.io/gethomepage/homepage:v1.13.2",
"newer": [
"v2.0.0",
"v2.1.0",
"v2.1.1",
"v2.1.2",
"v2.2.0",
"v2.3.0",
"v2.4.0",
"v2.5.0",
"v2.6.0",
"v2.7.0"
],
"newest_same_main": null,
"newest": "v2.7.0",
"reads": {
"v2.7.0": {
"node": "24.22.1",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {},
"unchecked": [],
"env": {
"NODE_VERSION": "24.22.1"
}
}
}
},
"ghost": {
"ref": "ghost:6.67.0-alpine",
"newer": [
"6.68.0-alpine",
"6.69.0-alpine",
"6.70.0-alpine",
"6.71.0-alpine",
"6.72.0-alpine",
"6.73.0-alpine"
],
"newest_same_main": "6.73.0-alpine",
"newest": "6.73.0-alpine",
"reads": {
"6.73.0-alpine": {
"node": "22.23.4",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {},
"unchecked": [],
"env": {
"NODE_VERSION": "22.23.4"
}
}
}
},
"metube": {
"ref": "ghcr.io/alexta69/metube:2026.09.29",
"newer": [
"2026.10.09",
"2026.10.19",
"2026.10.20",
"2026.10.22",
"2026.10.23",
"2026.10.25",
"2026.10.27"
],
"newest_same_main": "2026.10.27",
"newest": "2026.10.27",
"reads": {
"2026.10.27": {
"node": null,
"brotli": "1.2.1",
"brotlicffi": null,
"apk": {},
"dpkg": {
"libbrotli1": "1.1.0-2+deb13u1"
},
"unchecked": [],
"env": {
"PYTHON_VERSION": "3.14.10"
}
}
}
},
"romm": {
"ref": "rommapp/romm:5.4.1",
"newer": [],
"newest_same_main": null,
"newest": null,
"reads": {}
},
"seerr": {
"ref": "fallenbagel/jellyseerr:2.7.3",
"newer": [],
"newest_same_main": null,
"newest": null,
"reads": {}
},
"sparkyfitness": {
"ref": "codewithcj/sparkyfitness_server:v0.17.3",
"newer": [
"v1.6.0",
"v1.6.1",
"v1.6.2",
"v1.6.3",
"v1.6.4",
"v1.6.5",
"v1.7.0",
"v1.7.1",
"v1.7.2",
"v1.7.3",
"v1.8.0",
"v1.9.0"
],
"newest_same_main": null,
"newest": "v1.9.0",
"reads": {
"v1.9.0": {
"node": "24.22.0",
"brotli": null,
"brotlicffi": null,
"apk": {
"brotli-libs": "1.2.0-r1"
},
"dpkg": {},
"unchecked": [],
"env": {
"NODE_VERSION": "24.22.0"
}
}
}
},
"dawarich": {
"ref": "freikin/dawarich:1.15.3",
"newer": [
"1.16.0",
"1.17.0",
"1.18.0",
"1.18.1",
"1.19.0"
],
"newest_same_main": "1.19.0",
"newest": "1.19.0",
"reads": {
"1.19.0": {
"node": null,
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {
"libbrotli1": "1.1.0-2+deb13u1"
},
"unchecked": [],
"env": {}
}
}
},
"karakeep": {
"ref": "ghcr.io/karakeep-app/karakeep:0.33.2",
"newer": [
"0.34.0",
"0.34.1"
],
"newest_same_main": "0.34.1",
"newest": "0.34.1",
"reads": {
"0.34.1": {
"node": "24.22.1",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {
"libbrotli1": "1.0.9-2+b6"
},
"unchecked": [],
"env": {
"NODE_VERSION": "24.22.1"
}
}
}
},
"papra": {
"ref": "ghcr.io/papra-hq/papra:26.6.2-rootless",
"newer": [
"26.7.0-rootless",
"26.7.1-rootless"
],
"newest_same_main": "26.7.1-rootless",
"newest": "26.7.1-rootless",
"reads": {
"26.7.1-rootless": {
"node": "26.12.1",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {},
"unchecked": [],
"env": {
"NODE_VERSION": "26.12.1"
}
}
}
},
"sparkyfitness-web": {
"ref": "codewithcj/sparkyfitness:v0.17.3",
"newer": [
"v1.6.0",
"v1.6.1",
"v1.6.2",
"v1.6.3",
"v1.6.4",
"v1.6.5",
"v1.7.0",
"v1.7.1",
"v1.7.2",
"v1.7.3",
"v1.8.0",
"v1.9.0"
],
"newest_same_main": null,
"newest": "v1.9.0",
"reads": {
"v1.9.0": {
"node": null,
"brotli": null,
"brotlicffi": null,
"apk": {
"brotli-libs": "1.1.0-r2"
},
"dpkg": {},
"unchecked": [],
"env": {}
}
}
},
"wanderer": {
"ref": "flomp/wanderer-web:v0.20.0",
"newer": [
"v0.21.0",
"v0.21.1",
"v0.21.2"
],
"newest_same_main": "v0.21.2",
"newest": "v0.21.2",
"reads": {
"v0.21.2": {
"node": "22.23.4",
"brotli": null,
"brotlicffi": null,
"apk": {
"brotli-libs": "1.2.1-r0"
},
"dpkg": {},
"unchecked": [],
"env": {
"NODE_VERSION": "22.23.4"
}
}
}
},
"paperless-ngx": {
"ref": "ghcr.io/paperless-ngx/paperless-ngx:2.20.15",
"newer": [
"3.0.5",
"3.1.0",
"3.1.1",
"3.1.2",
"3.1.3",
"3.2.0",
"3.2.1",
"3.3.0",
"3.3.1",
"3.3.2",
"3.3.3",
"3.3.4"
],
"newest_same_main": null,
"newest": "3.3.4",
"reads": {
"3.3.4": {
"node": null,
"brotli": "1.2.0",
"brotlicffi": null,
"apk": {},
"dpkg": {
"libbrotli1": "1.1.0-2+b7"
},
"unchecked": [],
"env": {
"PYTHON_VERSION": "3.14.9"
}
}
}
},
"tandoor": {
"ref": "ghcr.io/tandoorrecipes/recipes:2.6.15",
"newer": [
"2.7.0",
"2.7.1",
"2.7.2"
],
"newest_same_main": "2.7.2",
"newest": "2.7.2",
"reads": {
"2.7.2": {
"node": "24.22.1",
"brotli": null,
"brotlicffi": null,
"apk": {
"brotli-libs": "1.2.1-r0",
"nodejs": "24.22.1-r0"
},
"dpkg": {},
"unchecked": [],
"env": {
"PYTHON_VERSION": "3.14.10"
}
}
}
},
"filebrowser": {
"ref": "gtstef/filebrowser:1.5.8-stable",
"newer": [
"2.0.0-stable",
"2.0.1-stable",
"2.0.2-stable"
],
"newest_same_main": null,
"newest": "2.0.2-stable",
"reads": {
"2.0.2-stable": {
"node": null,
"brotli": null,
"brotlicffi": null,
"apk": {
"brotli-libs": "1.2.1-r0"
},
"dpkg": {},
"unchecked": [],
"env": {}
}
}
},
"zipline": {
"ref": "ghcr.io/diced/zipline:4.8.0",
"newer": [
"4.8.1",
"4.8.2"
],
"newest_same_main": "4.8.2",
"newest": "4.8.2",
"reads": {
"4.8.2": {
"node": "24.22.1",
"brotli": null,
"brotlicffi": null,
"apk": {
"brotli-libs": "1.2.1-r0"
},
"dpkg": {},
"unchecked": [],
"env": {
"NODE_VERSION": "24.22.1"
}
}
}
},
"termix": {
"ref": "ghcr.io/lukegus/termix:2.8.0",
"newer": [
"2.9.0",
"2.9.1",
"2.9.2",
"26.10.0",
"26.10.1",
"26.10.2",
"26.10.3",
"26.10.4",
"26.10.5"
],
"newest_same_main": "2.9.2",
"newest": "26.10.5",
"reads": {
"2.9.2": {
"node": "26.10.0",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {},
"unchecked": [],
"env": {
"NODE_VERSION": "26.10.0"
}
},
"26.10.5": {
"node": "24.22.1",
"brotli": null,
"brotlicffi": null,
"apk": {},
"dpkg": {},
"unchecked": [],
"env": {
"NODE_VERSION": "24.22.1"
}
}
}
}
}
@@ -0,0 +1,21 @@
actualbudget 26.9.0 node=24.20.0 brotli=None cffi=None apk={} dpkg={}
actualbudget 26.10.0 node=24.21.0 brotli=None cffi=None apk={} dpkg={}
adventurelog v0.13.0 node=26.3.0 brotli=None cffi=None apk={} dpkg={}
adventurelog v0.13.1 node=26.12.1 brotli=None cffi=None apk={} dpkg={}
calcom v6.2.0 node=20.20.0 brotli=None cffi=None apk={} dpkg={'libbrotli1': '1.0.9-2+b6', 'python3': '3.11.2-1+b1', 'python3.11': '3.11.2-6+deb12u6'}
calibre-web v4.0.8 node=None brotli=1.2.0 cffi=None apk={} dpkg={'libbrotli1': '1.1.0-2build2', 'python3': '3.12.3-0ubuntu2.1', 'python3.13': '3.13.15-1+noble1'}
homepage v2.7.0 node=24.22.1 brotli=None cffi=None apk={} dpkg={}
ghost 6.73.0-alpine node=22.23.4 brotli=None cffi=None apk={} dpkg={}
metube 2026.10.27 node=None brotli=1.2.1 cffi=None apk={} dpkg={'libbrotli1': '1.1.0-2+deb13u1'}
sparkyfitness v1.9.0 node=24.22.0 brotli=None cffi=None apk={'brotli-libs': '1.2.0-r1'} dpkg={}
dawarich 1.19.0 node=None brotli=None cffi=None apk={} dpkg={'libbrotli1': '1.1.0-2+deb13u1'}
karakeep 0.34.1 node=24.22.1 brotli=None cffi=None apk={} dpkg={'libbrotli1': '1.0.9-2+b6'}
papra 26.7.1-rootless node=26.12.1 brotli=None cffi=None apk={} dpkg={}
sparkyfitness-web v1.9.0 node=None brotli=None cffi=None apk={'brotli-libs': '1.1.0-r2'} dpkg={}
wanderer v0.21.2 node=22.23.4 brotli=None cffi=None apk={'brotli-libs': '1.2.1-r0'} dpkg={}
paperless-ngx 3.3.4 node=None brotli=1.2.0 cffi=None apk={} dpkg={'libbrotli1': '1.1.0-2+b7'}
tandoor 2.7.2 node=24.22.1 brotli=None cffi=None apk={'brotli-libs': '1.2.1-r0', 'nodejs': '24.22.1-r0'} dpkg={}
filebrowser 2.0.2-stable node=None brotli=None cffi=None apk={'brotli-libs': '1.2.1-r0'} dpkg={}
zipline 4.8.2 node=24.22.1 brotli=None cffi=None apk={'brotli-libs': '1.2.1-r0'} dpkg={}
termix 2.9.2 node=26.10.0 brotli=None cffi=None apk={} dpkg={}
termix 26.10.5 node=24.22.1 brotli=None cffi=None apk={} dpkg={}
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
"""rt_candidates.py OUT.json APP=IMAGE:TAG ... — for each pin with a bad runtime: the registry's tags in the same
shape as the pinned tag, the newest in the same main version and the newest overall, and the RUNTIME read from each of
those images (image_runtime.read_image — the image, never release notes), judged with the watch's own table."""
import json, os, re, sys, urllib.request, urllib.error
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/felhom.eu/scripts")
import image_runtime as ir # noqa: E402
import security_watch as sw # noqa: E402
def tags(ref):
reg, path, _ = ir.split_ref(ref)
r = ir.Registry(reg, path)
url, out = "%s/v2/%s/tags/list?n=1000" % (r.base, path), []
while url:
req = urllib.request.Request(url, headers=dict({"User-Agent": ir.UA}, **r.auth))
resp = urllib.request.urlopen(req, timeout=60)
out += json.loads(resp.read()).get("tags") or []
link = resp.headers.get("Link", "")
m = re.search(r"<([^>]+)>;\s*rel=\"next\"", link)
url = (m.group(1) if m.group(1).startswith("http") else r.base + m.group(1)) if m else None
return out
def shape(tag):
return re.compile("^" + re.sub(r"\d+", r"(\\d+)", re.escape(tag)) + "$")
def nums(tag, rx):
m = rx.match(tag)
return tuple(int(x) for x in m.groups()) if m else None
def verdict(res):
if res.get("unchecked"):
return "NOT CHECKED: " + "; ".join(res["unchecked"])[:120]
adv = sw.runtime_advisories(res) if hasattr(sw, "runtime_advisories") else None
return adv
def main():
import concurrent.futures, threading
out, lock = {}, threading.Lock()
if os.path.isfile(sys.argv[1]):
out = json.load(open(sys.argv[1]))
todo = [a for a in sys.argv[2:] if a.split("=", 1)[0] not in out or "error" in out[a.split("=", 1)[0]]]
def one(arg):
rec = do(arg)
with lock:
out[arg.split("=", 1)[0]] = rec
json.dump(out, open(sys.argv[1], "w"), indent=1)
with concurrent.futures.ThreadPoolExecutor(5) as ex:
list(ex.map(one, todo))
return 0
def do(arg):
if True:
app, ref = arg.split("=", 1)
img, tag = ref.rsplit(":", 1)
rx = shape(tag)
cur = nums(tag, rx)
try:
ts = [t for t in tags(ref) if nums(t, rx)]
except Exception as e: # noqa: BLE001
print(app, "TAGS ERROR", e, flush=True)
return {"ref": ref, "error": "tags: %s" % e}
newer = sorted((t for t in ts if nums(t, rx) > cur), key=lambda t: nums(t, rx))
same = [t for t in newer if nums(t, rx)[0] == cur[0]]
pick = []
if same:
pick.append(same[-1])
if newer and newer[-1] not in pick:
pick.append(newer[-1])
rec = {"ref": ref, "newer": newer[-12:], "newest_same_main": same[-1] if same else None,
"newest": newer[-1] if newer else None, "reads": {}}
for t in pick: # the pinned tag's runtime is known (the watch's cache, R-1332)
res = ir.read_image("%s:%s" % (img, t))
rec["reads"][t] = {k: res.get(k) for k in ("node", "brotli", "brotlicffi", "apk", "dpkg", "unchecked", "env")}
print(app, t, "node=%s brotli=%s cffi=%s apk=%s dpkg=%s %s" % (
res.get("node"), res.get("brotli"), res.get("brotlicffi"), res.get("apk"), res.get("dpkg"),
("UNCHECKED " + "; ".join(res["unchecked"])[:100]) if res.get("unchecked") else ""), flush=True)
return rec
if __name__ == "__main__":
sys.exit(main())
@@ -0,0 +1,177 @@
{
"app": "privatebin",
"walk": "security",
"box_walk_version": 1,
"verdict": "failed",
"venue": "box 9202 (drill catalog), the guarded Update",
"from": {
"privatebin": "privatebin/pdo:2.1.0"
},
"to": {
"privatebin": "busybox:1.36.1"
},
"observables_before": {
"pinned_images": {
"privatebin": "privatebin/pdo:2.1.0"
},
"installed_images": {
"privatebin": "privatebin/pdo:2.1.0"
},
"catalog_images": null,
"live_compose_image_lines": [
"image: privatebin/pdo:2.1.0@sha256:3400b0a4714d62161727a710c82a3e319cfea364ac6e591aed653f5bb6bb8055"
],
"docker_inspect": [
"privatebin privatebin/pdo:2.1.0@sha256:3400b0a4714d62161727a710c82a3e319cfea364ac6e591aed653f5bb6bb8055 running=true restarts=0"
]
},
"setup_gate_before": {
"browser": {
"status": "200",
"redirect": null
},
"script": {
"status": "200",
"redirect": null
}
},
"seed": "read_back",
"drill_commit": "f8b4b5d966c0",
"sync_waited_s": 4.5,
"badge_before": {
"hu": [
{
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
"text": "Frissítés elérhető — ma"
}
],
"en": [
{
"title": "A newer version of this app is available. Select the Update button to start it.",
"text": "Update available — today"
}
]
},
"measured_at": "2026-10-28T07:12:54Z",
"update": {
"accepted": true,
"http": "202",
"phases": [
{
"t": 0.0,
"phase": "backing-up",
"label": "Biztonsági mentés készül a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 2.1,
"phase": "safety-dump",
"label": "Adatbázis pillanatkép…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 3.1,
"phase": "pulling",
"label": "Új verzió letöltése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 4.1,
"phase": "copying",
"label": "Az adatok másolása a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 5.1,
"phase": "verifying",
"label": "Működés ellenőrzése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 308.2,
"phase": "undoing",
"label": "Visszaállítás az előző változatra…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 314.3,
"phase": "undone",
"label": "Visszaállítva az előző változatra",
"updating": false,
"error": null,
"hold": null
}
],
"duration_s": 314.3,
"final_phase": "undone",
"update_error": null,
"hold_reason": null,
"state": "running"
},
"observables_after": {
"pinned_images": {
"privatebin": "privatebin/pdo:2.1.0"
},
"installed_images": {
"privatebin": "privatebin/pdo:2.1.0"
},
"catalog_images": {
"privatebin": "busybox:1.36.1"
},
"live_compose_image_lines": [
"image: privatebin/pdo:2.1.0@sha256:3400b0a4714d62161727a710c82a3e319cfea364ac6e591aed653f5bb6bb8055"
],
"docker_inspect": [
"privatebin privatebin/pdo:2.1.0@sha256:3400b0a4714d62161727a710c82a3e319cfea364ac6e591aed653f5bb6bb8055 running=true restarts=0"
]
},
"badge_after": {
"hu": [
{
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
"text": "Frissítés elérhető — ma"
}
],
"en": [
{
"title": "A newer version of this app is available. Select the Update button to start it.",
"text": "Update available — today"
}
]
},
"state_after": "running",
"hold_after": null,
"to_digests": {
"privatebin": "sha256:3400b0a4714d62161727a710c82a3e319cfea364ac6e591aed653f5bb6bb8055"
},
"why": "the update ended 'undone' (error None, hold None)",
"log": [
"08:12:21 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}",
"08:12:36 [1] deployed, controller state=running, pinned={'privatebin': 'privatebin/pdo:2.1.0'}",
"08:12:40 [2] setup gate as installed: {'browser': {'status': '200', 'redirect': None}, 'script': {'status': '200', 'redirect': None}}",
"08:12:40 privatebin: seeded paste id=e3b1cd796c9381ce",
"08:12:40 privatebin: readback http=200 marker_present=True",
"08:12:42 [5] drill commit f8b4b5d966c0: privatebin privatebin/pdo:2.1.0 -> busybox:1.36.1 (push rc=0)",
"08:12:50 [5] the box's drill mirror now at f8b4b5d9",
"08:12:55 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}",
"08:12:55 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None",
"08:12:57 + 2.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None",
"08:12:58 + 3.1s phase=pulling label=Új verzió letöltése… err=None hold=None",
"08:12:59 + 4.1s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None",
"08:13:00 + 5.1s phase=verifying label=Működés ellenőrzése… err=None hold=None",
"08:18:03 + 308.2s phase=undoing label=Visszaállítás az előző változatra… err=None hold=None",
"08:18:09 + 314.3s phase=undone label=Visszaállítva az előző változatra err=None hold=None"
]
}
@@ -0,0 +1,20 @@
08:12:21 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
08:12:36 [1] deployed, controller state=running, pinned={'privatebin': 'privatebin/pdo:2.1.0'}
08:12:40 [2] setup gate as installed: {'browser': {'status': '200', 'redirect': None}, 'script': {'status': '200', 'redirect': None}}
08:12:40 privatebin: seeded paste id=e3b1cd796c9381ce
08:12:40 privatebin: readback http=200 marker_present=True
08:12:42 [5] drill commit f8b4b5d966c0: privatebin privatebin/pdo:2.1.0 -> busybox:1.36.1 (push rc=0)
08:12:50 [5] the box's drill mirror now at f8b4b5d9
08:12:55 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
08:12:55 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
08:12:57 + 2.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
08:12:58 + 3.1s phase=pulling label=Új verzió letöltése… err=None hold=None
08:12:59 + 4.1s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
08:13:00 + 5.1s phase=verifying label=Működés ellenőrzése… err=None hold=None
08:18:03 + 308.2s phase=undoing label=Visszaállítás az előző változatra… err=None hold=None
08:18:09 + 314.3s phase=undone label=Visszaállítva az előző változatra err=None hold=None
08:18:28 [9] verdict failed -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/runtime-fixes-2026-10-28/walks/_negative-control/verdict.json
08:18:28 RESULT failed — the update ended 'undone' (error None, hold None)
08:18:28 [X] stop -> 200 {'ok': True, 'message': 'Stack privatebin stop completed'}
08:19:00 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'privatebin', 'volumes_removed': ['privatebin_privatebin_data'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note'
08:19:08 [X] after remove: deployed=False leftovers=''
@@ -0,0 +1,57 @@
{
"app": "adventurelog",
"walk": "security",
"box_walk_version": 1,
"verdict": "inconclusive",
"venue": "box 9202 (drill catalog), the guarded Update",
"from": {
"adventurelog": "ghcr.io/seanmorley15/adventurelog-backend:v0.13.0",
"adventurelog-postgres": "postgis/postgis:16-3.5-alpine",
"adventurelog-frontend": "ghcr.io/seanmorley15/adventurelog-frontend:v0.13.0"
},
"to": {
"adventurelog": "ghcr.io/seanmorley15/adventurelog-backend:v0.13.1",
"adventurelog-postgres": "postgis/postgis:16-3.5-alpine",
"adventurelog-frontend": "ghcr.io/seanmorley15/adventurelog-frontend:v0.13.1"
},
"observables_before": {
"pinned_images": {
"adventurelog": "ghcr.io/seanmorley15/adventurelog-backend:v0.13.1",
"adventurelog-frontend": "ghcr.io/seanmorley15/adventurelog-frontend:v0.13.1",
"adventurelog-postgres": "postgis/postgis:16-3.5-alpine"
},
"installed_images": {
"adventurelog": "ghcr.io/seanmorley15/adventurelog-backend:v0.13.1",
"adventurelog-frontend": "ghcr.io/seanmorley15/adventurelog-frontend:v0.13.1",
"adventurelog-postgres": "postgis/postgis:16-3.5-alpine"
},
"catalog_images": {
"adventurelog": "ghcr.io/seanmorley15/adventurelog-backend:v0.13.1",
"adventurelog-frontend": "ghcr.io/seanmorley15/adventurelog-frontend:v0.13.1",
"adventurelog-postgres": "postgis/postgis:16-3.5-alpine"
},
"live_compose_image_lines": [
"image: ghcr.io/seanmorley15/adventurelog-backend:v0.13.1",
"image: postgis/postgis:16-3.5-alpine",
"image: ghcr.io/seanmorley15/adventurelog-frontend:v0.13.1"
],
"docker_inspect": [
"adventurelog ghcr.io/seanmorley15/adventurelog-backend:v0.13.1 running=true restarts=0",
"adventurelog-postgres postgis/postgis:16-3.5-alpine running=true restarts=0",
"adventurelog-frontend ghcr.io/seanmorley15/adventurelog-frontend:v0.13.1 running=true restarts=0"
]
},
"why": "installed at {'adventurelog': 'ghcr.io/seanmorley15/adventurelog-backend:v0.13.1', 'adventurelog-frontend': 'ghcr.io/seanmorley15/adventurelog-frontend:v0.13.1', 'adventurelog-postgres': 'postgis/postgis:16-3.5-alpine'}, not at FROM",
"log": [
"10:31:08 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}",
"10:33:34 [1] deployed, controller state=unhealthy, pinned={'adventurelog': 'ghcr.io/seanmorley15/adventurelog-backend:v0.13.1', 'adventurelog-frontend': 'ghcr.io/seanmorley15/adventurelog-frontend:v0.13.1', 'adventurelog-postgres': 'postgis/postgis:16-3.5-alpine'}",
"10:33:34 [1] NOTE: the controller's own state is 'unhealthy', not 'running' — recorded, not treated as a failure; the fixture's front-door wait is the real gate",
"10:33:34 gate: travel not routed right now (404) — not cached, asked again next call",
"10:33:39 gate: travel not routed right now (404) — not cached, asked again next call",
"10:33:44 gate: travel not routed right now (404) — not cached, asked again next call",
"10:33:49 gate: travel not routed right now (404) — not cached, asked again next call",
"10:33:54 gate: travel not routed right now (404) — not cached, asked again next call",
"10:33:59 gate: travel not routed right now (404) — not cached, asked again next call",
"10:34:04 gate: travel is gated — passed as the household (cookie set)"
]
}
@@ -0,0 +1,15 @@
10:31:08 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
10:33:34 [1] deployed, controller state=unhealthy, pinned={'adventurelog': 'ghcr.io/seanmorley15/adventurelog-backend:v0.13.1', 'adventurelog-frontend': 'ghcr.io/seanmorley15/adventurelog-frontend:v0.13.1', 'adventurelog-postgres': 'postgis/postgis:16-3.5-alpine'}
10:33:34 [1] NOTE: the controller's own state is 'unhealthy', not 'running' — recorded, not treated as a failure; the fixture's front-door wait is the real gate
10:33:34 gate: travel not routed right now (404) — not cached, asked again next call
10:33:39 gate: travel not routed right now (404) — not cached, asked again next call
10:33:44 gate: travel not routed right now (404) — not cached, asked again next call
10:33:49 gate: travel not routed right now (404) — not cached, asked again next call
10:33:54 gate: travel not routed right now (404) — not cached, asked again next call
10:33:59 gate: travel not routed right now (404) — not cached, asked again next call
10:34:04 gate: travel is gated — passed as the household (cookie set)
10:34:08 [9] verdict inconclusive -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/runtime-fixes-2026-10-28/walks/adventurelog/verdict.json
10:34:08 RESULT inconclusive — installed at {'adventurelog': 'ghcr.io/seanmorley15/adventurelog-backend:v0.13.1', 'adventurelog-frontend': 'ghcr.io/seanmorley15/adventurelog-frontend:v0.13.1', 'adventurelog-postgres': 'postgis/postgis:16-3.5-alpine'}, not at FROM
10:34:11 [X] stop -> 200 {'ok': True, 'message': 'Stack adventurelog stop completed'}
10:34:43 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'adventurelog', 'volumes_removed': ['adventurelog_adventurelog_media', 'adventurelog_adventurelog_postgres_data'], 'hdd_paths_r
10:34:51 [X] after remove: deployed=False leftovers=''
@@ -0,0 +1,11 @@
=== adventurelog 08:19:56
adventurelog rc=1 08:27:27 RESULT failed — the app is 'unhealthy' after the update
=== ghost 08:28:10
ghost rc=0 08:42:49 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back
=== metube 08:43:30
metube rc=0 08:56:06 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back
=== papra 08:56:46
papra rc=1 08:58:10 RESULT inconclusive — C1: the fixture could not seed and read back before the update
=== zipline 08:58:51
zipline rc=0 09:17:52 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back
=== batch done 09:18:43
@@ -0,0 +1,7 @@
=== karakeep 09:19:45
karakeep rc=0 09:38:56 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back
=== tandoor 09:39:41
tandoor rc=0 09:55:20 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back
=== dawarich 09:56:03
dawarich rc=1 09:59:01 RESULT inconclusive — the drill could not be moved FROM -> TO
=== batch done 09:59:50
@@ -0,0 +1,69 @@
{
"app": "dawarich",
"walk": "security",
"box_walk_version": 1,
"verdict": "inconclusive",
"venue": "box 9202 (drill catalog), the guarded Update",
"from": {
"dawarich": "freikin/dawarich:1.15.3",
"dawarich-sidekiq": "freikin/dawarich:1.15.3",
"dawarich-db": "postgis/postgis:17-3.5-alpine",
"dawarich-redis": "redis:7.4-alpine"
},
"to": {
"dawarich": "freikin/dawarich:1.19.0",
"dawarich-sidekiq": "freikin/dawarich:1.19.0",
"dawarich-db": "postgis/postgis:17-3.5-alpine",
"dawarich-redis": "redis:7.4-alpine"
},
"observables_before": {
"pinned_images": {
"dawarich": "freikin/dawarich:1.15.3",
"dawarich-db": "postgis/postgis:17-3.5-alpine",
"dawarich-redis": "redis:7.4-alpine",
"dawarich-sidekiq": "freikin/dawarich:1.15.3"
},
"installed_images": {
"dawarich": "freikin/dawarich:1.15.3",
"dawarich-db": "postgis/postgis:17-3.5-alpine",
"dawarich-redis": "redis:7.4-alpine",
"dawarich-sidekiq": "freikin/dawarich:1.15.3"
},
"catalog_images": null,
"live_compose_image_lines": [
"image: freikin/dawarich:1.15.3@sha256:589e3606b11b61c3fa2d9661832cb73645a9b93a9cc7d807a071e2bc6c584498",
"image: freikin/dawarich:1.15.3@sha256:589e3606b11b61c3fa2d9661832cb73645a9b93a9cc7d807a071e2bc6c584498",
"image: postgis/postgis:17-3.5-alpine@sha256:894f570c0cf0664ed5576a8fd5d5bfb8fb1b19d592885b686c3a88c8bd90c41f",
"image: redis:7.4-alpine@sha256:858f009f9709ce576febc734aa78b8f6d624b82571f9ddb6bda4377c833b3499"
],
"docker_inspect": [
"dawarich-sidekiq freikin/dawarich:1.15.3@sha256:589e3606b11b61c3fa2d9661832cb73645a9b93a9cc7d807a071e2bc6c584498 running=true restarts=0",
"dawarich freikin/dawarich:1.15.3@sha256:589e3606b11b61c3fa2d9661832cb73645a9b93a9cc7d807a071e2bc6c584498 running=true restarts=0",
"dawarich-db postgis/postgis:17-3.5-alpine@sha256:894f570c0cf0664ed5576a8fd5d5bfb8fb1b19d592885b686c3a88c8bd90c41f running=true restarts=0",
"dawarich-redis redis:7.4-alpine@sha256:858f009f9709ce576febc734aa78b8f6d624b82571f9ddb6bda4377c833b3499 running=true restarts=0"
]
},
"setup_gate_before": {
"browser": {
"status": "404",
"redirect": null
},
"script": {
"status": "404",
"redirect": null
}
},
"seed": "read_back",
"drill_commit": null,
"why": "the drill could not be moved FROM -> TO",
"log": [
"09:56:12 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['ADMIN_PASSWORD']",
"09:56:13 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}",
"09:58:38 [1] deployed, controller state=running, pinned={'dawarich': 'freikin/dawarich:1.15.3', 'dawarich-db': 'postgis/postgis:17-3.5-alpine', 'dawarich-redis': 'redis:7.4-alpine', 'dawarich-sidekiq': 'freikin/dawarich:1.15.3'}",
"09:58:38 gate: timeline is gated — passed as the household (cookie set)",
"09:58:42 [2] setup gate as installed: {'browser': {'status': '404', 'redirect': None}, 'script': {'status': '404', 'redirect': None}}",
"09:58:52 dawarich: POST /api/v1/overland/batches http=201 (47.5663,19.1102 at 2026-09-11T11:37:00Z)",
"09:59:01 dawarich: readback http=200 found=True (controls: no key 401, wrong 401, empty range [])",
"09:59:01 [5] FROM ref not found in compose: freikin/dawarich:1.15.3"
]
}
@@ -0,0 +1,13 @@
09:56:12 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['ADMIN_PASSWORD']
09:56:13 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:58:38 [1] deployed, controller state=running, pinned={'dawarich': 'freikin/dawarich:1.15.3', 'dawarich-db': 'postgis/postgis:17-3.5-alpine', 'dawarich-redis': 'redis:7.4-alpine', 'dawarich-sidekiq': 'freikin/dawarich:1.15.3'}
09:58:38 gate: timeline is gated — passed as the household (cookie set)
09:58:42 [2] setup gate as installed: {'browser': {'status': '404', 'redirect': None}, 'script': {'status': '404', 'redirect': None}}
09:58:52 dawarich: POST /api/v1/overland/batches http=201 (47.5663,19.1102 at 2026-09-11T11:37:00Z)
09:59:01 dawarich: readback http=200 found=True (controls: no key 401, wrong 401, empty range [])
09:59:01 [5] FROM ref not found in compose: freikin/dawarich:1.15.3
09:59:01 [9] verdict inconclusive -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/runtime-fixes-2026-10-28/walks/dawarich/verdict.json
09:59:01 RESULT inconclusive — the drill could not be moved FROM -> TO
09:59:09 [X] stop -> 200 {'ok': True, 'message': 'Stack dawarich stop completed'}
09:59:41 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'dawarich', 'volumes_removed': ['dawarich_dawarich_db_data', 'dawarich_dawarich_public', 'dawarich_dawarich_redis', 'dawarich_d
09:59:50 [X] after remove: deployed=False leftovers=''
@@ -0,0 +1,228 @@
{
"app": "ghost",
"walk": "security",
"box_walk_version": 1,
"verdict": "proven",
"venue": "box 9202 (drill catalog), the guarded Update",
"from": {
"ghost": "ghost:6.67.0-alpine"
},
"to": {
"ghost": "ghost:6.73.0-alpine"
},
"observables_before": {
"pinned_images": {
"ghost": "ghost:6.67.0-alpine"
},
"installed_images": {
"ghost": "ghost:6.67.0-alpine"
},
"catalog_images": null,
"live_compose_image_lines": [
"image: ghost:6.67.0-alpine@sha256:1f7ecf094d54363014636c3540dbe9c368394504abaa283914e4fcf8d699f331"
],
"docker_inspect": [
"ghost ghost:6.67.0-alpine@sha256:1f7ecf094d54363014636c3540dbe9c368394504abaa283914e4fcf8d699f331 running=true restarts=0"
]
},
"setup_gate_before": {
"browser": {
"status": "302",
"redirect": "https://felhom.enkisfelhom.hu/__gate/start?…"
},
"script": {
"status": "401",
"redirect": null
}
},
"seed": "read_back",
"drill_commit": "703eb3540d2f",
"sync_waited_s": 4.5,
"badge_before": {
"hu": [
{
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
"text": "Frissítés elérhető — ma"
}
],
"en": [
{
"title": "A newer version of this app is available. Select the Update button to start it.",
"text": "Update available — today"
}
]
},
"measured_at": "2026-10-28T07:30:36Z",
"update": {
"accepted": true,
"http": "202",
"phases": [
{
"t": 0.0,
"phase": "backing-up",
"label": "Biztonsági mentés készül a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 2.1,
"phase": "safety-dump",
"label": "Adatbázis pillanatkép…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 3.1,
"phase": "pulling",
"label": "Új verzió letöltése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 96.3,
"phase": "copying",
"label": "Az adatok másolása a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 97.3,
"phase": "starting",
"label": "Indítás az új verzióval…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 98.3,
"phase": "verifying",
"label": "Működés ellenőrzése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 108.6,
"phase": "done",
"label": "Frissítve",
"updating": false,
"error": null,
"hold": null
}
],
"duration_s": 108.6,
"final_phase": "done",
"update_error": null,
"hold_reason": null,
"state": "running"
},
"observables_after": {
"pinned_images": {
"ghost": "ghost:6.73.0-alpine"
},
"installed_images": {
"ghost": "ghost:6.73.0-alpine"
},
"catalog_images": {
"ghost": "ghost:6.73.0-alpine"
},
"live_compose_image_lines": [
"image: ghost:6.73.0-alpine"
],
"docker_inspect": [
"ghost ghost:6.73.0-alpine running=true restarts=0"
]
},
"badge_after": {
"hu": [
{
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
"text": "Naprakész"
}
],
"en": [
{
"title": "This app is running the newest version available.",
"text": "Up to date"
}
]
},
"state_after": "running",
"hold_after": null,
"to_digests": {
"ghost": "sha256:4195f6c405e40230cd10c0770425cf500c1f542a96e9f6584c11649c150e5a89"
},
"four_observables": {
"pinned": {
"ghost": "ghost:6.73.0-alpine"
},
"installed": {
"ghost": "ghost:6.73.0-alpine"
},
"catalog": {
"ghost": "ghost:6.73.0-alpine"
},
"live_compose": [
"ghost:6.73.0-alpine"
]
},
"seed_read_after": true,
"setup_gate_after": {
"browser": {
"status": "301",
"redirect": "/identity/"
},
"script": {
"status": "301",
"redirect": "/identity/"
}
},
"memory": {
"soak_s": 600,
"interval_s": 10,
"samples": 60,
"containers": {
"ghost": {
"samples": 60,
"anon_peak_bytes": 115974144,
"limit_bytes": 536870912,
"anon_peak_pct": 21.6,
"cgroup_peak_pct": 24.7,
"oom_kill_delta": 0,
"oom_killed_flag": false,
"restarts_delta": 0,
"running_all_samples": true,
"cgroup": "/sys/fs/cgroup/system.slice/docker-e82983c8bd516ba1824ce3eb3273658f2f1b2298273882a011a392fffd95d0db.scope"
}
},
"oom_kills": 0,
"restarts": 0,
"peak_pct": 21.6
},
"why": "the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back",
"log": [
"08:28:20 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}",
"08:30:15 [1] deployed, controller state=running, pinned={'ghost': 'ghost:6.67.0-alpine'}",
"08:30:15 gate: blog is gated — passed as the household (cookie set)",
"08:30:19 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}",
"08:30:20 ghost: seeded site title Drill-1a37bb84e421",
"08:30:20 ghost: readback found=True (http 200, control passed)",
"08:30:23 [5] drill commit 703eb3540d2f: ghost ghost:6.67.0-alpine -> ghost:6.73.0-alpine (push rc=0)",
"08:30:31 [5] the box's drill mirror now at 703eb3540",
"08:30:36 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}",
"08:30:36 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None",
"08:30:38 + 2.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None",
"08:30:39 + 3.1s phase=pulling label=Új verzió letöltése… err=None hold=None",
"08:32:12 + 96.3s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None",
"08:32:13 + 97.3s phase=starting label=Indítás az új verzióval… err=None hold=None",
"08:32:14 + 98.3s phase=verifying label=Működés ellenőrzése… err=None hold=None",
"08:32:25 + 108.6s phase=done label=Frissítve err=None hold=None",
"08:32:44 ghost: readback found=True (http 200, control passed)",
"08:32:44 [7] memory soak 600 s …",
"08:42:49 [7] soak: peak 21.6% of the limit (anon), kills 0, restarts 0"
]
}
@@ -0,0 +1,24 @@
08:28:20 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
08:30:15 [1] deployed, controller state=running, pinned={'ghost': 'ghost:6.67.0-alpine'}
08:30:15 gate: blog is gated — passed as the household (cookie set)
08:30:19 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}
08:30:20 ghost: seeded site title Drill-1a37bb84e421
08:30:20 ghost: readback found=True (http 200, control passed)
08:30:23 [5] drill commit 703eb3540d2f: ghost ghost:6.67.0-alpine -> ghost:6.73.0-alpine (push rc=0)
08:30:31 [5] the box's drill mirror now at 703eb3540
08:30:36 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
08:30:36 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
08:30:38 + 2.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
08:30:39 + 3.1s phase=pulling label=Új verzió letöltése… err=None hold=None
08:32:12 + 96.3s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
08:32:13 + 97.3s phase=starting label=Indítás az új verzióval… err=None hold=None
08:32:14 + 98.3s phase=verifying label=Működés ellenőrzése… err=None hold=None
08:32:25 + 108.6s phase=done label=Frissítve err=None hold=None
08:32:44 ghost: readback found=True (http 200, control passed)
08:32:44 [7] memory soak 600 s …
08:42:49 [7] soak: peak 21.6% of the limit (anon), kills 0, restarts 0
08:42:49 [9] verdict proven -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/runtime-fixes-2026-10-28/walks/ghost/verdict.json
08:42:49 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back
08:42:50 [X] stop -> 200 {'ok': True, 'message': 'Stack ghost stop completed'}
08:43:22 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'ghost', 'volumes_removed': ['ghost_ghost_content'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'Az alkalm
08:43:30 [X] after remove: deployed=False leftovers=''
@@ -0,0 +1,290 @@
{
"app": "karakeep",
"walk": "security",
"box_walk_version": 1,
"verdict": "proven",
"venue": "box 9202 (drill catalog), the guarded Update",
"from": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.33.2",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"to": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.34.1",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"observables_before": {
"pinned_images": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.33.2",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"installed_images": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.33.2",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"catalog_images": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.33.2",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"live_compose_image_lines": [
"image: ghcr.io/karakeep-app/karakeep:0.33.2@sha256:b069e4307dec06ea06d16989c6861c30a1ff208568be44ed5fb5d422cd3e950c",
"image: ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1@sha256:5b19bbb160e9ff60681a3abd97e1c4ec9f64212301410de658c3900ab7ef31e7",
"image: getmeili/meilisearch:v1.41.0@sha256:860fa4baed04ae1c235de870edab0c8006227546dea1bbb6411fbfc5e27cf1db"
],
"docker_inspect": [
"karakeep ghcr.io/karakeep-app/karakeep:0.33.2@sha256:b069e4307dec06ea06d16989c6861c30a1ff208568be44ed5fb5d422cd3e950c running=true restarts=0",
"karakeep-meilisearch getmeili/meilisearch:v1.41.0@sha256:860fa4baed04ae1c235de870edab0c8006227546dea1bbb6411fbfc5e27cf1db running=true restarts=0",
"karakeep-chrome ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1@sha256:5b19bbb160e9ff60681a3abd97e1c4ec9f64212301410de658c3900ab7ef31e7 running=true restarts=0"
]
},
"setup_gate_before": {
"browser": {
"status": "302",
"redirect": "https://felhom.enkisfelhom.hu/__gate/start?…"
},
"script": {
"status": "401",
"redirect": null
}
},
"seed": "read_back",
"drill_commit": "e8612bd845c4",
"sync_waited_s": 4.5,
"badge_before": {
"hu": [
{
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
"text": "Frissítés elérhető — ma"
}
],
"en": [
{
"title": "A newer version of this app is available. Select the Update button to start it.",
"text": "Update available — today"
}
]
},
"measured_at": "2026-10-28T08:26:56Z",
"update": {
"accepted": true,
"http": "202",
"phases": [
{
"t": 0.0,
"phase": "backing-up",
"label": "Biztonsági mentés készül a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 12.3,
"phase": "safety-dump",
"label": "Adatbázis pillanatkép…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 13.4,
"phase": "pulling",
"label": "Új verzió letöltése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 67.7,
"phase": "copying",
"label": "Az adatok másolása a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 76.9,
"phase": "starting",
"label": "Indítás az új verzióval…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 83.0,
"phase": "verifying",
"label": "Működés ellenőrzése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 93.3,
"phase": "done",
"label": "Frissítve",
"updating": false,
"error": null,
"hold": null
}
],
"duration_s": 93.3,
"final_phase": "done",
"update_error": null,
"hold_reason": null,
"state": "running"
},
"observables_after": {
"pinned_images": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.34.1",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"installed_images": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.34.1",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"catalog_images": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.34.1",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"live_compose_image_lines": [
"image: ghcr.io/karakeep-app/karakeep:0.34.1",
"image: ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"image: getmeili/meilisearch:v1.41.0"
],
"docker_inspect": [
"karakeep ghcr.io/karakeep-app/karakeep:0.34.1 running=true restarts=0",
"karakeep-meilisearch getmeili/meilisearch:v1.41.0 running=true restarts=0",
"karakeep-chrome ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1 running=true restarts=0"
]
},
"badge_after": {
"hu": [
{
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
"text": "Naprakész"
}
],
"en": [
{
"title": "This app is running the newest version available.",
"text": "Up to date"
}
]
},
"state_after": "running",
"hold_after": null,
"to_digests": {
"karakeep": "sha256:69ae5315c618b7c14c1af3e34c6e211acdb231793af424ecd1cab0b70691d987",
"karakeep-chrome": "sha256:5b19bbb160e9ff60681a3abd97e1c4ec9f64212301410de658c3900ab7ef31e7",
"karakeep-meilisearch": "sha256:860fa4baed04ae1c235de870edab0c8006227546dea1bbb6411fbfc5e27cf1db"
},
"four_observables": {
"pinned": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.34.1",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"installed": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.34.1",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"catalog": {
"karakeep": "ghcr.io/karakeep-app/karakeep:0.34.1",
"karakeep-chrome": "ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"karakeep-meilisearch": "getmeili/meilisearch:v1.41.0"
},
"live_compose": [
"getmeili/meilisearch:v1.41.0",
"ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1",
"ghcr.io/karakeep-app/karakeep:0.34.1"
]
},
"seed_read_after": true,
"setup_gate_after": {
"browser": {
"status": "302",
"redirect": "https://felhom.enkisfelhom.hu/__gate/start?…"
},
"script": {
"status": "401",
"redirect": null
}
},
"memory": {
"soak_s": 600,
"interval_s": 10,
"samples": 174,
"containers": {
"karakeep": {
"samples": 58,
"anon_peak_bytes": 476987392,
"limit_bytes": 1610612736,
"anon_peak_pct": 29.6,
"cgroup_peak_pct": 35.9,
"oom_kill_delta": 0,
"oom_killed_flag": false,
"restarts_delta": 0,
"running_all_samples": true,
"cgroup": "/sys/fs/cgroup/system.slice/docker-570f3c919afe2768148f63e8232148f054a31becfa4e2bada4586d67b16a06d9.scope"
},
"karakeep-meilisearch": {
"samples": 58,
"anon_peak_bytes": 18882560,
"limit_bytes": 536870912,
"anon_peak_pct": 3.5,
"cgroup_peak_pct": 4.9,
"oom_kill_delta": 0,
"oom_killed_flag": false,
"restarts_delta": 0,
"running_all_samples": true,
"cgroup": "/sys/fs/cgroup/system.slice/docker-8190168785f017f894c51a37758ad618ba6aa782d20e54ca79b9c212c266f9cc.scope"
},
"karakeep-chrome": {
"samples": 58,
"anon_peak_bytes": 36986880,
"limit_bytes": 805306368,
"anon_peak_pct": 4.6,
"cgroup_peak_pct": 5.9,
"oom_kill_delta": 0,
"oom_killed_flag": false,
"restarts_delta": 0,
"running_all_samples": true,
"cgroup": "/sys/fs/cgroup/system.slice/docker-3548090e97767f2bef3bc5badb04d254f839925340720d7d59439f7b780db60c.scope"
}
},
"oom_kills": 0,
"restarts": 0,
"peak_pct": 29.6
},
"why": "the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back",
"log": [
"09:19:55 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}",
"09:21:35 [1] deployed, controller state=running, pinned={'karakeep': 'ghcr.io/karakeep-app/karakeep:0.33.2', 'karakeep-chrome': 'ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1', 'karakeep-meilisearch': 'getmeili/meilisearch:v1.41.0'}",
"09:21:35 gate: bookmarks is gated — passed as the household (cookie set)",
"09:26:38 app never answered on bookmarks/ (last rc=0 code=307)",
"09:26:42 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}",
"09:26:42 karakeep: users.create (the first account) http=200 role=admin",
"09:26:42 karakeep: POST /api/v1/bookmarks http=201",
"09:26:43 karakeep: readback http=200 found=True (controls: no key 401, wrong 401, absent 404)",
"09:26:43 [5] drill commit e8612bd845c4: karakeep ghcr.io/karakeep-app/karakeep:0.33.2 -> ghcr.io/karakeep-app/karakeep:0.34.1 (push rc=0)",
"09:26:52 [5] the box's drill mirror now at e8612bd84",
"09:26:57 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}",
"09:26:57 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None",
"09:27:09 + 12.3s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None",
"09:27:10 + 13.4s phase=pulling label=Új verzió letöltése… err=None hold=None",
"09:28:04 + 67.7s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None",
"09:28:14 + 76.9s phase=starting label=Indítás az új verzióval… err=None hold=None",
"09:28:20 + 83.0s phase=verifying label=Működés ellenőrzése… err=None hold=None",
"09:28:30 + 93.3s phase=done label=Frissítve err=None hold=None",
"09:28:49 karakeep: readback http=200 found=True (controls: no key 401, wrong 401, absent 404)",
"09:28:49 [7] memory soak 600 s …",
"09:38:56 [7] soak: peak 29.6% of the limit (anon), kills 0, restarts 0"
]
}
@@ -0,0 +1,26 @@
09:19:55 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:21:35 [1] deployed, controller state=running, pinned={'karakeep': 'ghcr.io/karakeep-app/karakeep:0.33.2', 'karakeep-chrome': 'ghcr.io/karakeep-app/karakeep-chrome:151.0.7922.47-r1', 'karakeep-meilisearch': 'getmeili/meilisearch:v1.41.0'}
09:21:35 gate: bookmarks is gated — passed as the household (cookie set)
09:26:38 app never answered on bookmarks/ (last rc=0 code=307)
09:26:42 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}
09:26:42 karakeep: users.create (the first account) http=200 role=admin
09:26:42 karakeep: POST /api/v1/bookmarks http=201
09:26:43 karakeep: readback http=200 found=True (controls: no key 401, wrong 401, absent 404)
09:26:43 [5] drill commit e8612bd845c4: karakeep ghcr.io/karakeep-app/karakeep:0.33.2 -> ghcr.io/karakeep-app/karakeep:0.34.1 (push rc=0)
09:26:52 [5] the box's drill mirror now at e8612bd84
09:26:57 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
09:26:57 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
09:27:09 + 12.3s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
09:27:10 + 13.4s phase=pulling label=Új verzió letöltése… err=None hold=None
09:28:04 + 67.7s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
09:28:14 + 76.9s phase=starting label=Indítás az új verzióval… err=None hold=None
09:28:20 + 83.0s phase=verifying label=Működés ellenőrzése… err=None hold=None
09:28:30 + 93.3s phase=done label=Frissítve err=None hold=None
09:28:49 karakeep: readback http=200 found=True (controls: no key 401, wrong 401, absent 404)
09:28:49 [7] memory soak 600 s …
09:38:56 [7] soak: peak 29.6% of the limit (anon), kills 0, restarts 0
09:38:56 [9] verdict proven -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/runtime-fixes-2026-10-28/walks/karakeep/verdict.json
09:38:56 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back
09:39:00 [X] stop -> 200 {'ok': True, 'message': 'Stack karakeep stop completed'}
09:39:32 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'karakeep', 'volumes_removed': ['karakeep_karakeep_data', 'karakeep_karakeep_meili'], 'hdd_paths_removed': [], 'hdd_paths_prese
09:39:41 [X] after remove: deployed=False leftovers=''
@@ -0,0 +1,230 @@
{
"app": "metube",
"walk": "security",
"box_walk_version": 1,
"verdict": "proven",
"venue": "box 9202 (drill catalog), the guarded Update",
"from": {
"metube": "ghcr.io/alexta69/metube:2026.09.29"
},
"to": {
"metube": "ghcr.io/alexta69/metube:2026.10.27"
},
"observables_before": {
"pinned_images": {
"metube": "ghcr.io/alexta69/metube:2026.09.29"
},
"installed_images": {
"metube": "ghcr.io/alexta69/metube:2026.09.29"
},
"catalog_images": null,
"live_compose_image_lines": [
"image: ghcr.io/alexta69/metube:2026.09.29@sha256:8e2fe9beeefc55a02f6e1d04cad0fc3c22e8f067d309188f016551dc99ec27b3"
],
"docker_inspect": [
"metube ghcr.io/alexta69/metube:2026.09.29@sha256:8e2fe9beeefc55a02f6e1d04cad0fc3c22e8f067d309188f016551dc99ec27b3 running=true restarts=0"
]
},
"setup_gate_before": {
"browser": {
"status": "302",
"redirect": "https://felhom.enkisfelhom.hu/__family/start?…"
},
"script": {
"status": "401",
"redirect": null
}
},
"seed": "read_back",
"drill_commit": "d8624a5e0b08",
"sync_waited_s": 4.5,
"badge_before": {
"hu": [
{
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
"text": "Frissítés elérhető — ma"
}
],
"en": [
{
"title": "A newer version of this app is available. Select the Update button to start it.",
"text": "Update available — today"
}
]
},
"measured_at": "2026-10-28T07:44:58Z",
"update": {
"accepted": true,
"http": "202",
"phases": [
{
"t": 0.0,
"phase": "backing-up",
"label": "Biztonsági mentés készül a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 3.1,
"phase": "safety-dump",
"label": "Adatbázis pillanatkép…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 4.1,
"phase": "pulling",
"label": "Új verzió letöltése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 28.7,
"phase": "copying",
"label": "Az adatok másolása a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 36.9,
"phase": "starting",
"label": "Indítás az új verzióval…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 37.9,
"phase": "verifying",
"label": "Működés ellenőrzése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 43.0,
"phase": "done",
"label": "Frissítve",
"updating": false,
"error": null,
"hold": null
}
],
"duration_s": 43.1,
"final_phase": "done",
"update_error": null,
"hold_reason": null,
"state": "running"
},
"observables_after": {
"pinned_images": {
"metube": "ghcr.io/alexta69/metube:2026.10.27"
},
"installed_images": {
"metube": "ghcr.io/alexta69/metube:2026.10.27"
},
"catalog_images": {
"metube": "ghcr.io/alexta69/metube:2026.10.27"
},
"live_compose_image_lines": [
"image: ghcr.io/alexta69/metube:2026.10.27"
],
"docker_inspect": [
"metube ghcr.io/alexta69/metube:2026.10.27 running=true restarts=0"
]
},
"badge_after": {
"hu": [
{
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
"text": "Naprakész"
}
],
"en": [
{
"title": "This app is running the newest version available.",
"text": "Up to date"
}
]
},
"state_after": "running",
"hold_after": null,
"to_digests": {
"metube": "sha256:845a67373a9f9e62b88e5f9067867202200d63db3615a051acbd77b09e86b9ce"
},
"four_observables": {
"pinned": {
"metube": "ghcr.io/alexta69/metube:2026.10.27"
},
"installed": {
"metube": "ghcr.io/alexta69/metube:2026.10.27"
},
"catalog": {
"metube": "ghcr.io/alexta69/metube:2026.10.27"
},
"live_compose": [
"ghcr.io/alexta69/metube:2026.10.27"
]
},
"seed_read_after": true,
"setup_gate_after": {
"browser": {
"status": "302",
"redirect": "https://felhom.enkisfelhom.hu/__family/start?…"
},
"script": {
"status": "401",
"redirect": null
}
},
"memory": {
"soak_s": 600,
"interval_s": 10,
"samples": 60,
"containers": {
"metube": {
"samples": 60,
"anon_peak_bytes": 62304256,
"limit_bytes": 805306368,
"anon_peak_pct": 7.7,
"cgroup_peak_pct": 9.4,
"oom_kill_delta": 0,
"oom_killed_flag": false,
"restarts_delta": 0,
"running_all_samples": true,
"cgroup": "/sys/fs/cgroup/system.slice/docker-f11f9ab4073dcd80259ea68f0e4da2debeb73f1056aee40b3bcd27126d797476.scope"
}
},
"oom_kills": 0,
"restarts": 0,
"peak_pct": 7.7
},
"why": "the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back",
"log": [
"08:43:40 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']",
"08:43:41 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}",
"08:44:36 [1] deployed, controller state=running, pinned={'metube': 'ghcr.io/alexta69/metube:2026.09.29'}",
"08:44:36 family gate: video is family-gated — passed as the household (cookie set)",
"08:44:40 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__family/start?…'}, 'script': {'status': '401', 'redirect': None}}",
"08:44:40 metube: POST /add http=200 {\"status\": \"ok\"}",
"08:44:44 metube: the download finished (991017 bytes)",
"08:44:44 metube: history has it=True; GET /download/<file> http=200",
"08:44:45 [5] drill commit d8624a5e0b08: metube ghcr.io/alexta69/metube:2026.09.29 -> ghcr.io/alexta69/metube:2026.10.27 (push rc=0)",
"08:44:53 [5] the box's drill mirror now at d8624a5e0",
"08:44:58 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}",
"08:44:58 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None",
"08:45:01 + 3.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None",
"08:45:02 + 4.1s phase=pulling label=Új verzió letöltése… err=None hold=None",
"08:45:27 + 28.7s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None",
"08:45:35 + 36.9s phase=starting label=Indítás az új verzióval… err=None hold=None",
"08:45:36 + 37.9s phase=verifying label=Működés ellenőrzése… err=None hold=None",
"08:45:41 + 43.0s phase=done label=Frissítve err=None hold=None",
"08:46:00 metube: history has it=True; GET /download/<file> http=200",
"08:46:00 [7] memory soak 600 s …",
"08:56:06 [7] soak: peak 7.7% of the limit (anon), kills 0, restarts 0"
]
}
@@ -0,0 +1,26 @@
08:43:40 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
08:43:41 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
08:44:36 [1] deployed, controller state=running, pinned={'metube': 'ghcr.io/alexta69/metube:2026.09.29'}
08:44:36 family gate: video is family-gated — passed as the household (cookie set)
08:44:40 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__family/start?…'}, 'script': {'status': '401', 'redirect': None}}
08:44:40 metube: POST /add http=200 {"status": "ok"}
08:44:44 metube: the download finished (991017 bytes)
08:44:44 metube: history has it=True; GET /download/<file> http=200
08:44:45 [5] drill commit d8624a5e0b08: metube ghcr.io/alexta69/metube:2026.09.29 -> ghcr.io/alexta69/metube:2026.10.27 (push rc=0)
08:44:53 [5] the box's drill mirror now at d8624a5e0
08:44:58 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
08:44:58 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
08:45:01 + 3.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
08:45:02 + 4.1s phase=pulling label=Új verzió letöltése… err=None hold=None
08:45:27 + 28.7s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
08:45:35 + 36.9s phase=starting label=Indítás az új verzióval… err=None hold=None
08:45:36 + 37.9s phase=verifying label=Működés ellenőrzése… err=None hold=None
08:45:41 + 43.0s phase=done label=Frissítve err=None hold=None
08:46:00 metube: history has it=True; GET /download/<file> http=200
08:46:00 [7] memory soak 600 s …
08:56:06 [7] soak: peak 7.7% of the limit (anon), kills 0, restarts 0
08:56:06 [9] verdict proven -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/runtime-fixes-2026-10-28/walks/metube/verdict.json
08:56:06 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back
08:56:06 [X] stop -> 200 {'ok': True, 'message': 'Stack metube stop completed'}
08:56:38 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'metube', 'volumes_removed': ['metube_metube_state'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'userdata_kept': ['/m
08:56:46 [X] after remove: deployed=False leftovers=''
@@ -0,0 +1,47 @@
{
"app": "papra",
"walk": "security",
"box_walk_version": 1,
"verdict": "inconclusive",
"venue": "box 9202 (drill catalog), the guarded Update",
"from": {
"papra": "ghcr.io/papra-hq/papra:26.6.2-rootless"
},
"to": {
"papra": "ghcr.io/papra-hq/papra:26.7.1-rootless"
},
"observables_before": {
"pinned_images": {
"papra": "ghcr.io/papra-hq/papra:26.6.2-rootless"
},
"installed_images": {
"papra": "ghcr.io/papra-hq/papra:26.6.2-rootless"
},
"catalog_images": null,
"live_compose_image_lines": [
"image: ghcr.io/papra-hq/papra:26.6.2-rootless@sha256:a281cb44176dbe5323e0f7ea2d6fd34d58914a3a8525c36437a086d1d7c4fef8"
],
"docker_inspect": [
"papra ghcr.io/papra-hq/papra:26.6.2-rootless@sha256:a281cb44176dbe5323e0f7ea2d6fd34d58914a3a8525c36437a086d1d7c4fef8 running=true restarts=0"
]
},
"setup_gate_before": {
"browser": {
"status": "302",
"redirect": "https://felhom.enkisfelhom.hu/__gate/start?…"
},
"script": {
"status": "401",
"redirect": null
}
},
"why": "C1: the fixture could not seed and read back before the update",
"log": [
"08:56:56 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}",
"08:58:06 [1] deployed, controller state=running, pinned={'papra': 'ghcr.io/papra-hq/papra:26.6.2-rootless'}",
"08:58:06 gate: papra is gated — passed as the household (cookie set)",
"08:58:10 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}",
"08:58:10 papra: sign-up http=403",
"08:58:10 papra: refused {\"message\":\"Missing or null Origin\",\"code\":\"MISSING_OR_NULL_ORIGIN\"}"
]
}
@@ -0,0 +1,17 @@
10:35:01 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
10:36:16 [1] deployed, controller state=running, pinned={'papra': 'ghcr.io/papra-hq/papra:26.6.2-rootless'}
10:36:16 gate: papra is gated — passed as the household (cookie set)
10:36:19 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}
10:36:19 papra: sign-up http=200
10:36:20 papra: sign-in as the seeded account http=200 ok=True
10:36:21 [5] drill commit 2af95d7c3b98: papra ghcr.io/papra-hq/papra:26.6.2-rootless -> ghcr.io/papra-hq/papra:26.7.1-rootless (push rc=0)
10:36:29 [5] the box's drill mirror now at 2af95d7c3
10:36:34 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
10:36:34 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
10:36:37 + 3.1s phase=pulling label=Új verzió letöltése… err=None hold=None
10:37:33 + 58.4s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
10:37:38 + 63.5s phase=starting label=Indítás az új verzióval… err=None hold=None
10:37:39 + 64.5s phase=verifying label=Működés ellenőrzése… err=None hold=None
10:37:49 + 74.8s phase=done label=Frissítve err=None hold=None
10:38:08 papra: sign-in as the seeded account http=200 ok=True
10:38:08 [7] memory soak 600 s …
@@ -0,0 +1,40 @@
./mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts/test_box_walk_drill_move.py:49: ResourceWarning: unclosed file <_io.TextIOWrapper name='/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts/box_walk.py' mode='r' encoding='UTF-8'>
self.assertIn("move_images(s, froms, tos)", open(w.__file__).read(), "_drill_bump no longer calls move_images")
ResourceWarning: Enable tracemalloc to get the object allocation traceback
.FF.
======================================================================
FAIL: test_one_image_two_targets_is_refused (__main__.DrillMove.test_one_image_two_targets_is_refused)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts/test_box_walk_drill_move.py", line 46, in test_one_image_two_targets_is_refused
self.assertEqual(out, TWO)
~~~~~~~~~~~~~~~~^^^^^^^^^^
AssertionError: 'serv[46 chars]h:1.19.0\n dawarich-sidekiq:\n image: frei[75 chars]ne\n' != 'serv[46 chars]h:1.15.3\n dawarich-sidekiq:\n image: frei[75 chars]ne\n'
services:
dawarich:
- image: freikin/dawarich:1.19.0
? ^ ^
+ image: freikin/dawarich:1.15.3
? ^ ^
dawarich-sidekiq:
- image: freikin/dawarich:1.19.0
? ^ ^
+ image: freikin/dawarich:1.15.3
? ^ ^
dawarich-db:
image: postgis/postgis:17-3.5-alpine
======================================================================
FAIL: test_shared_image_moves_both_services (__main__.DrillMove.test_shared_image_moves_both_services)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts/test_box_walk_drill_move.py", line 26, in test_shared_image_moves_both_services
self.assertIsNone(missing)
~~~~~~~~~~~~~~~~~^^^^^^^^^
AssertionError: 'freikin/dawarich:1.15.3' is not None
----------------------------------------------------------------------
Ran 5 tests in 0.005s
FAILED (failures=2)
@@ -0,0 +1,107 @@
-- W9: notices that are not about the product; an empty fix with a closed range
ok W9 a GitHub Actions advisory (the project's CI) is not about the image -> not listed
ok W9 an empty fix with a range ending at 2.6.0 -> ADVISORY, fixed after 2.6.0 (not 'no fixed version')
ok W9 negative: the same notice at 2.7.0 -> not listed
ok W9 control: an open range with no fix still says 'no fixed version named yet'
-- W1-W4: the classes
ok W1 traefik v3.7.13 -> ADVISORY, fixed v3.7.14
ok W1 negative: traefik v3.7.16 -> CURRENT (the rc is no fix, v2 is another channel)
ok W1 Nextcloud 34.0.4 -> no Server advisory (fixed 34.0.1); the Deck app's advisory is not ours
ok W1 Nextcloud 34.0.0 -> ADVISORY GHSA-nc01
ok W1 an unreadable range is LISTED (unsure), never dropped
ok W1 OSV: Go 1.27.2 -> GO-2026-6809 fixed 1.27.3; Go 1.27.3 -> none
ok W2 the recorded Cloudflare blog item -> ADVISORY for cloudflared (and only that item)
ok W2 the VULN- marker in 2026.10.4 -> ADVISORY fixed 2026.10.4; 2026.10.2's plain bump is not one
ok W2 the same blog item 71 days later -> nothing (30-day window)
ok W2 positive control at the pin it hit: cloudflared 2026.9.3 on 2026-10-26 -> ADVISORY
ok W3 filebrowser 1.5.6-stable -> BEHIND 1.5.7-stable (the beta is no channel, its CVE no fix)
ok W3 redis 7-alpine -> FLOATING
ok W3 postgres gap -> GAP (BEHIND still computed: no newer 16-…)
ok W3 an abandoned template -> GAP, nothing looked up (no route needed)
ok W4 a source that fails -> NOT CHECKED, with the reason
ok W4 the table prints the NOT CHECKED line
-- W5-W7: memory and mails
ok W5 a new advisory mails that night
ok W5 the mail carries our version, the fixed version, the lane
ok W5 the same advisory the next night mails NOTHING
ok W5 still open 7 days later -> one reminder
ok W5 and not again the next night
ok W5 a vendor notice mails once and never repeats
ok W5 a pin checked clean forgets its closed advisory
ok W5 box programs first in the subject
-- W6: a source down
ok W6 one night down -> no mail
ok W6 two nights -> one mail naming the source
ok W6 a third night -> no second mail
ok W6 back up -> the streak resets (one more night down -> no mail)
-- W7: weekly and seed
ok W7 Monday -> the weekly summary
ok W7 not twice the same Monday
ok W7 a Tuesday whose last weekly is 8 days old -> the weekly (a missed Monday)
ok W7 a seed mails nothing, records the advisory, and says what it would have mailed
ok W7 a pin the seed could not read is PENDING
ok W7 its first real read is recorded SILENTLY; a pin added later still mails
-- W13: one image in the catalog AND on DooPlex (R-1333)
XX W13 a new notice on both pins is mailed for BOTH (the catalog's 5.4.1 and DooPlex's 5.4.0) nd a notice that affects a version we ship.
Box programs first (none tonight).
rommapp/romm — CVE-2026-111497
What: s
Our version: 5.4.0 (t; t)
Fixed in: 1.0.1
Severity: high
Source: GitHub advisory
Link: l
Next: the homelab session updates this DooPlex workload (Felhom changes nothing on DooPlex; the list: documentation/security-watch/dooplex-workloads.txt)
A notice is mailed once, and again every 7 days while it stays open. Night of 2026-10-26.
XX W13 the memory keeps one entry per group ['rommapp/romm|CVE-2026-111497']
XX W13 the old shared key is copied to the DooPlex key: no mail again ([], {'rommapp/romm|CVE-2026-111497': {'first': '2026-10-27', 'last_mailed': '2026-10-27', 'program': 'rommapp/romm 5.4.0 (x)', 'summary': 's'}})
XX W13 a shared key whose catalog pin is gone moves to the DooPlex key (no stale twin, no mail) (['rommapp/romm|CVE-2026-111497'], [])
ok W13 DooPlex's pin checked clean forgets only DooPlex's entry
-- W8: the inventory and its gate
ok W8 a gap with no reason is a problem
ok W8 two sources parse
ok W8 an unknown kind is a problem
ok W8 a decoy pin whose line is only a comment REFUSES (rc 1, names demo/b)
-- W10: the runtime inside an image
ok W10 Node 24.18.1 -> ADVISORY from runtime, CVE-2026-111497, fixed 24.22.1
ok W10 negative control: Node 24.22.1 -> no advisory
ok W10 Python Brotli 1.2.0 -> ADVISORY, fixed 1.2.1
ok W10 negative control: Brotli 1.2.1 -> no advisory
ok W10 Node 20 (no fixed release on its line) -> ADVISORY naming the end of life
ok W10 a layer read error -> NOT CHECKED with source runtime
ok W10 a registry with no route -> a note, not a failure
RUNTIME-READ ex/node-old:1.0.0 0 s ok
ok W10 the result is cached by digest: one full read for two nights
RUNTIME-READ ex/broken:1.0.0 0 s NOT CHECKED: layer sha256:1234 unreadable: ReadError
ok W10 an UNCHECKED result is not cached (tomorrow tries again)
ok W10 main() hands the reader to run() (off only with --no-runtime)
ok W10 the reader counts what it read and from the cache (the log's RUNTIME line)
-- W11: ghcr.io tags are paged
ok W11 both pages are read (1.1.0 is on page 2)
-- W12: the DooPlex group
ok W12 the list file is read, group dooplex, the catalog's sources reused
ok W12 an image the catalog does not ship is a stated gap (runtime + registry only)
ok W12 a DooPlex advisory names the homelab session and not the lane
ok W12 a DooPlex image in a private registry -> NOT CHECKED with the reason
ok W12 the weekly mail has its own DooPlex block
FAIL: W13 a new notice on both pins is mailed for BOTH (the catalog's 5.4.1 and DooPlex's 5.4.0) nd a notice that affects a version we ship.
Box programs first (none tonight).
rommapp/romm — CVE-2026-111497
What: s
Our version: 5.4.0 (t; t)
Fixed in: 1.0.1
Severity: high
Source: GitHub advisory
Link: l
Next: the homelab session updates this DooPlex workload (Felhom changes nothing on DooPlex; the list: documentation/security-watch/dooplex-workloads.txt)
A notice is mailed once, and again every 7 days while it stays open. Night of 2026-10-26.
FAIL: W13 the memory keeps one entry per group ['rommapp/romm|CVE-2026-111497']
FAIL: W13 the old shared key is copied to the DooPlex key: no mail again ([], {'rommapp/romm|CVE-2026-111497': {'first': '2026-10-27', 'last_mailed': '2026-10-27', 'program': 'rommapp/romm 5.4.0 (x)', 'summary': 's'}})
FAIL: W13 a shared key whose catalog pin is gone moves to the DooPlex key (no stale twin, no mail) (['rommapp/romm|CVE-2026-111497'], [])
@@ -0,0 +1,260 @@
{
"app": "tandoor",
"walk": "security",
"box_walk_version": 1,
"verdict": "proven",
"venue": "box 9202 (drill catalog), the guarded Update",
"from": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
"tandoor-postgres": "postgres:17-alpine"
},
"to": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.7.2",
"tandoor-postgres": "postgres:17-alpine"
},
"observables_before": {
"pinned_images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
"tandoor-postgres": "postgres:17-alpine"
},
"installed_images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
"tandoor-postgres": "postgres:17-alpine"
},
"catalog_images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15",
"tandoor-postgres": "postgres:17-alpine"
},
"live_compose_image_lines": [
"image: ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"image: postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"docker_inspect": [
"tandoor ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72 running=true restarts=0",
"tandoor-postgres postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24 running=true restarts=0"
]
},
"setup_gate_before": {
"browser": {
"status": "302",
"redirect": "https://felhom.enkisfelhom.hu/__gate/start?…"
},
"script": {
"status": "401",
"redirect": null
}
},
"seed": "read_back",
"drill_commit": "973e46f0faee",
"sync_waited_s": 4.5,
"badge_before": {
"hu": [
{
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
"text": "Frissítés elérhető — ma"
}
],
"en": [
{
"title": "A newer version of this app is available. Select the Update button to start it.",
"text": "Update available — today"
}
]
},
"measured_at": "2026-10-28T08:42:49Z",
"update": {
"accepted": true,
"http": "202",
"phases": [
{
"t": 0.0,
"phase": "backing-up",
"label": "Biztonsági mentés készül a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 14.4,
"phase": "safety-dump",
"label": "Adatbázis pillanatkép…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 15.4,
"phase": "pulling",
"label": "Új verzió letöltése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 74.9,
"phase": "copying",
"label": "Az adatok másolása a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 84.1,
"phase": "starting",
"label": "Indítás az új verzióval…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 90.3,
"phase": "verifying",
"label": "Működés ellenőrzése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 116.0,
"phase": "done",
"label": "Frissítve",
"updating": false,
"error": null,
"hold": null
}
],
"duration_s": 116.0,
"final_phase": "done",
"update_error": null,
"hold_reason": null,
"state": "running"
},
"observables_after": {
"pinned_images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.7.2",
"tandoor-postgres": "postgres:17-alpine"
},
"installed_images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.7.2",
"tandoor-postgres": "postgres:17-alpine"
},
"catalog_images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.7.2",
"tandoor-postgres": "postgres:17-alpine"
},
"live_compose_image_lines": [
"image: ghcr.io/tandoorrecipes/recipes:2.7.2",
"image: postgres:17-alpine"
],
"docker_inspect": [
"tandoor ghcr.io/tandoorrecipes/recipes:2.7.2 running=true restarts=0",
"tandoor-postgres postgres:17-alpine running=true restarts=0"
]
},
"badge_after": {
"hu": [
{
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
"text": "Naprakész"
}
],
"en": [
{
"title": "This app is running the newest version available.",
"text": "Up to date"
}
]
},
"state_after": "running",
"hold_after": null,
"to_digests": {
"tandoor": "sha256:1b6d43c3c0f5d2888aa564d9daf29883212b79ad496f59f3c684c099eb1a57b9",
"tandoor-postgres": "sha256:266d3c257594e195b309ae9d1805e54c788f1d7b375f56bf6c367aac6c917e7b"
},
"four_observables": {
"pinned": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.7.2",
"tandoor-postgres": "postgres:17-alpine"
},
"installed": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.7.2",
"tandoor-postgres": "postgres:17-alpine"
},
"catalog": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.7.2",
"tandoor-postgres": "postgres:17-alpine"
},
"live_compose": [
"ghcr.io/tandoorrecipes/recipes:2.7.2",
"postgres:17-alpine"
]
},
"seed_read_after": true,
"setup_gate_after": {
"browser": {
"status": "302",
"redirect": "https://felhom.enkisfelhom.hu/__gate/start?…"
},
"script": {
"status": "401",
"redirect": null
}
},
"memory": {
"soak_s": 600,
"interval_s": 10,
"samples": 118,
"containers": {
"tandoor": {
"samples": 59,
"anon_peak_bytes": 843780096,
"limit_bytes": 1342177280,
"anon_peak_pct": 62.9,
"cgroup_peak_pct": 75.6,
"oom_kill_delta": 0,
"oom_killed_flag": false,
"restarts_delta": 0,
"running_all_samples": true,
"cgroup": "/sys/fs/cgroup/system.slice/docker-7e267d40de56cade5b109219bdb14a497eef99f7aebd2cfefe26b30ce04b5fcd.scope"
},
"tandoor-postgres": {
"samples": 59,
"anon_peak_bytes": 8794112,
"limit_bytes": 268435456,
"anon_peak_pct": 3.3,
"cgroup_peak_pct": 13.6,
"oom_kill_delta": 0,
"oom_killed_flag": false,
"restarts_delta": 0,
"running_all_samples": true,
"cgroup": "/sys/fs/cgroup/system.slice/docker-23e8a5b9b354887e951635ebb2ae3c1a40cd1505602f1ffc1b5aa0fd64bedeed.scope"
}
},
"oom_kills": 0,
"restarts": 0,
"peak_pct": 62.9
},
"why": "the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back",
"log": [
"09:39:50 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}",
"09:42:06 [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}",
"09:42:06 gate: recipes is gated — passed as the household (cookie set)",
"09:42:10 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}",
"09:42:21 tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.",
"09:42:26 tandoor: seeded superuser drillf3a74a",
"09:42:35 tandoor: readback of the seeded account found=True",
"09:42:36 [5] drill commit 973e46f0faee: tandoor ghcr.io/tandoorrecipes/recipes:2.6.15 -> ghcr.io/tandoorrecipes/recipes:2.7.2 (push rc=0)",
"09:42:44 [5] the box's drill mirror now at 973e46f0f",
"09:42:49 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}",
"09:42:49 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None",
"09:43:03 + 14.4s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None",
"09:43:04 + 15.4s phase=pulling label=Új verzió letöltése… err=None hold=None",
"09:44:04 + 74.9s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None",
"09:44:13 + 84.1s phase=starting label=Indítás az új verzióval… err=None hold=None",
"09:44:19 + 90.3s phase=verifying label=Működés ellenőrzése… err=None hold=None",
"09:44:45 + 116.0s phase=done label=Frissítve err=None hold=None",
"09:45:13 tandoor: readback of the seeded account found=True",
"09:45:13 [7] memory soak 600 s …",
"09:55:20 [7] soak: peak 62.9% of the limit (anon), kills 0, restarts 0"
]
}
@@ -0,0 +1,25 @@
09:39:50 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:42:06 [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
09:42:06 gate: recipes is gated — passed as the household (cookie set)
09:42:10 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}
09:42:21 tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
09:42:26 tandoor: seeded superuser drillf3a74a
09:42:35 tandoor: readback of the seeded account found=True
09:42:36 [5] drill commit 973e46f0faee: tandoor ghcr.io/tandoorrecipes/recipes:2.6.15 -> ghcr.io/tandoorrecipes/recipes:2.7.2 (push rc=0)
09:42:44 [5] the box's drill mirror now at 973e46f0f
09:42:49 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
09:42:49 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
09:43:03 + 14.4s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
09:43:04 + 15.4s phase=pulling label=Új verzió letöltése… err=None hold=None
09:44:04 + 74.9s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
09:44:13 + 84.1s phase=starting label=Indítás az új verzióval… err=None hold=None
09:44:19 + 90.3s phase=verifying label=Működés ellenőrzése… err=None hold=None
09:44:45 + 116.0s phase=done label=Frissítve err=None hold=None
09:45:13 tandoor: readback of the seeded account found=True
09:45:13 [7] memory soak 600 s …
09:55:20 [7] soak: peak 62.9% of the limit (anon), kills 0, restarts 0
09:55:20 [9] verdict proven -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/runtime-fixes-2026-10-28/walks/tandoor/verdict.json
09:55:20 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back
09:55:22 [X] stop -> 200 {'ok': True, 'message': 'Stack tandoor stop completed'}
09:55:54 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'tandoor', 'volumes_removed': ['tandoor_tandoor_media', 'tandoor_tandoor_postgres_data', 'tandoor_tandoor_static'], 'hdd_paths_
09:56:03 [X] after remove: deployed=False leftovers=''
@@ -0,0 +1,260 @@
{
"app": "zipline",
"walk": "security",
"box_walk_version": 1,
"verdict": "proven",
"venue": "box 9202 (drill catalog), the guarded Update",
"from": {
"zipline": "ghcr.io/diced/zipline:4.8.0",
"zipline-postgres": "postgres:16-alpine"
},
"to": {
"zipline": "ghcr.io/diced/zipline:4.8.2",
"zipline-postgres": "postgres:16-alpine"
},
"observables_before": {
"pinned_images": {
"zipline": "ghcr.io/diced/zipline:4.8.0",
"zipline-postgres": "postgres:16-alpine"
},
"installed_images": {
"zipline": "ghcr.io/diced/zipline:4.8.0",
"zipline-postgres": "postgres:16-alpine"
},
"catalog_images": {
"zipline": "ghcr.io/diced/zipline:4.8.0",
"zipline-postgres": "postgres:16-alpine"
},
"live_compose_image_lines": [
"image: ghcr.io/diced/zipline:4.8.0@sha256:8ae3cdf8cdbba2ac98754e9fc4ccec67bbaa86b6e6ab1ccf9683ddcff85eee72",
"image: postgres:16-alpine@sha256:721873c34ceb9f8d8fc265984940dc982404c105f19ad51be9fdc5970a6080ea"
],
"docker_inspect": [
"zipline ghcr.io/diced/zipline:4.8.0@sha256:8ae3cdf8cdbba2ac98754e9fc4ccec67bbaa86b6e6ab1ccf9683ddcff85eee72 running=true restarts=0",
"zipline-postgres postgres:16-alpine@sha256:721873c34ceb9f8d8fc265984940dc982404c105f19ad51be9fdc5970a6080ea running=true restarts=0"
]
},
"setup_gate_before": {
"browser": {
"status": "302",
"redirect": "https://felhom.enkisfelhom.hu/__gate/start?…"
},
"script": {
"status": "401",
"redirect": null
}
},
"seed": "read_back",
"drill_commit": "072b5e393cf6",
"sync_waited_s": 4.5,
"badge_before": {
"hu": [
{
"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.",
"text": "Frissítés elérhető — ma"
}
],
"en": [
{
"title": "A newer version of this app is available. Select the Update button to start it.",
"text": "Update available — today"
}
]
},
"measured_at": "2026-10-28T08:05:35Z",
"update": {
"accepted": true,
"http": "202",
"phases": [
{
"t": 0.0,
"phase": "backing-up",
"label": "Biztonsági mentés készül a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 21.5,
"phase": "safety-dump",
"label": "Adatbázis pillanatkép…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 22.6,
"phase": "pulling",
"label": "Új verzió letöltése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 75.8,
"phase": "copying",
"label": "Az adatok másolása a frissítés előtt…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 94.3,
"phase": "starting",
"label": "Indítás az új verzióval…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 100.4,
"phase": "verifying",
"label": "Működés ellenőrzése…",
"updating": true,
"error": null,
"hold": null
},
{
"t": 110.6,
"phase": "done",
"label": "Frissítve",
"updating": false,
"error": null,
"hold": null
}
],
"duration_s": 110.6,
"final_phase": "done",
"update_error": null,
"hold_reason": null,
"state": "running"
},
"observables_after": {
"pinned_images": {
"zipline": "ghcr.io/diced/zipline:4.8.2",
"zipline-postgres": "postgres:16-alpine"
},
"installed_images": {
"zipline": "ghcr.io/diced/zipline:4.8.2",
"zipline-postgres": "postgres:16-alpine"
},
"catalog_images": {
"zipline": "ghcr.io/diced/zipline:4.8.2",
"zipline-postgres": "postgres:16-alpine"
},
"live_compose_image_lines": [
"image: ghcr.io/diced/zipline:4.8.2",
"image: postgres:16-alpine"
],
"docker_inspect": [
"zipline ghcr.io/diced/zipline:4.8.2 running=true restarts=0",
"zipline-postgres postgres:16-alpine running=true restarts=0"
]
},
"badge_after": {
"hu": [
{
"title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.",
"text": "Naprakész"
}
],
"en": [
{
"title": "This app is running the newest version available.",
"text": "Up to date"
}
]
},
"state_after": "running",
"hold_after": null,
"to_digests": {
"zipline": "sha256:cb3769f50a5887e38d678ab466656bd2a56f3ce96bc8a4d0788cc479d19c05c9",
"zipline-postgres": "sha256:0cefaabd882e42bcb2a2f3dc56d3ce4770560ba62fd7f197f1a2e008fd5731ab"
},
"four_observables": {
"pinned": {
"zipline": "ghcr.io/diced/zipline:4.8.2",
"zipline-postgres": "postgres:16-alpine"
},
"installed": {
"zipline": "ghcr.io/diced/zipline:4.8.2",
"zipline-postgres": "postgres:16-alpine"
},
"catalog": {
"zipline": "ghcr.io/diced/zipline:4.8.2",
"zipline-postgres": "postgres:16-alpine"
},
"live_compose": [
"ghcr.io/diced/zipline:4.8.2",
"postgres:16-alpine"
]
},
"seed_read_after": true,
"setup_gate_after": {
"browser": {
"status": "404",
"redirect": null
},
"script": {
"status": "404",
"redirect": null
}
},
"memory": {
"soak_s": 600,
"interval_s": 10,
"samples": 118,
"containers": {
"zipline": {
"samples": 59,
"anon_peak_bytes": 179974144,
"limit_bytes": 536870912,
"anon_peak_pct": 33.5,
"cgroup_peak_pct": 48.3,
"oom_kill_delta": 0,
"oom_killed_flag": false,
"restarts_delta": 0,
"running_all_samples": true,
"cgroup": "/sys/fs/cgroup/system.slice/docker-13cd0ec3d1257598b49987d95f62ce6a3cf94d6997196e41b292a2619eaa304f.scope"
},
"zipline-postgres": {
"samples": 59,
"anon_peak_bytes": 6164480,
"limit_bytes": 268435456,
"anon_peak_pct": 2.3,
"cgroup_peak_pct": 17.4,
"oom_kill_delta": 0,
"oom_killed_flag": false,
"restarts_delta": 0,
"running_all_samples": true,
"cgroup": "/sys/fs/cgroup/system.slice/docker-bf142392d0a604ed9cc5b68fef18b51cea14b83f443aca529af314bc093242ff.scope"
}
},
"oom_kills": 0,
"restarts": 0,
"peak_pct": 33.5
},
"why": "the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back",
"log": [
"08:59:00 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}",
"09:00:15 [1] deployed, controller state=running, pinned={'zipline': 'ghcr.io/diced/zipline:4.8.0', 'zipline-postgres': 'postgres:16-alpine'}",
"09:00:15 gate: img is gated — passed as the household (cookie set)",
"09:05:17 app never answered on img/ (last rc=0 code=301)",
"09:05:20 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}",
"09:05:21 zipline: /api/setup http=200 :: {\"firstSetup\":false,\"user\":{\"id\":\"xipzcpgaywzis7vuz6tguewd\",\"username\":\"drillef0b08\",\"createdAt\":\"2026-10-28T08:05:20.978Z\",\"updatedAt\":\"2026-10-28T08:05:20.982",
"09:05:21 zipline: login as the seeded user http=200 ok=True",
"09:05:22 [5] drill commit 072b5e393cf6: zipline ghcr.io/diced/zipline:4.8.0 -> ghcr.io/diced/zipline:4.8.2 (push rc=0)",
"09:05:30 [5] the box's drill mirror now at 072b5e393",
"09:05:35 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}",
"09:05:35 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None",
"09:05:57 + 21.5s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None",
"09:05:58 + 22.6s phase=pulling label=Új verzió letöltése… err=None hold=None",
"09:06:51 + 75.8s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None",
"09:07:09 + 94.3s phase=starting label=Indítás az új verzióval… err=None hold=None",
"09:07:16 + 100.4s phase=verifying label=Működés ellenőrzése… err=None hold=None",
"09:07:26 + 110.6s phase=done label=Frissítve err=None hold=None",
"09:07:45 zipline: login as the seeded user http=200 ok=True",
"09:07:45 [7] memory soak 600 s …",
"09:17:52 [7] soak: peak 33.5% of the limit (anon), kills 0, restarts 0"
]
}
@@ -0,0 +1,25 @@
08:59:00 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:00:15 [1] deployed, controller state=running, pinned={'zipline': 'ghcr.io/diced/zipline:4.8.0', 'zipline-postgres': 'postgres:16-alpine'}
09:00:15 gate: img is gated — passed as the household (cookie set)
09:05:17 app never answered on img/ (last rc=0 code=301)
09:05:20 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}
09:05:21 zipline: /api/setup http=200 :: {"firstSetup":false,"user":{"id":"xipzcpgaywzis7vuz6tguewd","username":"drillef0b08","createdAt":"2026-10-28T08:05:20.978Z","updatedAt":"2026-10-28T08:05:20.982
09:05:21 zipline: login as the seeded user http=200 ok=True
09:05:22 [5] drill commit 072b5e393cf6: zipline ghcr.io/diced/zipline:4.8.0 -> ghcr.io/diced/zipline:4.8.2 (push rc=0)
09:05:30 [5] the box's drill mirror now at 072b5e393
09:05:35 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
09:05:35 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
09:05:57 + 21.5s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
09:05:58 + 22.6s phase=pulling label=Új verzió letöltése… err=None hold=None
09:06:51 + 75.8s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
09:07:09 + 94.3s phase=starting label=Indítás az új verzióval… err=None hold=None
09:07:16 + 100.4s phase=verifying label=Működés ellenőrzése… err=None hold=None
09:07:26 + 110.6s phase=done label=Frissítve err=None hold=None
09:07:45 zipline: login as the seeded user http=200 ok=True
09:07:45 [7] memory soak 600 s …
09:17:52 [7] soak: peak 33.5% of the limit (anon), kills 0, restarts 0
09:17:52 [9] verdict proven -> /mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/runtime-fixes-2026-10-28/walks/zipline/verdict.json
09:17:52 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back
09:18:03 [X] stop -> 200 {'ok': True, 'message': 'Stack zipline stop completed'}
09:18:35 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'zipline', 'volumes_removed': ['zipline_zipline_postgres_data', 'zipline_zipline_public', 'zipline_zipline_uploads'], 'hdd_path
09:18:43 [X] after remove: deployed=False leftovers=''