Part C/D: gate built + proven live (v0.280.0), defaults fixed, floor 0.280.0; decision 46 outcome; 01 §5 who may reach an app; R-707 narrowed, R-708/R-709/R-712 closed, R-713 filed
gates / gates (push) Successful in 26s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-29 09:20:47 +02:00
parent 14ae67f0b8
commit b0f8ffb801
46 changed files with 1632 additions and 4 deletions
@@ -0,0 +1,5 @@
before: gitea.dooplex.hu/admin/felhom-controller:0.279.0
gitea.dooplex.hu/admin/felhom-controller:0.280.0 Up 8 seconds (healthy)
2026/09/29 06:53:08 undo.go:675: [INFO] [stacks] applied-meta backfill (R-646): recorded 0 []; skipped 0 [] — not current with the catalog, their pinned version's .felhom.yml is no longer on the box
2026/09/29 06:53:08 scheduler.go:102: [INFO] [scheduler] Registered periodic job: conversion-copy-release (every 1h0m0s)
2026/09/29 06:53:08 scheduler.go:67: [DEBUG] [scheduler] periodic job registered: name="conversion-copy-release" interval=1h0m0s totalJobs=10
@@ -0,0 +1,16 @@
09:03:37 immich catalog meta: setup_gate = True probe = isInitialized
09:03:40 [1] made the drive paths this app requires: ['/mnt/felhom-drives/scratch_hdd/userdata/immich']
09:03:40 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
09:03:41 immich deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:03:41 n8n catalog meta: setup_gate = True probe = data.userManagement.showSetupOnFirstLoad
09:03:41 n8n deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:03:41 audiobookshelf catalog meta: setup_gate = True probe = isInit
09:03:44 [1] made the drive paths this app requires: ['/mnt/felhom-drives/scratch_hdd/userdata/audiobookshelf']
09:03:44 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
09:03:44 audiobookshelf deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:03:45 uptime-kuma catalog meta: setup_gate = True probe = None
09:03:45 uptime-kuma deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:04:29 immich state running | gate file present | record {'state': 'closed', 'since': '2026-09-29T07:03:40Z', 'hosts': ['g-immich.enkisfelhom.hu']}
09:04:32 n8n state running | gate file present | record {'state': 'closed', 'since': '2026-09-29T07:03:41Z', 'hosts': ['g-n8n.enkisfelhom.hu']}
09:04:35 audiobookshelf state running | gate file present | record {'state': 'closed', 'since': '2026-09-29T07:03:44Z', 'hosts': ['g-abs.enkisfelhom.hu']}
09:04:49 uptime-kuma state running | gate file present | record {'state': 'closed', 'since': '2026-09-29T07:03:45Z', 'hosts': ['g-kuma.enkisfelhom.hu']}
@@ -0,0 +1,837 @@
# stranger4.sh, 9202, 2026-09-29 07:03:31-07:08Z (UTC): per second, each gated host, API-style + browser-style. Gates opened: immich 07:06:02, n8n+audiobookshelf 07:06:22 (probe), uptime-kuma 07:07:08 (press). The one 500 at 07:06:53 is the controller restart (C6): closed, not open.
07:03:30 g-n8n api=[404 page not found|404] browser=404
07:03:30 g-immich api=[404 page not found|404] browser=404
07:03:30 g-abs api=[404 page not found|404] browser=404
07:03:30 g-kuma api=[404 page not found|404] browser=404
07:03:31 g-n8n api=[404 page not found|404] browser=404
07:03:31 g-immich api=[404 page not found|404] browser=404
07:03:31 g-abs api=[404 page not found|404] browser=404
07:03:31 g-kuma api=[404 page not found|404] browser=404
07:03:32 g-n8n api=[404 page not found|404] browser=404
07:03:32 g-immich api=[404 page not found|404] browser=404
07:03:32 g-abs api=[404 page not found|404] browser=404
07:03:32 g-kuma api=[404 page not found|404] browser=404
07:03:33 g-n8n api=[404 page not found|404] browser=404
07:03:33 g-immich api=[404 page not found|404] browser=404
07:03:33 g-abs api=[404 page not found|404] browser=404
07:03:33 g-kuma api=[404 page not found|404] browser=404
07:03:34 g-n8n api=[404 page not found|404] browser=404
07:03:35 g-immich api=[404 page not found|404] browser=404
07:03:35 g-abs api=[404 page not found|404] browser=404
07:03:35 g-kuma api=[404 page not found|404] browser=404
07:03:36 g-n8n api=[404 page not found|404] browser=404
07:03:36 g-immich api=[404 page not found|404] browser=404
07:03:36 g-abs api=[404 page not found|404] browser=404
07:03:36 g-kuma api=[404 page not found|404] browser=404
07:03:37 g-n8n api=[404 page not found|404] browser=404
07:03:37 g-immich api=[404 page not found|404] browser=404
07:03:37 g-abs api=[404 page not found|404] browser=404
07:03:37 g-kuma api=[404 page not found|404] browser=404
07:03:38 g-n8n api=[404 page not found|404] browser=404
07:03:38 g-immich api=[404 page not found|404] browser=404
07:03:38 g-abs api=[404 page not found|404] browser=404
07:03:38 g-kuma api=[404 page not found|404] browser=404
07:03:39 g-n8n api=[404 page not found|404] browser=404
07:03:39 g-immich api=[404 page not found|404] browser=404
07:03:39 g-abs api=[404 page not found|404] browser=404
07:03:39 g-kuma api=[404 page not found|404] browser=404
07:03:40 g-n8n api=[404 page not found|404] browser=404
07:03:41 g-immich api=[404 page not found|404] browser=404
07:03:41 g-abs api=[404 page not found|404] browser=404
07:03:41 g-kuma api=[404 page not found|404] browser=404
07:03:42 g-n8n api=[404 page not found|404] browser=404
07:03:42 g-immich api=[404 page not found|404] browser=404
07:03:42 g-abs api=[404 page not found|404] browser=404
07:03:42 g-kuma api=[404 page not found|404] browser=404
07:03:43 g-n8n api=[404 page not found|404] browser=404
07:03:43 g-immich api=[404 page not found|404] browser=404
07:03:43 g-abs api=[404 page not found|404] browser=404
07:03:43 g-kuma api=[404 page not found|404] browser=404
07:03:44 g-n8n api=[404 page not found|404] browser=404
07:03:44 g-immich api=[404 page not found|404] browser=404
07:03:44 g-abs api=[404 page not found|404] browser=404
07:03:44 g-kuma api=[404 page not found|404] browser=404
07:03:45 g-n8n api=[404 page not found|404] browser=404
07:03:45 g-immich api=[404 page not found|404] browser=404
07:03:45 g-abs api=[404 page not found|404] browser=404
07:03:45 g-kuma api=[404 page not found|404] browser=404
07:03:46 g-n8n api=[404 page not found|404] browser=404
07:03:47 g-immich api=[404 page not found|404] browser=404
07:03:47 g-abs api=[404 page not found|404] browser=404
07:03:47 g-kuma api=[404 page not found|404] browser=404
07:03:48 g-n8n api=[404 page not found|404] browser=404
07:03:48 g-immich api=[404 page not found|404] browser=404
07:03:48 g-abs api=[404 page not found|404] browser=404
07:03:48 g-kuma api=[404 page not found|404] browser=404
07:03:49 g-n8n api=[404 page not found|404] browser=404
07:03:49 g-immich api=[404 page not found|404] browser=404
07:03:49 g-abs api=[404 page not found|404] browser=404
07:03:49 g-kuma api=[404 page not found|404] browser=404
07:03:50 g-n8n api=[404 page not found|404] browser=404
07:03:50 g-immich api=[404 page not found|404] browser=404
07:03:50 g-abs api=[404 page not found|404] browser=404
07:03:50 g-kuma api=[404 page not found|404] browser=404
07:03:51 g-n8n api=[404 page not found|404] browser=404
07:03:51 g-immich api=[404 page not found|404] browser=404
07:03:51 g-abs api=[404 page not found|404] browser=404
07:03:51 g-kuma api=[404 page not found|404] browser=404
07:03:52 g-n8n api=[404 page not found|404] browser=404
07:03:52 g-immich api=[404 page not found|404] browser=404
07:03:53 g-abs api=[404 page not found|404] browser=404
07:03:53 g-kuma api=[404 page not found|404] browser=404
07:03:54 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:03:54 g-immich api=[404 page not found|404] browser=404
07:03:54 g-abs api=[404 page not found|404] browser=404
07:03:54 g-kuma api=[404 page not found|404] browser=404
07:03:55 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:03:55 g-immich api=[404 page not found|404] browser=404
07:03:55 g-abs api=[404 page not found|404] browser=404
07:03:55 g-kuma api=[404 page not found|404] browser=404
07:03:56 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:03:56 g-immich api=[404 page not found|404] browser=404
07:03:56 g-abs api=[404 page not found|404] browser=404
07:03:56 g-kuma api=[404 page not found|404] browser=404
07:03:57 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:03:57 g-immich api=[404 page not found|404] browser=404
07:03:57 g-abs api=[404 page not found|404] browser=404
07:03:57 g-kuma api=[404 page not found|404] browser=404
07:03:58 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:03:59 g-immich api=[404 page not found|404] browser=404
07:03:59 g-abs api=[404 page not found|404] browser=404
07:03:59 g-kuma api=[404 page not found|404] browser=404
07:04:00 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:00 g-immich api=[404 page not found|404] browser=404
07:04:00 g-abs api=[404 page not found|404] browser=404
07:04:00 g-kuma api=[404 page not found|404] browser=404
07:04:01 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:01 g-immich api=[404 page not found|404] browser=404
07:04:01 g-abs api=[404 page not found|404] browser=404
07:04:01 g-kuma api=[404 page not found|404] browser=404
07:04:02 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:02 g-immich api=[404 page not found|404] browser=404
07:04:02 g-abs api=[404 page not found|404] browser=404
07:04:02 g-kuma api=[404 page not found|404] browser=404
07:04:03 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:03 g-immich api=[404 page not found|404] browser=404
07:04:03 g-abs api=[404 page not found|404] browser=404
07:04:03 g-kuma api=[404 page not found|404] browser=404
07:04:04 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:05 g-immich api=[404 page not found|404] browser=404
07:04:05 g-abs api=[404 page not found|404] browser=404
07:04:05 g-kuma api=[404 page not found|404] browser=404
07:04:06 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:06 g-immich api=[404 page not found|404] browser=404
07:04:06 g-abs api=[404 page not found|404] browser=404
07:04:06 g-kuma api=[404 page not found|404] browser=404
07:04:07 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:07 g-immich api=[404 page not found|404] browser=404
07:04:07 g-abs api=[404 page not found|404] browser=404
07:04:07 g-kuma api=[404 page not found|404] browser=404
07:04:08 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:08 g-immich api=[404 page not found|404] browser=404
07:04:08 g-abs api=[404 page not found|404] browser=404
07:04:08 g-kuma api=[404 page not found|404] browser=404
07:04:09 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:09 g-immich api=[404 page not found|404] browser=404
07:04:09 g-abs api=[404 page not found|404] browser=404
07:04:09 g-kuma api=[404 page not found|404] browser=404
07:04:11 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:11 g-immich api=[404 page not found|404] browser=404
07:04:11 g-abs api=[404 page not found|404] browser=404
07:04:11 g-kuma api=[404 page not found|404] browser=404
07:04:12 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:12 g-immich api=[404 page not found|404] browser=404
07:04:12 g-abs api=[404 page not found|404] browser=404
07:04:12 g-kuma api=[404 page not found|404] browser=404
07:04:13 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:13 g-immich api=[404 page not found|404] browser=404
07:04:13 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:13 g-kuma api=[404 page not found|404] browser=404
07:04:14 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:14 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:14 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:14 g-kuma api=[404 page not found|404] browser=404
07:04:15 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:15 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:15 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:15 g-kuma api=[404 page not found|404] browser=404
07:04:17 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:17 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:17 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:17 g-kuma api=[404 page not found|404] browser=404
07:04:18 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:18 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:18 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:18 g-kuma api=[404 page not found|404] browser=404
07:04:19 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:19 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:19 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:19 g-kuma api=[404 page not found|404] browser=404
07:04:20 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:20 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:20 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:20 g-kuma api=[404 page not found|404] browser=404
07:04:21 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:21 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:21 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:21 g-kuma api=[404 page not found|404] browser=404
07:04:23 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:23 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:23 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:23 g-kuma api=[404 page not found|404] browser=404
07:04:24 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:24 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:24 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:24 g-kuma api=[404 page not found|404] browser=404
07:04:25 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:25 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:25 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:25 g-kuma api=[404 page not found|404] browser=404
07:04:26 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:26 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:26 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:26 g-kuma api=[404 page not found|404] browser=404
07:04:27 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:27 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:27 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:28 g-kuma api=[404 page not found|404] browser=404
07:04:29 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:29 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:29 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:29 g-kuma api=[404 page not found|404] browser=404
07:04:30 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:30 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:30 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:30 g-kuma api=[404 page not found|404] browser=404
07:04:31 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:31 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:31 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:31 g-kuma api=[404 page not found|404] browser=404
07:04:32 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:32 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:32 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:32 g-kuma api=[404 page not found|404] browser=404
07:04:33 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:33 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:33 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:34 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:35 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:35 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:35 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:35 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:36 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:36 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:36 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:36 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:37 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:37 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:37 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:37 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:38 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:38 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:38 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:38 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:39 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:39 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:39 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:40 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:41 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:41 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:41 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:41 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:42 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:42 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:42 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:42 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:43 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:43 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:43 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:43 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:44 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:44 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:44 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:44 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:45 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:45 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:45 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:46 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:47 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:47 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:47 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:47 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:48 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:48 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:48 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:48 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:49 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:49 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:49 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:49 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:50 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:50 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:50 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:50 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:51 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:51 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:51 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:51 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:53 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:53 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:53 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:53 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:54 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:54 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:54 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:54 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:55 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:55 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:55 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:55 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:56 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:56 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:56 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:56 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:57 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:57 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:57 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:58 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:59 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:59 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:59 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:04:59 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:00 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:00 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:00 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:00 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:01 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:01 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:01 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:01 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:02 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:02 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:02 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:02 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:03 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:03 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:04 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:04 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:05 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:05 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:05 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:05 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:06 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:06 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:06 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:06 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:07 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:07 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:07 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:07 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:08 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:08 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:08 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:08 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:09 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:09 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:10 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:10 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:11 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:11 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:11 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:11 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:12 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:12 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:12 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:12 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:13 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:13 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:13 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:13 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:14 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:14 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:14 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:14 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:15 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:16 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:16 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:16 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:17 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:17 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:17 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:17 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:18 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:18 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:18 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:18 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:19 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:19 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:19 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:19 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:20 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:20 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:20 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:20 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:21 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:21 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:22 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:22 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:23 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:23 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:23 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:23 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:24 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:24 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:24 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:24 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:25 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:25 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:25 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:25 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:26 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:26 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:26 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:26 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:27 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:28 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:28 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:28 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:29 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:29 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:29 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:29 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:30 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:30 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:30 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:30 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:31 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:31 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:31 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:31 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:32 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:32 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:32 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:32 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:33 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:34 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:34 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:34 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:35 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:35 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:35 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:35 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:36 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:36 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:36 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:36 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:37 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:37 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:37 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:37 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:38 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:38 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:38 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:38 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:39 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:40 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:40 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:40 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:41 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:41 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:41 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:41 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:42 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:42 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:42 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:42 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:43 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:43 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:43 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:43 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:44 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:44 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:44 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:44 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:46 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:46 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:46 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:46 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:47 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:47 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:47 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:47 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:48 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:48 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:48 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:48 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:49 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:49 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:49 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:49 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:50 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:50 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:50 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:50 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:51 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:52 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:52 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:52 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:53 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:53 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:53 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:53 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:54 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:54 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:54 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:54 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:55 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:55 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:55 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:55 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:56 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:56 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:56 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:56 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:57 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:58 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:58 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:58 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:59 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:59 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:59 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:05:59 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:00 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:00 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:00 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:00 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:01 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:01 g-immich api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:01 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:01 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:02 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:02 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:02 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:02 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:03 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:04 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:04 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:04 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:05 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:05 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:05 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:05 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:06 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:06 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:06 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:06 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:07 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:07 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:07 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:07 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:08 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:08 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:08 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:08 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:09 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:10 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:10 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:10 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:11 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:11 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:11 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:11 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:12 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:12 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:12 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:12 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:13 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:13 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:13 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:13 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:14 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:14 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:14 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:14 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:16 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:16 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:16 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:16 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:17 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:17 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:17 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:17 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:18 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:18 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:18 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:18 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:19 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:19 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:19 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:19 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:20 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:20 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:20 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:20 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:22 g-n8n api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:22 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:22 g-abs api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:22 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:23 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:23 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:23 g-abs api=[Unauthorized|401] browser=200
07:06:23 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:24 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:24 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:24 g-abs api=[Unauthorized|401] browser=200
07:06:24 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:25 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:25 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:25 g-abs api=[Unauthorized|401] browser=200
07:06:25 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:26 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:26 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:27 g-abs api=[Unauthorized|401] browser=200
07:06:27 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:28 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:28 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:28 g-abs api=[Unauthorized|401] browser=200
07:06:28 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:29 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:29 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:29 g-abs api=[Unauthorized|401] browser=200
07:06:29 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:30 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:30 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:30 g-abs api=[Unauthorized|401] browser=200
07:06:30 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:31 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:31 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:31 g-abs api=[Unauthorized|401] browser=200
07:06:31 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:32 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:33 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:33 g-abs api=[Unauthorized|401] browser=200
07:06:33 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:34 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:34 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:34 g-abs api=[Unauthorized|401] browser=200
07:06:34 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:35 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:35 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:35 g-abs api=[Unauthorized|401] browser=200
07:06:35 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:36 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:36 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:36 g-abs api=[Unauthorized|401] browser=200
07:06:36 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:37 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:37 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:37 g-abs api=[Unauthorized|401] browser=200
07:06:37 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:39 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:39 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:39 g-abs api=[Unauthorized|401] browser=200
07:06:39 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:40 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:40 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:40 g-abs api=[Unauthorized|401] browser=200
07:06:40 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:41 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:41 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:41 g-abs api=[Unauthorized|401] browser=200
07:06:41 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:42 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:42 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:42 g-abs api=[Unauthorized|401] browser=200
07:06:42 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:43 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:43 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:43 g-abs api=[Unauthorized|401] browser=200
07:06:44 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:45 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:45 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:45 g-abs api=[Unauthorized|401] browser=200
07:06:45 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:46 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:46 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:46 g-abs api=[Unauthorized|401] browser=200
07:06:46 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:47 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:47 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:47 g-abs api=[Unauthorized|401] browser=200
07:06:47 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:48 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:48 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:48 g-abs api=[Unauthorized|401] browser=200
07:06:48 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:49 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:50 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:50 g-abs api=[Unauthorized|401] browser=200
07:06:50 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:51 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:51 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:51 g-abs api=[Unauthorized|401] browser=200
07:06:51 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:52 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:52 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:52 g-abs api=[Unauthorized|401] browser=200
07:06:52 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:53 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:53 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:53 g-abs api=[Unauthorized|401] browser=200
07:06:53 g-kuma api=[|500] browser=500
07:06:54 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:54 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:55 g-abs api=[Unauthorized|401] browser=200
07:06:55 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:56 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:56 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:56 g-abs api=[Unauthorized|401] browser=200
07:06:56 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:57 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:57 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:57 g-abs api=[Unauthorized|401] browser=200
07:06:57 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:58 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:58 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:58 g-abs api=[Unauthorized|401] browser=200
07:06:58 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:06:59 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:06:59 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:06:59 g-abs api=[Unauthorized|401] browser=200
07:06:59 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:07:00 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:01 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:01 g-abs api=[Unauthorized|401] browser=200
07:07:01 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:07:02 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:02 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:02 g-abs api=[Unauthorized|401] browser=200
07:07:02 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:07:03 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:03 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:03 g-abs api=[Unauthorized|401] browser=200
07:07:03 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:07:04 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:04 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:04 g-abs api=[Unauthorized|401] browser=200
07:07:04 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:07:05 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:05 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:05 g-abs api=[Unauthorized|401] browser=200
07:07:05 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:07:07 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:07 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:07 g-abs api=[Unauthorized|401] browser=200
07:07:07 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:07:08 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:08 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:08 g-abs api=[Unauthorized|401] browser=200
07:07:08 g-kuma api=[{"error":"this app is waiting for its first setup"}|401] browser=302
07:07:09 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:09 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:09 g-abs api=[Unauthorized|401] browser=200
07:07:09 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:10 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:10 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:10 g-abs api=[Unauthorized|401] browser=200
07:07:10 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:11 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:11 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:11 g-abs api=[Unauthorized|401] browser=200
07:07:12 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:13 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:13 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:13 g-abs api=[Unauthorized|401] browser=200
07:07:13 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:14 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:14 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:14 g-abs api=[Unauthorized|401] browser=200
07:07:14 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:15 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:15 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:15 g-abs api=[Unauthorized|401] browser=200
07:07:15 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:16 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:16 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:16 g-abs api=[Unauthorized|401] browser=200
07:07:16 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:17 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:18 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:18 g-abs api=[Unauthorized|401] browser=200
07:07:18 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:19 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:19 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:19 g-abs api=[Unauthorized|401] browser=200
07:07:19 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:20 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:20 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:20 g-abs api=[Unauthorized|401] browser=200
07:07:20 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:21 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:21 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:21 g-abs api=[Unauthorized|401] browser=200
07:07:21 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:22 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:22 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:22 g-abs api=[Unauthorized|401] browser=200
07:07:22 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:23 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:24 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:24 g-abs api=[Unauthorized|401] browser=200
07:07:24 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:25 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:25 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:25 g-abs api=[Unauthorized|401] browser=200
07:07:25 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:26 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:26 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:26 g-abs api=[Unauthorized|401] browser=200
07:07:26 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:27 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:27 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:27 g-abs api=[Unauthorized|401] browser=200
07:07:27 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:28 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:28 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:28 g-abs api=[Unauthorized|401] browser=200
07:07:29 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:30 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:30 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:30 g-abs api=[Unauthorized|401] browser=200
07:07:30 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:31 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:31 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:31 g-abs api=[Unauthorized|401] browser=200
07:07:31 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:32 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:32 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:32 g-abs api=[Unauthorized|401] browser=200
07:07:32 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:33 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:33 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:33 g-abs api=[Unauthorized|401] browser=200
07:07:33 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:34 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:34 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:35 g-abs api=[Unauthorized|401] browser=200
07:07:35 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:36 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:36 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:36 g-abs api=[Unauthorized|401] browser=200
07:07:36 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:37 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:37 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:37 g-abs api=[Unauthorized|401] browser=200
07:07:37 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:38 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:38 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:38 g-abs api=[Unauthorized|401] browser=200
07:07:38 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:39 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:39 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:39 g-abs api=[Unauthorized|401] browser=200
07:07:39 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
07:07:41 g-n8n api=[<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C] browser=200
07:07:41 g-immich api=[{"message":"Cannot GET /api/x"}|404] browser=200
07:07:41 g-abs api=[Unauthorized|401] browser=200
07:07:41 g-kuma api=[<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport"] browser=302
@@ -0,0 +1,4 @@
09:05:53 immich STRANGER: browser -> 200 302 g-immich.enkisfelhom.hu/ -> 200 felhom.enkisfelhom.hu/__gate/start gate-page(en,hu-ascii)=(False, True) | api POST -> 401 '{"error":"this app is waiting for its first setup"}'
09:05:53 n8n STRANGER: browser -> 200 302 g-n8n.enkisfelhom.hu/ -> 200 felhom.enkisfelhom.hu/__gate/start gate-page(en,hu-ascii)=(False, True) | api POST -> 401 '{"error":"this app is waiting for its first setup"}'
09:05:53 audiobookshelf STRANGER: browser -> 200 302 g-abs.enkisfelhom.hu/ -> 200 felhom.enkisfelhom.hu/__gate/start gate-page(en,hu-ascii)=(False, True) | api POST -> 401 '{"error":"this app is waiting for its first setup"}'
09:05:53 uptime-kuma STRANGER: browser -> 200 302 g-kuma.enkisfelhom.hu/ -> 200 felhom.enkisfelhom.hu/__gate/start gate-page(en,hu-ascii)=(False, True) | api POST -> 401 '{"error":"this app is waiting for its first setup"}'
@@ -0,0 +1,6 @@
09:05:54 dashboard login -> 200 302 felhom.enkisfelhom.hu/login -> 302 felhom.enkisfelhom.hu/ -> 200 felhom.enkisfelhom.hu/launcher
09:05:54 immich HOUSEHOLD browser -> 200 in 0.20s | 302 g-immich.enkisfelhom.hu/ -> 302 felhom.enkisfelhom.hu/__gate/start -> 302 g-immich.enkisfelhom.hu/__felhom_gate/cb -> 200 g-immich.enkisfelhom.hu/ | gate page: False | len 10699
09:05:54 n8n HOUSEHOLD browser -> 200 in 0.21s | 302 g-n8n.enkisfelhom.hu/ -> 302 felhom.enkisfelhom.hu/__gate/start -> 302 g-n8n.enkisfelhom.hu/__felhom_gate/cb -> 200 g-n8n.enkisfelhom.hu/ | gate page: False | len 52122
09:05:54 audiobookshelf HOUSEHOLD browser -> 200 in 0.20s | 302 g-abs.enkisfelhom.hu/ -> 302 felhom.enkisfelhom.hu/__gate/start -> 302 g-abs.enkisfelhom.hu/__felhom_gate/cb -> 200 g-abs.enkisfelhom.hu/ | gate page: False | len 4136
09:05:54 uptime-kuma HOUSEHOLD browser -> 200 in 0.26s | 302 g-kuma.enkisfelhom.hu/ -> 302 felhom.enkisfelhom.hu/__gate/start -> 302 g-kuma.enkisfelhom.hu/__felhom_gate/cb -> 302 g-kuma.enkisfelhom.hu/ -> 200 g-kuma.enkisfelhom.hu/dashboard | gate page: False | len 1200
09:05:54 cookies per host: {'felhom.enkisfelhom.hu': ['felhom_session'], 'g-immich.enkisfelhom.hu': ['felhom_gate'], 'g-n8n.enkisfelhom.hu': ['felhom_gate'], 'g-abs.enkisfelhom.hu': ['felhom_gate'], 'g-kuma.enkisfelhom.hu': ['felhom_gate']}
@@ -0,0 +1,3 @@
09:06:02 immich admin-sign-up through the gate -> 201
09:06:02 n8n owner setup through the gate -> 200
09:06:02 audiobookshelf POST /init through the gate -> 200 OK
@@ -0,0 +1,4 @@
09:06:06 immich gate OPEN after 0s: record {'state': 'open', 'since': '2026-09-29T07:03:40Z', 'hosts': ['g-immich.enkisfelhom.hu'], 'opened_at': '2026-09-29T07:06:02Z', 'opened_by': 'probe'} | file absent
09:06:30 audiobookshelf gate OPEN after 24s: record {'state': 'open', 'since': '2026-09-29T07:03:44Z', 'hosts': ['g-abs.enkisfelhom.hu'], 'opened_at': '2026-09-29T07:06:22Z', 'opened_by': 'probe'} | file absent
09:06:33 n8n gate OPEN after 27s: record {'state': 'open', 'since': '2026-09-29T07:03:41Z', 'hosts': ['g-n8n.enkisfelhom.hu'], 'opened_at': '2026-09-29T07:06:22Z', 'opened_by': 'probe'} | file absent
09:06:41 uptime-kuma (no probe): {'state': 'closed', 'since': '2026-09-29T07:03:45Z', 'hosts': ['g-kuma.enkisfelhom.hu']} | file present
@@ -0,0 +1,6 @@
controller: Up 6 seconds (healthy)
controller.yml
serverstransports.yml
setup-gate-uptime-kuma.yml
after restart, stranger -> 200 302 g-kuma.enkisfelhom.hu/ -> 200 felhom.enkisfelhom.hu/__gate/start | gate page (hu-ascii): True
after restart, household with its gate cookie only (no dashboard session) -> 200 200 g-kuma.enkisfelhom.hu/dashboard
@@ -0,0 +1,5 @@
09:07:08 uptime-kuma app page: gate card True | button True
09:07:08 household presses 'Done, I set it up' -> 200 {'data': {'opened': True}, 'error': '', 'ok': True}
09:07:11 uptime-kuma record {'state': 'open', 'since': '2026-09-29T07:03:45Z', 'hosts': ['g-kuma.enkisfelhom.hu'], 'opened_at': '2026-09-29T07:07:08Z', 'opened_by': 'household'} | file absent
09:07:11 second press -> 409 {'data': None, 'error': 'Ez az alkalmazás már nyitva van.', 'ok': False}
09:07:14 uptime-kuma, stranger after the press -> 200 302 g-kuma.enkisfelhom.hu/ -> 200 g-kuma.enkisfelhom.hu/dashboard | gate page: False
@@ -0,0 +1,9 @@
09:07:14 immich AFTER OPEN, stranger browser -> 200 200 g-immich.enkisfelhom.hu/ | gate page: False
09:07:14 n8n AFTER OPEN, stranger browser -> 200 200 g-n8n.enkisfelhom.hu/ | gate page: False
09:07:14 audiobookshelf AFTER OPEN, stranger browser -> 200 200 g-abs.enkisfelhom.hu/ | gate page: False
09:07:15 immich phone app: login -> 201 token
09:07:15 immich phone app GET /api/users/me -> 200
09:07:15 immich phone app GET /api/server/ping -> 200
09:07:15 immich phone app GET /api/server/version -> 200
09:07:15 n8n login, no browser gate cookie -> 200
09:07:15 audiobookshelf login (its phone app's route), no gate cookie -> 200
@@ -0,0 +1,4 @@
## 2026-09-29T07:19:29Z floor 0.279.0 -> 0.280.0 (min_agent 0.131.0 from the v0.280.0 header)
HTTP/1.1 303 See Other
Location: /configuration?flash=floor_set
name="min_controller_version" value="0.280.0"
@@ -0,0 +1,127 @@
# Part C live proof (9202, controller 0.280.0, drill catalog): the BUILT gate on four class-4 apps.
# Stranger vs household through the product's own route; the gate opens by probe (immich, n8n, audiobookshelf) or by
# the household's press (uptime-kuma); the app and immich's phone-app API after. Test passwords are generated here,
# kept in memory only, never printed.
import json, secrets, sys, time, urllib.parse
sys.path.insert(0, '/mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/pg-calcom-claper-2026-09-28/tools')
sys.path.insert(0, '.')
import walk as w
from browser import Browser, hopstr
D = "enkisfelhom.hu"
PW = open(w.SC + "/.ctlpw").read().strip()
APPS = {"immich": "g-immich", "n8n": "g-n8n", "audiobookshelf": "g-abs", "uptime-kuma": "g-kuma"}
phase = sys.argv[1]
def gatefile(app):
return w.guest(f"test -f /opt/docker/stacks/traefik/dynamic/setup-gate-{app}.yml && echo present || echo absent").strip()
def record(app):
return ((w.stack(app).get("app_config") or {}).get("setup_gate")) or None
def stranger(app):
s = Browser("stranger")
st, body, hops = s.req(f"https://{APPS[app]}.{D}/")
b = ("waiting for its first setup" in body, "Jelentkezz be a Felhom" in body)
st2, body2, _ = s.req(f"https://{APPS[app]}.{D}/api/x", "POST", body={"a": 1}, accept="application/json")
return f"browser -> {st} {hopstr(hops)} gate-page(en,hu-ascii)={b} | api POST -> {st2} {body2[:55]!r}"
w.login()
if phase == "deploy":
for app, sub in APPS.items():
meta = (w.ctl("GET", f"/api/stacks/{app}/deploy-fields")[1].get("data") or {}).get("metadata") or {}
w.say(app, "catalog meta: setup_gate =", meta.get("setup_gate"), "probe =", (meta.get("setup_done_probe") or {}).get("field"))
v = w.deploy_values(app, sub)
code, d = w.ctl("POST", f"/api/stacks/{app}/deploy", {"values": v, "kept_data": "fresh"})
w.say(app, "deploy ->", code, str(d)[:90])
for app in APPS:
for _ in range(120):
st = w.stack(app)
if st.get("deployed") and (st.get("app_config") or {}).get("pinned_images") and st.get("state") in ("running", "unhealthy", "degraded"):
break
time.sleep(5)
w.say(app, "state", st.get("state"), "| gate file", gatefile(app), "| record", record(app))
if phase == "stranger":
for app in APPS:
w.say(app, "STRANGER:", stranger(app))
if phase == "household":
hh = Browser("household")
st, b, hops = hh.login_dashboard(D, PW)
w.say("dashboard login ->", st, hopstr(hops))
for app in APPS:
t0 = time.time(); st, body, hops = hh.req(f"https://{APPS[app]}.{D}/"); dt = time.time() - t0
w.say(app, f"HOUSEHOLD browser -> {st} in {dt:.2f}s | {hopstr(hops)} | gate page: {'waiting for its first setup' in body} | len {len(body)}")
w.say("cookies per host:", {h: sorted(v) for h, v in hh.jar.items()})
json.dump(hh.jar, open("c_jar.json", "w"))
if phase == "setup":
hh = Browser("household"); hh.jar = json.load(open("c_jar.json"))
creds = {a: ("admin@spike.hu", "Hh" + secrets.token_hex(10) + "7") for a in APPS}
json.dump(creds, open("c_creds.json", "w"))
st, b, _ = hh.req(f"https://g-immich.{D}/api/auth/admin-sign-up", "POST", accept="application/json",
body={"email": creds["immich"][0], "password": creds["immich"][1], "name": "Spike"})
w.say("immich admin-sign-up through the gate ->", st)
st, b, _ = hh.req(f"https://g-n8n.{D}/rest/owner/setup", "POST", accept="application/json",
body={"email": creds["n8n"][0], "firstName": "S", "lastName": "O", "password": creds["n8n"][1]})
w.say("n8n owner setup through the gate ->", st)
st, b, _ = hh.req(f"https://g-abs.{D}/init", "POST", accept="application/json",
body={"newRoot": {"username": "root", "password": creds["audiobookshelf"][1]}})
w.say("audiobookshelf POST /init through the gate ->", st, b[:40])
if phase == "watch":
t0 = time.time()
left = {"immich", "n8n", "audiobookshelf"}
while left and time.time() - t0 < 180:
for app in sorted(left):
r = record(app)
if r and r.get("state") == "open":
w.say(app, f"gate OPEN after {time.time() - t0:.0f}s: record {r} | file {gatefile(app)}")
left.discard(app)
time.sleep(5)
for app in left:
w.say(app, "gate still closed after 180 s:", record(app), gatefile(app))
w.say("uptime-kuma (no probe):", record("uptime-kuma"), "| file", gatefile("uptime-kuma"))
if phase == "after":
creds = json.load(open("c_creds.json"))
for app in ("immich", "n8n", "audiobookshelf"):
s = Browser("stranger")
st, body, hops = s.req(f"https://{APPS[app]}.{D}/")
w.say(app, f"AFTER OPEN, stranger browser -> {st} {hopstr(hops)} | gate page: {'waiting for its first setup' in body}")
m = Browser("immich-mobile")
st, b, _ = m.req(f"https://g-immich.{D}/api/auth/login", "POST", accept="application/json",
body={"email": creds["immich"][0], "password": creds["immich"][1]})
tok = json.loads(b).get("accessToken") if st in (200, 201) else None
w.say("immich phone app: login ->", st, "token" if tok else b[:60])
if tok:
for p in ("/api/users/me", "/api/server/ping", "/api/server/version"):
st, b, _ = m.req(f"https://g-immich.{D}{p}", accept="application/json", headers={"Authorization": "Bearer " + tok})
w.say(" immich phone app GET", p, "->", st)
n = Browser("n8n-api")
st, b, _ = n.req(f"https://g-n8n.{D}/rest/login", "POST", accept="application/json",
body={"emailOrLdapLoginId": creds["n8n"][0], "password": creds["n8n"][1]})
w.say("n8n login, no browser gate cookie ->", st)
a = Browser("abs-app")
st, b, _ = a.req(f"https://g-abs.{D}/login", "POST", accept="application/json",
body={"username": "root", "password": creds["audiobookshelf"][1]})
w.say("audiobookshelf login (its phone app's route), no gate cookie ->", st)
if phase == "press":
code, d = w.ctl("GET", "/apps/uptime-kuma", raw=True)
page = d if isinstance(d, str) else ""
w.say("uptime-kuma app page: gate card", 'id="setup-gate-card"' in page, "| button", "/apps/uptime-kuma/setup-gate/open" in page)
code, d = w.ctl("POST", "/apps/uptime-kuma/setup-gate/open", {})
w.say("household presses 'Done, I set it up' ->", code, str(d)[:80])
w.say("uptime-kuma record", record("uptime-kuma"), "| file", gatefile("uptime-kuma"))
code, d = w.ctl("POST", "/apps/uptime-kuma/setup-gate/open", {})
w.say("second press ->", code, str(d)[:80])
s = Browser("stranger")
time.sleep(3)
st, body, hops = s.req(f"https://g-kuma.{D}/")
w.say("uptime-kuma, stranger after the press ->", st, hopstr(hops), "| gate page:", "waiting for its first setup" in body)
@@ -0,0 +1,9 @@
# RP1 — gate file written before the first start
# mutation in internal/stacks/deploy.go:
# - '\tif meta.SetupGate {\n\t\tg, err := m.prepareSetupGate('
# + '\tif false && meta.SetupGate { // RED-PROOF RP1\n\t\tg, err := m.prepareSetupGate('
# go test -run ^TestSetupGate_WrittenBeforeTheFirstStartAndRecordedClosed$ ./internal/stacks
# verdict: RED (assertion)
=== RUN TestSetupGate_WrittenBeforeTheFirstStartAndRecordedClosed
setup_gate_test.go:82: the gate file did not exist when the app was first started — a stranger could reach its first-setup screen
--- FAIL: TestSetupGate_WrittenBeforeTheFirstStartAndRecordedClosed (0.01s)
@@ -0,0 +1,9 @@
# RP10 — the pass is bound to its app host
# mutation in internal/web/setup_gate.go:
# - 'hmac.Equal([]byte(mac), []byte(s.gateMAC("cookie", host, exp)))'
# + 'hmac.Equal([]byte(mac), []byte(s.gateMAC("cookie", "gapp.example.hu", exp))) // RED-PROOF RP10'
# go test -run ^TestSetupGate_TheHouseholdPassesWithItsSession$ ./internal/web
# verdict: RED (assertion)
=== RUN TestSetupGate_TheHouseholdPassesWithItsSession
setup_gate_test.go:166: the pass for gapp opened gapp-db: 200
--- FAIL: TestSetupGate_TheHouseholdPassesWithItsSession (0.06s)
@@ -0,0 +1,9 @@
# RP11 — the key survives a restart
# mutation in internal/web/setup_gate.go:
# - '\t\t\tif err := os.WriteFile(p, []byte(hex.EncodeToString(k)), 0o600); err != nil {'
# + '\t\t\tif err := error(nil); err != nil { // RED-PROOF RP11'
# go test -run ^TestSetupGate_ARestartKeepsTheHouseholdsPass$ ./internal/web
# verdict: RED (assertion)
=== RUN TestSetupGate_ARestartKeepsTheHouseholdsPass
setup_gate_test.go:197: after a restart the household's pass was refused: 401
--- FAIL: TestSetupGate_ARestartKeepsTheHouseholdsPass (0.06s)
@@ -0,0 +1,9 @@
# RP12 — an opened gate lets everything through
# mutation in internal/web/setup_gate.go:
# - '\tif !closed {\n\t\t// Opened;'
# + '\tif false && !closed { // RED-PROOF RP12\n\t\t// Opened;'
# go test -run ^TestSetupGate_AnOpenedGateLetsEverythingThrough$ ./internal/web
# verdict: RED (assertion)
=== RUN TestSetupGate_AnOpenedGateLetsEverythingThrough
setup_gate_test.go:212: an opened gate: 401, want 200
--- FAIL: TestSetupGate_AnOpenedGateLetsEverythingThrough (0.07s)
@@ -0,0 +1,10 @@
# RP13 — R-710: an absent record on an old install warns
# mutation in internal/web/known_login.go:
# - '\treturn err != nil || knownLoginNow().Sub(at) > afterInstallWindow\n'
# + '\t_ = at\n\treturn err != nil && false // RED-PROOF RP13 (the 0.279.0 shape)\n'
# go test -run ^TestKnownLogin_InEffectOnlyUntilReplaced$ ./internal/web
# verdict: RED (assertion)
=== RUN TestKnownLogin_InEffectOnlyUntilReplaced
known_login_test.go:46: R-710: installed long before the after_install existed: in effect = false, want true
known_login_test.go:46: R-710: no install time on record: in effect = false, want true
--- FAIL: TestKnownLogin_InEffectOnlyUntilReplaced (0.01s)
@@ -0,0 +1,9 @@
# RP14 — R-709: the page never carries an installed password
# mutation in internal/web/templates/deploy.html:
# - '<input type="password" id="field-{{.EnvVar}}" class="form-control" value="" placeholder="••••••••••••" disabled>'
# + '<input type="password" id="field-{{.EnvVar}}" class="form-control" value="{{index $.DeployedFieldValues .EnvVar}}" placeholder="••••••••••••" disabled>'
# go test -run ^TestR709_AnInstalledAppsPasswordIsNotInThePage$ ./internal/web
# verdict: RED (assertion)
=== RUN TestR709_AnInstalledAppsPasswordIsNotInThePage
r709_password_field_test.go:49: R-709: the installed app's admin password is in the HTML of its settings page
--- FAIL: TestR709_AnInstalledAppsPasswordIsNotInThePage (0.07s)
@@ -0,0 +1,9 @@
# RP15 — R-709: the reveal endpoint serves an installed password
# mutation in internal/web/handlers.go:
# - '\tif !allowed && stack.Deployed {'
# + '\tif false && !allowed && stack.Deployed { // RED-PROOF RP15'
# go test -run ^TestR709_TheRevealEndpointServesAnInstalledPassword$ ./internal/web
# verdict: RED (assertion)
=== RUN TestR709_TheRevealEndpointServesAnInstalledPassword
r709_password_field_test.go:86: installed password: 403 {"data":null,"error":"Ez a mező nem kérhető le.","ok":false}
--- FAIL: TestR709_TheRevealEndpointServesAnInstalledPassword (0.06s)
@@ -0,0 +1,9 @@
# RP16 — special generator
# mutation in internal/stacks/deploy.go:
# - '\t\tcase "special":\n\t\t\treturn randomWithSpecial(length)'
# + '\t\tcase "special":\n\t\t\treturn randomAlphanumeric(length) // RED-PROOF RP16'
# go test -run ^TestGenerateValue_PasswordWithASpecialCharacter$ ./internal/stacks
# verdict: RED (assertion)
=== RUN TestGenerateValue_PasswordWithASpecialCharacter
setup_gate_test.go:315: no special character
--- FAIL: TestGenerateValue_PasswordWithASpecialCharacter (0.00s)
@@ -0,0 +1,9 @@
# RP2 — an unwritable gate refuses the install
# mutation in internal/stacks/deploy.go:
# - '\t\tg, err := m.prepareSetupGate(req.StackName, stack.ComposePath, env)\n\t\tif err != nil {'
# + '\t\tg, err := m.prepareSetupGate(req.StackName, stack.ComposePath, env)\n\t\tif err != nil && false { // RED-PROOF RP2'
# go test -run ^TestSetupGate_AnUnwritableGateRefusesTheInstall$ ./internal/stacks
# verdict: RED (assertion)
=== RUN TestSetupGate_AnUnwritableGateRefusesTheInstall
setup_gate_test.go:114: an install whose gate could not be written was accepted
--- FAIL: TestSetupGate_AnUnwritableGateRefusesTheInstall (0.01s)
@@ -0,0 +1,9 @@
# RP3 — the probe opens only when the app says set up
# mutation in internal/stacks/setup_gate.go:
# - '\treturn got == done, got\n'
# + '\treturn true, got // RED-PROOF RP3\n'
# go test -run ^TestSetupGate_TheProbeOpensItOnlyWhenTheAppSaysSetUp$ ./internal/stacks
# verdict: RED (assertion)
=== RUN TestSetupGate_TheProbeOpensItOnlyWhenTheAppSaysSetUp
setup_gate_test.go:176: not yet set up, but the gate opened
--- FAIL: TestSetupGate_TheProbeOpensItOnlyWhenTheAppSaysSetUp (0.00s)
@@ -0,0 +1,9 @@
# RP4 — opening removes the traefik file
# mutation in internal/stacks/setup_gate.go:
# - '\tif err := m.removeSetupGateFile(name); err != nil {\n\t\tm.logger.Printf("[ERROR] [stacks] %s: setup gate opened'
# + '\tif err := error(nil); err != nil { // RED-PROOF RP4\n\t\tm.logger.Printf("[ERROR] [stacks] %s: setup gate opened'
# go test -run ^TestSetupGate_TheButtonOpensItOnce$ ./internal/stacks
# verdict: RED (assertion)
=== RUN TestSetupGate_TheButtonOpensItOnce
setup_gate_test.go:210: file still there after the press
--- FAIL: TestSetupGate_TheButtonOpensItOnce (0.00s)
@@ -0,0 +1,9 @@
# RP5 — the button opens once
# mutation in internal/stacks/setup_gate.go:
# - '\tif st.AppConfig == nil || !st.AppConfig.SetupGate.Closed() {\n\t\treturn ErrSetupGateNotClosed'
# + '\tif st.AppConfig == nil { // RED-PROOF RP5\n\t\treturn ErrSetupGateNotClosed'
# go test -run ^TestSetupGate_TheButtonOpensItOnce$ ./internal/stacks
# verdict: RED (assertion)
=== RUN TestSetupGate_TheButtonOpensItOnce
setup_gate_test.go:213: second press: setup gate gapp: the record could not be written
--- FAIL: TestSetupGate_TheButtonOpensItOnce (0.00s)
@@ -0,0 +1,9 @@
# RP6 — a restart rewrites the gate file from the record
# mutation in internal/stacks/setup_gate.go:
# - '\t\t\tif _, err := m.writeSetupGate(it.name, it.compose, cfg.Env); err != nil {'
# + '\t\t\tif _, err := "", error(nil); err != nil { // RED-PROOF RP6'
# go test -run ^TestSetupGate_ARestartKeepsItAndStaleFilesGo$ ./internal/stacks
# verdict: RED (assertion)
=== RUN TestSetupGate_ARestartKeepsItAndStaleFilesGo
setup_gate_test.go:234: the restart left the app open: the gate file was not rewritten from the record
--- FAIL: TestSetupGate_ARestartKeepsItAndStaleFilesGo (0.00s)
@@ -0,0 +1,10 @@
# RP7 — a restore keeps the gate record
# mutation in internal/stacks/life_records.go:
# - '\tcfg.SetupGate = prior.SetupGate\n'
# + '\t// RED-PROOF RP7\n'
# go test -run ^TestSetupGate_ARestoreKeepsTheRecord$ ./internal/stacks
# verdict: RED (assertion)
=== RUN TestSetupGate_ARestoreKeepsTheRecord
setup_gate_test.go:264: opened before: after the restore "", want "open"
setup_gate_test.go:264: still closed: after the restore "", want "closed"
--- FAIL: TestSetupGate_ARestoreKeepsTheRecord (0.00s)
@@ -0,0 +1,9 @@
# RP8 — a stranger is refused
# mutation in internal/web/setup_gate.go:
# - '\tif s.gateCookieValid(r, host) {'
# + '\tif true || s.gateCookieValid(r, host) { // RED-PROOF RP8'
# go test -run ^TestSetupGate_AStrangerIsRefused$ ./internal/web
# verdict: RED (assertion)
=== RUN TestSetupGate_AStrangerIsRefused
setup_gate_test.go:100: a stranger's browser: 200 "" — want 302 to the dashboard's gate page
--- FAIL: TestSetupGate_AStrangerIsRefused (0.06s)
@@ -0,0 +1,9 @@
# RP9 — a token is one-use
# mutation in internal/web/setup_gate.go:
# - '\tif _, seen := s.gate.used[t.Nonce]; seen {'
# + '\tif _, seen := s.gate.used[t.Nonce]; seen && false { // RED-PROOF RP9'
# go test -run ^TestSetupGate_TheHouseholdPassesWithItsSession$ ./internal/web
# verdict: RED (assertion)
=== RUN TestSetupGate_TheHouseholdPassesWithItsSession
setup_gate_test.go:163: a token worked twice: 302
--- FAIL: TestSetupGate_TheHouseholdPassesWithItsSession (0.06s)
@@ -0,0 +1,11 @@
# A stranger polls both gated app hosts every second during the deploys: no cookies, API style and browser style.
B=https://192.168.0.114; D=enkisfelhom.hu
end=$(( $(date +%s) + ${1:-900} ))
while [ $(date +%s) -lt $end ]; do
for h in g-n8n g-immich g-abs g-kuma; do
p=/api/x
r=$(curl -sk -m 5 -H "Host: $h.$D" -w '|%{http_code}' $B$p | tr -d '\n' | cut -c1-90)
b=$(curl -sk -m 5 -H "Host: $h.$D" -H 'Accept: text/html' -o /dev/null -w '%{http_code}' $B/)
echo "$(date -u +%T) $h api=[$r] browser=$b"
done; sleep 1
done
@@ -0,0 +1,22 @@
mealie BEFORE: default -> 200 | wrong -> 401
wger BEFORE: default -> 404 | wrong -> 404
mealie route output: FELHOM_AFTER_INSTALL_OK rc=0
mealie AFTER: default -> 401 | new -> 200 | wrong -> 401
wger route output: FELHOM_AFTER_INSTALL_OK rc=0
wger AFTER: default -> 404 | new -> 404 | wrong -> 404
uid=1000(wger) gid=1000(wger) groups=1000(wger),100(users)
/home/wger/src
wger (after the first set_password above): default -> 200-> | wrong -> 200->
wger route output: FELHOM_AFTER_INSTALL_OK rc=0
wger AFTER: default -> 200-> | new -> 200-> | wrong -> 200->
# wger re-run: the form's field is 'credential'; no Origin header (a browser's https Origin is refused by CSRF — R-712)
wger (after the first set_password above): default -> 200-> | wrong -> 200->
wger route output: FELHOM_AFTER_INSTALL_OK rc=0
wger AFTER: default -> 200-> | new -> 200-> | wrong -> 200->
# wger re-run 2: the username field is 'login'
wger (after the first set_password above): default -> 200-> | wrong -> 200->
wger route output: FELHOM_AFTER_INSTALL_OK rc=0
wger AFTER: default -> 200-> | new -> 302->/ | wrong -> 200->
calibre-web BEFORE: default -> 302->/ | wrong -> 200->
route output (no cd, absolute path, exec array): Password for user 'admin' changed rc=0
calibre-web AFTER: default -> 200-> | new -> 302->/ | wrong -> 200->
@@ -0,0 +1,18 @@
09:08:43 sync -> 200
09:08:48 catalog synced: wger after_install passes the password as argv
09:08:48 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['ADMIN_PASSWORD']
09:08:48 mealie deploy -> 202
09:08:48 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['ADMIN_PASSWORD']
09:08:48 wger deploy -> 202
09:08:52 [1] made the drive paths this app requires: ['/mnt/felhom-drives/scratch_hdd/userdata/calibre-web']
09:08:52 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH', 'ADMIN_PASSWORD']
09:08:52 calibre-web deploy -> 202
09:09:23 calibre-web after_install record after 30s: ok=True detail='None'
09:09:23 mealie after_install record after 30s: ok=True detail='None'
09:09:53 wger after_install record after 60s: ok=True detail='None'
mealie (200 = signed in) default MyPassword -> 401 | generated -> 200 | wrong -> 401
wger (302 = signed in; the browser's https Origin, R-712) default adminadmin -> 200 | generated -> 302 | wrong -> 200
calibre-web (302 = signed in) default admin123 -> 200 | generated -> 302 | wrong -> 200
09:10:11 mealie app page carries the known-login sentence (ASCII fragment "ismert, k"): False
09:10:11 wger app page carries the known-login sentence (ASCII fragment "ismert, k"): False
09:10:11 calibre-web app page carries the known-login sentence (ASCII fragment "ismert, k"): False
@@ -0,0 +1,2 @@
Status: Downloaded newer image for node:22-alpine
{"runs":2000,"bad":0,"plainLen":16,"plainHasSpecial":false}
@@ -0,0 +1,10 @@
18: - GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD:?the admin password is required (R-708)}
--- empty password:
rc=1
error while interpolating services.grafana.environment.[]: required variable GF_SECURITY_ADMIN_PASSWORD is missing a value: the admin password is required (R-708)
--- unset:
rc=1
error while interpolating services.grafana.environment.[]: required variable GF_SECURITY_ADMIN_PASSWORD is missing a value: the admin password is required (R-708)
--- set (control):
1
rc=0
@@ -0,0 +1,4 @@
romm 9202 drill catalog: known-login sentence ('ismert, k'): False | 'admin / admin' on page: False | page bytes 40950
zipline 9202 drill catalog: known-login sentence ('ismert, k'): False | 'admin / admin' on page: False | page bytes 40440
bookstack 9202 drill catalog: known-login sentence ('ismert, k'): False | 'admin / admin' on page: False | page bytes 40553
control: demo-hp live catalog 2026-09-29 06:10Z showed romm's sentence (A/A2-page-warning-after.txt)
@@ -0,0 +1,3 @@
mealie: reveal -> ok=True value length 30 | settings page 68582 bytes | the value in the page HTML: False | reveal control present: True
wger: reveal -> ok=True value length 30 | settings page 68080 bytes | the value in the page HTML: False | reveal control present: True
calibre-web: reveal -> ok=True value length 30 | settings page 71491 bytes | the value in the page HTML: False | reveal control present: True
@@ -0,0 +1,215 @@
# Applies the 2026-09-29 catalog changes (decision 46 gate + Part D) to a catalog checkout: argv[1] = repo root.
# Identical on the drill repo and the live repo, so the drill proves exactly what ships.
import sys, os
R = sys.argv[1]
T = lambda *p: os.path.join(R, "templates", *p)
def edit(path, old, new, count=1):
s = open(path).read()
n = s.count(old)
if n != count:
sys.exit(f"{path}: expected {count} of {old[:60]!r}, found {n}")
open(path, "w").write(s.replace(old, new))
def after_line(path, anchor, text):
edit(path, anchor, anchor + text)
GATE_NOTE = """
# --- The setup gate (controller >= 0.280.0, `09` §3 decision 46) ---
# The first visitor would create the admin. So a fresh install is closed to everyone but the household (a browser
# signed in to the dashboard) until the first setup is done%s
setup_gate: true
"""
# --- decision 46: the gate, on four class-4 apps -------------------------------------------------------------
probes = {
"immich": ("; immich's own status says so (measured on 9202 2026-09-29:\n# isInitialized false -> true once the admin exists).",
"setup_done_probe:\n url: http://immich-server:2283/api/server/config\n field: isInitialized\n done: \"true\"\n"),
"n8n": ("; n8n's own settings say so (measured on 9202 2026-09-29:\n# showSetupOnFirstLoad true -> false once the owner exists).",
"setup_done_probe:\n url: http://n8n:5678/rest/settings\n field: data.userManagement.showSetupOnFirstLoad\n done: \"false\"\n"),
"audiobookshelf": ("; audiobookshelf's own status says so (`/status` isInit — upstream, measured on 9202 by the\n# 2026-09-29 live proof).",
"setup_done_probe:\n url: http://audiobookshelf:80/status\n field: isInit\n done: \"true\"\n"),
"uptime-kuma": (". uptime-kuma says it only over socket.io, so the household presses \"Done, I set it up\"\n# on the app page.", ""),
}
for app, (why, probe) in probes.items():
p = T(app, ".felhom.yml")
s = open(p).read()
assert "setup_gate" not in s, app
i = s.index("\n# --- App info")
s = s[:i] + "\n" + (GATE_NOTE % why).rstrip("\n") + "\n" + probe + s[i:]
open(p, "w").write(s)
# --- Part D1: mealie ------------------------------------------------------------------------------------------
p = T("mealie", ".felhom.yml")
edit(p, """ description: "Az alkalmazás aldomainje"
# --- App info (info page content) ---""", """ description: "Az alkalmazás aldomainje"
# `09` §3 decision 45: Mealie starts with changeme@example.com / MyPassword. The box replaces that password with
# this generated one right after the install (after_install below); the app page shows it as the first password.
- env_var: ADMIN_PASSWORD
label: "Admin jelszó (changeme@example.com)"
type: password
generate: "password:24"
description: "Az első bejelentkezéshez: changeme@example.com és ez a jelszó. Utána a profilodban módosítható."
locked_after_deploy: true
# --- App info (info page content) ---""")
edit(p, " - 'Jelentkezz be: changeme@example.com / MyPassword'\n - 'Változtasd meg azonnal az email címet és jelszót'\n",
" - 'Jelentkezz be: changeme@example.com és a Beállítások oldalon látható első jelszó'\n - 'Változtasd meg az email címet a sajátodra'\n")
edit(p, " - 'Sign in: changeme@example.com / MyPassword'\n - 'Change the e-mail address and password straight away'\n",
" - 'Sign in: changeme@example.com and the first password shown on the settings page'\n - 'Change the e-mail address to your own'\n")
edit(p, """# --- Controller-side health probe ---
healthcheck:
checks:
- type: tcp
port: 9000""", """# --- After a fresh install (controller >= 0.279.0, decision 45) ---
# Mealie's OWN user repository sets the seeded user's password (what its scripts/change_password.py does, without the
# prompts). Measured on 9202 2026-09-29: afterwards MyPassword answers 401 at /api/auth/token, the new one 200.
after_install:
service: mealie
env: [ADMIN_PASSWORD]
# The password is the LAST ARGUMENT (sys.argv[1]), never pasted into the code: a quote in it cannot break or change
# the program (security review 2026-09-29).
command: ["python3", "-c", "import sys\\nfrom mealie.core.security.security import hash_password\\nfrom mealie.db.db_setup import session_context\\nfrom mealie.repos.repository_factory import AllRepositories\\nwith session_context() as s:\\n r = AllRepositories(s, group_id=None, household_id=None)\\n u = r.users.get_one('changeme@example.com', 'email')\\n r.users.update_password(u.id, hash_password(sys.argv[1]))\\n print('FELHOM_AFTER_INSTALL_OK')\\n", "${ADMIN_PASSWORD}"]
success: "FELHOM_AFTER_INSTALL_OK"
# --- Controller-side health probe ---
healthcheck:
checks:
- type: tcp
port: 9000""")
edit(p, """ - env_var: SUBDOMAIN
label: 'Subdomain'
description: 'The subdomain this app answers on'
""", """ - env_var: SUBDOMAIN
label: 'Subdomain'
description: 'The subdomain this app answers on'
- env_var: ADMIN_PASSWORD
label: 'Admin password (changeme@example.com)'
description: 'For the first sign-in: changeme@example.com and this password. Change it in your profile afterwards.'
""")
# --- Part D1: wger (+ R-712: a browser's https Origin was refused by CSRF) --------------------------------------
p = T("wger", ".felhom.yml")
edit(p, """ generate: "hex:32"
locked_after_deploy: true
# --- App info (info page content) ---""", """ generate: "hex:32"
locked_after_deploy: true
# `09` §3 decision 45: wger starts with admin / adminadmin. The box replaces that password with this generated
# one right after the install (after_install below); the app page shows it as the first password.
- env_var: ADMIN_PASSWORD
label: "Admin jelszó (admin)"
type: password
generate: "password:24"
description: "Az első bejelentkezéshez: admin és ez a jelszó. Utána a beállításokban módosítható."
locked_after_deploy: true
# --- App info (info page content) ---""")
edit(p, " - 'Jelentkezz be: admin / adminadmin'\n - 'Változtasd meg azonnal a jelszót'\n",
" - 'Jelentkezz be: admin és a Beállítások oldalon látható első jelszó'\n - 'Add meg az email címedet a beállításokban'\n")
edit(p, " - 'Sign in: admin / adminadmin'\n - 'Change the password straight away'\n",
" - 'Sign in: admin and the first password shown on the settings page'\n - 'Add your e-mail address in the settings'\n")
edit(p, "\n# --- Controller-side health probe ---\nhealthcheck:", """
# --- After a fresh install (controller >= 0.279.0, decision 45) ---
# Django's own set_password on the seeded admin. Measured on 9202 2026-09-29: afterwards adminadmin no longer signs in
# at /en/user/login, the new one does.
after_install:
service: wger
env: [ADMIN_PASSWORD]
# The password is the LAST ARGUMENT (sys.argv[1]), never pasted into the code: a quote in it cannot break or change
# the program (security review 2026-09-29). Django is set up the way manage.py does it (settings.main).
command: ["python3", "-c", "import os, sys; sys.path.insert(0, '/home/wger/src'); os.chdir('/home/wger/src'); os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.main'); import django; django.setup(); from django.contrib.auth.models import User; u = User.objects.get(username='admin'); u.set_password(sys.argv[1]); u.save(); print('FELHOM_AFTER_INSTALL_OK')", "${ADMIN_PASSWORD}"]
success: "FELHOM_AFTER_INSTALL_OK"
# --- Controller-side health probe ---
healthcheck:""")
edit(p, """ - env_var: SECRET_KEY
label: 'Encryption key'
""", """ - env_var: SECRET_KEY
label: 'Encryption key'
- env_var: ADMIN_PASSWORD
label: 'Admin password (admin)'
description: 'For the first sign-in: admin and this password. Change it in the settings afterwards.'
""")
p = T("wger", "docker-compose.yml")
edit(p, " - DJANGO_DB_ENGINE=django.db.backends.sqlite3\n", """ # R-712 (measured 2026-09-29 on 9202): behind traefik wger saw the request as http and refused a browser's
# https Origin with "CSRF verification failed" — nobody could sign in from a browser.
- CSRF_TRUSTED_ORIGINS=https://${SUBDOMAIN}.${DOMAIN}
- X_FORWARDED_PROTO_HEADER_SET=True
- DJANGO_DB_ENGINE=django.db.backends.sqlite3
""")
# --- Part D2: calibre-web -----------------------------------------------------------------------------------------
p = T("calibre-web", ".felhom.yml")
edit(p, """ description: "A külső merevlemez elérési útja, ahol a Calibre könyvtár található"
locked_after_deploy: true
# --- App info (info page content) ---""", """ description: "A külső merevlemez elérési útja, ahol a Calibre könyvtár található"
locked_after_deploy: true
# `09` §3 decision 45: Calibre-Web starts with admin / admin123. The box replaces that password with this
# generated one right after the install (after_install below). Its password policy demands a special character,
# hence `:special` (controller >= 0.280.0).
- env_var: ADMIN_PASSWORD
label: "Admin jelszó (admin)"
type: password
generate: "password:24:special"
description: "Az első bejelentkezéshez: admin és ez a jelszó. Kell benne kis- és nagybetű, szám és egy különleges karakter."
locked_after_deploy: true
# --- App info (info page content) ---""")
edit(p, " - 'Jelentkezz be: admin / admin123'\n - 'Változtasd meg azonnal a jelszót'\n",
" - 'Jelentkezz be: admin és a Beállítások oldalon látható első jelszó'\n")
edit(p, " - 'Sign in: admin / admin123'\n - 'Change the password straight away'\n",
" - 'Sign in: admin and the first password shown on the settings page'\n")
edit(p, "\n# --- Controller-side health probe ---\nhealthcheck:", """
# --- After a fresh install (controller >= 0.280.0, decision 45) ---
# Calibre-Web's OWN `cps.py -s user:password`, as the app user. Measured on 9202 2026-09-29: afterwards admin123 no
# longer signs in, the new one does; a password without a special character is refused by its policy.
after_install:
service: calibre-web
user: abc
env: [ADMIN_PASSWORD]
command: ["python3", "/app/calibre-web-automated/cps.py", "-p", "/config/app.db", "-s", "admin:${ADMIN_PASSWORD}"]
success: "Password for user 'admin' changed"
# --- Controller-side health probe ---
healthcheck:""")
edit(p, """ label: 'E-book library path'
description: 'The path to the external hard drive where the Calibre library lives'
placeholder: '/mnt/felhom-drives/hdd_1'
""", """ label: 'E-book library path'
description: 'The path to the external hard drive where the Calibre library lives'
placeholder: '/mnt/felhom-drives/hdd_1'
- env_var: ADMIN_PASSWORD
label: 'Admin password (admin)'
description: 'For the first sign-in: admin and this password. It needs a lower and an upper case letter, a digit and a special character.'
""")
# --- Part D3: romm and zipline — their default_creds notes are stale (they are class 4) ---------------------------
import re
for app, cred in (("romm", "admin / admin"), ("zipline", "admin / zipline")):
p = T(app, ".felhom.yml")
s = open(p).read()
s, n = re.subn(r"(?m)^[ \t]*default_creds: ['\"]" + re.escape(cred) + r"['\"][ \t]*\n", "", s)
assert n == 2 and "default_creds" not in s, (app, n)
open(p, "w").write(s)
edit(T("romm", ".felhom.yml"), ' - "Jelentkezz be az alapértelmezett admin / admin fiókkal"\n',
' - "Az első megnyitáskor hozd létre az admin fiókodat"\n')
edit(T("romm", ".felhom.yml"), ' - "Sign in with the default admin / admin account"\n',
' - "On the first visit, create your admin account"\n')
edit(T("zipline", ".felhom.yml"), " - 'Jelentkezz be: admin / zipline'\n - 'Változtasd meg azonnal a jelszót'\n",
" - 'Az első megnyitáskor hozd létre az admin fiókodat'\n")
edit(T("zipline", ".felhom.yml"), " - 'Sign in: admin / zipline'\n - 'Change the password straight away'\n",
" - 'On the first visit, create your admin account'\n")
# --- Part D4: R-708 — grafana refuses to start without its admin password; never `admin` ---------------------------
edit(T("grafana", "docker-compose.yml"), "GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD:-admin}",
"GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD:?the admin password is required (R-708)}")
print("catalog patched:", R)
@@ -0,0 +1,13 @@
set -u
DOM=enkisfelhom.hu; J=/tmp/cwj.$$
login() { rm -f $J; T=$(curl -sk -c $J -b $J -H "Host: c-cw.$DOM" https://127.0.0.1/login | grep -o 'name="csrf_token" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"$//')
curl -sk -o /dev/null -w '%{http_code}->%{redirect_url}' -c $J -b $J -H "Host: c-cw.$DOM" -X POST --data-urlencode "csrf_token=$T" --data-urlencode "username=admin" --data-urlencode "password=$1" --data-urlencode "remember_me=on" https://127.0.0.1/login | sed "s|https\?://[^/]*||"; }
echo "calibre-web BEFORE: default -> $(login admin123) | wrong -> $(login wrongxyz123)"
# a password in the shape of generate: password:24:special (made here, never printed)
S='-_.!@#%+='
while :; do P=$(head -c 400 /dev/urandom | tr -dc 'A-Za-z0-9_.!@#%+=-' | head -c 24); case "$P" in [A-Za-z0-9]*) ;; *) continue;; esac
echo "$P" | grep -q '[a-z]' && echo "$P" | grep -q '[A-Z]' && echo "$P" | grep -q '[0-9]' && echo "$P" | grep -q '[-_.!@#%+=]' && break; done
OUT=$(docker exec -u abc calibre-web python3 /app/calibre-web-automated/cps.py -p /config/app.db -s "admin:$P" 2>&1; echo "rc=$?")
echo "route output (no cd, absolute path, exec array): $(echo "$OUT" | grep -v -iE 'ProxyFix|magic shel|SESSION_COOKIE' | tr '\n' ' ' | sed "s/$(printf '%s' "$P" | sed 's/[.[\*^$/]/\\&/g')/<redacted>/g" | cut -c1-200)"
echo "calibre-web AFTER: default -> $(login admin123) | new -> $(login "$P") | wrong -> $(login wrongxyz123)"
unset P; rm -f $J
@@ -0,0 +1,46 @@
# Part D live proof (9202, controller 0.280.0, drill catalog): fresh installs of mealie, wger, calibre-web; the box's
# after_install replaces each default login; then default / generated / wrong through each app's own login.
# The generated passwords live in this process and reach the guest over STDIN only; never printed.
import json, os, subprocess, sys, time
sys.path.insert(0, '/mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/pg-calcom-claper-2026-09-28/tools')
import walk as w
APPS = {"mealie": "d-mealie", "wger": "d-wger", "calibre-web": "d-cw"}
w.login()
code, _ = w.ctl("POST", "/api/sync", {})
w.say("sync ->", code)
for _ in range(24):
time.sleep(5)
meta = (w.ctl("GET", "/api/stacks/wger/deploy-fields")[1].get("data") or {}).get("metadata") or {}
ai = meta.get("after_install") or {}
if ai and "sys.argv[1]" in " ".join(ai.get("command") or []):
w.say("catalog synced: wger after_install passes the password as argv"); break
for app, sub in APPS.items():
v = w.deploy_values(app, sub)
code, d = w.ctl("POST", f"/api/stacks/{app}/deploy", {"values": v, "kept_data": "fresh"})
w.say(app, "deploy ->", code)
t0 = time.time()
left = set(APPS)
while left and time.time() - t0 < 900:
for app in sorted(left):
rec = (w.stack(app).get("app_config") or {}).get("after_install")
if rec:
w.say(app, f"after_install record after {time.time() - t0:.0f}s: ok={rec.get('ok')} detail={str(rec.get('detail'))[:80]!r}")
left.discard(app)
time.sleep(10)
for app in left:
w.say(app, "NO after_install record after 900 s")
pw = {a: w.GENERATED[a]["ADMIN_PASSWORD"] for a in APPS}
script = open(os.path.join(os.path.dirname(__file__), "d_login.sh")).read()
subprocess.run(["ssh", "hp", "cat > /root/d_login.sh && pct push 9202 /root/d_login.sh /root/d_login.sh && rm /root/d_login.sh"],
input=script, text=True, check=True, capture_output=True)
r = subprocess.run(["ssh", "hp", "pct exec 9202 -- bash /root/d_login.sh; pct exec 9202 -- rm -f /root/d_login.sh"],
input="\n".join(pw[a] for a in ("mealie", "wger", "calibre-web")) + "\n", text=True, capture_output=True, timeout=300)
out = r.stdout
for a in pw.values():
out = out.replace(a, "<redacted>")
print(out, end="")
# the page: no known-login sentence once replaced (ASCII fragment; control: a class-3 app not installed still shows it)
for app in APPS:
page = w.page(f"/apps/{app}")
w.say(app, "app page carries the known-login sentence (ASCII fragment \"ismert, k\"):", "ismert, k" in page)
@@ -0,0 +1,13 @@
# Part D live: default / generated / wrong through each app's OWN login. Generated passwords on STDIN.
set -u
DOM=enkisfelhom.hu; J=/tmp/dl.$$
read -r PM; read -r PW; read -r PC
mealie() { curl -sk -o /dev/null -w '%{http_code}' -H "Host: d-mealie.$DOM" -X POST --data-urlencode "username=changeme@example.com" --data-urlencode "password=$1" https://127.0.0.1/api/auth/token; }
wger() { rm -f $J; T=$(curl -sk -c $J -b $J -H "Host: d-wger.$DOM" https://127.0.0.1/en/user/login | grep -o 'name="csrfmiddlewaretoken" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"$//')
curl -sk -o /dev/null -w '%{http_code}' -c $J -b $J -H "Host: d-wger.$DOM" -H "Origin: https://d-wger.$DOM" -H "Referer: https://d-wger.$DOM/en/user/login" -H "X-Forwarded-Proto: https" -X POST --data-urlencode "csrfmiddlewaretoken=$T" --data-urlencode "login=admin" --data-urlencode "password=$1" https://127.0.0.1/en/user/login; }
cw() { rm -f $J; T=$(curl -sk -c $J -b $J -H "Host: d-cw.$DOM" https://127.0.0.1/login | grep -o 'name="csrf_token" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"$//')
curl -sk -o /dev/null -w '%{http_code}' -c $J -b $J -H "Host: d-cw.$DOM" -X POST --data-urlencode "csrf_token=$T" --data-urlencode "username=admin" --data-urlencode "password=$1" --data-urlencode "remember_me=on" https://127.0.0.1/login; }
echo "mealie (200 = signed in) default MyPassword -> $(mealie MyPassword) | generated -> $(mealie "$PM") | wrong -> $(mealie wrongxyz123)"
echo "wger (302 = signed in; the browser's https Origin, R-712) default adminadmin -> $(wger adminadmin) | generated -> $(wger "$PW") | wrong -> $(wger wrongxyz123)"
echo "calibre-web (302 = signed in) default admin123 -> $(cw admin123) | generated -> $(cw "$PC") | wrong -> $(cw wrongxyz123)"
unset PM PW PC; rm -f $J
@@ -0,0 +1,27 @@
# Part D1 probe (9202): the default login before, the app's own route with a generated password (made HERE, never
# printed), then default / new / wrong through the app's own login API via traefik.
set -u
DOM=enkisfelhom.hu
mealie_login() { curl -sk -o /dev/null -w '%{http_code}' -H "Host: c-mealie.$DOM" -X POST --data-urlencode "username=changeme@example.com" --data-urlencode "password=$1" https://127.0.0.1/api/auth/token; }
wger_login() { curl -sk -o /dev/null -w '%{http_code}' -H "Host: c-wger.$DOM" -H 'Content-Type: application/json' -X POST -d "{\"username\":\"admin\",\"password\":\"$1\"}" https://127.0.0.1/api/v2/login/; }
echo "mealie BEFORE: default -> $(mealie_login MyPassword) | wrong -> $(mealie_login wrongxyz123)"
echo "wger BEFORE: default -> $(wger_login adminadmin) | wrong -> $(wger_login wrongxyz123)"
P=$(head -c 300 /dev/urandom | tr -dc A-Za-z0-9 | head -c 24)
OUT=$(docker exec mealie python3 -c "
from mealie.core.security.security import hash_password
from mealie.db.db_setup import session_context
from mealie.repos.repository_factory import AllRepositories
with session_context() as s:
r = AllRepositories(s, group_id=None, household_id=None)
u = r.users.get_one('changeme@example.com', 'email')
r.users.update_password(u.id, hash_password('$P'))
print('FELHOM_AFTER_INSTALL_OK')
" 2>&1; echo "rc=$?")
echo "mealie route output: $(echo "$OUT" | tail -3 | tr '\n' ' ' | sed "s/$P/<redacted>/g")"
echo "mealie AFTER: default -> $(mealie_login MyPassword) | new -> $(mealie_login "$P") | wrong -> $(mealie_login wrongxyz123)"
Q=$(head -c 300 /dev/urandom | tr -dc A-Za-z0-9 | head -c 24)
OUT=$(docker exec wger sh -c "cd /home/wger/src && python3 manage.py shell -c \"from django.contrib.auth.models import User; u = User.objects.get(username='admin'); u.set_password('$Q'); u.save(); print('FELHOM_AFTER_INSTALL_OK')\"" 2>&1; echo "rc=$?")
echo "wger route output: $(echo "$OUT" | tail -3 | tr '\n' ' ' | sed "s/$Q/<redacted>/g")"
echo "wger AFTER: default -> $(wger_login adminadmin) | new -> $(wger_login "$Q") | wrong -> $(wger_login wrongxyz123)"
docker exec wger sh -c 'id; pwd' | head -2
unset P Q
@@ -0,0 +1,10 @@
set -u
DOM=enkisfelhom.hu; J=/tmp/wj.$$
wger_login() { rm -f $J; T=$(curl -sk -c $J -b $J -H "Host: c-wger.$DOM" https://127.0.0.1/en/user/login | grep -o 'name="csrfmiddlewaretoken" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"$//')
curl -sk -o /dev/null -w '%{http_code}->%{redirect_url}' -c $J -b $J -H "Host: c-wger.$DOM" -X POST --data-urlencode "csrfmiddlewaretoken=$T" --data-urlencode "login=admin" --data-urlencode "password=$1" https://127.0.0.1/en/user/login | sed "s|https\?://[^/]*||"; }
echo "wger (after the first set_password above): default -> $(wger_login adminadmin) | wrong -> $(wger_login wrongxyz123)"
Q=$(head -c 300 /dev/urandom | tr -dc A-Za-z0-9 | head -c 24)
OUT=$(docker exec wger sh -c "cd /home/wger/src && python3 manage.py shell -c \"from django.contrib.auth.models import User; u = User.objects.get(username='admin'); u.set_password('$Q'); u.save(); print('FELHOM_AFTER_INSTALL_OK')\"" 2>&1; echo "rc=$?")
echo "wger route output: $(echo "$OUT" | tail -2 | tr '\n' ' ' | sed "s/$Q/<redacted>/g")"
echo "wger AFTER: default -> $(wger_login adminadmin) | new -> $(wger_login "$Q") | wrong -> $(wger_login wrongxyz123)"
unset Q; rm -f $J
@@ -0,0 +1,34 @@
function generatePassword(fieldId, confirmFieldId, spec) {
const letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const SPECIAL = '-_.!@#%+=';
var parts = (spec || '').split(':');
var n = parseInt(parts[1], 10);
if (parts[0] !== 'password' || !(n >= 12 && n <= 64)) { n = 16; }
var special = parts[2] === 'special';
var chars = special ? letters + SPECIAL : letters;
let pass = '';
for (;;) {
pass = '';
const arr = new Uint32Array(n);
crypto.getRandomValues(arr);
for (let i = 0; i < n; i++) {
pass += chars[arr[i] % chars.length];
}
if (!special || (/[a-z]/.test(pass) && /[A-Z]/.test(pass) && /[0-9]/.test(pass) && /[-_.!@#%+=]/.test(pass) && /^[A-Za-z0-9]/.test(pass))) {
break;
}
}
document.getElementById(fieldId).value = pass;
if (confirmFieldId) {
var ce = document.getElementById(confirmFieldId);
if (ce) ce.value = pass;
}
}
var out={};
function field(){return {value:''};}
global.document={getElementById:function(id){out[id]=out[id]||{value:''};return out[id];}};
var bad=0, n=0, specialSeen=0;
for (var k=0;k<2000;k++){ generatePassword('f','c','password:24:special'); var p=out['f'].value; n++;
if (p.length!==24||!/[a-z]/.test(p)||!/[A-Z]/.test(p)||!/[0-9]/.test(p)||!/[-_.!@#%+=]/.test(p)||!/^[A-Za-z0-9]/.test(p)||/['"$\\: `]/.test(p)||out['c'].value!==p) bad++; }
generatePassword('f','c',''); var plain=out['f'].value;
console.log(JSON.stringify({runs:n, bad:bad, plainLen:plain.length, plainHasSpecial:/[^A-Za-z0-9]/.test(plain)}));
@@ -0,0 +1,6 @@
cd /opt/docker/stacks/grafana || exit 1
grep -n 'GF_SECURITY_ADMIN_PASSWORD=' docker-compose.yml
echo "--- empty password:"; GF_SECURITY_ADMIN_PASSWORD= DOMAIN=x SUBDOMAIN=y docker compose -f docker-compose.yml config >/dev/null 2>/tmp/gerr; echo "rc=$?"; head -2 /tmp/gerr
echo "--- unset:"; env -u GF_SECURITY_ADMIN_PASSWORD DOMAIN=x SUBDOMAIN=y docker compose -f docker-compose.yml config >/dev/null 2>/tmp/gerr; echo "rc=$?"; head -2 /tmp/gerr
echo "--- set (control):"; GF_SECURITY_ADMIN_PASSWORD=Xy12345678 DOMAIN=x SUBDOMAIN=y docker compose -f docker-compose.yml config 2>/dev/null | grep -c 'GF_SECURITY_ADMIN_PASSWORD'; echo "rc=${PIPESTATUS[0]}"
rm -f /tmp/gerr