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
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:
@@ -124,6 +124,18 @@ a trust boundary too: a default password, or a "first visitor creates the admin"
|
||||
household acts. Rule and per-app status: `09` §3 decision 45 and `app-catalog-felhom.eu/FIRST-ADMIN.md` (the audit
|
||||
of all 53 apps, 2026-09-28).
|
||||
|
||||
**Who may reach an app, and through what (recorded 2026-09-29 — no document said it before; spike finding F1).**
|
||||
Every app is reached only through the box's traefik (no catalog app publishes a host port except crafty-controller's
|
||||
game ports; none uses host networking — read from the catalog 2026-09-29). traefik routes by host name: the tunnel's
|
||||
`*.domain` and the LAN both land there. The dashboard (`felhom.<domain>`) has its own password; its session cookie is
|
||||
**host-only** and never reaches an app host. An app answers anyone who reaches its host, with the app's own login —
|
||||
**except while its setup gate is closed** (`09` §3 decision 46, controller ≥ 0.280.0): then traefik asks the
|
||||
controller first (`forwardAuth`), and only a browser holding a gate cookie for that one host gets through. The cookie
|
||||
is minted after a valid dashboard session vouched for the browser (a 60-second, one-use token bound to the host, on
|
||||
the dashboard's own `/__gate/start`). The controller is in an app's request path ONLY while its gate is closed; once
|
||||
open, the gate's traefik router is removed and the app is reached exactly as without it. The gate decides who creates
|
||||
the first admin; it does not decide who may sign up afterwards (R-711).
|
||||
|
||||
---
|
||||
|
||||
## 6. Enrollment & identity
|
||||
|
||||
@@ -502,7 +502,15 @@ R-636's louder repeated alarm.
|
||||
app is not yet set up, the box lets only a person logged in to the household's dashboard reach it; the gate opens
|
||||
when the app's own status says an admin exists, or when the household presses "Done, I set it up". Option B: one
|
||||
fix per app (route (b), R-707). A is built only if the spike passes its exit test in writing; otherwise B continues
|
||||
and the spike's result is the recorded reason. Outcome: *(filled in by the 2026-09-29 session)*.
|
||||
and the spike's result is the recorded reason. **Outcome (2026-09-29): the spike PASSED** (`audits/login-gate-2026-09-29/
|
||||
B/B-VERDICT.md`, written before any build): on 9202 a stranger never reached a first-setup screen (~530 polls during
|
||||
two installs, 0 app answers), the household passed with its dashboard session in 0.2 s, both probes flipped on the
|
||||
setup, immich's phone-app API worked unchanged once the gate's router was removed, and the dashboard cookie was never
|
||||
widened (a redirect handshake mints a 60-second, one-use token per app host instead). **Built in controller v0.280.0**
|
||||
and proven live on immich, n8n, audiobookshelf (probe) and uptime-kuma (button). Costs, stated: ~2 ms per gated
|
||||
request; a gated app answers 500 while the controller is down (closed, not open); a phone app cannot reach a gated
|
||||
app; an app with no probe waits for the household's press, and the press trusts the household. Not covered by the
|
||||
gate: open sign-up after the setup (R-711). Design record: `01-topology-and-trust.md` §5.
|
||||
Same day, operator: CC changes the admin passwords of demo-hp's installed bookstack and calibre-web and stores them
|
||||
in the operator's credentials file (not in any repo).
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -818,11 +818,13 @@ class (an image `VOLUME` at an unmounted path) is still live — `immich-server`
|
||||
| **R-704** | **[P3-LOW] The box's crash-loop stop (decision 28) outlives the app: after remove and reinstall, the new install is still held.** Measured 2026-09-28 on 9202: calcom crash-looped at 08:22 and 08:28 (`unhealthy_stop`, `crash_loop`, trip 2, recorded 08:28:59Z); it was then REMOVED through the product twice and installed fresh twice (09:14:51Z the last). At 09:45 the new, healthy install's Update was refused `409 held` with the crash-loop sentence („…újra és újra összeomlott…"), and `GET /api/stacks/calcom` carried the old `hold_reason` while `state=running`. Start lifted it (`the unhealthy stop is LIFTED by Start`). So a household that removes a crash-looping app and installs it again (the obvious fix) finds its updates refused for a crash of a previous install. Not measured: whether the nightly update leg also skips it; whether other holds (restore hold) behave the same. **Fix direction:** the remove clears the app's box-set holds, as `DeleteAppBackupPrefs` clears its backup preferences (R-474). Evidence: `audits/pg-calcom-claper-2026-09-28/box/calcom/hold.txt`, `…/box/calcom/move.txt`. **-- 2026-09-28 later: SECOND and worse instance, then FIXED in controller v0.278.0.** demo-hp's fresh nextcloud (installed 10:13) carried an UPDATE hold from a nextcloud of 2026-09-13 (set before v0.242.0 made removals clear update holds; nothing ever swept it). At the manual off-site run (15:17) the backup leg logged `Skipping volume dump for nextcloud — the app is HELD stopped`, captured no unit, and pushed a snapshot that `carried NO database dump and NO volume tar` — a freshly installed app silently NOT backed up. **Fix:** a removal also clears the crash-loop stop (`settings.ClearUpdateHold`), and a new install (plain or "use my kept data") drops a leftover update/crash-loop hold of an app that is not installed (`Router.dropLeftoverHold`); restore holds (R-379) untouched. Red-proofed RP4–RP6 (`audits/kept-offsite-2026-09-28/redproofs/`). Floor 0.278.0. **STILL OPEN: live proof of the install-time drop** (a box with a leftover hold on an uninstalled app). | **WATCHING — P2; owner: CC (install-time drop, live)** |
|
||||
| **R-705** | **[P3-LOW] There is no way to run the night's chain now — only its pieces.** Asked by the operator 2026-09-28 (to finish a proof in the day). What exists (read from source, controller v0.278.0): the backup page's off-site run-now (`POST /backup/offbox/run`) runs the dump leg first (the R-44 pre-phase: DB dumps, volume dumps with brief app stops, unit capture) and then the push — used live on demo-hp 2026-09-28 15:17, 3m57s; the debug API has `backup/dbdump`, `backup/crossdrive` (Tier 2), `backup/integrity`, `backup/offsite-proof`. **Missing:** the automatic update leg (`RunUpdateLeg`, chained only to the scheduled off-site job) and the whole-guest backup (the agent's, on its own 24 h / 7 d cadence) have no manual trigger; the only way to run the chain in order is to move the backup window (`POST /backups/window`), which takes W..W+2h at least. **Needs:** a debug action "run tonight's chain now" (dump → Tier 2 → off-site → update leg, in order, one at a time), and an agent-side "whole-guest backup now" for demo boxes. Not built. **-- 2026-09-28 evening: the controller half BUILT (v0.279.0):** debug `POST /api/debug/backup/night-chain` runs dump → Tier 2 → off-site → update leg in order, one at a time, refused while anything else runs; the leg gets its normal length from its own start. Proven on 9202: 44 s, a second press 409, the leg deadline 22:00. **Still open: the whole-guest backup (agent side) has no manual trigger.** | **OPEN — P3, agent half only; owner: CC** |
|
||||
| **R-706** | **[P3-LOW] Removing an app "with its backups" leaves its off-site verification copy on the drive.** Measured 2026-09-28 on demo-hp: after a full off-site restore of nextcloud (which leaves the downloaded copy in `backups/offsite-restore/nextcloud`, ~1 GB, by design, for the household to inspect), `POST /api/stacks/nextcloud/remove` with `remove_backups: true` removed the unit and listed `backup_paths_removed` WITHOUT the verification copy; it stayed until the restore page's own delete (`POST /backup/offbox/verify-copy/delete`, 302 `scratch_deleted`). A household that removes an app to free space keeps 1 GB it cannot see on the app list. **Fix direction:** the removal with backups also deletes the app's verification copy (the same `DeleteOffsiteRestoreCopy`). Evidence: `audits/kept-offsite-2026-09-28/E/E9-teardown.txt`. **-- 2026-09-28 evening: FIXED in controller v0.279.0** — a removal with its backups also deletes the verification copy and lists it among the removed paths (`TestR706_…`, red-proofed RP7). Not yet seen live (needs a full off-site restore then a removal). | **WATCHING — P3; owner: CC (live)** |
|
||||
| **R-707** | **[P2] 37 apps still start with a login a stranger can take (`09` §3 decision 45).** Audit of all 53 apps: `app-catalog-felhom.eu/FIRST-ADMIN.md` (class, fix route, status, measured or read). Open: **3 hard-coded defaults** — calibre-web (`admin / admin123`, measured working on demo-hp and 9202; its own `cps.py -s` route needs a generated password WITH a special character — our generator is letters+digits, a controller change), mealie (`changeme@example.com / MyPassword`), wger (`admin / adminadmin`); **34 open first-run screens** (the first visitor creates the admin: actualbudget, adventurelog, audiobookshelf, calcom, docmost, emby, ghost, gitea, gramps-web, home-assistant, homebox, immich, jellyfin, komga, n8n, navidrome, opengist, outline, papra, plant-it, radarr, rallly, recipe-importer, romm, seerr, sonarr, sparkyfitness, tandoor, termix, uptime-kuma, vikunja, wanderer, wishlist, zipline). **Stale notes:** romm's `default_creds` `admin / admin` answers 401 on demo-hp (like a wrong password) — the page now warns with a login that does not exist; zipline's looks stale too. **Measured on demo-hp 2026-09-28 (read-only):** bookstack's default still logs in on the INSTALLED app (the fix is for new installs; the page now warns). Each fix: route (a) env or (b) the app's own CLI/API via `after_install:`, proven on 9202 with the default failing and the generated password working; route (c) a page sentence. Several sessions (operator, 2026-09-28). | **OPEN — P2; owner: CC** |
|
||||
| **R-708** | **[P3-LOW] grafana falls back to password `admin` when its admin field is empty.** `templates/grafana/docker-compose.yml:18` `GF_SECURITY_ADMIN_PASSWORD=${…:-admin}` (read 2026-09-28, the audit). Today the field is generated and required, so it is never empty on a normal install — but an edit, an import or a restore that drops the value would publish grafana with `admin / admin`. **Fix direction:** no default in the compose (`${GF_SECURITY_ADMIN_PASSWORD:?}` refuses to start instead). | **OPEN — P3; owner: CC** |
|
||||
| **R-709** | **[P3-LOW] The deploy page writes the generated admin passwords of installed apps into its HTML.** `internal/web/templates/deploy.html` renders a `type: password` field's decrypted value into a disabled `<input value=…>` (read 2026-09-28; used by the proofs of R-702/R-707 to read the first password as the household sees it). `type: secret` fields got a fetch-on-demand reveal in R-254; `type: password` fields did not. The page needs a login, so this is exposure to a logged-in session's HTML (browser cache, a shared screen, a saved page), not to strangers. **Fix direction:** the R-254 reveal for password fields too. | **OPEN — P3; owner: CC** |
|
||||
| **R-707** | **[P2] 37 apps still start with a login a stranger can take (`09` §3 decision 45).** Audit of all 53 apps: `app-catalog-felhom.eu/FIRST-ADMIN.md` (class, fix route, status, measured or read). Open: **3 hard-coded defaults** — calibre-web (`admin / admin123`, measured working on demo-hp and 9202; its own `cps.py -s` route needs a generated password WITH a special character — our generator is letters+digits, a controller change), mealie (`changeme@example.com / MyPassword`), wger (`admin / adminadmin`); **34 open first-run screens** (the first visitor creates the admin: actualbudget, adventurelog, audiobookshelf, calcom, docmost, emby, ghost, gitea, gramps-web, home-assistant, homebox, immich, jellyfin, komga, n8n, navidrome, opengist, outline, papra, plant-it, radarr, rallly, recipe-importer, romm, seerr, sonarr, sparkyfitness, tandoor, termix, uptime-kuma, vikunja, wanderer, wishlist, zipline). **Stale notes:** romm's `default_creds` `admin / admin` answers 401 on demo-hp (like a wrong password) — the page now warns with a login that does not exist; zipline's looks stale too. **Measured on demo-hp 2026-09-28 (read-only):** bookstack's default still logs in on the INSTALLED app (the fix is for new installs; the page now warns). Each fix: route (a) env or (b) the app's own CLI/API via `after_install:`, proven on 9202 with the default failing and the generated password working; route (c) a page sentence. Several sessions (operator, 2026-09-28). **2026-09-29 (controller v0.280.0, catalog `d0e7e2e`):** every class-3 app fixed — mealie, wger, calibre-web by `after_install` (calibre-web with the new `password:24:special`), proven on 9202 fresh installs (`audits/login-gate-2026-09-29/D/`); the setup gate (decision 46, spike PASSED) built and live on immich, n8n, audiobookshelf (probes measured) and uptime-kuma (button) (`…/C/`); romm's and zipline's stale notes removed. **Left: 30 class-4 apps** — gate each (probe measured on 9202 where one exists — 11 upstream candidates listed in `…/B/B-VERDICT.md` §3; the button otherwise). | **OPEN — P2; owner: CC; 30 of 37 left** |
|
||||
| **R-708** | **[P3-LOW] grafana falls back to password `admin` when its admin field is empty.** `templates/grafana/docker-compose.yml:18` `GF_SECURITY_ADMIN_PASSWORD=${…:-admin}` (read 2026-09-28, the audit). Today the field is generated and required, so it is never empty on a normal install — but an edit, an import or a restore that drops the value would publish grafana with `admin / admin`. **Fix direction:** no default in the compose (`${GF_SECURITY_ADMIN_PASSWORD:?}` refuses to start instead). **Fixed 2026-09-29** (catalog `d0e7e2e`): `${GF_SECURITY_ADMIN_PASSWORD:?…}` — `docker compose config` with it empty or unset exits 1 naming R-708, set → 0 (`audits/login-gate-2026-09-29/D/D4-grafana-r708.txt`). | **CLOSED — 2026-09-29** |
|
||||
| **R-709** | **[P3-LOW] The deploy page writes the generated admin passwords of installed apps into its HTML.** `internal/web/templates/deploy.html` renders a `type: password` field's decrypted value into a disabled `<input value=…>` (read 2026-09-28; used by the proofs of R-702/R-707 to read the first password as the household sees it). `type: secret` fields got a fetch-on-demand reveal in R-254; `type: password` fields did not. The page needs a login, so this is exposure to a logged-in session's HTML (browser cache, a shared screen, a saved page), not to strangers. **Fix direction:** the R-254 reveal for password fields too. **Fixed in controller v0.280.0:** an installed app's password field renders empty with a reveal eye (`/stacks/<n>/auto-field/reveal` now serves `type: password` of an installed app, never a restore-generated one). Red-proofs RP14/RP15; live on 9202: mealie, wger, calibre-web — the revealed value is NOT in the settings page HTML (`…/D/D6-r709-live.txt`). | **CLOSED — 2026-09-29** |
|
||||
| **R-710** | **[P2-MEDIUM] An app installed before its template gained an `after_install:` is never warned about its default login.** MEASURED 2026-09-29 on demo-hp: bookstack's page carried no known-login sentence although its default `admin@admin.com / password` still logged in (the app was installed before the catalog added bookstack's `after_install` on 2026-09-28; the command never runs for an installed app). `internal/web/known_login.go` reads an ABSENT `after_install` record as "not run yet" for ever. Evidence `audits/login-gate-2026-09-29/A/A2-page-warning-after.txt`. Also: the page has no way to learn of a password the household changed by hand (the brief's Part A4). **Fix direction:** absent record + installed longer than the command's window = in effect; a household "I changed it" press recorded in `app.yaml`. | **OPEN — P2; owner: CC** |
|
||||
| **R-711** | **[P2-MEDIUM] About a dozen class-4 apps keep open sign-up after their first admin exists — the setup gate (decision 46) does not close that.** FOUND 2026-09-29 by the gate spike (`audits/login-gate-2026-09-29/B/B-VERDICT.md` F3). The gate decides who becomes the admin; once it opens, a stranger can still make an ordinary account on adventurelog, homebox, papra, plant-it, sparkyfitness, vikunja, wanderer, rallly, opengist, wishlist, termix, docmost (READ from `app-catalog-felhom.eu/FIRST-ADMIN.md`, not measured). **Fix direction:** per app, route (a) — disable sign-up after the first user (env or the app's own setting), measured on 9202. | **OPEN — P2; owner: CC** |
|
||||
| **R-712** | **[P2-MEDIUM] wger refused every browser sign-in behind traefik: "CSRF verification failed".** MEASURED 2026-09-29 on 9202 (live catalog wger 2.6): a POST to `/en/user/login` with the browser's `Origin: https://…` answered 403 — Django saw the request as http (no trusted proxy header) and no `CSRF_TRUSTED_ORIGINS`. Found while proving R-707's wger route. **Fixed** (catalog `d0e7e2e`): `CSRF_TRUSTED_ORIGINS=https://${SUBDOMAIN}.${DOMAIN}` + `X_FORWARDED_PROTO_HEADER_SET=True`; proven on a fresh install: the generated password signs in (302) with the https Origin (`audits/login-gate-2026-09-29/D/D2-live.txt`). | **CLOSED — 2026-09-29** |
|
||||
| **R-713** | **[P3-LOW] claper's `after_install` pastes the household's password into Elixir code, and the controller does not refuse a value that would break such code.** FOUND 2026-09-29 by a background security review of the drill commit (mealie/wger had the same shape and were changed to pass the password as `sys.argv[1]`). claper's `bin/claper rpc '… "${ADMIN_PASSWORD}" …'` has no argv: a household-typed password with `"` or `#{` breaks the command (recorded as failed; the page then warns) or changes the Elixir it runs — inside the household's own claper container, as that app. The generated value (letters + digits) is safe. **Fix direction:** (1) controller: `expandAfterInstall` refuses a value holding a quote, a backslash, `$`, `{`, `}`, a backtick or a newline — or a declared per-field encoding; (2) claper: read the value some other way (a file the command reads, or `System.get_env` from a one-shot env). | **OPEN — P3; owner: CC** |
|
||||
|
||||
<!-- DUE-CHECKS-BEGIN — machine-readable. Parsed by scripts/due_checks_gate.py.
|
||||
One row per dated check. The R-number must have a row above. Dates are UTC.
|
||||
|
||||
Reference in New Issue
Block a user