From 070cea5bd15d5c22e143980c03fc496003883410 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Sat, 17 Oct 2026 23:56:53 +0200 Subject: [PATCH] Night 2026-10-18: register (175 -> 173; closed R-981 R-1142 R-1063 R-1069 R-1143 R-994; opened R-1144..R-1147), STATUS morning list, golden 0.329.0 record, evidence, report Golden 0.329.0 baked at the floor's version, NOT vouched. Hub 0.158.0 built, NOT deployed. Sunday rotation: no duplicate bake of an unvouched golden at the floor's version. --- CONTEXT.md | 6 + REPORT-night-2026-10-18.md | 120 ++++++ REUSE.md | 2 + STATUS.md | 10 +- .../architecture/07-backup-architecture.md | 2 +- .../P1/r981-homepage-after-9201.txt | 16 + .../P1/r981-homepage-before.txt | 73 ++++ .../P1/redproof-catalog-gate-r1142.txt | 6 + .../P1/redproof-privpolicy.txt | 16 + .../night-2026-10-18/P1/redproof-r1063.txt | 12 + .../night-2026-10-18/P1/redproof-r1069.txt | 9 + .../night-2026-10-18/P1/redproof-r1143.txt | 7 + .../P1/redproof-userdata-env.txt | 12 + .../audits/night-2026-10-18/P2/box-walk.txt | 27 ++ .../P2/floors-global-and-clear.txt | 12 + .../audits/night-2026-10-18/P2/floors-set.txt | 9 + .../P2/global-floor-readback.txt | 8 + .../night-2026-10-18/P2/homepage-public.txt | 1 + .../audits/night-2026-10-18/P2/https-only.txt | 8 + .../night-2026-10-18/P6/memory-phase1.tsv | 89 ++++ .../night-2026-10-18/P6/memory-phase2.tsv | 391 ++++++++++++++++++ .../night-2026-10-18/P6/oom-kill-dmesg.txt | 12 + .../audits/night-2026-10-18/P6/peaks.md | 6 + .../audits/night-2026-10-18/P6/phase1-run.txt | 12 + .../P6/phase2-limit-raise.txt | 4 + .../audits/night-2026-10-18/P6/run-logs.txt | 27 ++ .../audits/night-2026-10-18/P6/teardown.txt | 7 + documentation/backlog/CLOSED-ITEMS.md | 11 + documentation/backlog/OPEN-ITEMS.md | 24 +- documentation/runbooks/nightly-rotation.md | 6 +- .../golden-0.329.0-2026-10-18/00-boot.txt | 14 + .../02-round-trip.txt | 3 + .../golden-0.329.0-2026-10-18/03-teardown.txt | 6 + .../04-agent-sha.txt | 4 + .../tests/golden-0.329.0-2026-10-18/README.md | 43 ++ .../tests/golden-0.329.0-2026-10-18/bake.log | 342 +++++++++++++++ 36 files changed, 1339 insertions(+), 18 deletions(-) create mode 100644 REPORT-night-2026-10-18.md create mode 100644 documentation/audits/night-2026-10-18/P1/r981-homepage-after-9201.txt create mode 100644 documentation/audits/night-2026-10-18/P1/r981-homepage-before.txt create mode 100644 documentation/audits/night-2026-10-18/P1/redproof-catalog-gate-r1142.txt create mode 100644 documentation/audits/night-2026-10-18/P1/redproof-privpolicy.txt create mode 100644 documentation/audits/night-2026-10-18/P1/redproof-r1063.txt create mode 100644 documentation/audits/night-2026-10-18/P1/redproof-r1069.txt create mode 100644 documentation/audits/night-2026-10-18/P1/redproof-r1143.txt create mode 100644 documentation/audits/night-2026-10-18/P1/redproof-userdata-env.txt create mode 100644 documentation/audits/night-2026-10-18/P2/box-walk.txt create mode 100644 documentation/audits/night-2026-10-18/P2/floors-global-and-clear.txt create mode 100644 documentation/audits/night-2026-10-18/P2/floors-set.txt create mode 100644 documentation/audits/night-2026-10-18/P2/global-floor-readback.txt create mode 100644 documentation/audits/night-2026-10-18/P2/homepage-public.txt create mode 100644 documentation/audits/night-2026-10-18/P2/https-only.txt create mode 100644 documentation/audits/night-2026-10-18/P6/memory-phase1.tsv create mode 100644 documentation/audits/night-2026-10-18/P6/memory-phase2.tsv create mode 100644 documentation/audits/night-2026-10-18/P6/oom-kill-dmesg.txt create mode 100644 documentation/audits/night-2026-10-18/P6/peaks.md create mode 100644 documentation/audits/night-2026-10-18/P6/phase1-run.txt create mode 100644 documentation/audits/night-2026-10-18/P6/phase2-limit-raise.txt create mode 100644 documentation/audits/night-2026-10-18/P6/run-logs.txt create mode 100644 documentation/audits/night-2026-10-18/P6/teardown.txt create mode 100644 documentation/tests/golden-0.329.0-2026-10-18/00-boot.txt create mode 100644 documentation/tests/golden-0.329.0-2026-10-18/02-round-trip.txt create mode 100644 documentation/tests/golden-0.329.0-2026-10-18/03-teardown.txt create mode 100644 documentation/tests/golden-0.329.0-2026-10-18/04-agent-sha.txt create mode 100644 documentation/tests/golden-0.329.0-2026-10-18/README.md create mode 100644 documentation/tests/golden-0.329.0-2026-10-18/bake.log diff --git a/CONTEXT.md b/CONTEXT.md index 2d96cd41..a99ecff2 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -16,6 +16,12 @@ > and holds nothing of its own; this file does hold its own content, namely the standing rulings below. +> **2026-10-18 (night) — controller 0.329.0 is the floor (MinAgent 0.158.1); golden 0.329.0 baked, NOT vouched; hub 0.158.0 +> built, NOT deployed.** Each app's own `appdata/` (R-1142), empty allow-list (R-981), drive retirement asks the +> agent first (R-1063), plain no-durable-id refusal (R-1069), `:latest` for releases only (R-1143), Immich 3072M/2048M +> (R-994). Hub 0.158.0: agent-only vouch, R-895 snapshot alarms, R-1140 access log. Installer `--rotate-recovery-only` +> on `main`, untagged (R-1141). `REPORT-night-2026-10-18.md`. + > **2026-10-17 (evening) — the catalog allow-list, agent 0.159.1, break-glass rotation (operator D1 = A, D2 = A).** > Controller v0.328.0 (floor, MinAgent 0.158.1): `internal/privpolicy` refuses container rights not on the list compiled > into the controller before ANY compose write (design: `02-controller-module-map.md` „[DESIGN] The catalog diff --git a/REPORT-night-2026-10-18.md b/REPORT-night-2026-10-18.md new file mode 100644 index 00000000..83301d87 --- /dev/null +++ b/REPORT-night-2026-10-18.md @@ -0,0 +1,120 @@ +# REPORT — night 2026-10-17 → 18 (unattended) + +## How I read the brief (no question could be asked) + +- **Part 7 (website cards) — NOT done, on purpose.** Both apps are closed to new installs (wger `lifecycle: hidden`, + plant-it `lifecycle: abandoned`), so the install wizard refuses them and a card would offer an app a visitor cannot get. + R-1036 is now a two-option question for the operator (STATUS D14). Recommendation not followed → this line says why. +- **„Measure on 9201"** = demo-hp's guest 9201 (Tier 0); homepage was not installed anywhere, so it was installed there + as a throwaway, measured, and removed after. +- **The hub image build** is allowed by the brief (Part 4.4) although `unprompted-work.md` forbids a hub build in an + unattended session without a task file: the brief is that task file. No deploy. +- **The Immich limit was raised on 9202 with `docker update`** for the measurement only (after two OOM kills), then put + back to the template's new values through the product (sync + restart). +- **R-1063 was not pressed live**: demo-hp's only user-data drive carries its apps and is not a backup target, so the + agent would say yes and really retire it. Fake-agent tests over TLS instead. + +## The morning list (top of STATUS) + +1. **Vouch golden 0.329.0 and agent 0.159.1 together** (Configuration → Day-0 artifacts): golden sha256 + `58dc40df555676d87200e5cb24cdc65f39cbacb2417e15a1955013526de4f68c`, agent sha256 + `de8f6ad96860ec399757a88d8bbb0191c089c9bb99db8212482c12daab41aff9` (read from the registry tonight — it matches the + brief), bundle `2af3d27d686fe611f3f44e89ba3d5123a5572f51eaf87e0ac63df00a41e67cd6`, Min agent **0.158.1**. +2. **May I deploy hub 0.158.0** (agent-only vouch, off-site snapshot alarm, 90-day access log)? Image + `sha256:e420397895b5e0857605cde72e649be032be31656bf569657e9864b8552a24aa`, built from felhom.eu `7d64038f`. +3. Decide D14 (the two website cards) and D15 (may the public estimator's Immich figure move up). + +## Each part + +| Part | Done? | What | +|---|---|---| +| 1.1 R-981 homepage socket | **done** | The socket served nothing: homepage's rendered `docker.yaml` is empty, no container carries `homepage.*` labels, no controller code names homepage. **Fix: the socket is removed** (template + allow-list); the allow-list now has **no exception at all**. Proven on 9201 (rc.2, then 0.329.0): homepage opens (container 200, traefik 200, public 200), `docker inspect` shows no socket mount, 0 refusals on all three test boxes. | +| 1.2 R-1142 own appdata folder | **done** | Root = `${HDD_PATH}/appdata//`. **The boring choice: a map compiled into the controller** (`allowlist.json` `appdata_folders`), not a `.felhom.yml` field — the catalog is the threat, so it must not name the folder. Map: **`paperless-ngx → paperless`** (the only slug ≠ folder in all 65 templates, the drill catalog and the three test boxes). Catalog gate mirrored; the lists stay byte-identical. | +| 1.3 R-1063 drive retirement order | **done** (unit-proven) | Agent asked first; 403/409 → nothing changes, plain 409 (HU + EN). New gap R-1144. | +| 1.4 R-1069 virtio refusal | **done** (unit-proven) | The agent's refusal → `disk.err.no_durable_id` (HU + EN). Agent unchanged. No page changed → no new fixture. | +| 1.5 R-1143 `:latest` | **done** | Release tags only; proven live (rc.1/rc.2 pushed no `:latest`). | +| 2 Controller release | **done** | 0.329.0: per-box floors → all three moved in < 8 min → box walk green (0 refusals, all containers healthy, login + files 200, homepage public 200, https-only check OK) → **global floor 0.329.0 / MinAgent 0.158.1** (303 `floor_set`, read back from the hub DB with its WAL) → per-box floors cleared. | +| 3 Golden | **done** | 0.329.0 baked at the floor's version, registry round trip = bake sha, teardown clean. **Not vouched.** Sunday runbook: no duplicate bake (wording added). No controller push after the bake. | +| 4 Hub | **built, not deployed** | v0.158.0: agent-only vouch, R-895 alarms, R-1140 access log — all red-proofed; `05`/`09` sentences. | +| 5 Agent | **committed, not released** | felhom-agent `6545ccc` („Unreleased"): the orphan check runs only after a failed snapshot step. R-1141: `--rotate-recovery-only` in felhom.eu (publishes with the next installer tag). No password rotated. | +| 6 Immich | **done** | Peaks below; limits raised (catalog `8cf03e0`). Synthetic library removed. | +| 7 Website | **not done** | See above (D14). | + +## Immich peaks (9202, 4,000 synthetic photos + all jobs; 30-s samples) + +| Container | Limit (before) | Anon peak | Peak / limit | memory.current peak at the limit | with room | Typical (median anon) | New limit | +|---|---|---|---|---|---|---|---| +| immich-server | 2048M | 1,596 MB | **77 %** — OOM-killed twice | 2,047 | 2,848 | 828 | **3072M** | +| immich-machine-learning | 1536M | 1,175 MB | **76 %** | 1,498 | 1,159 | 989 | **2048M** | +| immich-postgres | 768M | 76 MB | 9 % | 359 | — | 61 | 768M | +| immich-redis | 128M | 10 MB | 7 % | 43 | — | 10 | 128M | + +`mem_request` stays 2048M (typical total 1,888 MB): the install check judges the request, so an 8 GB box still installs +Immich alone (same verdict as yesterday); only the soft overcommit warning can appear on a guest below 6 GB. Result: 4,030 +photos, 75 people. Docker reported `OOMKilled=false` for both kills; the kernel log shows them +(`audits/night-2026-10-18/P6/oom-kill-dmesg.txt`) — the known LXC blind spot. + +## Versions and commits + +- felhom-controller **0.329.0** — `2fe6341`, `03ab121` (review fixes); images rc.1, rc.2, 0.329.0 (`aee51f3a…`). +- app-catalog-felhom.eu — `d928932` (homepage, gate), `fc93846` (gate review fix), `8cf03e0` (Immich). +- felhom.eu — `7d64038f` (hub v0.158.0 code, installer flag, docs); this commit (register, STATUS, evidence, runbook). +- felhom-agent — `6545ccc` (Unreleased). +- Hub image 0.158.0 built (not deployed). Golden 0.329.0 published (not vouched). +- Fixtures: none changed — the three new texts travel in JSON answers; every page fixture byte-identical. + +## Red-proofs (each: the old shape put back, the test seen failing, the fix restored) + +`audits/night-2026-10-18/P1/`: `redproof-privpolicy.txt` (R-1142: six binds admitted; R-981: „1 entries"), +`redproof-userdata-env.txt` (review fixes), `redproof-catalog-gate-r1142.txt` (four decoys), `redproof-r1063.txt`, +`redproof-r1069.txt`, `redproof-r1143.txt`. Hub (helper): agent-only vouch, two R-895 verdicts, the access log's secret +test and its wiring. Agent (helper): the check on a successful backup („ran 2 times, want 1"), four installer mutations. + +## The security review of my own pushed commit + +A background review flagged „authorization bypass" in `privpolicy.go`; its text did not reach me, so I looked myself and +found two real holes, both fixed and red-proofed before any release: an app NAMED like a folder the map gives another +app (`paperless`) got that folder; and with no drive, `policyEnv` took the app's own `USERDATA_PATH` (a deploy field a +catalog push can add) as a root. If the review meant something else, it is still open. + +## Register — 175 before, 173 after; opened 4, closed 6 + +Closed: R-981, R-1142, R-1063, R-1069, R-1143, R-994. Opened: R-1144, R-1145, R-1146, R-1147. Narrowed: R-1140, R-895, +R-1141. Waiting on the operator: R-1036. + +## Observations + +1. „Retire anyway" stops the drive's apps before the host is asked; on a refusal they stay stopped. FILED: R-1144. +2. The installer sets the console password before it vaults it. FILED: R-1145. +3. The installer harness is red on main and no gate runs it. FILED: R-1146. +4. The public estimator's Immich figure is from a 200-photo test. FILED: R-1147. +5. R-1140's „≈ 500 lines a day" was 3.7× low (≈ 1,870). NOT-A-FINDING: corrected in the row; the log is still small. +6. The controller's `test_build_push_once.sh` „local build" case failed when run in place (its workspace sat inside the + source). NOT-A-FINDING: fixed in the session (the test runs a copy, as the build dir does). +7. The agent's new orphan-check shape is not proven live. NOT-A-FINDING: it is unreleased; the next release's proof + shows one green backup with no check and one failed backup carrying the finding (agent CHANGELOG). +8. The Immich teardown also deleted 20 older test photos from an earlier session on the scratch box (the device search + matched them). NOT-A-FINDING: 9202 holds throwaways only; said here. +9. The scratch Immich's admin password was replaced to run the bench; the new one was shredded. NOT-A-FINDING: a later + bench resets it the same way (bcrypt into the `user` table — `immich-admin` needs a terminal). + +## Teardown — three layers + +- **Machines:** 9201 — homepage removed through the product (no container, no volume, no `app.yaml`); controller + 0.329.0. 9202 — synthetic library and bench folder removed, Immich back on the template's limits (3072M/2048M), healthy; + 9202 stays on its hand-set controller 0.327.1 (self-update off, by design). Drill VM — CT 9100 purged, token shredded, + VM off, disk back to `virgin`. DooPlex — the 11 GB photo set deleted from the scratchpad; no Docker cleanup run. +- **Hosts:** nothing changed on demo-hp, felhom-pve or Tester 1's host. +- **Hub:** global floor 0.329.0 / 0.158.1; no per-box floor; no deploy; no vouch. + +## Instruction files and the poster + +- `runbooks/nightly-rotation.md` (a runbook, not an instruction file): the Sunday golden step does not bake a duplicate + of an unvouched golden at the floor's version. +- Instruction files: none edited. +- System poster: **none of the three** — no fact in `felhom-system-poster.facts.md` changed tonight (the hub's 90-day + access log becomes one when hub 0.158.0 is deployed; that session updates the facts file). +- `unproven.py --summary`: not walked 35 of 55 — unchanged. + +Architecture documents read: `02` (the catalog allow-list), `03` (the R-1012 check), `05` (Day-0 manifest, R-120), +`07` (the off-site tier), `09` §3 decisions 162 and 250. diff --git a/REUSE.md b/REUSE.md index 0b0fe346..a002ffde 100644 --- a/REUSE.md +++ b/REUSE.md @@ -76,6 +76,8 @@ | `cloudflare.TokenZones` / `ZoneEquals` | hub/internal/cloudflare/reach.go | `(ctx, base, token) (names, total, err)` | R-138: what zones a pasted token can see | Every failure wraps `ErrReachUnknown` (refuse the save); the token never appears in an error; `/zones` is READ scope, not write | | `offsitekeys.Registrar` (`Install` / `Confirm` / `Audit` / `OpenWindow` / `CloseWindow` / `MoveAside`) | hub/internal/offsitekeys/offsitekeys.go | `(ctx, Target, password, …)` | EVERY write to a sub-account's `.ssh/authorized_keys` and every repo move-aside | **The only writer of that file, and the only deleter on a sub-account (`DeleteSetAside`: `.orphaned-*` only, decision 74).** `read()` is read-only (R-827). Uses the provider's port-23 restricted shell (`dd of=` takes stdin, `mv` overwrites, `test` does NOT exist — measured); an unpinned line is a deletion route and is dropped on every install; the window line goes FIRST (first match wins). Never `rm`. | | `offsitekeys.Service` (`RegisterKey`, `ConfirmKey`, `AuditAll`, `OpenWindowFor`, `CloseWindowFor`, `SweepExpiredWindows`) | hub/internal/offsitekeys/service.go | — | Binding the registrar to the store, descriptor and operator events | The box-facing API (`/api/v1/offsite/register-key…`) answers with NO credential — pinned by `TestOffsiteKeyEndpoints_AuthAndNoPasswordInAnyResponse`. | +| `offsitekeys` snapshot watch + `store.Get/SetOffsiteSnapshotListing` / `OffsiteRunTimesSince` (v0.158.0, R-895 slice 2) | hub/internal/offsitekeys/snapshot_watch.go, hub/internal/store/offsite_snapshots.go | — | Judging the 07:10 `snapshots/` listing against yesterday's (baseline in `hub_settings`) and the box's reported runs | Raises `offsite_snapshots_vanished` / `_unexplained` — operator-only and hub-origin (NOT in `allowedEventTypes`). The first listing is a baseline; a move-aside or RESET drops it. | +| `accesslog.New` / `Middleware` / `Mark` (v0.158.0, R-1140) | hub/internal/accesslog/accesslog.go | `Mark(ctx, kind)` | The hub's own access log (`/access-log/`, 90 days) and marking the identity KIND an auth check established | Never log a value: the path only (no query; `/bind/` and 32+-char segments redacted). A new auth path calls `Mark` with its kind. A logging failure never fails a request. | | `(*Store).SaveOneTimeSecret` / `OffsitePassword` / `SealLegacyOffsiteSecrets` | hub/internal/store/offsite_seal.go | — | Storing / reading the sub-account password | **Sealed AES-256-GCM; no key → refused (fail-closed).** Under `go test` every store gets a fixed key (`testing.Testing()`); production needs `OFFSITE_SECRET_KEY`. Never serve the value to a box. | | `(*Store).sealAtRest` / `openAtRest` / `sealAPIKey` / `apiKeyHash` / `SealLegacyBoxSecrets` | hub/internal/store/r879_box_seal.go | — | Any box-facing secret column (`hosts.api_key`, `customer_configs.api_key` / `retrieval_password`, `host_pbs_secrets.value`) | **R-879: same seal; a looked-up key is matched on `api_key_hash`, never opened** — box auth needs no sealing key. A sealed value that does not open sets `SecretsUnreadable` (field ""): serve/compare paths 500 on it and `SaveCustomerConfig` / `UpsertHost` refuse it (a load-modify-save would blank the secret). A new writer of an API key must write the hash in the same statement (`sealAPIKey`). Pinned by `store/r879_box_seal_test.go`, `api/r879_box_seal_test.go`. | diff --git a/STATUS.md b/STATUS.md index 12987e95..ec2feb8e 100644 --- a/STATUS.md +++ b/STATUS.md @@ -2,7 +2,7 @@ **Ready for the first real tester (Tester-2): yes. Tester 2 (a laptop) is off; nothing was sent to it.** -**Updated 2026-10-17 (evening).** Controller 0.328.0 is the floor for every box (17:22 local): the box refuses a catalog change that asks for dangerous container rights (your D2 = A). Agent 0.159.1 (a gone, decommissioned drive is forgotten; an orphan thin snapshot is named in the backup failure; new Go) — runs on demo-hp, Tester 1 and demo-felhom; **your vouch in the hub is still open**. New emergency root passwords on demo-hp, Tester 1, demo-felhom (your D1 = A; read them in the hub). Hub 0.157.0 deployed on your yes — `REPORT-agent-allowlist-rotation-2026-10-17.md`. **Earlier:** **Updated 2026-10-17 (afternoon, later).** Controller 0.327.1 is the floor for every box since 12:06 UTC: FileBrowser is published only after its default password is checked (your D11 = A), and the install check uses real memory amounts with a clear message (your D10 = A) — `REPORT-filebrowser-memory-ci-2026-10-17.md`. **Earlier:** Controller 0.326.0 is the floor for every box since 09:55 UTC: FileBrowser's default password is checked at every FileBrowser start. Tester 1 is back on the live app list (test apps and drives removed); six memory limits raised — `REPORT-tester1-limits-filebrowser-2026-10-17.md`. **Earlier today:** controller 0.325.0 was the floor since 08:21 UTC (after the three test boxes): two more password doors count a try before checking it, family sign-ins are stored as fingerprints, a file-share rename always applies; five apps' Redis saves snapshots now, which a full disk cannot damage — `REPORT-burndown-3-2026-10-17.md`. **Earlier (2026-10-17 night):** controller 0.324.0 was the floor for every box since 02:46 UTC (all three test boxes made tonight's off-site backup on it first): a restore now brings the database password back with the data (your 1A), restic 0.19.1 (your 2A), dashboard hardening — `REPORT-night-2026-10-17.md`. **Earlier (2026-10-16 evening):** 0.323.0, Debian 13 — `REPORT-debian13-restic-2026-10-16.md`. **Earlier (midday):** Controller 0.319.0 (the app page in panels, the login in one panel) is the floor, MinAgent 0.158.1 — `REPORT-app-page-tuning-2026-10-16.md`. **Earlier (morning):** Storage identity build B shipped: agent 0.158.1 and golden 0.318.0 vouched by you, controller 0.318.0 is the floor (MinAgent 0.158.1), installer 1.33.0 published — new one-disk boxes get their own data area. Open items: see `documentation/backlog/OPEN-ITEMS.md`. Older notes, day by day: +**Updated 2026-10-18 (night).** Controller 0.329.0 is the floor for every box (21:36 UTC, MinAgent 0.158.1), after the three test boxes: each app reaches only its own data folder on the drive; homepage no longer controls Docker, so no app has a special right; when the host refuses to retire a drive, nothing changes and the household reads why; a virtual disk without a serial gets a plain sentence. Immich gets 3 GB (it was killed twice at 2 GB on a 4,000-photo import). Golden 0.329.0 is baked, NOT vouched. Hub 0.158.0 is built, NOT deployed — `REPORT-night-2026-10-18.md`. **Earlier:** **Updated 2026-10-17 (evening).** Controller 0.328.0 is the floor for every box (17:22 local): the box refuses a catalog change that asks for dangerous container rights (your D2 = A). Agent 0.159.1 (a gone, decommissioned drive is forgotten; an orphan thin snapshot is named in the backup failure; new Go) — runs on demo-hp, Tester 1 and demo-felhom; **your vouch in the hub is still open**. New emergency root passwords on demo-hp, Tester 1, demo-felhom (your D1 = A; read them in the hub). Hub 0.157.0 deployed on your yes — `REPORT-agent-allowlist-rotation-2026-10-17.md`. **Earlier:** **Updated 2026-10-17 (afternoon, later).** Controller 0.327.1 is the floor for every box since 12:06 UTC: FileBrowser is published only after its default password is checked (your D11 = A), and the install check uses real memory amounts with a clear message (your D10 = A) — `REPORT-filebrowser-memory-ci-2026-10-17.md`. **Earlier:** Controller 0.326.0 is the floor for every box since 09:55 UTC: FileBrowser's default password is checked at every FileBrowser start. Tester 1 is back on the live app list (test apps and drives removed); six memory limits raised — `REPORT-tester1-limits-filebrowser-2026-10-17.md`. **Earlier today:** controller 0.325.0 was the floor since 08:21 UTC (after the three test boxes): two more password doors count a try before checking it, family sign-ins are stored as fingerprints, a file-share rename always applies; five apps' Redis saves snapshots now, which a full disk cannot damage — `REPORT-burndown-3-2026-10-17.md`. **Earlier (2026-10-17 night):** controller 0.324.0 was the floor for every box since 02:46 UTC (all three test boxes made tonight's off-site backup on it first): a restore now brings the database password back with the data (your 1A), restic 0.19.1 (your 2A), dashboard hardening — `REPORT-night-2026-10-17.md`. **Earlier (2026-10-16 evening):** 0.323.0, Debian 13 — `REPORT-debian13-restic-2026-10-16.md`. **Earlier (midday):** Controller 0.319.0 (the app page in panels, the login in one panel) is the floor, MinAgent 0.158.1 — `REPORT-app-page-tuning-2026-10-16.md`. **Earlier (morning):** Storage identity build B shipped: agent 0.158.1 and golden 0.318.0 vouched by you, controller 0.318.0 is the floor (MinAgent 0.158.1), installer 1.33.0 published — new one-disk boxes get their own data area. Open items: see `documentation/backlog/OPEN-ITEMS.md`. Older notes, day by day: `documentation/backlog/STATUS-HISTORY.md`. Reports: `REPORT-night-2026-10-14.md`, `REPORT-immich-rollout-2026-10-14.md`, `REPORT-seo-felho-tarhely-2026-10-14.md`, `REPORT-immich-repair-2026-10-14.md`, `REPORT-power-cut-fixes-2026-10-14.md`, `REPORT-night-power-2026-10-13.md`, `REPORT-poweroff.md`. ## What works @@ -57,14 +57,18 @@ | D6 | R-992 | The scratch box cannot read the private drill catalog: give it a read-only login, or make that copy readable? | **A read-only login** | Readable copy: the drill catalog becomes public | every new-app test needs hand-staging | new-app tests | | D7 | R-990, R-989 | Rule yes / no / later on the forum ideas (`audits/forum-research-2026-10-12/FELHOM.md` §5) and the selfh.st ideas (`audits/selfhst-survey-2026-10-12/FELHOM.md` §6) | — | — | nothing changes; the research ages | — | | D8 | R-206 | Install DooPlex's Docker settings from git (restarts Docker), and prune the build cache weekly: yes or no? | **Yes, in a quiet window** | — | a rebuild of DooPlex still has the settings in git | — | -| D13 | R-1140 | Keep the hub's access logs 90 days (today about 13 hours)? | **A — a small hub-only access log on the hub's own disk** (≈ 15 MB for 90 days) | B: longer logs for every container on DooPlex (≈ 1.3 GB compressed) | the next „was the key used?" question has about 13 hours of logs | — | +| D13 | R-1140 | **DECIDED 2026-10-17: A** — the hub keeps its own access log, 90 days. Built in hub 0.158.0 (≈ 19 MB for 90 days: the hub serves ≈ 1,870 requests a day, not 500); it waits for your deploy yes (morning list). | done | — | — | — | +| D14 | R-1036 | The apps page lacks Plant-it and wger. Both are closed to new installs (wger hidden, Plant-it abandoned by its makers): add their cards anyway? | **No — leave them off** and close the row; the site shows only what a visitor can install | Yes: first open them for install again (wger's login throttle, Plant-it has no upstream), then the cards | nothing changes; the site lists 62 catalog apps, all installable | — | +| D15 | R-1147 | The public machine estimator sizes Immich from a 200-photo test. Tonight's 4,000-photo test needed more. May the public figures move up? | **Yes** — CC re-runs the estimator with the new figures and shows you the before/after first | No: the page keeps the old Immich figure | a buyer with a big photo library may pick too small a machine | — | | D10 | R-1125 | **DECIDED 2026-10-17: A** — the 23 memory requests now match real use (catalog `1af6ea7`); the install refusal and page say what to do (controller 0.327.0). An 8 GB box no longer installs the whole household set. | done | — | — | — | | D11 | R-1126 | **DECIDED 2026-10-17: A** — FileBrowser is published only after its default password is checked; it never answers on the default (controller 0.327.1). The tunnel still runs before the claim, by design (`01` §5). | done | — | — | — | | D12 | R-1129 | **CLOSED 2026-10-17: not a defect** — CC misread the CI log; the failure mail always worked. A forced test mail went to admin@felhom.eu at 10:48:54 UTC (CC saw it arrive). Your key change did no harm. | done | — | — | — | | D9 | R-1062 | The N100's USB drive is also its whole-box backup drive. Split it in two anyway? | **No — keep one drive**; the lived-in box keeps its nightly whole-box backup | Split: the box loses its local whole-box backup (or add a second drive first) | it stays one drive; multi-drive tests stay on Tester 1 | — | ## Waiting on you — do -- **Vouch agent 0.159.1** in the hub (Configs → Day-0 artifacts: 0.159.1, sha256 `de8f6ad9…aff9`, bundle `2af3d27d…7cd6`). The three test hosts already run it. If you do not: a new box installs 0.158.1. +- **Vouch golden 0.329.0 and agent 0.159.1 together** (Configuration → Day-0 artifacts): golden sha256 `58dc40df555676d87200e5cb24cdc65f39cbacb2417e15a1955013526de4f68c`, agent sha256 `de8f6ad96860ec399757a88d8bbb0191c089c9bb99db8212482c12daab41aff9` (read from the registry tonight: matches), bundle `2af3d27d686fe611f3f44e89ba3d5123a5572f51eaf87e0ac63df00a41e67cd6`, Min agent **0.158.1**. If you do not: a new box installs golden 0.318.0 with agent 0.158.1 and then updates itself to the floor. +- **May I deploy hub 0.158.0** (you can vouch an agent without a new golden; the alarm for missing off-site copies; the hub's own 90-day access log)? Built tonight, not installed (night rule). The next daytime session asks you. If you say no: the hub stays 0.157.0 and nothing changes. +- **Sunday night's golden:** a golden at the floor's version (0.329.0) already exists, unvouched. The Sunday rotation does not bake a duplicate (runbook updated); it repeats the vouch line above if it is still open, and bakes only if the floor has moved above 0.329.0. - **Nézd meg a demo-hp-n a Calibre-Web „Adatok és mentés" fülét és a Fájlkezelőt** (`felhom.enkisfelhom.hu`, controller 0.321.0, minden dobozon kiadva). A mentés egy részben, egyszerű szavakkal; a Fájlkezelő nem kér frissítést és nem ajánl „Install app"-ot. - **Look at `roms/roms/` on the N100's drive in the file manager (R-1099).** RomM now scans `roms//`. A game uploaded through RomM before today sits one folder deeper: if there are platform folders in `roms/roms/`, move them up into `roms/` and press „Scan” in RomM. If not: those games show under a platform called „roms”. - **Nézd meg a Calibre-Web oldalát a demo-hp-n** (`felhom.enkisfelhom.hu`, controller 0.319.0, minden dobozon kiadva). A fejléc, a fülsor és minden rész most külön panel (az „A” stílus). A belépési adatok egy panelben vannak, egymás mellett. A Calibre-Web jelszaváról a doboz nem tud, mert az alkalmazás előbb települt, mint hogy a sablonban jelszó lett volna — ezt most egy mondat mondja ki. Ha nem tetszik, írd meg, mit változtassak. Ha nem nézed meg: semmi nem romlik el. diff --git a/documentation/architecture/07-backup-architecture.md b/documentation/architecture/07-backup-architecture.md index cdfe89b3..58a61493 100644 --- a/documentation/architecture/07-backup-architecture.md +++ b/documentation/architecture/07-backup-architecture.md @@ -253,7 +253,7 @@ It carries guest sizing, `pve_storage[]`, and an app half with per-app `storage_ the identity bundle's shape is `{tunnel_token, pbs_token, wg_private_key, restic_repo_password}` (`felhom-agent/internal/escrow/identity.go:26-39`). -**[DESIGN] Off-site deletion custody (decisions 68–69, 2026-10-03) — BUILT hub v0.127.0 / controller v0.289.1, live on both demo boxes.** The restic repository password stays on the box only. The box's off-site key is append-only (pinned in `authorized_keys`, written by the hub — the key registrar); the box never receives the sub-account password, which the hub stores encrypted at rest. Old snapshots are pruned by the box itself, only in a weekly window the hub opens, behind a fake-snapshot guard (R-822); the window has run live on both demo boxes since 2026-10-05 (R-95, closed). The guard's residual — past-dated fakes steering the keeps, and a window check that trusts the box's own counts — is R-822 and R-895. A Felhom-side pruner holding repository passwords is rejected. +**[DESIGN] Off-site deletion custody (decisions 68–69, 2026-10-03) — BUILT hub v0.127.0 / controller v0.289.1, live on both demo boxes.** The restic repository password stays on the box only. The box's off-site key is append-only (pinned in `authorized_keys`, written by the hub — the key registrar); the box never receives the sub-account password, which the hub stores encrypted at rest. Old snapshots are pruned by the box itself, only in a weekly window the hub opens, behind a fake-snapshot guard (R-822); the window has run live on both demo boxes since 2026-10-05 (R-95, closed). The guard's residual — past-dated fakes steering the keeps, and a window check that trusts the box's own counts — is R-822 and R-895. **Hub v0.158.0 (built 2026-10-18, deploy waits on the operator) adds the hub's own check:** the 07:10 key audit compares the repository's `snapshots/` listing, over the hub's own login, with yesterday's — files gone that no clean-up window explains raise `offsite_snapshots_vanished` (error), files no reported box run explains raise `offsite_snapshots_unexplained` (warning); both operator-only (R-895 slice 2). A Felhom-side pruner holding repository passwords is rejected. **[DESIGN, built hub 2026-10-07 — R-32 option A, `09` §3 decision 167] What RESET does to the household's off-site copy.** On the shared pool box a sub-account is a LOGIN, not the data: deleting it leaves its folder (measured diff --git a/documentation/audits/night-2026-10-18/P1/r981-homepage-after-9201.txt b/documentation/audits/night-2026-10-18/P1/r981-homepage-after-9201.txt new file mode 100644 index 00000000..281e94fb --- /dev/null +++ b/documentation/audits/night-2026-10-18/P1/r981-homepage-after-9201.txt @@ -0,0 +1,16 @@ +== controller +gitea.dooplex.hu/admin/felhom-controller:0.329.0-rc.2 Up 2 minutes (healthy) +== homepage mounts after the restart +volume /var/lib/docker/volumes/homepage_homepage_config/_data -> /app/config rw=true + +== socket mount count: 0 +homepage Up 49 seconds (healthy) +GET / (container) -> 200 48359B +GET /api/services (container) -> 200 556B +GET /api/widgets (container) -> 200 162B +GET https://home.enkisfelhom.hu/ through traefik -> 200 +== allow-list refusals since the controller start: 0 +23:51:00 [X] stop -> 200 {'ok': True, 'message': 'Stack homepage stop completed'} +23:51:32 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'homepage', 'volumes_removed': ['homepage_homepage_config'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'A +23:51:40 [X] after remove: deployed=False leftovers='/opt/docker/stacks/homepage' +remove: 200 diff --git a/documentation/audits/night-2026-10-18/P1/r981-homepage-before.txt b/documentation/audits/night-2026-10-18/P1/r981-homepage-before.txt new file mode 100644 index 00000000..1bfebab2 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P1/r981-homepage-before.txt @@ -0,0 +1,73 @@ +== mounts +volume /var/lib/docker/volumes/homepage_homepage_config/_data -> /app/config rw=true +bind /var/run/docker.sock -> /var/run/docker.sock rw=false + +== config files +total 20 +drwxr-xr-x 3 root root 4096 Oct 17 20:34 . +drwxr-xr-x 1 node node 4096 Oct 17 20:34 .. +-rw-r--r-- 1 node node 31 Oct 17 20:34 kubernetes.yaml +drwxr-xr-x 2 root root 4096 Oct 17 20:34 logs +-rw-r--r-- 1 node node 184 Oct 17 20:34 settings.yaml +== docker.yaml (non-comment lines) +grep: /app/config/docker.yaml: No such file or directory +== services.yaml (non-comment lines) +grep: /app/config/services.yaml: No such file or directory +== widgets.yaml (non-comment lines) +grep: /app/config/widgets.yaml: No such file or directory +== settings.yaml (non-comment lines) +--- +providers: + openweathermap: openweathermapapikey + weatherapi: weatherapiapikey +== bookmarks.yaml (non-comment lines) +grep: /app/config/bookmarks.yaml: No such file or directory +== labels on other containers (homepage.*) +== GET / -> 200 48359B + +== GET /api/services -> 200 556B +[{"name":"My First Group","services":[{"name":"My First Service","href":"http://localhost/","description":"Homepage is awesome","weight":100,"type":"service","widgets":[]}],"groups":[]},{"name":"My Second Group","services":[{"name":"My Second Service","href":"http://localhost/","description":"Homepage is the best","weight":100,"type":"service","widgets":[]}],"groups":[]},{"name":"My Third Group"," +== GET /api/widgets -> 200 162B +[{"type":"resources","options":{"index":0,"cpu":true,"memory":true,"disk":"/"}},{"type":"search","options":{"index":1,"provider":"duckduckgo","target":"_blank"}}] +== GET /api/bookmarks -> 200 286B +[{"name":"Developer","bookmarks":[{"name":"Github","abbr":"GH","href":"https://github.com/"}]},{"name":"Social","bookmarks":[{"name":"Reddit","abbr":"RE","href":"https://reddit.com/"}]},{"name":"Entertainment","bookmarks":[{"name":"YouTube","abbr":"YT","href":"https://youtube.com/"}]}] +== socket use in logs +1 +Skipping ownership changes for /app/config +Skipping ownership changes for /app/config/logs +/app/.next already owned by correct UID/GID or running as root, skipping chown +▲ Next.js 16.2.6 +- Local: http://[::1]:3000 +- Network: http://[::]:3000 +✓ Ready in 0ms +settings.yaml was copied to the config folder +[2026-10-17T20:34:11.277Z] info: kubernetes.yaml was copied to the config folder +[2026-10-17T20:34:31.258Z] info: docker.yaml was copied to the config folder +[2026-10-17T20:34:31.264Z] info: services.yaml was copied to the config folder +[2026-10-17T20:34:31.292Z] info: widgets.yaml was copied to the config folder +[2026-10-17T20:34:31.317Z] info: bookmarks.yaml was copied to the config folder +== docker.yaml non-comment lines: +--- +== services.yaml non-comment lines: +--- +- My First Group: + - My First Service: + href: http://localhost/ + description: Homepage is awesome +- My Second Group: + - My Second Service: + href: http://localhost/ + description: Homepage is the best +- My Third Group: + - My Third Service: + href: http://localhost/ + description: Homepage is 😎 +== widgets.yaml non-comment lines: +--- +- resources: + cpu: true + memory: true + disk: / +- search: + provider: duckduckgo + target: _blank diff --git a/documentation/audits/night-2026-10-18/P1/redproof-catalog-gate-r1142.txt b/documentation/audits/night-2026-10-18/P1/redproof-catalog-gate-r1142.txt new file mode 100644 index 00000000..40f56496 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P1/redproof-catalog-gate-r1142.txt @@ -0,0 +1,6 @@ +== RED-PROOF catalog gate (R-1142): root back at ${HDD_PATH}/appdata + XX FACT: app a binds app b's appdata folder (R-1142) rc=0 (expected 1) + XX FACT: a name that only STARTS like its own (R-1142) rc=0 (expected 1) + XX FACT: the whole appdata/ (R-1142) rc=0 (expected 1) + XX FACT: paperless-ngx binds appdata/paperless-ngx (the slug, where a folder is listed) rc=0 (expected 1) +fails: 4 diff --git a/documentation/audits/night-2026-10-18/P1/redproof-privpolicy.txt b/documentation/audits/night-2026-10-18/P1/redproof-privpolicy.txt new file mode 100644 index 00000000..aa1f9f99 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P1/redproof-privpolicy.txt @@ -0,0 +1,16 @@ +== RED-PROOF R-1142 (box): HDD root back at ${HDD_PATH}/appdata (v0.328.0) + privpolicy_test.go:499: immich binding ${HDD_PATH}/appdata/nextcloud:/data was admitted + privpolicy_test.go:499: romm binding ${HDD_PATH}/appdata/paperless/media:/m was admitted + privpolicy_test.go:499: immich binding ${HDD_PATH}/appdata:/all was admitted + privpolicy_test.go:499: immich binding ${HDD_PATH}/appdata/immich-other:/x was admitted + privpolicy_test.go:499: paperless-ngx binding ${HDD_PATH}/appdata/paperless-ngx:/x was admitted + privpolicy_test.go:499: immich binding /mnt/felhom-drives/adatlemez/felhom-data/appdata/nextcloud:/x was admitted +FAIL +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.008s +FAIL + +== RED-PROOF R-981 (box): the old one-entry allowlist.json compiled in + privpolicy_test.go:466: the compiled allow-list has 1 entries; R-981 left it empty +FAIL +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.005s +FAIL diff --git a/documentation/audits/night-2026-10-18/P1/redproof-r1063.txt b/documentation/audits/night-2026-10-18/P1/redproof-r1063.txt new file mode 100644 index 00000000..1d1fbbef --- /dev/null +++ b/documentation/audits/night-2026-10-18/P1/redproof-r1063.txt @@ -0,0 +1,12 @@ +== RED-PROOF R-1063: mark + default moved BEFORE agent.Decommission (the v0.328.0 order) + decommission_test.go:154: the drive reads decommissioned although the agent refused + decommission_test.go:157: default moved to "/mnt/new" although the agent refused + decommission_test.go:154: the drive reads decommissioned although the agent refused + decommission_test.go:157: default moved to "/mnt/new" although the agent refused + decommission_test.go:176: a transport failure: err=a meghajtó leszerelése sikertelen: agentapi: dial: refused policy=false marked=true +--- FAIL: TestFinalizeDecommission_AgentRefusalChangesNothing (0.01s) + --- FAIL: TestFinalizeDecommission_AgentRefusalChangesNothing/403 (0.01s) + --- FAIL: TestFinalizeDecommission_AgentRefusalChangesNothing/409 (0.00s) +FAIL +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.021s +FAIL diff --git a/documentation/audits/night-2026-10-18/P1/redproof-r1069.txt b/documentation/audits/night-2026-10-18/P1/redproof-r1069.txt new file mode 100644 index 00000000..aa67b6a0 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P1/redproof-r1069.txt @@ -0,0 +1,9 @@ +== RED-PROOF R-1069 (web): ErrNoDurableID branch removed from runStorageInit + r1069_no_durable_id_test.go:30: HU text lacks "virtu": "formázás sikertelen: agentapi: format refused — the device has no durable id (path-only formats are not permitted)" + r1069_no_durable_id_test.go:30: HU text lacks "sorozatsz": "formázás sikertelen: agentapi: format refused — the device has no durable id (path-only formats are not permitted)" + r1069_no_durable_id_test.go:30: HU text lacks "nem v": "formázás sikertelen: agentapi: format refused — the device has no durable id (path-only formats are not permitted)" + r1069_no_durable_id_test.go:30: HU text lacks "zemeltet": "formázás sikertelen: agentapi: format refused — the device has no durable id (path-only formats are not permitted)" +== RED-PROOF R-1069 (agentapi): the 409 text match removed from FormatDisk + crashguard_test.go:84: body {"ok":false,"error":"format refused: device has no durable i: ErrNoDurableID=false want true (err agentapi: format: HTTP 409: format refused: device has no durable id to bind the format to (path-only formats are not permitted)) +FAIL +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/agentapi 0.012s diff --git a/documentation/audits/night-2026-10-18/P1/redproof-r1143.txt b/documentation/audits/night-2026-10-18/P1/redproof-r1143.txt new file mode 100644 index 00000000..69239904 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P1/redproof-r1143.txt @@ -0,0 +1,7 @@ +== RED-PROOF R-1143: every build adds :latest (the v0.328.0 shape) + FAIL --print-tags 0.999.0-rc.1 -> no :latest: output contains 'felhom-controller:latest', which must not happen + FAIL --print-tags 0.999.0-rc.12 -> no :latest: output contains 'felhom-controller:latest', which must not happen + FAIL --print-tags dev -> no :latest: output contains 'felhom-controller:latest', which must not happen + FAIL --print-tags 0.999 -> no :latest: output contains 'felhom-controller:latest', which must not happen + ok --print-tags 0.999.0 (a release) -> :latest too +5 of 16 cases FAILED diff --git a/documentation/audits/night-2026-10-18/P1/redproof-userdata-env.txt b/documentation/audits/night-2026-10-18/P1/redproof-userdata-env.txt new file mode 100644 index 00000000..df6bca90 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P1/redproof-userdata-env.txt @@ -0,0 +1,12 @@ +== RED-PROOF security review 2026-10-18 (box): policyEnv keeps an app-env USERDATA_PATH + allowlist_test.go:97: an app with no drive kept its own USERDATA_PATH "/mnt/felhom-drives/a/felhom-data/appdata" as a root +FAIL +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.009s +FAIL + +== RED-PROOF security review 2026-10-18 (box): an app named like a mapped folder owns it + privpolicy_test.go:532: AppdataFolder(paperless) = "paperless" — a template named like paperless-ngx's folder must not own it + privpolicy_test.go:535: a template named paperless was admitted to paperless-ngx's folder +FAIL +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.005s +FAIL diff --git a/documentation/audits/night-2026-10-18/P2/box-walk.txt b/documentation/audits/night-2026-10-18/P2/box-walk.txt new file mode 100644 index 00000000..2dc1ca5b --- /dev/null +++ b/documentation/audits/night-2026-10-18/P2/box-walk.txt @@ -0,0 +1,27 @@ +=== demo-hp (enkisfelhom.hu) +containers: 25 running; not healthy/running: +unhealthy: 0 +2026/10/17 21:27:25 updater.go:855: [INFO] [selfupdate] Post-update startup: update successful (0.329.0-rc.2 → 0.329.0) +allow-list refusals since start: 0 +2026/10/17 21:27:26 sync.go:142: [INFO] [sync] Initial sync: Sablonok naprakészek — nincs változás +installed apps (stacks with app.yaml): 13 +public https://felhom.enkisfelhom.hu/login: 200 +public https://files.enkisfelhom.hu/: 200 +=== demo-felhom (demo-felhom.eu) +containers: 9 running; not healthy/running: +unhealthy: 0 +2026/10/17 21:27:12 [INFO] [selfupdate] Post-update startup: update successful (0.328.0 → 0.329.0) +allow-list refusals since start: 0 +2026/10/17 21:27:13 [INFO] [sync] Initial sync: Sablonok frissítve — a katalógus új változata betöltve; a telepített alkalmazások fájljai nem változtak +installed apps (stacks with app.yaml): 5 +public https://felhom.demo-felhom.eu/login: 200 +public https://files.demo-felhom.eu/: 200 +=== tester-1 (enkicsifelhom.hu) +containers: 10 running; not healthy/running: +unhealthy: 0 +2026/10/17 21:27:24 [INFO] [selfupdate] Post-update startup: update successful (0.328.0 → 0.329.0) +allow-list refusals since start: 0 +2026/10/17 21:27:26 [INFO] [sync] Initial sync: Sablonok frissítve — a katalógus új változata betöltve; a telepített alkalmazások fájljai nem változtak +installed apps (stacks with app.yaml): 3 +public https://felhom.enkicsifelhom.hu/login: 200 +public https://files.enkicsifelhom.hu/: 200 diff --git a/documentation/audits/night-2026-10-18/P2/floors-global-and-clear.txt b/documentation/audits/night-2026-10-18/P2/floors-global-and-clear.txt new file mode 100644 index 00000000..6f2944bf --- /dev/null +++ b/documentation/audits/night-2026-10-18/P2/floors-global-and-clear.txt @@ -0,0 +1,12 @@ +== global floor 2026-10-17T21:36:01Z +HTTP/1.1 303 See Other +Location: /configuration?flash=floor_set +clear tester-1: +HTTP/1.1 303 See Other +Location: /customers/tester-1?flash=floor_set +clear demo-hp: +HTTP/1.1 303 See Other +Location: /customers/demo-hp?flash=floor_set +clear demo-felhom: +HTTP/1.1 303 See Other +Location: /customers/demo-felhom?flash=floor_set diff --git a/documentation/audits/night-2026-10-18/P2/floors-set.txt b/documentation/audits/night-2026-10-18/P2/floors-set.txt new file mode 100644 index 00000000..56bcceb7 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P2/floors-set.txt @@ -0,0 +1,9 @@ +set tester-1: +HTTP/1.1 303 See Other +Location: /customers/tester-1?flash=floor_set +set demo-hp: +HTTP/1.1 303 See Other +Location: /customers/demo-hp?flash=floor_set +set demo-felhom: +HTTP/1.1 303 See Other +Location: /customers/demo-felhom?flash=floor_set diff --git a/documentation/audits/night-2026-10-18/P2/global-floor-readback.txt b/documentation/audits/night-2026-10-18/P2/global-floor-readback.txt new file mode 100644 index 00000000..026b722e --- /dev/null +++ b/documentation/audits/night-2026-10-18/P2/global-floor-readback.txt @@ -0,0 +1,8 @@ +integrity: ok +('min_controller_version', '0.329.0') +('min_controller_version_declared_min_agent', '0.329.0=0.158.1') +per-box floor columns: [] +table customer_configs per-box floor columns: ['min_controller_version', 'min_controller_declared_min_agent', 'min_controller_set_at'] + min_controller_version set: [] + min_controller_declared_min_agent set: [] + min_controller_set_at set: [] diff --git a/documentation/audits/night-2026-10-18/P2/homepage-public.txt b/documentation/audits/night-2026-10-18/P2/homepage-public.txt new file mode 100644 index 00000000..1fee1a59 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P2/homepage-public.txt @@ -0,0 +1 @@ +homepage public https://home.enkisfelhom.hu/ -> 200 diff --git a/documentation/audits/night-2026-10-18/P2/https-only.txt b/documentation/audits/night-2026-10-18/P2/https-only.txt new file mode 100644 index 00000000..58e209f3 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P2/https-only.txt @@ -0,0 +1,8 @@ + OK http://files.demo-felhom.eu/r1033-check?q=1 -> 301 https://files.demo-felhom.eu/r1033-check?q=1 + OK http://gist.demo-felhom.eu/r1033-check?q=1 -> 301 https://gist.demo-felhom.eu/r1033-check?q=1 + OK http://no-such-name-r1033.demo-felhom.eu/r1033-check?q=1 -> 301 https://no-such-name-r1033.demo-felhom.eu/r1033-check?q=1 + OK http://prowlarr.demo-felhom.eu/r1033-check?q=1 -> 301 https://prowlarr.demo-felhom.eu/r1033-check?q=1 + OK http://radarr.demo-felhom.eu/r1033-check?q=1 -> 301 https://radarr.demo-felhom.eu/r1033-check?q=1 + OK http://sonarr.demo-felhom.eu/r1033-check?q=1 -> 301 https://sonarr.demo-felhom.eu/r1033-check?q=1 + OK http://torrent.demo-felhom.eu/r1033-check?q=1 -> 301 https://torrent.demo-felhom.eu/r1033-check?q=1 +== every public name redirects http -> https diff --git a/documentation/audits/night-2026-10-18/P6/memory-phase1.tsv b/documentation/audits/night-2026-10-18/P6/memory-phase1.tsv new file mode 100644 index 00000000..725c0617 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P6/memory-phase1.tsv @@ -0,0 +1,89 @@ +time container current_mb anon_mb file_mb peak_mb limit_mb +2026-10-17T20:42:46Z immich-server 929 790 88 933 2048 +2026-10-17T20:42:46Z immich-machine-learning 268 156 105 285 1536 +2026-10-17T20:42:46Z immich-postgres 98 21 68 113 768 +2026-10-17T20:42:46Z immich-redis 8 3 3 14 128 +2026-10-17T20:43:16Z immich-server 2047 1596 330 2050 2048 +2026-10-17T20:43:16Z immich-machine-learning 1498 1110 386 1536 1536 +2026-10-17T20:43:16Z immich-postgres 155 67 75 161 768 +2026-10-17T20:43:16Z immich-redis 10 4 3 14 128 +2026-10-17T20:43:46Z immich-server 2047 1369 625 2050 2048 +2026-10-17T20:43:46Z immich-machine-learning 1361 1029 319 1536 1536 +2026-10-17T20:43:46Z immich-postgres 165 69 84 171 768 +2026-10-17T20:43:46Z immich-redis 10 5 3 14 128 +2026-10-17T20:44:17Z immich-server 2047 1134 812 2050 2048 +2026-10-17T20:44:17Z immich-machine-learning 1319 990 318 1536 1536 +2026-10-17T20:44:17Z immich-postgres 177 71 92 180 768 +2026-10-17T20:44:17Z immich-redis 11 5 3 15 128 +2026-10-17T20:44:47Z immich-server 2047 1202 720 2050 2048 +2026-10-17T20:44:47Z immich-machine-learning 1340 987 314 1536 1536 +2026-10-17T20:44:47Z immich-postgres 186 71 101 190 768 +2026-10-17T20:44:47Z immich-redis 11 6 3 15 128 +2026-10-17T20:45:18Z immich-server 2047 1227 744 2050 2048 +2026-10-17T20:45:18Z immich-machine-learning 1464 1144 309 1536 1536 +2026-10-17T20:45:18Z immich-postgres 195 72 109 198 768 +2026-10-17T20:45:18Z immich-redis 12 6 3 15 128 +2026-10-17T20:45:48Z immich-server 2047 1277 652 2050 2048 +2026-10-17T20:45:48Z immich-machine-learning 1364 1040 280 1536 1536 +2026-10-17T20:45:48Z immich-postgres 203 73 115 207 768 +2026-10-17T20:45:48Z immich-redis 12 6 3 16 128 +2026-10-17T20:46:18Z immich-server 2047 1297 600 2050 2048 +2026-10-17T20:46:18Z immich-machine-learning 1256 1013 227 1536 1536 +2026-10-17T20:46:18Z immich-postgres 206 73 119 213 768 +2026-10-17T20:46:18Z immich-redis 13 7 4 17 128 +2026-10-17T20:46:49Z immich-server 2047 1345 597 2050 2048 +2026-10-17T20:46:49Z immich-machine-learning 1304 1147 142 1536 1536 +2026-10-17T20:46:49Z immich-postgres 192 73 104 213 768 +2026-10-17T20:46:49Z immich-redis 13 7 4 18 128 +2026-10-17T20:47:19Z immich-server 2047 1294 621 2050 2048 +2026-10-17T20:47:19Z immich-machine-learning 1249 1105 139 1536 1536 +2026-10-17T20:47:19Z immich-postgres 203 73 115 213 768 +2026-10-17T20:47:19Z immich-redis 15 7 6 19 128 +2026-10-17T20:47:49Z immich-server 2047 1309 653 2050 2048 +2026-10-17T20:47:49Z immich-machine-learning 1190 1115 60 1536 1536 +2026-10-17T20:47:49Z immich-postgres 181 73 93 213 768 +2026-10-17T20:47:49Z immich-redis 15 7 6 20 128 +2026-10-17T20:48:20Z immich-server 2047 1232 693 2050 2048 +2026-10-17T20:48:20Z immich-machine-learning 1093 1018 60 1536 1536 +2026-10-17T20:48:20Z immich-postgres 193 73 105 213 768 +2026-10-17T20:48:20Z immich-redis 16 7 7 21 128 +2026-10-17T20:48:50Z immich-server 2047 1305 587 2050 2048 +2026-10-17T20:48:50Z immich-machine-learning 1123 1047 58 1536 1536 +2026-10-17T20:48:50Z immich-postgres 188 73 101 213 768 +2026-10-17T20:48:50Z immich-redis 17 8 7 21 128 +2026-10-17T20:49:21Z immich-server 2047 1212 739 2050 2048 +2026-10-17T20:49:21Z immich-machine-learning 1236 1175 47 1536 1536 +2026-10-17T20:49:21Z immich-postgres 183 73 95 213 768 +2026-10-17T20:49:21Z immich-redis 19 8 8 23 128 +2026-10-17T20:49:51Z immich-server 2047 1245 665 2050 2048 +2026-10-17T20:49:51Z immich-machine-learning 1050 1003 47 1536 1536 +2026-10-17T20:49:51Z immich-postgres 190 73 102 213 768 +2026-10-17T20:49:51Z immich-redis 19 8 8 23 128 +2026-10-17T20:50:21Z immich-server 2047 1426 525 2050 2048 +2026-10-17T20:50:21Z immich-machine-learning 1148 1057 47 1536 1536 +2026-10-17T20:50:21Z immich-postgres 195 73 107 213 768 +2026-10-17T20:50:21Z immich-redis 21 8 10 25 128 +2026-10-17T20:50:52Z immich-server 2047 1383 540 2050 2048 +2026-10-17T20:50:52Z immich-machine-learning 1139 1072 47 1536 1536 +2026-10-17T20:50:52Z immich-postgres 200 73 111 213 768 +2026-10-17T20:50:52Z immich-redis 21 8 10 25 128 +2026-10-17T20:51:22Z immich-server 2047 1315 637 2050 2048 +2026-10-17T20:51:22Z immich-machine-learning 1110 1046 47 1536 1536 +2026-10-17T20:51:22Z immich-postgres 206 74 117 213 768 +2026-10-17T20:51:22Z immich-redis 21 8 10 26 128 +2026-10-17T20:51:52Z immich-server 2043 1198 705 2050 2048 +2026-10-17T20:51:52Z immich-machine-learning 1212 1150 47 1536 1536 +2026-10-17T20:51:52Z immich-postgres 218 75 128 223 768 +2026-10-17T20:51:52Z immich-redis 21 8 10 26 128 +2026-10-17T20:52:23Z immich-server 2042 1249 690 2050 2048 +2026-10-17T20:52:23Z immich-machine-learning 1148 1090 47 1536 1536 +2026-10-17T20:52:23Z immich-postgres 227 76 135 230 768 +2026-10-17T20:52:23Z immich-redis 21 9 11 27 128 +2026-10-17T20:52:53Z immich-server 1672 1320 282 1672 2048 +2026-10-17T20:52:53Z immich-machine-learning 1151 1098 47 1536 1536 +2026-10-17T20:52:53Z immich-postgres 202 49 140 237 768 +2026-10-17T20:52:53Z immich-redis 22 9 11 27 128 +2026-10-17T20:53:23Z immich-server 2047 1478 494 2048 2048 +2026-10-17T20:53:23Z immich-machine-learning 1151 1088 47 1536 1536 +2026-10-17T20:53:23Z immich-postgres 192 51 128 237 768 +2026-10-17T20:53:23Z immich-redis 22 9 12 27 128 diff --git a/documentation/audits/night-2026-10-18/P6/memory-phase2.tsv b/documentation/audits/night-2026-10-18/P6/memory-phase2.tsv new file mode 100644 index 00000000..10be5ea5 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P6/memory-phase2.tsv @@ -0,0 +1,391 @@ +{"photos":4030,"videos":0,"usage":11201384478,"usagePhotos":11201384478,"usageVideos":0,"usageByUser":[{"userId":"3054bbba-1bdb-4f61-9e2a-7abdfd602daa","userName":"Household","photos":4020,"videos":0,"usage":11152710828,"usagePhotos":11152710828,"usageVideos":0,"quotaSizeInBytes":null},{"userId":"bf +"total":75 +time container current_mb anon_mb file_mb peak_mb limit_mb restarts +2026-10-17T20:54:22Z immich-server 2047 984 986 2048 2048 1 +2026-10-17T20:54:22Z immich-machine-learning 1060 1000 47 1536 1536 0 +2026-10-17T20:54:22Z immich-postgres 204 51 139 237 768 0 +2026-10-17T20:54:22Z immich-redis 23 9 12 28 128 0 +2026-10-17T20:54:53Z immich-server 2047 1184 773 2048 2048 1 +2026-10-17T20:54:53Z immich-machine-learning 1189 1129 47 1536 1536 0 +2026-10-17T20:54:53Z immich-postgres 209 52 143 237 768 0 +2026-10-17T20:54:53Z immich-redis 23 9 12 28 128 0 +2026-10-17T20:55:23Z immich-server 2047 1192 744 2048 2048 1 +2026-10-17T20:55:23Z immich-machine-learning 1199 1137 47 1536 1536 0 +2026-10-17T20:55:23Z immich-postgres 213 52 147 237 768 0 +2026-10-17T20:55:23Z immich-redis 25 9 14 29 128 0 +2026-10-17T20:55:54Z immich-server 2047 1199 729 2048 2048 1 +2026-10-17T20:55:54Z immich-machine-learning 1140 1040 47 1536 1536 0 +2026-10-17T20:55:54Z immich-postgres 218 52 152 237 768 0 +2026-10-17T20:55:54Z immich-redis 25 9 14 30 128 0 +2026-10-17T20:56:25Z immich-server 2047 1159 772 2048 2048 1 +2026-10-17T20:56:25Z immich-machine-learning 1194 1145 47 1536 1536 0 +2026-10-17T20:56:25Z immich-postgres 223 52 157 237 768 0 +2026-10-17T20:56:25Z immich-redis 27 9 16 32 128 0 +2026-10-17T20:56:56Z immich-server 2047 1112 893 2048 2048 1 +2026-10-17T20:56:56Z immich-machine-learning 1150 1083 47 1536 1536 0 +2026-10-17T20:56:56Z immich-postgres 233 52 166 237 768 0 +2026-10-17T20:56:56Z immich-redis 27 9 16 32 128 0 +2026-10-17T20:57:26Z immich-server 2047 1079 915 2048 2048 1 +2026-10-17T20:57:26Z immich-machine-learning 1116 1067 47 1536 1536 0 +2026-10-17T20:57:26Z immich-postgres 239 54 171 242 768 0 +2026-10-17T20:57:26Z immich-redis 27 9 16 33 128 0 +2026-10-17T20:57:57Z immich-server 2046 1022 959 2048 2048 1 +2026-10-17T20:57:57Z immich-machine-learning 1177 1115 47 1536 1536 0 +2026-10-17T20:57:57Z immich-postgres 245 52 178 248 768 0 +2026-10-17T20:57:57Z immich-redis 28 10 16 33 128 0 +2026-10-17T20:58:27Z immich-server 2032 1104 877 2048 2048 1 +2026-10-17T20:58:27Z immich-machine-learning 1159 1101 47 1536 1536 0 +2026-10-17T20:58:27Z immich-postgres 249 52 182 255 768 0 +2026-10-17T20:58:27Z immich-redis 30 10 18 35 128 0 +2026-10-17T20:58:58Z immich-server 2045 1066 903 2048 2048 1 +2026-10-17T20:58:58Z immich-machine-learning 1131 1068 47 1536 1536 0 +2026-10-17T20:58:58Z immich-postgres 252 52 186 255 768 0 +2026-10-17T20:58:58Z immich-redis 30 10 18 35 128 0 +2026-10-17T20:59:29Z immich-server 1969 1057 817 2048 2048 1 +2026-10-17T20:59:29Z immich-machine-learning 1155 1078 47 1536 1536 0 +2026-10-17T20:59:29Z immich-postgres 242 52 175 258 768 0 +2026-10-17T20:59:29Z immich-redis 33 10 21 38 128 0 +2026-10-17T20:59:59Z immich-server 855 716 102 855 2048 2 +2026-10-17T20:59:59Z immich-machine-learning 991 927 47 1536 1536 0 +2026-10-17T20:59:59Z immich-postgres 210 19 179 258 768 0 +2026-10-17T20:59:59Z immich-redis 34 10 21 38 128 0 +2026-10-17T21:00:30Z immich-server 2047 1440 512 2048 2048 2 +2026-10-17T21:00:30Z immich-machine-learning 1099 1043 47 1536 1536 0 +2026-10-17T21:00:30Z immich-postgres 236 42 180 258 768 0 +2026-10-17T21:00:30Z immich-redis 33 10 21 38 128 0 +2026-10-17T21:01:01Z immich-server 1973 1143 742 2048 2048 2 +2026-10-17T21:01:01Z immich-machine-learning 1220 1157 47 1536 1536 0 +2026-10-17T21:01:01Z immich-postgres 238 42 182 258 768 0 +2026-10-17T21:01:01Z immich-redis 33 10 21 38 128 0 +2026-10-17T21:01:31Z immich-server 2047 1168 738 2048 2048 2 +2026-10-17T21:01:31Z immich-machine-learning 1183 1079 47 1536 1536 0 +2026-10-17T21:01:31Z immich-postgres 269 59 193 273 768 0 +2026-10-17T21:01:31Z immich-redis 36 10 23 41 128 0 +2026-10-17T21:02:02Z immich-server 1935 1301 587 2048 2048 2 +2026-10-17T21:02:02Z immich-machine-learning 1126 1061 47 1536 1536 0 +2026-10-17T21:02:02Z immich-postgres 275 59 199 277 768 0 +2026-10-17T21:02:02Z immich-redis 36 10 23 41 128 0 +2026-10-17T21:02:33Z immich-server 2046 1398 599 2048 2048 2 +2026-10-17T21:02:33Z immich-machine-learning 1160 1103 47 1536 1536 0 +2026-10-17T21:02:33Z immich-postgres 281 60 205 287 768 0 +2026-10-17T21:02:33Z immich-redis 36 10 23 41 128 0 +2026-10-17T21:03:03Z immich-server 1578 774 729 2048 2048 2 +2026-10-17T21:03:03Z immich-machine-learning 1190 1130 47 1536 1536 0 +2026-10-17T21:03:03Z immich-postgres 287 60 210 289 768 0 +2026-10-17T21:03:03Z immich-redis 35 10 23 41 128 0 +2026-10-17T21:03:34Z immich-server 1646 787 783 2048 2048 2 +2026-10-17T21:03:34Z immich-machine-learning 1210 1149 47 1536 1536 0 +2026-10-17T21:03:34Z immich-postgres 295 60 217 298 768 0 +2026-10-17T21:03:34Z immich-redis 36 10 23 41 128 0 +2026-10-17T21:04:05Z immich-server 1699 780 842 2048 2048 2 +2026-10-17T21:04:05Z immich-machine-learning 1179 1128 47 1536 1536 0 +2026-10-17T21:04:05Z immich-postgres 300 60 223 302 768 0 +2026-10-17T21:04:05Z immich-redis 36 10 23 41 128 0 +2026-10-17T21:04:35Z immich-server 1758 783 898 2048 2048 2 +2026-10-17T21:04:35Z immich-machine-learning 1144 1079 47 1536 1536 0 +2026-10-17T21:04:35Z immich-postgres 308 60 231 311 768 0 +2026-10-17T21:04:35Z immich-redis 36 10 24 41 128 0 +2026-10-17T21:05:06Z immich-server 1812 783 952 2048 2048 2 +2026-10-17T21:05:06Z immich-machine-learning 1209 1146 47 1536 1536 0 +2026-10-17T21:05:06Z immich-postgres 317 63 236 318 768 0 +2026-10-17T21:05:06Z immich-redis 36 10 24 41 128 0 +2026-10-17T21:05:37Z immich-server 1852 781 995 2048 2048 2 +2026-10-17T21:05:37Z immich-machine-learning 1101 1047 47 1536 1536 0 +2026-10-17T21:05:37Z immich-postgres 320 60 242 324 768 0 +2026-10-17T21:05:37Z immich-redis 38 10 26 44 128 0 +2026-10-17T21:06:08Z immich-server 1917 784 1057 2048 2048 2 +2026-10-17T21:06:08Z immich-machine-learning 1022 980 47 1536 1536 0 +2026-10-17T21:06:08Z immich-postgres 324 60 247 329 768 0 +2026-10-17T21:06:08Z immich-redis 38 10 26 44 128 0 +2026-10-17T21:06:38Z immich-server 2011 798 1136 2048 2048 2 +2026-10-17T21:06:38Z immich-machine-learning 1176 1074 47 1536 1536 0 +2026-10-17T21:06:38Z immich-postgres 332 60 253 336 768 0 +2026-10-17T21:06:38Z immich-redis 39 10 26 44 128 0 +2026-10-17T21:07:09Z immich-server 2045 803 1165 2048 2048 2 +2026-10-17T21:07:09Z immich-machine-learning 1120 1054 47 1536 1536 0 +2026-10-17T21:07:09Z immich-postgres 338 60 260 343 768 0 +2026-10-17T21:07:09Z immich-redis 39 10 26 44 128 0 +2026-10-17T21:07:40Z immich-server 2044 823 1148 2048 2048 2 +2026-10-17T21:07:40Z immich-machine-learning 1146 1081 47 1536 1536 0 +2026-10-17T21:07:40Z immich-postgres 344 60 265 349 768 0 +2026-10-17T21:07:40Z immich-redis 39 10 26 44 128 0 +2026-10-17T21:08:10Z immich-server 2041 796 1169 2048 2048 2 +2026-10-17T21:08:10Z immich-machine-learning 1126 1043 47 1536 1536 0 +2026-10-17T21:08:10Z immich-postgres 348 60 269 352 768 0 +2026-10-17T21:08:10Z immich-redis 39 10 26 44 128 0 +2026-10-17T21:08:41Z immich-server 2044 799 1169 2048 2048 2 +2026-10-17T21:08:41Z immich-machine-learning 1039 988 47 1536 1536 0 +2026-10-17T21:08:41Z immich-postgres 347 60 269 353 768 0 +2026-10-17T21:08:41Z immich-redis 41 10 28 45 128 0 +2026-10-17T21:09:11Z immich-server 2047 806 1165 2048 2048 2 +2026-10-17T21:09:11Z immich-machine-learning 1212 1150 47 1536 1536 0 +2026-10-17T21:09:11Z immich-postgres 346 60 267 353 768 0 +2026-10-17T21:09:11Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:09:42Z immich-server 2046 796 1174 2048 2048 2 +2026-10-17T21:09:42Z immich-machine-learning 1093 1030 47 1536 1536 0 +2026-10-17T21:09:42Z immich-postgres 345 60 267 353 768 0 +2026-10-17T21:09:42Z immich-redis 42 10 28 46 128 0 +2026-10-17T21:10:12Z immich-server 2078 797 1205 2079 4096 2 +2026-10-17T21:10:12Z immich-machine-learning 1153 1106 47 1536 3072 0 +2026-10-17T21:10:12Z immich-postgres 345 60 266 353 768 0 +2026-10-17T21:10:12Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:10:43Z immich-server 2116 799 1240 2117 4096 2 +2026-10-17T21:10:43Z immich-machine-learning 1159 1100 47 1536 3072 0 +2026-10-17T21:10:43Z immich-postgres 344 60 265 353 768 0 +2026-10-17T21:10:43Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:11:13Z immich-server 2143 793 1274 2153 4096 2 +2026-10-17T21:11:13Z immich-machine-learning 1134 1064 47 1536 3072 0 +2026-10-17T21:11:13Z immich-postgres 342 60 264 353 768 0 +2026-10-17T21:11:13Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:11:44Z immich-server 2181 796 1308 2181 4096 2 +2026-10-17T21:11:44Z immich-machine-learning 1112 1049 47 1536 3072 0 +2026-10-17T21:11:44Z immich-postgres 343 60 264 353 768 0 +2026-10-17T21:11:44Z immich-redis 42 10 28 46 128 0 +2026-10-17T21:12:14Z immich-server 2207 796 1334 2209 4096 2 +2026-10-17T21:12:14Z immich-machine-learning 1085 1023 47 1536 3072 0 +2026-10-17T21:12:14Z immich-postgres 342 60 263 353 768 0 +2026-10-17T21:12:14Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:12:45Z immich-server 2220 799 1345 2222 4096 2 +2026-10-17T21:12:45Z immich-machine-learning 1125 1064 47 1536 3072 0 +2026-10-17T21:12:45Z immich-postgres 341 60 262 353 768 0 +2026-10-17T21:12:45Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:13:15Z immich-server 2233 799 1357 2235 4096 2 +2026-10-17T21:13:15Z immich-machine-learning 686 629 47 1536 3072 0 +2026-10-17T21:13:15Z immich-postgres 340 60 261 353 768 0 +2026-10-17T21:13:15Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:13:46Z immich-server 2230 792 1363 2235 4096 2 +2026-10-17T21:13:46Z immich-machine-learning 775 731 47 1536 3072 0 +2026-10-17T21:13:46Z immich-postgres 339 60 261 353 768 0 +2026-10-17T21:13:46Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:14:16Z immich-server 2234 796 1363 2238 4096 2 +2026-10-17T21:14:16Z immich-machine-learning 756 700 47 1536 3072 0 +2026-10-17T21:14:16Z immich-postgres 339 60 261 353 768 0 +2026-10-17T21:14:16Z immich-redis 42 10 28 46 128 0 +2026-10-17T21:14:47Z immich-server 2238 800 1363 2242 4096 2 +2026-10-17T21:14:47Z immich-machine-learning 817 750 47 1536 3072 0 +2026-10-17T21:14:47Z immich-postgres 339 60 261 353 768 0 +2026-10-17T21:14:47Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:15:17Z immich-server 2238 801 1363 2243 4096 2 +2026-10-17T21:15:17Z immich-machine-learning 835 768 47 1536 3072 0 +2026-10-17T21:15:17Z immich-postgres 339 61 261 353 768 0 +2026-10-17T21:15:17Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:15:48Z immich-server 2236 798 1363 2243 4096 2 +2026-10-17T21:15:48Z immich-machine-learning 772 706 47 1536 3072 0 +2026-10-17T21:15:48Z immich-postgres 339 61 261 353 768 0 +2026-10-17T21:15:48Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:16:18Z immich-server 2237 799 1363 2243 4096 2 +2026-10-17T21:16:18Z immich-machine-learning 740 675 47 1536 3072 0 +2026-10-17T21:16:18Z immich-postgres 340 61 261 353 768 0 +2026-10-17T21:16:18Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:16:49Z immich-server 2237 799 1363 2243 4096 2 +2026-10-17T21:16:49Z immich-machine-learning 816 759 47 1536 3072 0 +2026-10-17T21:16:49Z immich-postgres 341 61 262 353 768 0 +2026-10-17T21:16:49Z immich-redis 42 10 28 46 128 0 +2026-10-17T21:17:19Z immich-server 2238 800 1363 2243 4096 2 +2026-10-17T21:17:19Z immich-machine-learning 730 666 47 1536 3072 0 +2026-10-17T21:17:19Z immich-postgres 341 61 262 353 768 0 +2026-10-17T21:17:19Z immich-redis 41 10 28 46 128 0 +2026-10-17T21:17:50Z immich-server 2238 800 1363 2245 4096 2 +2026-10-17T21:17:50Z immich-machine-learning 834 763 51 1536 3072 0 +2026-10-17T21:17:50Z immich-postgres 343 61 264 353 768 0 +2026-10-17T21:17:50Z immich-redis 42 10 29 46 128 0 +2026-10-17T21:18:20Z immich-server 2251 813 1363 2252 4096 2 +2026-10-17T21:18:20Z immich-machine-learning 740 660 51 1536 3072 0 +2026-10-17T21:18:20Z immich-postgres 347 61 267 353 768 0 +2026-10-17T21:18:20Z immich-redis 42 10 29 47 128 0 +2026-10-17T21:18:51Z immich-server 2261 822 1363 2264 4096 2 +2026-10-17T21:18:51Z immich-machine-learning 837 766 51 1536 3072 0 +2026-10-17T21:18:51Z immich-postgres 348 61 269 353 768 0 +2026-10-17T21:18:51Z immich-redis 42 10 29 47 128 0 +2026-10-17T21:19:21Z immich-server 2265 827 1363 2266 4096 2 +2026-10-17T21:19:21Z immich-machine-learning 849 767 51 1536 3072 0 +2026-10-17T21:19:21Z immich-postgres 353 61 273 357 768 0 +2026-10-17T21:19:21Z immich-redis 42 10 29 47 128 0 +2026-10-17T21:19:52Z immich-server 2255 816 1363 2269 4096 2 +2026-10-17T21:19:52Z immich-machine-learning 744 672 51 1536 3072 0 +2026-10-17T21:19:52Z immich-postgres 355 61 274 359 768 0 +2026-10-17T21:19:52Z immich-redis 42 10 29 47 128 0 +2026-10-17T21:20:22Z immich-server 2266 828 1363 2269 4096 2 +2026-10-17T21:20:22Z immich-machine-learning 695 631 51 1536 3072 0 +2026-10-17T21:20:22Z immich-postgres 356 61 276 360 768 0 +2026-10-17T21:20:22Z immich-redis 42 10 30 47 128 0 +2026-10-17T21:20:53Z immich-server 2266 828 1364 2270 4096 2 +2026-10-17T21:20:53Z immich-machine-learning 806 740 51 1536 3072 0 +2026-10-17T21:20:53Z immich-postgres 358 61 278 362 768 0 +2026-10-17T21:20:53Z immich-redis 42 10 30 47 128 0 +2026-10-17T21:21:23Z immich-server 2283 834 1374 2285 4096 2 +2026-10-17T21:21:23Z immich-machine-learning 843 775 51 1536 3072 0 +2026-10-17T21:21:23Z immich-postgres 359 61 279 363 768 0 +2026-10-17T21:21:23Z immich-redis 43 10 30 47 128 0 +2026-10-17T21:21:54Z immich-server 2516 967 1460 2634 4096 2 +2026-10-17T21:21:54Z immich-machine-learning 731 664 51 1536 3072 0 +2026-10-17T21:21:54Z immich-postgres 358 61 278 368 768 0 +2026-10-17T21:21:54Z immich-redis 42 10 30 47 128 0 +2026-10-17T21:22:24Z immich-server 2841 1202 1543 2870 4096 2 +2026-10-17T21:22:24Z immich-machine-learning 750 697 51 1536 3072 0 +2026-10-17T21:22:24Z immich-postgres 350 61 270 368 768 0 +2026-10-17T21:22:24Z immich-redis 42 10 30 47 128 0 +2026-10-17T21:22:54Z immich-server 2847 1208 1544 2870 4096 2 +2026-10-17T21:22:54Z immich-machine-learning 728 662 51 1536 3072 0 +2026-10-17T21:22:54Z immich-postgres 350 61 270 368 768 0 +2026-10-17T21:22:54Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:23:25Z immich-server 2847 1208 1544 2870 4096 2 +2026-10-17T21:23:25Z immich-machine-learning 663 598 51 1536 3072 0 +2026-10-17T21:23:25Z immich-postgres 346 61 267 368 768 0 +2026-10-17T21:23:25Z immich-redis 43 10 30 48 128 0 +2026-10-17T21:23:55Z immich-server 2847 1208 1544 2870 4096 2 +2026-10-17T21:23:55Z immich-machine-learning 741 674 51 1536 3072 0 +2026-10-17T21:23:55Z immich-postgres 344 61 265 368 768 0 +2026-10-17T21:23:55Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:24:26Z immich-server 2847 1208 1544 2870 4096 2 +2026-10-17T21:24:26Z immich-machine-learning 655 590 51 1536 3072 0 +2026-10-17T21:24:26Z immich-postgres 341 61 262 368 768 0 +2026-10-17T21:24:26Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:24:56Z immich-server 2848 1208 1544 2870 4096 2 +2026-10-17T21:24:56Z immich-machine-learning 636 572 51 1536 3072 0 +2026-10-17T21:24:56Z immich-postgres 341 61 262 368 768 0 +2026-10-17T21:24:56Z immich-redis 43 10 30 48 128 0 +2026-10-17T21:25:26Z immich-server 2844 1203 1544 2870 4096 2 +2026-10-17T21:25:26Z immich-machine-learning 708 591 51 1536 3072 0 +2026-10-17T21:25:26Z immich-postgres 340 61 261 368 768 0 +2026-10-17T21:25:26Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:25:57Z immich-server 2802 1160 1544 2870 4096 2 +2026-10-17T21:25:57Z immich-machine-learning 660 597 51 1536 3072 0 +2026-10-17T21:25:57Z immich-postgres 340 61 261 368 768 0 +2026-10-17T21:25:57Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:26:27Z immich-server 2802 1160 1544 2870 4096 2 +2026-10-17T21:26:27Z immich-machine-learning 626 562 51 1536 3072 0 +2026-10-17T21:26:27Z immich-postgres 340 61 260 368 768 0 +2026-10-17T21:26:27Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:26:57Z immich-server 2803 1160 1544 2870 4096 2 +2026-10-17T21:26:57Z immich-machine-learning 566 502 51 1536 3072 0 +2026-10-17T21:26:57Z immich-postgres 340 61 261 368 768 0 +2026-10-17T21:26:57Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:27:28Z immich-server 2802 1160 1544 2870 4096 2 +2026-10-17T21:27:28Z immich-machine-learning 551 496 51 1536 3072 0 +2026-10-17T21:27:28Z immich-postgres 340 61 261 368 768 0 +2026-10-17T21:27:28Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:27:58Z immich-server 2805 1163 1544 2870 4096 2 +2026-10-17T21:27:58Z immich-machine-learning 566 498 51 1536 3072 0 +2026-10-17T21:27:58Z immich-postgres 340 61 261 368 768 0 +2026-10-17T21:27:58Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:28:28Z immich-server 2805 1163 1544 2870 4096 2 +2026-10-17T21:28:28Z immich-machine-learning 588 512 51 1536 3072 0 +2026-10-17T21:28:28Z immich-postgres 340 61 262 368 768 0 +2026-10-17T21:28:28Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:28:59Z immich-server 2805 1163 1544 2870 4096 2 +2026-10-17T21:28:59Z immich-machine-learning 499 435 51 1536 3072 0 +2026-10-17T21:28:59Z immich-postgres 341 61 262 368 768 0 +2026-10-17T21:28:59Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:29:29Z immich-server 2400 775 1544 2870 4096 2 +2026-10-17T21:29:29Z immich-machine-learning 464 399 51 1536 3072 0 +2026-10-17T21:29:29Z immich-postgres 341 61 262 368 768 0 +2026-10-17T21:29:29Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:29:59Z immich-server 2403 777 1544 2870 4096 2 +2026-10-17T21:29:59Z immich-machine-learning 528 476 51 1536 3072 0 +2026-10-17T21:29:59Z immich-postgres 341 61 262 368 768 0 +2026-10-17T21:29:59Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:30:30Z immich-server 2403 777 1544 2870 4096 2 +2026-10-17T21:30:30Z immich-machine-learning 481 426 51 1536 3072 0 +2026-10-17T21:30:30Z immich-postgres 341 61 262 368 768 0 +2026-10-17T21:30:30Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:31:00Z immich-server 2403 777 1544 2870 4096 2 +2026-10-17T21:31:00Z immich-machine-learning 563 496 51 1536 3072 0 +2026-10-17T21:31:00Z immich-postgres 342 62 262 368 768 0 +2026-10-17T21:31:00Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:31:31Z immich-server 2397 771 1544 2870 4096 2 +2026-10-17T21:31:31Z immich-machine-learning 533 465 51 1536 3072 0 +2026-10-17T21:31:31Z immich-postgres 343 62 263 368 768 0 +2026-10-17T21:31:31Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:32:01Z immich-server 2397 771 1544 2870 4096 2 +2026-10-17T21:32:01Z immich-machine-learning 576 513 51 1536 3072 0 +2026-10-17T21:32:01Z immich-postgres 342 62 263 368 768 0 +2026-10-17T21:32:01Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:32:31Z immich-server 2397 772 1544 2870 4096 2 +2026-10-17T21:32:31Z immich-machine-learning 458 391 51 1536 3072 0 +2026-10-17T21:32:31Z immich-postgres 343 62 264 368 768 0 +2026-10-17T21:32:31Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:33:02Z immich-server 2398 772 1544 2870 4096 2 +2026-10-17T21:33:02Z immich-machine-learning 540 472 51 1536 3072 0 +2026-10-17T21:33:02Z immich-postgres 338 56 264 368 768 0 +2026-10-17T21:33:02Z immich-redis 43 10 30 48 128 0 +2026-10-17T21:33:32Z immich-server 2397 772 1544 2870 4096 2 +2026-10-17T21:33:32Z immich-machine-learning 508 438 51 1536 3072 0 +2026-10-17T21:33:32Z immich-postgres 337 56 264 368 768 0 +2026-10-17T21:33:32Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:34:02Z immich-server 2406 781 1544 2870 4096 2 +2026-10-17T21:34:02Z immich-machine-learning 644 539 51 1536 3072 0 +2026-10-17T21:34:02Z immich-postgres 337 56 264 368 768 0 +2026-10-17T21:34:02Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:34:33Z immich-server 2397 773 1544 2870 4096 2 +2026-10-17T21:34:33Z immich-machine-learning 576 510 51 1536 3072 0 +2026-10-17T21:34:33Z immich-postgres 336 54 264 368 768 0 +2026-10-17T21:34:33Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:35:03Z immich-server 2424 800 1544 2870 4096 2 +2026-10-17T21:35:03Z immich-machine-learning 544 476 51 1536 3072 0 +2026-10-17T21:35:03Z immich-postgres 336 54 264 368 768 0 +2026-10-17T21:35:03Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:35:34Z immich-server 2433 810 1544 2870 4096 2 +2026-10-17T21:35:34Z immich-machine-learning 569 514 51 1536 3072 0 +2026-10-17T21:35:34Z immich-postgres 336 54 264 368 768 0 +2026-10-17T21:35:34Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:36:04Z immich-server 2436 812 1544 2870 4096 2 +2026-10-17T21:36:04Z immich-machine-learning 569 505 51 1536 3072 0 +2026-10-17T21:36:04Z immich-postgres 336 54 264 368 768 0 +2026-10-17T21:36:04Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:36:34Z immich-server 2438 814 1544 2870 4096 2 +2026-10-17T21:36:34Z immich-machine-learning 578 511 51 1536 3072 0 +2026-10-17T21:36:34Z immich-postgres 337 54 265 368 768 0 +2026-10-17T21:36:34Z immich-redis 42 10 30 48 128 0 +2026-10-17T21:37:05Z immich-server 2437 813 1544 2870 4096 2 +2026-10-17T21:37:05Z immich-machine-learning 588 522 51 1536 3072 0 +2026-10-17T21:37:05Z immich-postgres 336 54 265 368 768 0 +2026-10-17T21:37:05Z immich-redis 41 9 30 48 128 0 +2026-10-17T21:37:35Z immich-server 2437 813 1544 2870 4096 2 +2026-10-17T21:37:35Z immich-machine-learning 588 522 51 1536 3072 0 +2026-10-17T21:37:35Z immich-postgres 336 54 265 368 768 0 +2026-10-17T21:37:35Z immich-redis 41 9 30 48 128 0 +2026-10-17T21:38:05Z immich-server 2437 813 1544 2870 4096 2 +2026-10-17T21:38:05Z immich-machine-learning 588 522 51 1536 3072 0 +2026-10-17T21:38:05Z immich-postgres 337 55 265 368 768 0 +2026-10-17T21:38:05Z immich-redis 40 9 30 48 128 0 +2026-10-17T21:38:36Z immich-server 2437 813 1544 2870 4096 2 +2026-10-17T21:38:36Z immich-machine-learning 588 522 51 1536 3072 0 +2026-10-17T21:38:36Z immich-postgres 337 55 265 368 768 0 +2026-10-17T21:38:36Z immich-redis 41 9 30 48 128 0 +2026-10-17T21:39:06Z immich-server 2358 737 1544 2870 4096 2 +2026-10-17T21:39:06Z immich-machine-learning 588 522 51 1536 3072 0 +2026-10-17T21:39:06Z immich-postgres 337 55 265 368 768 0 +2026-10-17T21:39:06Z immich-redis 41 9 30 48 128 0 +2026-10-17T21:39:36Z immich-server 2358 737 1544 2870 4096 2 +2026-10-17T21:39:36Z immich-machine-learning 588 522 51 1536 3072 0 +2026-10-17T21:39:36Z immich-postgres 337 55 265 368 768 0 +2026-10-17T21:39:36Z immich-redis 41 9 30 48 128 0 +2026-10-17T21:40:07Z immich-server 2358 737 1544 2870 4096 2 +2026-10-17T21:40:07Z immich-machine-learning 588 522 51 1536 3072 0 +2026-10-17T21:40:07Z immich-postgres 337 55 265 368 768 0 +2026-10-17T21:40:07Z immich-redis 42 9 30 48 128 0 +2026-10-17T21:40:37Z immich-server 2356 735 1544 2870 4096 2 +2026-10-17T21:40:37Z immich-machine-learning 588 522 51 1536 3072 0 +2026-10-17T21:40:37Z immich-postgres 337 55 265 368 768 0 +2026-10-17T21:40:37Z immich-redis 41 9 30 48 128 0 +2026-10-17T21:41:07Z immich-server 2288 668 1544 2870 4096 2 +2026-10-17T21:41:07Z immich-machine-learning 588 522 51 1536 3072 0 +2026-10-17T21:41:07Z immich-postgres 332 51 265 368 768 0 +2026-10-17T21:41:07Z immich-redis 42 9 30 48 128 0 +2026-10-17T21:41:38Z immich-server 2288 668 1544 2870 4096 2 +2026-10-17T21:41:38Z immich-machine-learning 588 522 51 1536 3072 0 +2026-10-17T21:41:38Z immich-postgres 332 51 265 368 768 0 +2026-10-17T21:41:38Z immich-redis 41 9 30 48 128 0 +2026-10-17T21:42:08Z immich-server 2288 668 1544 2870 4096 2 +2026-10-17T21:42:08Z immich-machine-learning 545 479 51 1536 3072 0 +2026-10-17T21:42:08Z immich-postgres 326 46 265 368 768 0 +2026-10-17T21:42:08Z immich-redis 41 9 30 48 128 0 +2026-10-17T21:42:38Z immich-server 2288 668 1544 2870 4096 2 +2026-10-17T21:42:38Z immich-machine-learning 248 156 83 1536 3072 0 +2026-10-17T21:42:38Z immich-postgres 321 41 265 368 768 0 +2026-10-17T21:42:38Z immich-redis 41 9 30 48 128 0 +2026-10-17T21:43:09Z immich-server 2288 668 1544 2870 4096 2 +2026-10-17T21:43:09Z immich-machine-learning 248 156 83 1536 3072 0 +2026-10-17T21:43:09Z immich-postgres 321 41 265 368 768 0 +2026-10-17T21:43:09Z immich-redis 41 9 30 48 128 0 diff --git a/documentation/audits/night-2026-10-18/P6/oom-kill-dmesg.txt b/documentation/audits/night-2026-10-18/P6/oom-kill-dmesg.txt new file mode 100644 index 00000000..0f60359d --- /dev/null +++ b/documentation/audits/night-2026-10-18/P6/oom-kill-dmesg.txt @@ -0,0 +1,12 @@ +[Sat Oct 17 22:52:33 2026] kworker/u32:3 invoked oom-killer: gfp_mask=0xc00(GFP_NOIO), order=0, oom_score_adj=0 +[Sat Oct 17 22:52:33 2026] oom_kill_process.cold+0x8/0x87 +[Sat Oct 17 22:52:33 2026] Memory cgroup stats for /lxc/9202/ns/system.slice/docker-e1de41a8de6df8e74683884b308056fc7af506bed539c4b04ee241533992581d.scope: +[Sat Oct 17 22:52:33 2026] Memory cgroup min protection 0kB -- low protection 0kB +[Sat Oct 17 22:52:33 2026] Tasks state (memory values in pages): +[Sat Oct 17 22:52:33 2026] [ pid ] uid tgid total_vm rss rss_anon rss_file rss_shmem pgtables_bytes swapents oom_score_adj name +[Sat Oct 17 22:52:33 2026] oom-kill:constraint=CONSTRAINT_MEMCG,nodemask=(null),cpuset=/,mems_allowed=0,oom_memcg=/lxc/9202/ns/system.slice/docker-e1de41a8de6df8e74683884b308056fc7af506bed539c4b04ee241533992581d.scope,task_memcg=/lxc/9202/ns/system.slice/docker-e1de41a8de6df8e74683884b308056fc7af506bed539c4b04ee241533992581d.scope,task=immich,pid=320902,uid=100000 +[Sat Oct 17 22:52:33 2026] Memory cgroup out of memory: Killed process 320902 (immich) total-vm:28934320kB, anon-rss:972844kB, file-rss:72780kB, shmem-rss:0kB, UID:100000 pgtables:12884kB oom_score_adj:0 +[Sat Oct 17 22:52:33 2026] oom-kill:constraint=CONSTRAINT_MEMCG,nodemask=(null),cpuset=/,mems_allowed=0,oom_memcg=/lxc/9202/ns/system.slice/docker-e1de41a8de6df8e74683884b308056fc7af506bed539c4b04ee241533992581d.scope,task_memcg=/lxc/9202/ns/system.slice/docker-e1de41a8de6df8e74683884b308056fc7af506bed539c4b04ee241533992581d.scope,task=immich,pid=320902,uid=100000 +[Sat Oct 17 22:52:33 2026] Memory cgroup out of memory: Killed process 320902 (immich) total-vm:28934320kB, anon-rss:972844kB, file-rss:72780kB, shmem-rss:0kB, UID:100000 pgtables:12884kB oom_score_adj:0 +[Sat Oct 17 22:59:48 2026] oom-kill:constraint=CONSTRAINT_MEMCG,nodemask=(null),cpuset=/,mems_allowed=0,oom_memcg=/lxc/9202/ns/system.slice/docker-e1de41a8de6df8e74683884b308056fc7af506bed539c4b04ee241533992581d.scope,task_memcg=/lxc/9202/ns/system.slice/docker-e1de41a8de6df8e74683884b308056fc7af506bed539c4b04ee241533992581d.scope,task=immich,pid=381179,uid=100000 +[Sat Oct 17 22:59:48 2026] Memory cgroup out of memory: Killed process 381179 (immich) total-vm:28959504kB, anon-rss:1008108kB, file-rss:74088kB, shmem-rss:0kB, UID:100000 pgtables:12764kB oom_score_adj:0 diff --git a/documentation/audits/night-2026-10-18/P6/peaks.md b/documentation/audits/night-2026-10-18/P6/peaks.md new file mode 100644 index 00000000..6aa35567 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P6/peaks.md @@ -0,0 +1,6 @@ +| Container | catalog limit | anon peak (MB) | anon peak / limit | memory.current peak at catalog limit | memory.current peak with the raised limit | typical anon (median, active) | +|---|---|---|---|---|---|---| +| immich-server | 2048 | 1596 | 77 % | 2047 | 2848 | 828 | +| immich-machine-learning | 1536 | 1175 | 76 % | 1498 | 1159 | 989 | +| immich-postgres | 768 | 76 | 9 % | 359 | - | 61 | +| immich-redis | 128 | 10 | 7 % | 43 | - | 10 | diff --git a/documentation/audits/night-2026-10-18/P6/phase1-run.txt b/documentation/audits/night-2026-10-18/P6/phase1-run.txt new file mode 100644 index 00000000..0895e702 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P6/phase1-run.txt @@ -0,0 +1,12 @@ +/immich-server restarts=1 OOMKilled=false started=2026-10-17T20:52:35.992961129Z +@2026-10-17T20:42:46Z start ip=172.19.0.5 +token length 42 +{"photos":30,"videos":0,"usage":146019749,"usagePhotos":146019749,"usageVideos":0,"usageByUser":[{"userId":"3054bbba-1bdb-4f61-9e2a-7abdfd602daa","userName":"Household","photos":20,"videos":0,"usage":97346099,"usagePhotos":97346099,"usageVideos":0,"quotaSizeInBytes":null},{"userId":"bf1bdfa8-dc38-4fbd-b1e9-84ae98a6dcfd","userName":"Member","photos":10,"videos":0,"usage":48673650,"usagePhotos":48673650,"usageVideos":0,"quotaSizeInBytes":null}]} +@2026-10-17T20:42:46Z upload_start +@2026-10-17T20:49:51Z upload_done 4000 201 +@2026-10-17T20:49:52Z jobs pending=4782 +@2026-10-17T20:50:52Z jobs pending=4985 +@2026-10-17T20:51:53Z jobs pending=5179 +@2026-10-17T20:52:39Z jobs_idle + +@2026-10-17T20:52:39Z settle_start diff --git a/documentation/audits/night-2026-10-18/P6/phase2-limit-raise.txt b/documentation/audits/night-2026-10-18/P6/phase2-limit-raise.txt new file mode 100644 index 00000000..05ad9136 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P6/phase2-limit-raise.txt @@ -0,0 +1,4 @@ +immich-server +immich-machine-learning +/immich-server mem=4294967296 +/immich-machine-learning mem=3221225472 diff --git a/documentation/audits/night-2026-10-18/P6/run-logs.txt b/documentation/audits/night-2026-10-18/P6/run-logs.txt new file mode 100644 index 00000000..af789e99 --- /dev/null +++ b/documentation/audits/night-2026-10-18/P6/run-logs.txt @@ -0,0 +1,27 @@ +@2026-10-17T20:42:46Z start ip=172.19.0.5 +token length 42 +{"photos":30,"videos":0,"usage":146019749,"usagePhotos":146019749,"usageVideos":0,"usageByUser":[{"userId":"3054bbba-1bdb-4f61-9e2a-7abdfd602daa","userName":"Household","photos":20,"videos":0,"usage":97346099,"usagePhotos":97346099,"usageVideos":0,"quotaSizeInBytes":null},{"userId":"bf1bdfa8-dc38-4fbd-b1e9-84ae98a6dcfd","userName":"Member","photos":10,"videos":0,"usage":48673650,"usagePhotos":48673650,"usageVideos":0,"quotaSizeInBytes":null}]} +@2026-10-17T20:42:46Z upload_start +@2026-10-17T20:49:51Z upload_done 4000 201 +@2026-10-17T20:49:52Z jobs pending=4782 +@2026-10-17T20:50:52Z jobs pending=4985 +@2026-10-17T20:51:53Z jobs pending=5179 +@2026-10-17T20:52:39Z jobs_idle + +@2026-10-17T20:52:39Z settle_start +@2026-10-17T20:54:25Z phase2_start +@2026-10-17T20:54:25Z jobs pending=5606 restarts=1 +@2026-10-17T20:59:29Z jobs pending=6583 restarts=1 +@2026-10-17T21:00:00Z queues unreadable (server restarting?) +@2026-10-17T21:04:39Z jobs pending=6514 restarts=2 +@2026-10-17T21:09:41Z jobs pending=4701 restarts=2 +@2026-10-17T21:14:44Z jobs pending=3465 restarts=2 +@2026-10-17T21:19:47Z jobs pending=2669 restarts=2 +@2026-10-17T21:24:50Z jobs pending=1597 restarts=2 +@2026-10-17T21:29:52Z jobs pending=973 restarts=2 +@2026-10-17T21:34:54Z jobs pending=340 restarts=2 +@2026-10-17T21:37:55Z jobs_idle restarts=2 +{"photos":4030,"videos":0,"usage":11201384478,"usagePhotos":11201384478,"usageVideos":0,"usageByUser":[{"userId":"3054bbba-1bdb-4f61-9e2a-7abdfd602daa","userName":"Household","photos":4020,"videos":0,"usage":11152710828,"usagePhotos":11152710828,"usageVideos":0,"quotaSizeInBytes":null},{"userId":"bf +"total":75 +@2026-10-17T21:37:55Z settle_start + 4000 201 diff --git a/documentation/audits/night-2026-10-18/P6/teardown.txt b/documentation/audits/night-2026-10-18/P6/teardown.txt new file mode 100644 index 00000000..713bcd3b --- /dev/null +++ b/documentation/audits/night-2026-10-18/P6/teardown.txt @@ -0,0 +1,7 @@ +bench assets found: 4020 +delete -> 204 +{"photos":10,"videos":0,"usage":48673650,"usagePhotos":48673650,"usageVideos":0,"usageByUser":[{"userId":"3054bbba-1bdb- +library and bench dir removed: 2/2 gone +/immich-server mem=3221225472 healthy +/immich-machine-learning mem=2147483648 healthy +3 diff --git a/documentation/backlog/CLOSED-ITEMS.md b/documentation/backlog/CLOSED-ITEMS.md index 981bca79..9d3a56df 100644 --- a/documentation/backlog/CLOSED-ITEMS.md +++ b/documentation/backlog/CLOSED-ITEMS.md @@ -26,6 +26,17 @@ --- +## 2026-10-18 — each app's own folder, no allow-list exception, drive retirement order, plain refusals, `:latest`, Immich (controller v0.329.0, catalog `d928932` `fc93846` `8cf03e0`) + +| Row | What | Closed | Evidence | +|---|---|---|---| +| **R-981** | **The homepage app gets the Docker socket (that is root in the guest) and has no login, no setup gate and no family gate.** (P3) | CLOSED 2026-10-18 — **controller v0.329.0 + catalog `d928932`**: the socket mount is gone from the template; no Felhom feature used it (the rendered `docker.yaml` empty, no `homepage.*` labels on the box); the box's allow-list is now EMPTY, so the socket is refused for every app. Live on demo-hp 9201: homepage opens (200 in the container, through traefik and on its public name), its container has no socket mount, 0 allow-list refusals on the three test boxes. The throwaway homepage was removed after. | `audits/night-2026-10-18/P1/r981-homepage-before.txt`, `r981-homepage-after-9201.txt`, `redproof-privpolicy.txt`, `P2/box-walk.txt` | +| **R-1142** | **The catalog allow-list (R-971, controller v0.328.0) lets one app bind ANOTHER app's folder under `${HDD_PATH}/appdata/`.** (P3) | CLOSED 2026-10-18 — **controller v0.329.0 + catalog `d928932`/`fc93846`**: the `${HDD_PATH}` root is `appdata//`; the folder map is compiled in with the allow-list (`appdata_folders`: paperless-ngx → paperless — the only slug ≠ folder in every template, the drill catalog and the three test boxes). The security review of the pushed commit found two more doors, closed before the release: an app NAMED like another app's mapped folder gets no root, and `USERDATA_PATH` is always derived, never the app's env. The catalog gate mirrors it. 0 refusals on the three test boxes. | `audits/night-2026-10-18/P1/redproof-privpolicy.txt`, `redproof-userdata-env.txt`, `redproof-catalog-gate-r1142.txt`, `P2/box-walk.txt` | +| **R-1063** | **„Végleges leszerelés" leaves a half-state when the agent refuses: the dashboard marks the drive decommissioned first and never undoes it.** (P3) | CLOSED 2026-10-18 — **controller v0.329.0**: the agent is asked FIRST; the mark and the default move only after its yes. Its 403/409 come back typed and reach the household as a plain 409 (HU + EN: nothing changed, what to do). Proven with a fake agent over TLS and the web flow (red-proofed: the old order marks the drive and moves the default). **Not pressed live:** demo-hp's only user-data drive carries its apps and is not a backup target, so the agent would say yes. Follow-up: R-1144 (the „anyway" mode still stops the drive's apps before asking). | `audits/night-2026-10-18/P1/redproof-r1063.txt` | +| **R-1069** | **A disk passed into a Felhom VM on a virtio bus cannot be formatted, and the household reads the agent's raw English refusal.** (P3) | CLOSED 2026-10-18 — **controller v0.329.0**: the agent's „device has no durable id" refusal (409) is `agentapi.ErrNoDurableID`; the format endpoint, the drive init and the wipe say in HU + EN that the dashboard cannot format this disk, the disk did not change, and the operator or whoever set up the virtual machine can give it a serial number (or a SATA bus). The agent's safety rule is unchanged. Unit-proven (red-proofed: the raw agent text reached the household); not re-run on an OMV VM tonight. | `audits/night-2026-10-18/P1/redproof-r1069.txt` | +| **R-1143** | **The controller `build.sh` pushes `:latest` with EVERY build, release candidates included** (P4) | CLOSED 2026-10-18 — **controller v0.329.0**: `build.sh` adds `:latest` only for an x.y.z tag (one `TAGS` array feeds build, push and multiarch; `--print-tags`). Live: 0.329.0-rc.1 and rc.2 were pushed without a `:latest` line; 0.329.0 moved it (same digest `aee51f3a…`). `test_build_push_once.sh` 16 cases, red-proofed. | `audits/night-2026-10-18/P1/redproof-r1143.txt` | +| **R-994** | **Seven apps peak above 80 % of a memory limit, and 23 apps' typical use is above their catalog `mem_request`.** (P3) | CLOSED 2026-10-18 — the last part, Immich, **catalog `8cf03e0`**: a 4,000-photo synthetic import on 9202 killed `immich-server` twice at 2048M (kernel memcg kill, Docker `OOMKilled=false`); anon peak 1,596 MB (77 %); ML 1,175 of 1536M (76 %). Limits now server 3072M, ML 2048M (`mem_limit` 6016M); `mem_request` stays 2048M (typical 1,888 MB), so the install check's verdict on an 8 GB box is unchanged. The other six were raised 2026-10-17; the 23 requests are R-1125 (done). The public estimator's Immich figure: R-1147. | `audits/night-2026-10-18/P6/` (peaks.md, memory-phase1/2.tsv, oom-kill-dmesg.txt, teardown.txt) | + ## 2026-10-17 — the catalog allow-list, break-glass rotation (controller v0.328.0, hub v0.157.0, catalog `07d1ef7`) | Row | What | Closed | Evidence | diff --git a/documentation/backlog/OPEN-ITEMS.md b/documentation/backlog/OPEN-ITEMS.md index 376a93f6..d262c169 100644 --- a/documentation/backlog/OPEN-ITEMS.md +++ b/documentation/backlog/OPEN-ITEMS.md @@ -124,20 +124,17 @@ stopping line that lies. | **R-494** | Install & onboarding | P4 | **NARROWED 2026-09-14 by operator ruling → [P3-LOW] the hub COULD create the tunnel at customer creation, for a domain already on Cloudflare. Not blocking: every customer has their own domain and the operator creates the tunnel per day-0 A.1 (`architecture/01-topology-and-trust.md`).** *Original finding, kept:* **[P1-HIGH] A new customer's dashboard has NO reachable address unless the operator hand-makes a Cloudflare tunnel — the link in the setup-code mail is dead.** MEASURED 2026-09-14 on a fresh install from the public ISO (drill intervention **I1**): the claim mail points at `https://felhom.drill0242.felhom.eu`; that name has **no A and no AAAA** record (`dig @1.1.1.1`, control `felhom.enkisfelhom.hu` resolves); the hub has **no tunnel- or DNS-creation code** (`hub/internal/cloudflare/` holds only geo-rule removal; `cf_tunnel_token` is a pasted, optional form field, `configs.go:1478`) — day-0 runbook A.1 makes it a manual Cloudflare-dashboard step that nothing on the customer-create page asks for; the box's own split-horizon resolver on the appliance LAN IP answered `google.com` but not the dashboard name at 13:27:39Z; the agent applied the record at **13:27:44Z** (`lanresolver: applied split-horizon record … ip=192.168.0.158`, 3 m 46 s after the controller started), so the box CAN answer the name — **but only to a device that uses the box as its DNS server, and no document, screen or mail tells a household to do that**; the router and the installer-offered DNS answer nothing. The page was reachable only at the guest's LAN address with the name forced (`curl --resolve …:443:192.168.0.158`). **A volunteer could not have done that.** **What it needs:** an operator ruling — the hub creates the tunnel and DNS at customer creation, or the product gives a household a LAN address that works with no DNS change. | **READY — rank P3-LOW; owner: CC** **Re-ranked 2026-10-03: P3→P4: operator-side automation; the operator creates the tunnel by hand per the day-0 runbook.** | — | — | CC | | **R-504** | Install & onboarding | P4 | **[P3-LOW] `iso.felhom.eu` cannot show an index page on its own — its root returns 404, and the download page lives on the website instead.** MEASURED 2026-09-14: `https://iso.felhom.eu/` and `/index.html` → 404; only named objects answer. The host is an R2 bucket behind a custom domain; whether R2 would serve an uploaded `index.html` at `/` was **not measured** (uploading anything to the public bucket is a publication). The ISO v1.27.0 task puts the Hungarian download page at `felhom.eu/letoltes` (published with the ISO, after the operator's yes). **Remaining:** a redirect from `iso.felhom.eu/` to that page needs a Cloudflare rule the session has no credential for. | **WAITING-ON-OPERATOR — rank P3-LOW; owner: operator (Cloudflare rule)** **Re-ranked 2026-10-03: P3→P4: households are sent to the website's download page; the bare address is cosmetic.** | — | — | operator | -## Apps & catalog — 20 rows (P3 11, P4 9) +## Apps & catalog — 18 rows (P3 9, P4 9) | ID | Category | Sev | What | State | Blocked on | Next action | Owner | |---|---|---|---|---|---|---|---| | **R-1091** | Apps & catalog | P3 | **Catalog copy that is wrong or stale at the pinned tag, found writing the guides — each needs an operator word or a live check, so none was changed tonight.** From source at each app's tag (evidence per app in `audits/app-guides-2026-10-15/B/`): (1) and (2) **DONE 2026-10-16** (operator decision D12: reword): calcom's use case now names Apple Calendar or a CalDAV calendar instead of Google/Outlook, and bentopdf's tagline and use case say the browser does the work and the file stays on the device (catalog CHANGELOG 2026-10-16); (3) **sabnzbd**, **nzbget** use_cases say Radarr/Sonarr/Jellyseerr hand them jobs — the box wires only qBittorrent and Transmission (`mediawire.go`), and a hand link needs a path mapping; (4) **onlyoffice** first_steps 3–4 tell the household to wire Nextcloud by hand — the integration toggle does it (`internal/integrations/onlyoffice_nextcloud.go`); (5) **glance**, **homepage** first_steps send the household into config files in a Docker volume no household tool reaches; (6) **lubelogger** starts with only the „Dashboard" tab and in miles (shipped `appsettings.json`), so first step 3 cannot be done as written; (7) **home-assistant** first_steps promise auto-discovered devices — the app runs on a Docker bridge, where mDNS/SSDP were measured deaf (spike R-6); (8) **homebox** and **gitea** `add_people` name menus that moved or read differently at the tag; **bookstack** `default_creds` still says `admin@admin.com / password`, which after_install replaces; **dawarich** names the API key's page „Settings" (source suggests the account page); **code-server** says „install your tools" with no sudo; **komga** names the discontinued Tachiyomi; **seerr** `docs_url` points at Overseerr; **wanderer**'s comment still says it cannot close sign-up (R-714 is fixed in the same file); (9) **nzbget** and **grafana** deploy-field descriptions say the password can be changed later — nzbget re-applies its env password at every start and grafana ignores the field after first start (R-1086 is the qBittorrent/Transmission side). | OPEN — filed 2026-10-15 | — | Live-check (5)–(7) and (9) on 9202; fix (3), (4), (8) as copy with the freeze re-admitted; re-run the guide label check for any app whose copy moves | CC | -| **R-1142** | Apps & catalog | P3 | **The catalog allow-list (R-971, controller v0.328.0) lets one app bind ANOTHER app's folder under `${HDD_PATH}/appdata/`.** The data root is `appdata/` as a whole: a per-app rule needs a name map, because paperless-ngx keeps `appdata/paperless`. A catalog push could give app A app B's files (not the box: no privilege, the household's own data). | OPEN — filed 2026-10-17 | — | A per-app appdata name in `.felhom.yml` (or a map in the controller), then `appdata//` as the root; catalog gate the same | CC | | **R-1092** | Apps & catalog | P4 | **Three apps show no guide: plant-it and home-assistant carry one HIDDEN (`checked_version: ""`), emby has none.** plant-it: `lifecycle: abandoned`, and its pinned image does not exist upstream, so there is no screen to check labels against. home-assistant: its frontend follows the browser language and the Hungarian strings are fetched at build time, not kept in git, so the Hungarian labels cannot be checked against source (the draft is written; the shipped frontend in the image could check them). emby: its server's web UI is in no public source at 4.11.0.4. Evidence: `audits/app-guides-2026-10-15/B/`. The other 62 templates show a checked guide (controller ≥ 0.315.0). | OPEN — filed 2026-10-15 | — | home-assistant: check the Hungarian labels against the frontend files in the pinned image (read-only, on a box running it), then set checked_version; emby: label-check against the image's own web files the same way; plant-it: nothing while abandoned | CC | -| **R-981** | Apps & catalog | P3 | **The homepage app gets the Docker socket (that is root in the guest) and has no login, no setup gate and no family gate.** Fix: remove the socket mount, or put homepage behind the family gate. Security review 2026-10-12 (`audits/security-review-2026-10-12/`); detail held off-git for the operator (`/mnt/5_hdd/felhom.eu/evidence/security-review-2026-10-12-PRIVATE/`). | OPEN | — | Change the catalog template; prove on 9202 | CC | | **R-676** | Apps & catalog | P3 | **[P3-LOW] Watch: immich's first start restarted 12 times — decision 28's crash-loop stop (6 in 10 min) would stop it.** From the 2026-09-17 chaos night (DB connection dropped during the first-start geocoding import on a 6 GB guest; it did not recover that night). No healthy app in any drill evidence restarts on a first start (1831 samples, 40 live containers), so the threshold stands; this row exists so the first immich install under v0.269.x is watched. `audits/night-2026-09-24/A3/40-first-start-restarts.txt` **2026-09-25 night (read from source, v0.271.0): a DEPLOY's first start is NOT covered by decision 28's suppression** — `Deploying` clears when `compose up -d` returns (`deploy.go` "Clear deploying flag"), and `ObserveUnhealthy` then samples the app; an automatic update's step, verify and undo ARE covered (`Updating`, pinned by `TestD28_NoCrashLoopStopDuringAnAutomaticStep`). So a first start that restarts ≥ 6 times in 10 min is stopped — which R-676 already accepts for a broken first start; a healthy slow first start would be stopped too. **-- 2026-09-30: the first-start restarts are explained.** immich's first-start geodata import OOM-kills its database at 512M on a guest with no swap (R-732, measured: 61–104 kills); the 2026-09-17 chaos-night case (DB connection dropped during the import on a 6 GB guest) fits it. Fixed in the catalog (`56c4888`, 768M). The watch itself (decision 28 on a DEPLOY's first start) is unchanged. | **OPEN — P3; owner: CC (watch)** | — | — | CC | -| **R-994** | Apps & catalog | P3 | **Seven apps peak above 80 % of a memory limit, and 23 apps' typical use is above their catalog `mem_request`.** MEASURED 2026-10-13 (`documentation/audits/sizing-2026-10-13/SIZING.md` §3, `evidence/catalog-check.json`). Near a limit — risk: the container is stopped for using too much memory: docmost (container 475 of 512 MB), romm (703 of 768), termix (117 of 128), uptime-kuma (227 of 256, tester-1 telemetry), grafana (435 of 512), immich (`immich-server` 1,665 of 2,048 during a 200-photo import), tandoor (827 of 1,024). No container was killed during the bench. Under-stated request (typical ÷ request): calcom ×4.0, adventurelog ×3.6, termix ×3.4, claper ×2.5, grafana ×2.2, komga ×2.2, docmost ×2.1, recipe-importer ×2.1, uptime-kuma ×2.1, zipline ×2.0, and 13 more ≤ ×1.8. Templates NOT changed (read-only run). | **NARROWED 2026-10-17** — the six other limits raised (catalog `bff82f9`: docmost 768M, romm 1024M, termix 256M, uptime-kuma 384M, grafana 768M, tandoor 1280M; peaks now 46–69 %; live on 9201: docmost 805306368 bytes); the 23 requests → R-1125 (operator: wait). **Left: Immich** (`immich-server` 1,665 of 2,048 MB on a 200-photo import; tester-1's real library peaked at 2.9 GB) — raise after a measurement with a larger library. | — | Measure Immich with a larger library (bench), then its limit | CC | | **R-1018** | Apps & catalog | P3 | **The OnlyOffice links (FileBrowser, Nextcloud) have no recorded live proof since the move to Proxmox.** `controller/internal/integrations/` holds two handlers; no audit after the Proxmox move shows a document opened from FileBrowser or Nextcloud in OnlyOffice (searched 2026-10-14). The media-app links of `15` §6 will copy this code, including its revoke-on-stop rule (`lifecycle.go:10-13`). | **OPEN** — filed 2026-10-14 | — | One live walk on a Tier-0 box: install OnlyOffice + FileBrowser, open a document, save, read it back; then stop one app and record what the link does | CC | | **R-1028** | Apps & catalog | P3 | **Plex's claim code can run out during the install, and the box cannot recover it.** plex.tv's code lives 4 minutes from the moment the household copies it; the clock covers the wizard, the image pull (`plexinc/pms-docker` is 351 MB, measured) and the first start. Plex reads `PLEX_CLAIM` only on its first run, and the field is `locked_after_deploy` — so a late code leaves an unclaimed server and the only way back is remove + install again. Reported by the operator during the 2026-10-14 test; on Tester 1's line the pull+start took 8.5 s and the claim worked (`audits/media-all-drives-2026-10-14/``G-auth/G3-plex-claim.txt`), so it bites on a slow line or a slow hand. **K6, 2026-10-14 night (`audits/media-drive-events-2026-10-14/``K6-1-unclaimed-plex.txt`):** an unclaimed Plex starts with no code at all, and `POST /myplex/claim?token=` on the RUNNING server reaches plex.tv (a wrong code → 500 after plex.tv's 401). So the box can pull + start first and ask for the code after: no race. A real claim needs the household's code — the morning step on the throwaway `plex-k6` on Tester 1. Narrowed 2026-10-14 night. **PROVEN 2026-10-15 morning (`K6-2-claim-after-start.txt`):** the operator's real code, given to the RUNNING unclaimed `plex-k6` → 200, `claimed` 0→1, `PlexOnlineToken` written, and the open door closed (no token → 401). `ADVERTISE_IP` was unset and the claim did not need it; whether clients find the server without it was not measurable (the throwaway had no published port). **BUILT 2026-10-15 (v0.313.0):** `after_start` field — not asked at install; the Plex page asks for the code once Plex runs and claims the running server; the gate opens only when Plex says claimed. Proven up to the code on 9201 (G5). | **NARROWED** — the dashboard claim with a real code is the last step | a household Plex code | Claim through the Plex page with a real code (G5c); then close | CC | | **R-1029** | Apps & catalog | P3 | **Plex's folder picker shows the drives as identical „media” folders.** With one bind per drive at the same path (`/mnt/felhom-drives//userdata/media`), the leaf of every library folder is `media`; the drive's name sits two levels up, so in Plex's picker the household sees several folders all called „media” (reported by the operator during the 2026-10-14 test on Tester 1). It conflicts with `15` §2 reason 2 (the same path everywhere). | **READY** — filed 2026-10-14 | the layout decision (STATUS D9) | Decide in `15` §2: the players (`:ro`, never linked) may get a readable path per drive (e.g. `/media/`) without breaking the hardlink rule, which binds only the download/library apps | CC | -| **R-1036** | Apps & catalog | P3 | **The apps page lags the catalog by two apps.** `app-catalog-felhom.eu/templates/` holds **64** apps; `/alkalmazasok` and `/en/apps` render **63** cards, one of which (`filebrowser`) is built in and not a catalog template — so **62 catalog apps are listed**. Missing: **`plant-it`** and **`wger`**, both in the catalog since 2026-10-06/08. Their website assets are ALREADY present (`plant-it-logo.svg` + 3 screenshots, `wger-logo.png` + 3 screenshots, renamed to the catalog slug by `a3507761`, 2026-10-08) — only the cards were never written, so this is not a new-asset job. Found 2026-10-14 while reconciling the app count for the „felhő tárhely” page, where four places said **60** and the rest said **62**. **Done in that session:** every stated count on the site set to **62** (`index.html`, `szolgaltatasok.html`, `en/services.html` were 60), which is what the apps page actually shows — so no visitor can count the cards and find the number wrong. **62 is still not the catalog's number.** **To close:** write the two cards on both apps pages (gate 15 keeps the two pages' app sets equal, so they move together), then raise every stated count 62 → 64 in the same commit. **The operator chose this split at the 2026-10-14 STOP** over doing it inside the SEO change. **2026-10-15 (R-1048):** Prowlarr's card added on both pages and every stated count 62 → 63 (the media group 19 → 20), so the site still states what it shows; the two owed cards would make it 65. **Note before writing them:** `wger` is `lifecycle: hidden` and `plant-it` `lifecycle: abandoned` — neither is offered for a new install, so a card would advertise an app the wizard refuses. | **OPEN** | — | write the `plant-it` + `wger` cards on both apps pages, then 62 → 64 everywhere, one commit | CC | +| **R-1036** | Apps & catalog | P3 | **The apps page lags the catalog by two apps.** `app-catalog-felhom.eu/templates/` holds **64** apps; `/alkalmazasok` and `/en/apps` render **63** cards, one of which (`filebrowser`) is built in and not a catalog template — so **62 catalog apps are listed**. Missing: **`plant-it`** and **`wger`**, both in the catalog since 2026-10-06/08. Their website assets are ALREADY present (`plant-it-logo.svg` + 3 screenshots, `wger-logo.png` + 3 screenshots, renamed to the catalog slug by `a3507761`, 2026-10-08) — only the cards were never written, so this is not a new-asset job. Found 2026-10-14 while reconciling the app count for the „felhő tárhely” page, where four places said **60** and the rest said **62**. **Done in that session:** every stated count on the site set to **62** (`index.html`, `szolgaltatasok.html`, `en/services.html` were 60), which is what the apps page actually shows — so no visitor can count the cards and find the number wrong. **62 is still not the catalog's number.** **To close:** write the two cards on both apps pages (gate 15 keeps the two pages' app sets equal, so they move together), then raise every stated count 62 → 64 in the same commit. **The operator chose this split at the 2026-10-14 STOP** over doing it inside the SEO change. **2026-10-15 (R-1048):** Prowlarr's card added on both pages and every stated count 62 → 63 (the media group 19 → 20), so the site still states what it shows; the two owed cards would make it 65. **Note before writing them:** `wger` is `lifecycle: hidden` and `plant-it` `lifecycle: abandoned` — neither is offered for a new install, so a card would advertise an app the wizard refuses. | **WAITING-ON-OPERATOR 2026-10-18.** The night brief asked for the two cards; **not written**, because both apps are closed to new installs: `wger` is `lifecycle: hidden` and `plant-it` `lifecycle: abandoned`, so the install wizard refuses both and a card would offer an app a visitor cannot get. The site states what it shows (63 cards, 62 catalog apps listed). | operator decision | Pick: (A) leave both off the site and close this row (recommended: the site shows only what can be installed), or (B) re-open them for install first (wger's throttle R-752, plant-it's upstream), then write the cards | operator | | **R-1071** | Apps & catalog | P3 | **Jellyfin cannot use films that sit on a NAS share (the pilot's OMV), and the pilot's wish is exactly that.** MEASURED 2026-10-15: an OMV SMB share added as „Hálózati tárhely” mounts and verifies (`/mnt/felhom-drives/omv-filmek`) — but only with a user name AND a WRITABLE share (read-only → refused „az alkalmazások nem tudnak rá írni”) — and the household's „Újraindítás most” binds only local drives into Jellyfin (`per-drive binds 1 [/mnt/felhom-drives/filmlemez/userdata/media]`). By design: R-108 (a NAS is browse-only, never an app's namespace); `media_library.go` skips `Kind == "network"`. A design decision, not a defect (R-370). Evidence: `audits/omv-vm-2026-10-15/B6-omv-share.txt`. | WAITING-ON-OPERATOR | Operator: should a media app read a NAS share read-only (a new bind kind), or is the answer „put the films on a drive the box owns”? | Operator rules; if yes, a design note in `15-media-library.md` first. | Operator | | **R-76** | Apps & catalog | P4 | **FileBrowser-created folders break the setgid chain, and a drop-zone's mode is not stable** **MIGRATED FROM `ROADMAP.md` 2026-08-22 (R-369) — originally filed 2026-07-26, size S, roadmap state `idea (surfaced by the R-75 spike, 2026-07-26)`.** Moved verbatim; nothing added or reinterpreted. The roadmap keeps its copy as history, marked moved. | **OPEN — migrated from ROADMAP 2026-08-22, rank unchanged** **2026-10-06 night: not a catalog fix** — the setgid chain is set by the controller's FileBrowser setup; a controller row. | — | Two related findings from `audits/SPIKE-catalog-data-paths-2026-07-26.md` P3/P5, both **pre-existing** and deliberately left alone by that spike. **(a)** FileBrowser Quantum 1.3.3 creates files `0644` and folders `0755` and does **not** propagate the setgid bit — even though the entrypoint wrapper's `umask 002` really is in effect (`/proc/1/status` `Umask: 0002`). Group inheritance itself works (a file uploaded into a 2775 group-100 dir landed group 100, not the process gid 1000), so the convention's *group* half holds and only its *mode* half is lost. The consequence is proven with a control: inside a UI-created `0755` folder a gid-1000 process's file landed group **1000**, while the identical write into the 2775 parent landed group **100**. So **any folder a customer creates through FileBrowser breaks the shared-group chain one level down.** Latent today — every userdata-touching catalog app that declares an identity declares uid/gid **1000**, the same uid FileBrowser runs as, so owner permissions mask it; it bites the day a content app runs as a different non-root uid with gid 1000. The comment at `infra/infra.go:156` is right that the image ignores `-e UMASK` but does not say t | CC | | **R-707** | Apps & catalog | P4 | **[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). **2026-09-29 afternoon (controller v0.281.0, catalog `6faf432`):** 28 more class-4 apps gated — 32 of 34 — each proven on 9202 (`audits/gate-rollout-2026-09-29/`B): stranger → gate page / 401, household reached the first-setup screen, the gate opened (9 by a measured probe, the rest by the press), the app answered after. seerr, outline, rallly: gated, their opening needs a media server / e-mail (not proven). **Left:** wanderer (R-714); plant-it is not installable. | **NARROWED** (2026-10-03 triage: the row's verdict was finished, but it names open work no other row carries — seerr, outline and rallly are gated, but the gate OPENING is not proven (needs a media server / e-mail)) — **CLOSED — 2026-09-29 (the rest → R-714)** | — | — | CC | @@ -148,6 +145,7 @@ stopping line that lies. | **R-1100** | Apps & catalog | P3 | **One sign-in for the dashboard and FileBrowser (proxy auth) — spike first.** Since controller 0.320.0 every app with a folder has „Fájlok ↗", and the box can show FileBrowser's password — but FileBrowser still asks for its OWN login the first time, so the household signs in twice. FileBrowser Quantum has a proxy-auth method (`auth.methods.proxyAuth`, header-trusted) that could take the dashboard session through traefik; nobody has measured it. Design: `architecture/02-controller-module-map.md` „Logins and folders". | OPEN — filed 2026-10-16 (task logins-folders). | — | Spike on demo-hp: proxy auth at the pinned tag (source + measured), a forwardAuth in traefik that answers only for a dashboard session, what a stranger reaching `files.` with a forged header gets, and what happens to FileBrowser's shares. | CC | | **R-1099** | Apps & catalog | P4 | **The N100 may hold RomM games in the old upload place, now shown under a fake „roms” platform.** Until 2026-10-16 RomM's own upload wrote to the drive's `roms/roms//`; after the mapping fix (catalog `fb18471`, R-1089) those files are at RomM's `library/roms/roms/…`. Measured on 9201: such a game showed as missing in its platform and again under a platform „roms” (`audits/romm-ghost-2026-10-16/B/b-after.txt`). Files put in with the file manager are not affected — they are now found. The N100 runs RomM (hub `/apps/romm`); CC does not log in to the lived-in box. | OPEN — filed 2026-10-16 | Operator: look at `roms/roms/` on the N100's drive in the file manager | If it holds platform folders: move them up one level into `roms/`, then run „Scan” in RomM; if it is empty, close | Operator | | **R-1117** | Apps & catalog | P4 | **Immich's and Nextcloud's Redis keep a volume they do not need** (upstream runs both without one; queues and caches only). Deferred from R-1096 on purpose: removing a volume from the compose leaves the old volume on installed boxes, and the nightly dump / an old backup's restore for a volume the compose no longer declares is unchecked. The RDB switch (catalog `5d9450b`) already removed the full-disk danger. | DEFERRED — filed 2026-10-17 | — | Measure the dump and an old-backup restore without the volume on 9202; then the template change + an orphan-volume note | CC | +| **R-1147** | Apps & catalog | P3 | **The public machine estimator (`/gepigeny`) sizes Immich from a 200-photo bench; a 4,000-photo import needs more.** The estimator's Immich peak is 3,290 MB (`audits/sizing-2026-10-13/`); tonight's import on 9202 (`audits/night-2026-10-18/P6/`) peaked at 2,848 MB for the server alone with room (anon 1,596), plus 1,498 ML, 359 postgres, 43 redis — and killed the server twice at the old 2 GB limit. The limits were raised (catalog `8cf03e0`); the public figures were not, because they follow an operator ruling („raised only, 2026-10-14"). | OPEN — filed 2026-10-18 | operator: may the public figures move? | Re-run the estimator inputs with the 4,000-photo figures, show the operator the before/after verdicts, then publish | CC | ## App updates — 4 rows (P3 4) @@ -167,7 +165,7 @@ stopping line that lies. | **R-973** | Backup & restore | P3 | **A compromised controller can make the whole-guest backup run again and again, and each run prunes older restore points: the local tier directly, and the off-site tier through the store's own nightly keep-last-2.** So `07` §8 row 10 (ransomware) is weaker than it reads. The second reader confirmed the local half; the off-site half is inferred. Fix: a cadence or daily cap on the local-API backup route, and off-site snapshots that a nightly prune cannot remove. Security review 2026-10-12 (`audits/security-review-2026-10-12/`); detail held off-git for the operator (`/mnt/5_hdd/felhom.eu/evidence/security-review-2026-10-12-PRIVATE/`). | OPEN | — | Add the cap with a test; decide the off-site retention shape | CC | | **R-232** | Backup & restore | P2 | **DooPlex's backup makes every copy inside the same box — and nothing tells anyone when it fails.** Surveyed read-only 2026-08-06 (`audits/RECON-dooplex-backup-2026-08-06.md`). **What works:** five sets, 14/14 successful runs in 14 days; a file was restored from the `data` repo and matched the live original **byte for byte**; every set except two is cross-disk; k3s is integrity-checked on every run. **What the matrix exposes, ranked:** (a) **`notify_failure` is a no-op** — `NOTIFY_ON_FAILURE=true` but `NOTIFY_WEBHOOK_URL` is commented out, so a failed backup notifies **nobody**; the project already has a working Resend path that CI uses. Cheapest item, and it makes every other failure visible. (b) **Nothing leaves the box** — no rclone, no remote repo, no off-site target anywhere; Longhorn's target is `nfs://192.168.0.180:` pointing at DooPlex itself, and the only outbound-looking cron pulls *inbound* from Hetzner for a different project. The machine that runs the hub managing the customers' off-site chain has no off-site copy of its own. (c) **The backup tree is a single writable path** and the restic repos are not append-only — one bad script or ransomware destroys every copy at once. (d) **Two same-disk sets**: `.claude-memory` and the PostgreSQL dumps, whose source directory sits *inside* the backup tree. (e) **Longhorn `retain=1`** — one generation per volume, so a corruption noticed a day late has no earlier copy. (f) **`/opt/backup/docs/BACKUP-RESTORE.md` does not exist** though the systemd unit advertises it. (g) **`secrets/restic-repo` has never held a snapshot** — `backup-secrets.sh` contains no `restic` call; the secrets are GPG files on `sda1` only. (h) **No restore has ever been run** beyond today's single-file probe — the matrix's "ever demonstrated?" column is otherwise entirely empty. **Not a finding:** the restic passphrase. The on-box copy is on `sdb1`, a different disk from the backups, and the **operator holds an offline copy out of band** — so a disk loss is recoverable. The narrow residual is that it is operator-held rather than system-held, unlike the customer case's hub-vaulted escrow, so it should be confirmed current and findable by someone else. **Nothing was changed by the recon.** | **NARROWED 2026-10-08 — owner Viktor.** (a) DONE with the operator's yes in chat: `notify_failure` now mails admin@felhom.eu through Resend; proven by one test mail that reached the inbox (`audits/day-2026-10-08/r232/`; no backup was started). (b) partly: the hub database leaves DooPlex nightly to ep0 (R-173); everything else stays on the box. (c)–(h) unchanged. **2026-10-09 (operator yes in chat): (b) and (h) DONE for Gitea and the secrets.** Nightly 00:20 `felhom-dooplex-offsite` pushes Gitea (614 MB of repositories, the `gitea` database dump taken first, `app.ini`) and the nightly GPG secrets export, encrypted with a NEW key, to ep0 `operator` (`host/dooplex-gitea`) on the hub-DB write-only token — no change on ep0; first push 57 s; restore test weekly (manifest, `git fsck` every repo, `pg_restore --list`), run once: 27 805 files, 10 repos OK; `DooplexGiteaOffsiteStale`/`DooplexGiteaRestoreTestStale` in force (`absent()` included, promtool + 2 red-proofs); every backup unit now mails on failure (`OnFailure=`, dry run reached the inbox). **First real Gitea restore:** into a throwaway on the bench, 10/10 repos, product `main` = live, a file byte for byte, a login (`runbooks/gitea-restore.md`). The hub came back too (R-173, closed). **The registry is left out on purpose:** its images rebuild from the code. **Correction to the recon §7:** the API mirror holds ONE repo (`homelab-manifests`), not all — Gitea had a single copy, on DooPlex. `audits/dooplex-survival-2026-10-09/` **LEFT:** (c) append-only for the on-box tree, (d)–(g) as written; the paper copy of the new key (operator). **READY** for the rest | — | — | operator | | **R-893** | Backup & restore | P3 | **After a failed OFF-SITE replay, the rollback pours the NEWER pre-restore copy over the OLDER volume just put back.** Read in source 2026-10-06 (R-638 option A, not measured): `internal/backup/offbox_reconstitute.go` writes the undo copy from the live (newer) database, replaces the volumes with the snapshot's older tars, then — when the replay fails — `rollbackSafetyDump` loads that newer dump over the older database volume. The loader only drops what the dump knows, so tables the newer migration removed stay; and when the snapshot's older definition was written, the rollback branch does not put the newer definition back, so the older app starts on rolled-back data; non-database volumes stay at the snapshot's state. An order change cannot fix it (the only undo is a logical dump, and its volume was replaced). Known limit in `07` §6.3. **-- 2026-10-08 design:** `audits/day-2026-10-08/design-R-893.md` — re-verified; and the screen's „your data is back as it was" (`err.backup.db_restore_failed_rolled_back`) is false for files, other volumes and the app version. Question D8 on STATUS's decision sheet. **-- 2026-10-08 14:16 operator ruling D8 (`09` §3 decision 192):** yes, both, in that order — first the app stays stopped for support (option C), next „put back exactly as it was" (option A). | **NARROWED — 2026-10-09: the first half DELIVERED in controller 0.304.0. Slice 0 (the live measurement) NOT run: 9202 has no off-site, and a dump cannot be cut by hand inside an encrypted off-site copy on Tester 1; it needs a scratch off-site repo — a plan, not a finding.** **NARROWED 2026-10-08 — the first half (D8 option C, the app held stopped) is built on controller main and ships tomorrow; what stays open is the second half, „put back exactly as it was” (option A: a pre-restore copy of the app's volumes and placed files, a fit check, disk for one copy; the slice-0 measurement on 9202 first).** **OPEN — filed 2026-10-06** **2026-10-06 night: verified in source, no code** — `offbox_reconstitute.go:758` (undo dump from the live DB), `:778-860` (files and volumes from the snapshot), `:804` (the snapshot's definition is written when its version differs), `:898` (the rollback loads the newer dump over the older volume; nothing writes the live definition back). Not a reorder fix: it needs R-638 option B (a rebuilding loader) or a pre-restore volume copy (disk cost; R-685's class). Which state a household gets after a failed off-site replay is the operator's call. Next: the 9202 measurement, then the design. | a design: R-638 option B (a loader that rebuilds instead of overlays) or a pre-restore volume copy | Measure it once on 9202 (a forced replay failure after an off-site restore over a migrated app); then a design for the operator | CC | -| **R-895** | Backup & restore | P2 | **The hub's clean-up-window check trusts the snapshot counts the box sends, so a broken-into box (or past-dated fakes added through the add-only key) can shrink the real off-site history without an alarm.** READ 2026-10-06 night in source (R-822's design): the before/after comparison uses counts the box itself reports (`hub/internal/offsitekeys/service.go:284`, `:343`); new fakes keep the count level. Decision 68 already accepts a box-trusted count. | **OPEN — filed 2026-10-06 night** **2026-10-07 07:58: kept open for later (`09` §3 decision 166).** **2026-10-17: READY — design updated with the measurement** (`audits/agent-allowlist-rotation-2026-10-17/P4/design-R-895.md`): the hub needs NO new credential (the sealed sub-account password it already uses daily; write-capable today); the provider shows upload times (2026-09-01 evidence on demo-hp's sub-account). Slice 1 in hub v0.157.0 (deployed 2026-10-17 on the operator's yes): the daily key audit also lists `snapshots/` read-only and LOGS count/newest/oldest — the first 07:10 run is the live measurement. | the first logged listings (hub 07:10 audit), compared with the box's own count | Option B of `audits/night-burndown-2026-10-06/design-R-822.md`: the hub lists the repo's `snapshots/` files over its own login before and after a window and alarms on snapshots no box run explains | CC | +| **R-895** | Backup & restore | P2 | **The hub's clean-up-window check trusts the snapshot counts the box sends, so a broken-into box (or past-dated fakes added through the add-only key) can shrink the real off-site history without an alarm.** READ 2026-10-06 night in source (R-822's design): the before/after comparison uses counts the box itself reports (`hub/internal/offsitekeys/service.go:284`, `:343`); new fakes keep the count level. Decision 68 already accepts a box-trusted count. | **NARROWED 2026-10-18 — slice 2 built, not deployed** (hub v0.158.0): the 07:10 audit compares the `snapshots/` listing with yesterday's by name — files gone that no clean-up window explains → `offsite_snapshots_vanished` (error), files no reported box run explains → `offsite_snapshots_unexplained` (warning); operator-only, hub-origin (not in `allowedEventTypes`). First listing = baseline; a move-aside or RESET drops it; vanishing judged on a pinned tier only; files younger than 1 h judged the next day. Red-proofed twice (`snapshot_watch_test.go`). **Not built:** the window's before/after on the hub's own count (design §3.1) and refusing a window while unexplained files exist (§3.2). Unmeasured: the provider shell's `ls -l` time zone (± 3 h slack until then). | the operator's yes to deploy hub v0.158.0 | Deploy; read the first 07:10 lines (newest upload vs the box's last run = the time-zone calibration), shrink the slack; then decide §3.1/§3.2 | CC | | **R-923** | Backup & restore | P2 | **The password manager (Vaultwarden) runs on DooPlex and holds the keys that open DooPlex's own off-site copies — a loss of DooPlex loses the keys with the copies.** Operator finding, 2026-10-09 11:19: "the password manager also runs on DooPlex (Vaultwarden), so I probably need to back up its DB somewhere too." Measured: `vaultwarden-system/vaultwarden` (1.37.3), PVC `vaultwarden-data` 7.4 MB (`db.sqlite3` + WAL, `rsa_key.pem`, no attachments); its only backups were Longhorn on DooPlex. **A key in a password manager that runs on DooPlex is not off DooPlex** — R-173's "both keys are off DooPlex" (2026-10-05) and the hub-DB runbook Step 0 were wrong in that sense. Also seen: Vaultwarden warns its `ADMIN_TOKEN` is plain text (an Argon2 hash is its guidance). | **NARROWED 2026-10-09 (operator yes in chat):** Vaultwarden's own `backup` copy + `rsa_key.pem` ride the nightly encrypted DooPlex→ep0 job (`scripts/dooplex-offsite/`), checked on every push and every Sunday (integrity, users, items — rows only). That copy opens only with the DooPlex off-site key, and the vault only with the master password — so the circle is broken only once both are on paper outside DooPlex: `runbooks/break-glass-sheet.md`, `runbooks/total-loss-of-dooplex.md`. **LEFT:** the operator prints the sheet and stores it away from home; the `ADMIN_TOKEN` hash (a DooPlex change, operator's word). | operator: print the sheet | Operator: print + store the sheet; then close | operator | | **R-49** | Backup & restore | P3 | **[P2] The offsite capture set is ~90% cache and duplication — 1.1 GB of a 1.2 GB immich "photo backup".** Measured 2026-07-19: `immich_ml_cache.tar` **823 660 032 B (~60%)** — re-downloadable ML model weights; `immich_postgres_data.tar` **308 251 136 B (~23%)** — a raw tar of the postgres data dir that DUPLICATES the logical `.sql` dump captured beside it; `upload/backups/` **18 MB** — immich's own nightly dump, a backup inside the backup, growing daily; plus the stranded pre-v3 `dccc13fe…` tree (~36 MB) no DB has ever referenced. Actual irreplaceable content: **72 MB of originals**. **MIGRATED FROM `ROADMAP.md` 2026-08-22 (R-369) — originally filed 2026-07-19, size S–M, roadmap state `idea`.** Moved verbatim; nothing added or reinterpreted. The roadmap keeps its copy as history, marked moved. | **OPEN — migrated from ROADMAP 2026-08-22, rank unchanged** **Re-ranked 2026-10-03: P2→P3: wasted space and transfer, no data risk; needs a capture-set ruling, not a sale blocker.** | — | **Evidence: `audits/DIAG-immich-restore-round2-2026-07-19.md` §4 (full byte breakdown).** This is the customer's offsite quota and transfer cost, and it lands on the Hetzner sub-account they are billed for. **Recorded, deliberately not changed** — a capture-set exclusion is a data-loss-shaped decision and gets its own ruling, not a drive-by edit. Candidates in priority order: (a) `immich_ml_cache` — pure cache, strongest case; (b) the `postgres_data` volume tar where a logical dump of the same DB is already captured (the dump is what the restore path actually replays); (c) `upload/backups/`. Likely generalises past immich into a template-classification rule about cache volumes and self-backup directories, so it should be specified against the catalog, not one app | CC | | **R-231** | Backup & restore | P3 | **`/opt/backup/scripts/` on DooPlex is unversioned host state** — found 2026-08-06 while adding the auto-memory store to the backup set. No repository tracks the scripts that protect the recovery chain, so the edit made that day (`CLAUDE_MEMORY_DIR` in `backup-config.sh`, multi-path restic call in `backup-data.sh`) exists only on the box. This is the same class the part-2 session was closing, found inside the fix for it; the change is transcribed in `felhom.eu/workspace/README.md` so it is at least *recorded*. **Two related facts, both understating current safety:** the backup destination (`/mnt/5_hdd/backup`) is on the **same physical disk** as the workspace it protects, and the DooPlex backup set has **no off-site leg** (`sync-hetzner-backups.sh` is jarrs.eu and pulls *from* Hetzner *to* DooPlex). Bringing a root-owned production backup script under version control, and deciding what installs it, is its own scoped change. | **VERIFY** — **MEASURED 2026-10-13 — the due check is GREEN** (read by the sizing session, two channels): `systemctl show dooplex-backup.service` → `Result=success`, `ExecMainStatus=0`, ran 03:27:39–03:33:29 CEST; its journal ends „All backup components completed successfully!”, and the manifests leg (the header-token change) logged „Successfully backed up homelab-manifests” with the plain URL `https://gitea.dooplex.hu/admin/homelab-manifests` (no token in it). Left open, not closed: the row also carries the same-disk and no-off-site facts, which closing would drop — the owner decides. **VERIFY** — **2026-10-12 evening: the token left the clone URL** (operator yes in chat; homelab-manifests `1943a70`, installed by the role): `backup-manifests.sh` sends it as an `http.extraHeader` through `GIT_CONFIG_*` env; read-only proof: `git ls-remote` of the private repo with the header → HEAD, without → refused. The 2026-10-13 03:10 run is the test of both changes. **VERIFY** — **2026-10-12: in git and installed from it** (operator yes in chat, operator in the session): homelab-manifests `fdd324b`, `homelab-ansible/roles/dooplex_backup/` (11 scripts + the timer units, byte-identical to the live ones; no secret in any file; `install.sh` dry run / `--apply`). The install changed only the units' mode (744 → 644). Baseline: last night's run `Result=success`, exit 0 (`audits/answers-2026-10-12/s20-backup-scripts.txt`). **Seen by the commit's security review, NOT changed (a DooPlex behaviour change needs the operator's word):** `backup-manifests.sh` puts the Gitea token into the clone URL for the mirror run (visible in the process list for those seconds) and strips it from the stored remote afterwards; no token VALUE is in any file, and the repo is private (anonymous API read = 404). A header-based fetch (`git -c http.extraHeader=…` from the token file) would remove it — one line in the decision list. **READY** — operator ruling 2026-10-12 (S20, `09` §3 decision 215): yes — the scripts into a repo + an install script; the operator present for the install. **READY** — owner Viktor | — | Owner: close the row (the install from git is proven) and file the same-disk / no-off-site facts as their own row if they still hold | CC | @@ -192,15 +190,13 @@ stopping line that lies. | **R-32** | Backup & restore | P4 | **[P2-HIGH] RESET must purge the customer base dir; the orphan card must stay honest; unattributed bytes must be visible.** The rehearsal's S7 said in advance that an orphan card would BE a finding — and one appeared (16:58:14). Cause: RESET's `"hetzner":"ok"` leg destroys the sub-account, but **a Hetzner sub-account is an access-control object, not a data object** — its directory survives, so re-enabling offsite recreated an account over the previous lifecycle's ciphertext, encrypted under a key that same RESET had destroyed. **MIGRATED FROM `ROADMAP.md` 2026-08-22 (R-369) — originally filed 2026-07-21, size M, roadmap state `idea`.** Moved verbatim; nothing added or reinterpreted. The roadmap keeps its copy as history, marked moved. | **OPEN — migrated from ROADMAP 2026-08-22, rank unchanged** **2026-10-06 night: design written** (`audits/night-burndown-2026-10-06/design-R-32.md`) — pick A: purge the repo + set-aside copies through the sub-account's own password login BEFORE deleting it (no main-account credential); the „repo data destroyed" comment at `hub/internal/offsite/offsite.go:276-280` is false for the shared tier; part (3) waits on a read-only measurement (`du` on port 23). Operator: agree to route A. **2026-10-07 07:58: `09` §3 decision 167 — option A yes, and delete the old RESET leftovers once.** **2026-10-07 (Part D step 2, read only):** the hub shows bx11 holding 3.3 GB of data while the four live customers account for ~0.6 GB → **~2.7 GB belongs to no live customer**; no live customer shows a set-aside folder, so the leftovers are in homes whose sub-account is gone, reachable only by the pool box's MAIN account. **The one-time clean-up is STOPPED:** no main-account login for bx11 is held on DooPlex (the API token in the credentials file sees no box). Needs: the main-account login, or the operator lists and deletes in the Hetzner console (`audits/day-2026-10-07/D/D2-listing-readonly.txt`). **2026-10-07: option A DELIVERED (hub 0.142.0):** RESET purges the repo and every `.orphaned-*` through the sub-account's own login before deleting it, and keeps the sub-account if the purge fails (red-proved, `audits/day-2026-10-07/D/`). Not yet seen live (no scratch RESET today). **The one-time clean-up of the ~2.7 GB of leftovers is STOPPED:** it needs the pool box's main-account login (see above). **2026-10-07 14:43 — `09` §3 decision 173: leave the ~2.7 GB of old leftovers for now; re-ranked P2 → P4.** Option A itself is delivered (hub 0.142.0). What stays open is ONLY the leftovers: they were computed (box total minus live customers), never listed, and deleting them needs the pool box's MAIN login, which reaches every customer's data. **Blocker: a safe main-account path.** | — | **Ruling from the run (three parts, deliberately separate):** (1) because RESET destroys custody, the ciphertext it leaves behind is unrecoverable **BY DESIGN** → RESET gains a **main-account purge of the customer base dir** (the existing operator ack already covers it); (2) the **move-aside guard STAYS** for reinstall-*without*-RESET — there custody survives and the card's "history recoverable" promise is true (R-26 depends on exactly that); (3) the operator **Restic tab shows per-customer directory bytes vs attributed snapshot bytes**, so dead data cannot hide. Measured on the pool box that night: **49 M attributed** (2 snapshots, 48.717 MiB) against **1.4 G + 3.0 M unattributed** across TWO `.orphaned-*` dirs. Evidence `restic-and-pool.txt` | CC | | **R-1087** | Backup & restore | P4 | **Whole-box copies left on the OLD local target are never pruned after the target moves.** MEASURED 2026-10-15 (storage-identity build B space check): the N100's host root (`local`) holds three copies from 2026-07-28 (5.5–5.7 GB each, ≈ 16.8 GB); its agent's `local_backup_target` is now `felhom-backup` (the USB disk, retention 3), and retention prunes only the current target. On a small-root box such leftovers would starve the local copies (R-548). Evidence: `audits/storage-identity-buildB-2026-10-15/space/felhom-pve-9201.txt`. | OPEN | — | Decide whether the agent prunes its own `vzdump-lxc--*` files on a former target (after a newer copy exists on the new one), or the target move asks; until then, the N100's three July files can be removed by hand with the operator's word. | CC | -## Storage & devices — 12 rows (P3 6, P4 6) +## Storage & devices — 11 rows (P3 5, P4 6) | ID | Category | Sev | What | State | Blocked on | Next action | Owner | |---|---|---|---|---|---|---|---| -| **R-1069** | Storage & devices | P3 | **A disk passed into a Felhom VM on a virtio bus cannot be formatted, and the household reads the agent's raw English refusal.** MEASURED 2026-10-15 (OMV KVM plugin, „Add host disk”, default Bus `virtio`): `POST /api/disks/format` → 500 „agentapi: format: HTTP 409: format refused: device has no durable id to bind the format to (path-only formats are not permitted)”. A virtio-blk disk without a serial has no `/dev/disk/by-id` link inside the guest, so the anti-retarget guard refuses — correct and safe. The same disk on Bus `sata` got `byid:ata-QEMU_HARDDISK_QM00003` and formatted. Affects every hypervisor that passes disks as virtio without a serial (OMV KVM, Proxmox without `serial=`). The pilot guide says `sata`. Evidence: `audits/omv-vm-2026-10-15/B4c-second-disk-format.txt`. | OPEN | — | Translate the refusal for the household („Ezt a lemezt a Felhom nem tudja biztonságosan azonosítani — a virtuális gépben állítsd a lemez buszát SATA-ra”); optionally fall back to a filesystem-UUID binding after a blank-format. | CC | | **R-1073** | Storage & devices | P3 | **Felhom in a virtual machine sees no disk health: SMART is UNKNOWN for its own system disk and any passed disk.** MEASURED 2026-10-15 on the OMV-VM copy: every storage target reported `smart.health = UNKNOWN`, all counters null (the guest sees QEMU disks). On the pilot's box the NVMe and the „old, not stable” Toshiba would be watched by OMV only, and Felhom's drive-health alarms (R-330/R-332's whole point) cannot fire. Evidence: the host report in `audits/omv-vm-2026-10-15/README.md` (memory/disk section) and `C-hub-events-Tester4.txt`. | WAITING-ON-OPERATOR | Operator: is a VM install a supported shape, and if so, is „OMV watches SMART” acceptable or must Felhom say on the dashboard that it cannot watch the disks? | Operator rules; then CC adds a household line on the Meghajtók page when SMART is unavailable. | Operator | | **R-1093** | Storage & devices | P3 | **An EMPTY partition asks for the typed „data will be erased" confirmation.** MEASURED 2026-10-16 (build B, scratch VM, agent 0.158.1): `POST /api/storage/init` for a blank part → `needs_confirmation`, reason „device has a partition table" — `lsblk` reports the PARENT disk's table (PTTYPE) for a partition, so the agent's probe reads an empty part as data-bearing. Safe direction (more friction, never less), but `16` §6 says an empty part is self-serve and the wizard shows „adatot tartalmaz". Evidence: `audits/storage-identity-buildB-2026-10-15/live/12-partitions-format.txt`. | OPEN | — | In the agent's device probe, ignore a PTTYPE that a partition inherits from its parent (judge only the part's own signature and children); a red-proved test with a blank part fixture. Next agent release. | CC | | **R-1062** | Storage & devices | P4 | **The N100's USB drive cannot be split in two without losing the box's whole-guest backup target.** The operator asked (2026-10-15 16:31) for two halves for multi-drive tests. Read first (`audits/n100-lived-in-2026-10-15/B/`): no family files — 2.7 GB nightly vzdumps of guest 9201 (`dump/`, PVE storage `felhom-backup` = the whole-guest backup target), 3.1 GB app backups + an off-site restore copy, 422 MB leftover app data of removed apps, empty media folders. The agent refuses a decommission of a backup target (`refuseIfBackupTarget`) and the N100 has no other drive to move that role to. Nothing changed. | **WAITING-ON-OPERATOR** — filed 2026-10-15 | operator decision | Keep one drive (CC's pick: the lived-in box keeps its local whole-guest backup), or give a word to drop that backup leg / add a second drive first | operator | -| **R-1063** | Storage & devices | P3 | **„Végleges leszerelés" leaves a half-state when the agent refuses: the dashboard marks the drive decommissioned first and never undoes it.** `handleStorageDecommission` → `finalizeDecommissionWith` calls `settings.SetDecommissioned` (and may move the default) BEFORE `agent.Decommission`; on the agent's 403 (protected role) or 409 (whole-guest backup target) it returns the error and keeps the mark — the dashboard would show a retired drive the agent kept serving. Read from code 2026-10-15 (`felhom-controller` `internal/web/storage_handlers.go`); NOT pressed on the lived-in N100 on purpose. | **OPEN** — filed 2026-10-15 | — | Measure on demo-hp (a backup-target drive), then: ask the agent first (or undo the mark and the default on a refusal); a test with a refusing agent seam, red first | CC | | **R-1064** | Storage & devices | P4 | **Removing a storage path does not mention the cross-drive backup copies it holds.** demo-hp 2026-10-15: `/mnt/sizing-bench` removed through `/settings/storage/remove` (302, „Adattároló eltávolítva") while calibre-web's and paperless-ngx's `cross_drive.destination_path` pointed at it; the copies stay on disk, the records still name the removed path. The in-use check counts HDD_PATH only (`appsUsingPath`). | **OPEN** — filed 2026-10-15 | — | Read what tonight's tier-2 run (01:30) does with the two records; then: name the copies in the removal's confirmation (or count them as in use) | CC | | **R-330** | Storage & devices | P3 | **Disk health Phase 2 — the three SMART attributes the wire does not carry.** The failing drive's most telling counter was **187 `Reported_Uncorrect`**, sitting at normalized **1** against threshold **0** with a raw count of **1001** — one point from failing and structurally unable to get there. Also wanted: **199 `UDMA_CRC_Error_Count`** (cabling) and **188 `Command_Timeout`**. None are on the agent→controller wire today, so v0.215.0's ladder could not use them. Phase 2 also persists periodic SMART **samples** (the right home is `metrics.MetricsStore`, NOT the Phase-1 state file, which is one record per disk and must stay that way). **This is a declared WIRE change, so under the G-1 gate the hub must model the new fields in the SAME session** — that is precisely why it was kept out of Phase 1, where it would have turned a one-word severity fix into a three-repo change | **READY** — **2026-10-12: the wire half is CLOSED in this row** — released in agent v0.150.0 (boxes run 0.154.0), controller and hub decode 187/188/199. **Only open work:** the verdict slice (use the three counters in the disk verdict and the household's words) and persisting samples. **READY (M) — NEW 2026-08-14** **2026-10-06 night: the wire half BUILT on main (unreleased):** the agent sends SMART 187 `reported_uncorrect`, 188 `command_timeout` (raw, vendor-packed on some drives — carried as reported), 199 `udma_crc_errors` (pointer + omitempty: unknown is absent, never 0); the controller decodes them and the hub's host-report mirror models them (G-1 wire gate green; it convicted the agent half alone). **Carried only** — no verdict, banner, mail or alarm reads them (`TestR330_CountersChangeNoVerdictYet`); using them changes what a household is told and is the next slice, with persisting samples. Red-proofs `audits/night-burndown-2026-10-06/r330/`. Ships with agent v0.150.0 and the next controller and hub releases. | R-328 (closed) | The verdict slice: 187/188/199 into the disk verdict with tests; then persist samples | CC | | **R-332** | Storage & devices | P3 | **The new Hiba-from-counters path has never fired on real hardware.** v0.215.0's whole point is a verdict the product could not previously reach, and it is proven only against the committed fixture's values in unit tests (12 scenario groups, 11 of 12 red-proofs failing as required). The live validation on demo-hp proved the **negative** — three healthy disks still read Rendben across the deploy, no false alert — and the **severity wire** end to end, but no live disk has actually reached Hiba. **This is the honest gap and it must not be closed by pointing at the fixture tests**: the drive that produced the fixture is in DooPlex, which is Tier 2 and never a drill target, and the demo boxes are all-flash and healthy | **WATCHING — NEW 2026-08-14, NARROWED same day.** One item originally in this gap is now PROVEN LIVE: the **persisted state surviving a controller restart**. The v0.215.0→v0.216.0 redeploy destroyed and rebuilt the container, and the new one read back a `changed_at` written by the PREVIOUS version (`2026-08-14T07:23:14.640216851Z`, still intact at 09:31:35Z) instead of re-baselining — Scenario L on real hardware, not just the production-path unit test. **What remains unproven is the verdict itself, plus the stronger restart half: an already-ALERTED disk not re-alerting** | a real degrading disk, or an injection harness | **Closing condition:** a live disk reaching Hiba from counters, OR a deliberate injection through the REAL pipeline (agent `/disks` → controller check → hub event), not a hand-set verdict | CC | @@ -208,8 +204,9 @@ stopping line that lies. | **R-1076** | Storage & devices | P4 | **A cheap SSD reports a vendor-less WWN, so a WWN-first disk key may not be unique.** MEASURED 2026-10-15 on the N100's system SSD (AirDisk 512 GB): `ID_WWN=0x5000000123456f1f` — NAA-5 with OUI `000000`, a pattern that looks like a placeholder; its serial `QDF922W009654S30EX` looks real. The agent's wipe binding prefers `wwn-` links (A/internal/storage/durable_device.go:32). Not known whether two units share the WWN. Evidence: `audits/storage-identity-2026-10-15/B-n100.txt`. | OPEN | — | Check a second unit of the same model (or vendor data); if shared, make the agent skip OUI-000000 WWNs (the design already keys on model+serial, `architecture/16-storage-physical-identity.md` §3). | CC | | **R-1077** | Storage & devices | P4 | **No USB enclosure that hides or fakes a disk's serial has been measured.** The storage-identity spike (2026-10-15) had none at hand and found none in earlier evidence; the design's `usb_bridge` unknown rule (`architecture/16-storage-physical-identity.md` §3) is therefore an assumption. Cheap single- and dual-bay bridges are known to report one bridge serial for any disk. Evidence: `audits/storage-identity-2026-10-15/README.md` case 4b. | OPEN | — | Buy or borrow one cheap USB enclosure (single and dual bay), run `tools/physdisk_probe.py` against it, and set the rule from what it reports. | Operator (a device) then CC | | **R-1094** | Storage & devices | P4 | **The whole-disk format refusal tells the household to format the free part — which is refused while the other part is in use.** SEEN 2026-10-16 (controller 0.318.0): 409 „Ezen a lemezen egy használatban lévő meghajtó van, ezért a teljes lemez nem formázható. Csak a szabad részét formázhatod." — since agent 0.158.1 a part next to a mounted part can only be USED (the root wrapper trusts no „Felhom's own" claim). Evidence: `audits/storage-identity-buildB-2026-10-15/live/14-samedisk-refusal-offer.txt`. | READY | — | Reword `err.web.meghajto_hasznalatban_formazas` (hu + en): „… nem formázható. A szabad részét használatba veheted." Next controller release; the copy gates run. | CC | +| **R-1144** | Storage & devices | P3 | **„Végleges leszerelés — mégis" stops the drive's apps before the agent is asked; when the agent refuses, the drive stays (fixed tonight, R-1063) but its apps stay stopped.** `handleStorageDecommission` mode `anyway` calls `StopStack` for every app on the drive, then `finalizeDecommission`; on the agent's 403/409 the household reads the plain refusal, and its apps are down until started by hand. Read from code 2026-10-18 (controller v0.329.0, `internal/web/storage_handlers.go`); not pressed live. | OPEN — filed 2026-10-18 | — | Start again the apps this press stopped when the refusal is a policy one (or ask the agent before stopping); a test with a refusing fake agent; next controller release | CC | -## Security & access — 21 rows (P1 1, P2 2, P3 12, P4 6) +## Security & access — 22 rows (P1 1, P2 2, P3 13, P4 6) | ID | Category | Sev | What | State | Blocked on | Next action | Owner | |---|---|---|---|---|---|---|---| @@ -217,8 +214,8 @@ stopping line that lies. | **R-985** | Security & access | P3 | **Our zero-knowledge wording is stronger than the product: on a live box the operator can reach the off-site backup key (through the vaulted root credential and the operator tunnel) without the customer's recovery code.** Design-shaped; decision for the operator in `STATUS.md`. Fix options: change the wording, or remove operator root reach to the key. Security review 2026-10-12 (`audits/security-review-2026-10-12/`); detail held off-git for the operator (`/mnt/5_hdd/felhom.eu/evidence/security-review-2026-10-12-PRIVATE/`). | WAITING-ON-OPERATOR — design-proposal | operator decision | Decide the wording or the change | operator | | **R-1042** | Security & access | P3 | **The boxes' Cloudflare keys cannot change zone settings, so Cloudflare's own „Always Use HTTPS” cannot be switched on.** Measured 2026-10-14 on all three zones (`audits/https-only-2026-10-14/``1A-1-zones-and-keys.txt`): each `cf_api_token` is valid and sees only its own zone, but GET/PATCH `settings/always_use_https`, `ssl`, `security_header` answer 403; the redirect and transform rule phases too. The https-only fix therefore lives on the box (decision 246). A second layer at Cloudflare needs „Zone Settings: Edit” (and, for headers, „Transform Rules”) added to each customer's key — the hub's zone-reach check stays. | **WAITING-ON-OPERATOR** — filed 2026-10-14 | a key permission only the operator can grant | Optional: widen each customer key, then switch „Always Use HTTPS” on per zone | operator | | **R-1104** | Security & access | P3 | **Check https-only on Tester 2 when it reports again.** R-1033 (plain http on every public name) is closed on the three boxes that report (35 names → 301, 2026-10-16). Tester 2 (`sajatfelhom.hu`) has been off since 2026-10-04 on controller 0.292.0; its addresses answer Cloudflare 530 (tunnel down), so nothing is served in plain http while it is off. When it comes back it takes the floor (≥ 0.312.0 carries the redirect). | OPEN — filed 2026-10-16 | Tester 2 reporting again | Run `scripts/https_only_check.py` with Tester 2 in it; close | CC | -| **R-1140** | Security & access | P3 | **The hub's ingress access logs cover about 13 hours, so a question like R-954's („did anyone use the old key?") cannot be answered next time.** Measured 2026-10-17: the ingress-nginx controller logs to the container log only; k3s keeps `container-log-max-size=10Mi` × `max-files=5` — 03:30 to 16:18 today; 268 `hub.felhom.eu` lines in that window. 90 days needs either a DooPlex k3s setting (all containers, ≈ 9 GB raw / ≈ 1.3 GB compressed at today's rate) or a hub-only access log kept on the hub's own volume (≈ 500 lines a day, ≈ 15 MB for 90 days). Both change DooPlex or the hub beyond this session. | WAITING-ON-OPERATOR — filed 2026-10-17 | operator decision | Pick: (A) a hub-only access log on the hub PVC, 90 days (recommended: small, no DooPlex change), or (B) longer k3s container logs | operator | -| **R-1141** | Security & access | P3 | **`felhom-host-install --rotate-recovery` exists only as part of a full installer re-run, which also reinstalls the vouched agent and the root files.** On a box running a newer agent than the vouched one (demo-hp on the candidate, 2026-10-17) it would move the agent back; on a household box it is a much larger act than a password change. The 2026-10-17 rotation therefore ran the installer's own `step_break_glass` ALONE (`audits/agent-allowlist-rotation-2026-10-17/P3/`). | OPEN — filed 2026-10-17 | — | A `--rotate-recovery-only` mode (step 4b and nothing else), or a signed op; the runbook `break-glass.md` §5 points at it | CC | +| **R-1140** | Security & access | P3 | **The hub's ingress access logs cover about 13 hours, so a question like R-954's („did anyone use the old key?") cannot be answered next time.** Measured 2026-10-17: the ingress-nginx controller logs to the container log only; k3s keeps `container-log-max-size=10Mi` × `max-files=5` — 03:30 to 16:18 today; 268 `hub.felhom.eu` lines in that window. 90 days needs either a DooPlex k3s setting (all containers, ≈ 9 GB raw / ≈ 1.3 GB compressed at today's rate) or a hub-only access log kept on the hub's own volume (≈ 500 lines a day, ≈ 15 MB for 90 days). Both change DooPlex or the hub beyond this session. | **NARROWED 2026-10-18 — built, not deployed.** Hub v0.158.0 (image `sha256:e4203978…`, felhom.eu `7d64038f`): the hub writes its own access log, one line per request (time, method, path without query, status, duration, source, the credential KIND and identity kind — never a value; `/bind/` and 32+-character segments redacted), `/data/access-log/access-YYYY-MM-DD.log`, deleted after 90 days (`05` §16.4). **Rate corrected:** ≈ 1,870 hub lines a day through the ingress (measured 2026-10-17, most are `/wait` long-polls), not ≈ 500 — so ≈ 0.2 MB a day, ≈ 19 MB for 90 days. Red-proofed (`TestAccessLog_NeverWritesASecret` leaks a fake token with the raw URL). The night does not deploy the hub (decision 162). | the operator's yes to deploy hub v0.158.0 | Deploy hub v0.158.0 (daytime, on the operator's yes); read one day's file on the PVC; close | CC | +| **R-1141** | Security & access | P3 | **`felhom-host-install --rotate-recovery` exists only as part of a full installer re-run, which also reinstalls the vouched agent and the root files.** On a box running a newer agent than the vouched one (demo-hp on the candidate, 2026-10-17) it would move the agent back; on a household box it is a much larger act than a password change. The 2026-10-17 rotation therefore ran the installer's own `step_break_glass` ALONE (`audits/agent-allowlist-rotation-2026-10-17/P3/`). | **NARROWED 2026-10-18 — built on `main`, not published.** `felhom-host-install.sh --rotate-recovery-only` runs step 4b alone (felhom.eu `7d64038f`): reads the hub, host id and host key from the agent config, refuses byo and every other mode flag, asks the hub's `/healthz` before the password changes, never touches the agent or root files. The default install path is unchanged in behaviour (harness verdicts and 9 transcripts identical old vs new; demo-hp `--preflight-only` identical; `--rotate-recovery-only --dry-run` on demo-hp changed nothing). `step_break_glass` moved, byte-identical, ahead of the argument parse. `break-glass.md` §5 points at it. Publishes only with the next `installer-v…` tag. | the next installer tag | Cut the next `installer-v…` tag (with the other untagged installer changes); close | CC | | **R-955** | Security & access | P4 | **The cross-box check of the hub API is done in source and tests but not fully proven: if a later check masks a missing id check, a box's key could read or change another box's hub record without any test noticing.** Read 2026-10-12: every box-facing `/api/v1` route takes the box from its own key or refuses a different id; 14 routes already had a refusal test, 5 got one (`crossbox_refusal_test.go`). Left: red-prove the 4 new tests that were not red-proved (as the restore-directive one was), and the live read-only check with one demo box's key against the other demo box's id. | OPEN — filed 2026-10-12 by the security review | — | Red-prove the 4 tests; run the live GET check on the two demo boxes | CC | | **R-924** | Security & access | P2 | **The operator signing keys exist only on DooPlex, with no passphrase and in no backup — a loss of DooPlex means no box ever accepts a signed agent update, config bundle or OS step again without an on-site re-enrollment.** MEASURED 2026-10-09: `/mnt/5_hdd/felhom.eu/felhom-op-operational`, `felhom-rec-recovery`, `felhom_op_ed25519` (0600 `kisfenyo`); `ssh-keygen -y -P ''` opens all three (no passphrase); `/mnt/5_hdd/felhom.eu` is in no backup set, the off-site job does not carry them. `04` §1 says the operational key is "passphrase-protected" and the recovery key "kept offline" — today neither holds (custody ruling 1 of 2026-09-16 put both on DooPlex for this phase; `04` §3.1). Both keys share one fate, so the cold key cannot do its one job (re-pin after losing the operational key). `runbooks/total-loss-of-dooplex.md` S6. | **NARROWED 2026-10-09 — operator ruling: option A** (print both AND copy them). The three key files and their public halves ride the nightly encrypted DooPlex→ep0 copy (`scripts/dooplex-offsite/`, a missing key refuses the push); the Sunday restore test proves each private key still derives its own public half (never printed). **LEFT:** the operator prints S6a/S6b (`runbooks/break-glass-sheet.md`); the keys still have no passphrase (custody ruling 1 of 2026-09-16 stands until the first sale). | operator: print | Operator: print the two keys; then close | operator | | **R-132** | Security & access | P3 | **`curl -w '%{redirect_url}'` reconstructs the request URL WITH its basic-auth credential** — so a `-u ":$HUB_PW"` call that never put the password in a URL still printed it **Merged 2026-10-05 from R-350 (duplicate):** (1) 2026-08-20 occurrence: POST /configuration/artifacts answers 303; leak lives only in the CC transcript under ~/.claude/projects/ on DooPlex, not in git/evidence (checked then). (2) `-v` and `--libcurl` also re-render the credential, not only %{redirect_url}; confirm redirects with %{http_code} + follow-up GET. (3) Rotation path: hub /configuration form (current_password/new_password/confirm_password); DB override wins over ConfigMap (break-glass); CC can rotate file-to-file without printing (operator-present-one-time-secrets) if asked. | **WAITING-ON-OPERATOR** — **ACTION: rotate `HUB_PW`** **Folded R-580 2026-10-03** (the same `curl -w %{redirect_url}` credential echo, seen again 2026-09-18). **Note 2026-10-12 (security review):** `manifests/hub.yaml` also carries the hub login's bcrypt hash in this public repository (the break-glass field); when `HUB_PW` is rotated, decide whether that field should stay empty. | — | Happened on 2026-07-31 while red-proofing the R-120 gate: the hub operator password was written to the session transcript by the write-out format, not by the request. `-u` is safe; the *reporting* was not. Rule: read the redirect from `-D -` and grep `^Location:`, never `%{redirect_url}`, on any authenticated call. Rotate the hub password (`/configuration` → Login password; ConfigMap `auth.password_hash` is the reset path) and update `~/.config/credentials` | Viktor | @@ -234,6 +231,7 @@ stopping line that lies. | **R-1054** | Security & access | P3 | **The hub's operator/global API key is still one bearer that can do everything on `/api/v1`, including reading every box's break-glass root password (`GET /admin/hosts/{id}/recovery-credential`).** Hub v0.152.0 gave the web surface scoped tokens (`05` §17) but tokens are refused on `/api/v1` by design. Who uses the global key today is not listed in one place. Fix: list its consumers; move each operator use to a scoped token on the web side (or a token class on the API), and keep the global key only where a box path needs it — or retire it. | OPEN — filed 2026-10-15 by the token build | — | List the global key's consumers (pod env, scripts, runbooks) | CC | | **R-1118** | Security & access | P3 | **CC's secrets moved off the plain `~/.config/credentials` into an encrypted store with a broker and guards; what is left is retiring the old file.** BUILT 2026-10-17 (store B, operator ruling 11:28): private repo `admin/cc-secrets` (`ARCHITECTURE.md`, the design verbatim in `docs/`), `sec` (no get), PreToolUse refusals + PostToolUse masking for Bash and Read in `~/.claude/settings.json` (every CC session on DooPlex), nightly transcript sweep with mail. 55 tests, 18 red-proofs, 36-row child-session proof in both launch modes, fresh-session proof (`audits/cc-creds-build-2026-10-17/`). 25 names in the store (23 imported, `RESEND_API` from CC's environment, a self-test value). `12-agent-tooling.md` §5 points at it. | NARROWED — built; the old file's retirement is R-1134 | the week with no reader (R-1134) | `sec doctor` stays all OK; R-1134 | CC | | **R-1121** | Security & access | P3 | **`~/rotated-secrets-2026-10-09.txt` still exists on DooPlex** — 632 bytes, modified 2026-10-09 13:08 +0200, mode 600 (SPIKE Q6: `test -e` + `stat` only, not opened). Left by the R-925 rotation work. If any value in it is still valid, it is one more plaintext secrets file in the home folder, readable by every CC session. | WAITING-ON-OPERATOR | what the file holds — only the operator knows | Operator: confirm every value in it is revoked, then `shred -u` it; or move the live ones into the R-1118 store | operator | +| **R-1145** | Security & access | P3 | **The installer's step 4b sets the new console root password (chpasswd) BEFORE it vaults it at the hub; if the vault then fails, root@pam holds a password nobody has.** The console is the last door into a broken box. Found 2026-10-18 while building `--rotate-recovery-only` (R-1141), which now asks the hub's `/healthz` first — that narrows it, it does not make the vault-then-set order. The full install path keeps the old order. | OPEN — filed 2026-10-18 | — | Vault first (or stage), set the password only after the hub answers 2xx, and keep the old one on any failure; harness case with a failing vault | CC | ## Box system & updates — 12 rows (P2 1, P3 7, P4 4) @@ -344,7 +342,7 @@ stopping line that lies. | **R-1135** | Process & tooling | P4 | **CI's failure mail links the run at the in-cluster Gitea address** (`http://gitea.gitea-system.svc.cluster.local:3000/...`), which a reader outside the cluster cannot open. Seen in the forced test mail 2026-10-17 (job 1997). | OPEN — filed 2026-10-17 | — | Use the public Gitea URL in the alarm step's link | CC | | **R-1136** | Process & tooling | P4 | **felhom.eu CI runs take ~6.9 minutes and complete, so the 5-minute job timeout R-265 assumes does not hold there** (runs 1996, 1997; `script-tests` alone ~356 s). Found by the R-1129 proof helper 2026-10-17. | OPEN — filed 2026-10-17 | — | Measure the runner's real timeout; correct R-265's assumption or speed up `script-tests` | CC | | **R-1137** | Process & tooling | P4 | **A CI rerun may overwrite a failed job's log** — failure mails arrived for controller commits `c02c9d83` and `29a3ce8c` while their jobs (1944, 1959) now read green. UNPROVEN (a reading, 2026-10-17). | OPEN — filed 2026-10-17 | — | Confirm with one deliberate red + rerun on a scratch repo; if true, the CI check must read the first attempt | CC | -| **R-1143** | Process & tooling | P4 | **The controller `build.sh` pushes `:latest` with EVERY build, release candidates included**, and the legacy `controller/docker-compose.yml` follows `:latest`. Nothing current pulls it (the update button takes the highest x.y.z tag), but a legacy-shaped box would take an rc. Seen 2026-10-17 (rc.1–rc.5 each moved `:latest`). | OPEN — filed 2026-10-17 | — | Push `:latest` only for a release tag, or not at all; pin it in `test_build_push_once.sh` | CC | +| **R-1146** | Process & tooling | P4 | **`scripts/hostinstall-mode-harness.sh` is red on `main` and no gate runs it.** 2 of 47 fail on the unchanged default path: shellcheck SC2066 at the `for f in "$d/pve-enterprise.list"` loop, and GL8-F6 (cause not read). `repo_gates.py` runs only `hostinstall_gates.py`, so nobody sees it. Found 2026-10-18 (R-1141 work). | OPEN — filed 2026-10-18 | — | Fix the two (the loop is on the default path: ship it with the next installer tag), then register the harness in `repo_gates.py` with a decoy | CC |