/ in the Result-recording section, and add a pointer dir/README for 1.28.0 to its audit record (evidence-backup-promise-2026-09-16/phaseD-iso-gate.txt). Optional existence check left out. — felhom.eu/documentation/runbooks/iso-release-gate.md:319-322 'Result recording' says only 'in the release report' — names no home. documenta | 4 |
| R-591 | P4 | STILL-TRUE-SMALL | FIX: Deep-copy Meta.I18n in deepCopyStack (map plus nested values). — The copy is deepCopyStack in controller/internal/stacks/manager.go (row says Copy()); it deep-copies AppConfig (:1137-1148), DeployFields (:1162), OptionalConfig (:1174), Integrations (:1186) and has no I18n line (grep I18n in manager.go: none). Meta.I18n defined at internal/stacks/metadata.go:94. | 4 |
| R-594 | P4 | STILL-TRUE-SMALL | FIX: Add ALLOWLIST_EN of (app, path, reason); registered occurrences pass, unregistered convict, and any entry matching nothing is itself a failure. — app-catalog-felhom.eu/scripts/check-copy-i18n.py: grep ALLOWLIST/allowlist — no hit; no way to register a true occurrence. | 3 |
| R-599 | P4 | STILL-TRUE-SMALL | FIX: Make both 409 bodies say when the last report arrived and when deletion opens (last report + configured stale threshold), and name the wait in target-selection.md's drill section. — felhom.eu/hub/internal/web/hosts.go:898 'http.Error(w, "Host is ONLINE — deletion is refused (a live agent would receive 401s permanently).", http.StatusConflict)' — no last-report age or opening time. target-sele | 4 |
| R-602 | P4 | FIXED-BY-LATER-WORK | felhom.eu e02bc038 'hub v0.119.0 — ... R-596/R-598 closed' added the finding; felhom.eu/documentation/architecture/10-localisation.md:809-812 'the `felhom_lang` cookie and got the **Hungarian** page for `en`. ... The cookie is the right instrument for the anonymous claim page and the **wrong**' and :509 '`langFor`'s order is fixed: `?lang=` → **the household's setting when a session exists**'. Onl | 4 |
| R-603 | P4 | STILL-TRUE-SMALL | FIX: Add a test helper that compares against html.EscapeString(want) and use it in the render tests that assert English copy; the bundle gate with a 27-entry allowlist is the larger alternative. — No gate or helper: grep for html.EscapeString(want/'/R-603 in felhom-controller/controller scripts+internal: none. controller/internal/i18n/locales/en.json has 27 lines containing an apostrophe today | 4 |
| R-605 | P4 | STILL-TRUE-SMALL | FIX: Give harness-level refusal its own exit code (e.g. 3 = REFUSED) in both scripts and map it to a distinct label in catalog_gates.py. — app-catalog-felhom.eu/scripts/catalog_gates.py:122 'VERDICT = {0: "OK", 1: "FAILED", 2: "INCONCLUSIVE"}' — harness refusal and per-app undetermined both exit 2 and print the same word. | 3 |
| R-610 | P4 | NOT-WORTH-IT | PICK close-as-accepted: A power cut landing inside the sub-second `starting` phase has never been measured; all three live cuts landed in `verifying`, which runs the same recovery code. | 5 |
| R-617 | P4 | FIXED-BY-LATER-WORK | felhom.eu@462ab4a5 (2026-09-22) documentation/architecture/09-update-architecture.md:1969 "`POST /api/v1/repos/migrate` is the route that works (the project's Gitea tokens carry" - continues at :1970 "`write:repository` but not `write:user`, so `POST /user/repos` answers 403"; recipe at :1979. The one-line note the row asked for exists (in the architecture doc rather than operations/). The optiona | 4 |
| R-618 | P4 | STILL-TRUE-NOT-SMALL | Remaining open work = the controller-side idea (let `verifying` accept docker's own `healthy`). grep for docker health status in felhom-controller@7690c27 controller/internal/stacks/update.go returns nothing; no R-618 reference in Go source. It is an undecided design question (operator), not a defect; the three probe fixes (app-catalog@793c4fb) and the gate scripts/check-probe-matches-compose.py a | 4 |
| R-619 | P4 | STILL-TRUE-SMALL | FIX: In getDeployFields, copy meta.DeployFields and set Required=true for every field with Type=="password" before writing the response (copy, do not mutate the shared metadata; the web deploy page uses GetDeployFields separately and is untouched). — felhom-controller@7690c27 controller/internal/api/router.go:395 `meta, appCfg, err := r.stackMgr.GetDeployFields(name)` then :402 `"metadata": meta | 6 |
| R-621 | P4 | STILL-TRUE-NOT-SMALL | Capture is done: felhom-controller@7690c27 controller/internal/stacks/update.go:1054 `outDir := filepath.Join(dir, "hold-logs", ts)`. The open part (show it on the app page's hold panel / logs fallback) is not built: grep for hold-logs/holdLogs in controller templates and handlers returns only update.go:1050-1082 and undo.go:535,550 (writers). Surfacing needs a page change with HU/EN copy and a de | 4 |
| R-624 | P4 | STILL-TRUE-NOT-SMALL | Row's own latest update: remaining class is vaultwarden (closed sign-up by design) and code-server; the open decision is whether the harness may hold an app's admin secret (operator). Not verifiable further from source; needs a decision, not a fix. | 2 |
| R-644 | P4 | UNCHECKED | About the live state of gokapi on scratch guest 9202 (crash-loop, deployed:true). Only the box shows it; no ssh allowed. | 1 |
| R-652 | P4 | STILL-TRUE-NOT-SMALL | app-catalog@917a779 templates/romm/.felhom.yml:249 still carries `"memory_peak_pct": 80.9` with `"memory_tight": true` and no `memory_basis: anon` (contrast paperless-ngx/.felhom.yml:249 `"memory_basis": "anon"`). Needs a live re-measure of romm plus an undecided cache-thrash rule. | 4 |
| R-654 | P4 | NOT-WORTH-IT | PICK close-as-accepted: opengist 1.15 moved its pages under /-/; an old /login bookmark answers 404. The front page redirects correctly. | 3 |
| R-687 | P4 | NOT-WORTH-IT | PICK close-as-accepted: Three live proofs a scratch box cannot give (a 3-hour leg, a failing off-site leg, a files_may_change step without a whole copy) plus one log text that names the window's deadline instead of a manually started leg's deadline. | 5 |
| R-688 | P4 | NOT-WORTH-IT | PICK close-as-accepted: Deleting a customer does not remove their Cloudflare tunnel and DNS records; the dialog now says so and lists what to remove by hand. | 4 |
| R-691 | P4 | STILL-TRUE-NOT-SMALL | Open work = the Tier 2 (second-drive) path of Use/Load is not live-proven; needs a two-drive Tier-0 box (9202 has one drive). Live-only gap, not a source defect; not checkable from source. | 2 |
| R-693 | P4 | STILL-TRUE-NOT-SMALL | grep for memory_scales_with_limit / scales_with_limit across app-catalog-felhom.eu, felhom-controller/controller and felhom.eu/scripts returns nothing - no basis that tells growth-to-fill from pressure exists. Needs a design (new harness signal). | 3 |
| R-705 | P4 | FIXED-BY-LATER-WORK | The remaining half (manual whole-guest backup) EXISTS and predates the row: felhom-controller bbed5af (v0.47.0, 2026-06-12) 'backups page — whole-guest backup visibility + manual trigger'. Live source @7690c27: controller/internal/web/backup_handlers.go:324 `case r.URL.Path == "/api/guest-backup/trigger" && r.Method == http.MethodPost:`; :340 `if err := s.backupTrigger.TriggerNow(); err != nil {`; | 8 |
| R-707 | P4 | STILL-TRUE-NOT-SMALL | Open work = live proof that the gate OPENS for seerr, outline and rallly (needs a media server / e-mail on a test box). Live-only proof gap; the gating itself is in source (catalog 6faf432 per row). | 2 |
| R-718 | P4 | STILL-TRUE-SMALL | FIX: Add a key app_info.close_signup_restart ("The app restarts once for this." / HU twin) and render it under the close card when the app has an after_setup env switch (the same SignupNative fact); add the same sentence to the gate-open confirmation where after_setup.env exists. — felhom-controller@7690c27 controller/internal/web/templates/app_info.html:112 `{{T "app_info.close_signup_text"}}< | 6 |
| R-719 | P4 | STILL-TRUE-NOT-SMALL | Built: felhom.eu hub/internal/web/selfbind.go:160 "// R-719 (v0.126.0): „Új linket kérek" on an expired or used link." Open part is the operator's review of the changed shape and a live mint+send proof (unit-proven only) - an operator decision, not a CC fix. | 3 |
| R-725 | P4 | STILL-TRUE-SMALL | FIX: Reword bind.invalid.body to point at the button below (e.g. 'Ha lejárt, kérj újat lent.' / 'If it has expired, ask for a new one below.'), keeping the operator alternative; optionally drop the ✔ glyph the console font renders as 'V' and update the golden. — felhom.eu hub/internal/i18n/locales/hu.json:79 `"bind.invalid.body": "A hivatkozás 7 napig érvényes. Ha lejárt, kérj újat az ügyfélszolgá | 6 |
| R-731 | P4 | STILL-TRUE-NOT-SMALL | The shape-switch control lives only in audit tools: felhom.eu/documentation/audits/catalog-currency-2026-09-30/00-currency.py, 04-analyse.py; no standing currency script in app-catalog-felhom.eu/scripts or felhom.eu/scripts (ls/grep for currency/shape returns only golden_currency_gate.py, which is unrelated). Making it standing means promoting a registry-reading tool with tests - more than an hour | 4 |
| R-734 | P4 | STILL-TRUE-NOT-SMALL | grep for '.immich' / hash ignore list in app-catalog-felhom.eu/scripts/*.py and templates/immich/.felhom.yml returns nothing - no exclusion exists. The row says the rule change needs an operator word; calibre-web shows the mark is sometimes right, so the rule needs design. | 3 |
| R-739 | P4 | STILL-TRUE-NOT-SMALL | app-catalog@917a779 templates/wanderer/docker-compose.yml:117 `image: getmeili/meilisearch:v1.36.0`; grep MEILI_UPGRADE_DB in the compose returns nothing. Remaining: the template switch, a fixture (PocketBase create refused) and a measured step on the bench - live work. | 3 |
| R-759 | P4 | STILL-TRUE-NOT-SMALL | Five checklist rows of wger need live measurement on 9202 (2.5, 3.7, 6.3, 8.2, 9.1); not verifiable from source. | 2 |
| R-760 | P4 | STILL-TRUE-SMALL | FIX: Read the vikunja 2.6.0 image config for a HEALTHCHECK/shell; if none and the image has no shell, add a comment saying why there is no compose healthcheck (like adventurelog-frontend's R-655 comment); otherwise add a healthcheck of the family the image supports (REUSE.md §2). No image: line moves, so no catalog_since. — app-catalog@917a779 templates/vikunja/docker-compose.yml: service vikunja | 4 |
| R-761 | P4 | STILL-TRUE-SMALL | FIX: Change the comment to name `{slug}-logo.svg` (preferred) and `{slug}-logo.png` (fallback), matching config.go AppLogoURL/AppLogoPNGURL; comment-only. — app-catalog@917a779 templates/paperless-ngx/.felhom.yml:22 `# Logo: {assets.base_url}/assets/{slug}-logo.webp` vs felhom-controller controller/internal/config/config.go:511 `return fmt.Sprintf("/static/assets/%s-logo.svg", slug)` and | 3 |
| R-764 | P4 | STILL-TRUE-NOT-SMALL | grep smtp/mail in app-catalog templates/wger/.felhom.yml and docker-compose.yml finds only first_steps text (.felhom.yml:74 'Add meg az email címedet a beállításokban'); no smtp_mapping. A mapping needs a live boot proof with mail off (REUSE.md §2) - more than an hour; wger is hidden. | 3 |
| R-766 | P4 | FIXED-BY-LATER-WORK | Hub releases after the assets push (felhom.eu 40f07429, 2026-10-01): hub v0.131.0 (2026-10-04) .. v0.136.0 (d4be9f6f, 2026-10-05). The build copies website assets: felhom.eu scripts/build-hub.sh:98 `cp "${WEBSITE_ASSETS_DIR}"/*-logo.svg "${BUILD_DIR}/assets/" 2>/dev/null // true`, and the hub build workspace /mnt/5_hdd/felhom.eu/build/felhom-hub/workspace/assets/ holds radicale-logo.svg + 3 screen | 8 |
| R-768 | P4 | NOT-WORTH-IT | PICK close-as-accepted: Grimoire is not built because upstream rules out public exposure and ships no image for v1.x; the row only watches for that to change. | 1 |
| R-769 | P4 | STILL-TRUE-NOT-SMALL | New-app idea waiting on an operator decision (a fork as new upstream, after R-767). No source to check. | 1 |
| R-770 | P4 | STILL-TRUE-NOT-SMALL | New-app idea waiting on the operator's go/no-go (CC recommends not building). No source to check. | 1 |
| R-771 | P4 | STILL-TRUE-NOT-SMALL | New-app idea waiting on the operator's go/no-go. No source to check. | 1 |
| R-779 | P4 | STILL-TRUE-NOT-SMALL | Live proof gap on the real Cloudflare tunnel needing the operator's phone off wifi; not checkable from source. | 1 |
| R-781 | P4 | STILL-TRUE-SMALL | FIX: After the clone, delete the real onboarding/.md records (all but _TEMPLATE.md and the exempt wger.md the cases use) from the scratch clone, so genuine cases judge only the records they build; alternative: point the stand-in sibling at the real felhom.eu documentation tree read-only. — app-catalog@917a779 scripts/test_gate_decoys.py:498 `sh(["git", "clone", "-q", "file://" + ROOT, cat], c | 6 |
| R-786 | P4 | STILL-TRUE-NOT-SMALL | app-catalog@917a779 onboarding/sparkyfitness.md has 8 '/ open' rows, incl. :18 0.5, :20 0.7, :28 1.6, :29 1.7, :58 5.4, :68 8.3 (plus 0.1 licence = R-784, 2.1 = R-807). Most need live measurement (runtime internet, phone sign-in, second memory watch). | 3 |
| R-793 | P4 | NOT-WORTH-IT | PICK close-as-accepted: Four apps ship enterprise/BUSL code that is off as Felhom runs them; the row reminds us never to enable EE features or the -enterprise meilisearch image. | 2 |
| R-794 | P4 | STILL-TRUE-NOT-SMALL | app-catalog@917a779 seven redis 7 images: dawarich/docker-compose.yml:164 `image: redis:7.4-alpine`, docmost:86, immich:123, outline:88, nextcloud:103, paperless-ngx:125, romm:136 `image: redis:7-alpine`. Moving each needs a harness-proven ladder step (7 apps). | 3 |
| R-796 | P4 | NOT-WORTH-IT | PICK close-as-accepted: MeTube's browser/phone 'send to MeTube' helpers cannot pass the family gate; households paste links in the page. | 2 |
| R-797 | P4 | NOT-WORTH-IT | PICK close-as-accepted: CI's single-repo clone cannot check rule 3 of the family-gate gate; it says NOT CHECKED, and the pre-push hook checks it. | 2 |
| R-798 | P4 | STILL-TRUE-SMALL | FIX: Remove the dead SWAGGER_ENABLED line (or rename to API_DOCS_ENABLED=false, which v3.5.0 reads and defaults to false). No image: line moves. — app-catalog@917a779 templates/grimmory/docker-compose.yml:29 ` - SWAGGER_ENABLED=false` still present. | 2 |
| R-799 | P4 | STILL-TRUE-SMALL | FIX: Add "download_type": "video" to the POST /add body. — app-catalog@917a779 scripts/upgrade_fixtures_box.py:2183 `data=json.dumps({"url": self.URL, "quality": "best", "format": "any", "auto_start": True}), method="POST")` - no download_type. | 2 |
| R-804 | P4 | NOT-WORTH-IT | PICK close-as-accepted: plant-it's image repository does not exist; the template is already abandoned and not installable, and no box runs it. | 2 |
| R-805 | P4 | STILL-TRUE-NOT-SMALL | app-catalog-felhom.eu scripts/check-volume-persistence.py:342 'if m["class"] == "named-declared" and m.get("files", 0) == 0:' — only named volumes judged empty; binds not. Last change 917a779 (R-788). The rule change itself is small, but it flips Grimmory/komga/paperless-ngx/radarr/sonarr to UNDETERMINED and needs a live re-sweep to regenerate the verdict tables; the row also asks for a decision. | 6 |
| R-806 | P4 | STILL-TRUE-SMALL | FIX: Make routed_ports return the traefik loadbalancer.server.scheme (reuse upgrade_boxport LB_SCHEME_RE) and have the GET exercise use that scheme with curl -k for https. The gramps-web :5000 non-answer stays a separate live look (narrow the row to it). — app-catalog-felhom.eu scripts/check-volume-persistence.py:586 'code = _sh(a + [f"http://{ip}:{port}{path}"], timeout=40)' — plain http always; | 6 |
| R-807 | P4 | STILL-TRUE-NOT-SMALL | Per-app upload seeds for 13 apps (claper, crafty-controller, dawarich, docmost, gramps-web, immich, outline, sparkyfitness, tandoor, vikunja, wger, wishlist, zipline) + plex/wanderer; each needs a live fixture run. Gate rule at scripts/check-volume-persistence.py:342 still makes empty declared volumes UNDETERMINED (917a779). | 3 |
| R-814 | P4 | UNCHECKED | Live Hetzner console state (box 611421 status); not visible in source. Operator action only. | 2 |
| R-815 | P4 | UNCHECKED | First GC completion on felhom-offsite is PBS server-side live state; grep of documentation found no GC completion record (DIAG-backup-missed-2026-07-26.md:43 'prune/GC history NOT COLLECTED'). | 3 |
| R-816 | P4 | STILL-TRUE-NOT-SMALL | Needs a live exercise of six failure classes on a scratch guest; no source change can close it. | 2 |
| R-817 | P4 | STILL-TRUE-SMALL | FIX: Add a dated correction under decision 56: the swap rolls back to the image running when the swap began (controllerswap.go Swap/rollback); the kept previous image is for a hand roll-back. Do not rewrite the ruling itself. — felhom.eu documentation/architecture/09-update-architecture.md:619 '56. **A box keeps the controller image it runs and the one before it** (the self-update's roll-back targ | 8 |
| R-818 | P4 | STILL-TRUE-SMALL | FIX: Add a dated correction note under the v0.109.0 entry (and the hub CHANGELOG mentions at :695/:701) naming the real closed rows from CLOSED-ITEMS.md. Also present in felhom-controller/CHANGELOG.md:3107 and :3234 (R-330/R-331 for v0.224.0/v0.225.0) — a second repo; either note it there too or narrow the row. — felhom.eu hub/CHANGELOG.md:759 '## v0.109.0 — the Backup card told every operator tha | 6 |
| R-819 | P4 | STILL-TRUE-SMALL | FIX: Let rule 3 accept an id found in CLOSED-ITEMS.md (and check the stand's status agrees), fix the R-273/R-356 dangling ids, register the gate in repo_gates.py with a decoy. — Ran python3 scripts/check_stands.py (read-only): still convicts e.g. 'fail.stolen-machine: register id R-281 is not in OPEN-ITEMS.md', 'fail.customer-self-restore: register id R-356 ...'. grep 'stands' in scripts/repo_gate | 6 |
| R-832 | P4 | STILL-TRUE-NOT-SMALL | Deferred roadmap item: a third-location copy of ep0 is money + operator decision (decision 71). Nothing in source to change. | 1 |
| R-844 | P4 | STILL-TRUE-NOT-SMALL | Needs a household timeline on the controller, which does not exist (row: 'when the box gets a household timeline'). A new surface, not a fix. | 2 |
| R-855 | P4 | STILL-TRUE-SMALL | FIX: Add a small helper (e.g. osSvc.DockerNightsEffective()) mapping negative→0 and 0→2, and print that in the start log. — felhom.eu hub/cmd/hub/main.go:450 'logger.Printf("[INFO] osupdates: the Docker engine set is approved only by the operator, after %d healthy ring-0 night(s)", osSvc.DockerNights)' prints the raw value; internal/osupdates/service.go:169 'negative means none'. | 4 |
| R-856 | P4 | STILL-TRUE-NOT-SMALL | Row is marked an operator design question (crash-restart suppression for app mails); not a defect yet. | 1 |
| R-857 | P4 | STILL-TRUE-SMALL | FIX: Have newest_baked accept an optional suffix after the date and, for equal versions, prefer the newest bake-log timestamp (or refuse two dirs for one version); add 're-vouch at once after a same-version re-bake' to the runbook. — felhom.eu scripts/golden_currency_gate.py:146 'EVIDENCE_RE = re.compile(r"^golden-(\d+)\.(\d+)\.(\d+)-\d{4}-\d{2}-\d{2}$")' and :237-238 'found.sort() / return found[ | 7 |
| R-878 | P4 | STILL-TRUE-NOT-SMALL | Next action is 'measure a large volume first' — a live measurement; the fix direction is a behaviour change to the catch-up. | 2 |
| R-881 | P4 | STILL-TRUE-SMALL | FIX: Add an rm -f of /usr/local/sbin/felhom-priv-apply to the uninstall step (tolerate-absent, like felhom-pbs-apply at :1161) and fix the :1679 comment; ships at the next installer tag. — felhom.eu scripts/felhom-host-install.sh: grep 'felhom-priv-apply' → no hit anywhere in the installer (uninstall does not remove it); :1679 '+ guest-hook snippet under /var/lib/vz/snippets/ (agent-installed at r | 4 |
| R-884 | P4 | UNCHECKED | Live ArgoCD diff on DooPlex (forbidden to touch here). Related: homelab-manifests mon-system/monitoring.yaml:399-426 is the same prometheus Deployment R-211 concerns. | 2 |
| R-885 | P4 | STILL-TRUE-SMALL | FIX: Finish and push the in-progress script_tests_gate.py (walks scripts/ for test_*.py, exit-code verdict, nesting guard) registered in repo_gates.py; coordinate with the session that owns the dirty tree. — On main (b018ca90) scripts/repo_gates.py runs no test_*.py suite. NOTE: the felhom.eu working tree holds UNCOMMITTED work for exactly this row by another session: '?? scripts/script_tests_gate | 6 |
| R-30 | P3 | STILL-TRUE-NOT-SMALL | Design change (presence from the Dir-2 long-poll instead of the report clock), size M; no commit with R-30 after aa9c08f0 (filing). | 3 |
| R-31 | P3 | STILL-TRUE-NOT-SMALL | felhom.eu hub/internal/web/configs.go:1594 'd, err := s.offsite.ProvisionOffsite(ctx, cfg.CustomerID, in)' still in-request; :1584 detaches from the request context (mid-cancel fixed) but no async/status card. | 5 |
| R-35 | P3 | STILL-TRUE-NOT-SMALL | felhom-controller controller/internal/report/config_refresh.go:65 'config-refresh: applied config_version=%d — self-restarting to load it'; sessions are in-memory only: controller/internal/web/auth.go:259-260 's.sessions[token] = &session{'. Hot-apply or persisted sessions is a design change with security weight. | 6 |
| R-49 | P3 | STILL-TRUE-NOT-SMALL | app-catalog-felhom.eu templates/immich/.felhom.yml:28-34 backup block has no cache/volume exclusion; row itself says a capture-set exclusion needs its own ruling (data-loss-shaped). | 4 |
| R-50b | P3 | FIXED-BY-LATER-WORK | Claim 'fetched via fetch_raw from raw/branch/main — no tag, no pin' no longer true: bee68484 (installer v1.23.0, R-110/R-183) pinned fetch_raw to the vouched agent tag — felhom.eu scripts/felhom-host-install.sh:533 '"$GITEA_BASE/$GITEA_OWNER/$AGENT_REPO/raw/tag/v$ART_AGENT_VER/$path" \' (leg b). Leg (c)-like signed delivery: felhom-agent c9fa2e7 (R-840 config bundle) and configs/test_felhom_config | 7 |
| R-78 | P3 | STILL-TRUE-NOT-SMALL | An owed operator decision + spike (local_api authority); not a code defect. | 1 |
| R-79 | P3 | STILL-TRUE-NOT-SMALL | felhom-controller controller/internal/monitor/healthcheck.go:100 'fmt.Sprintf("SSD disk usage critical: %.0f%%"', :213 'Protected container not running: %s'; rendered raw at controller/internal/web/alerts.go:241 'Message: issue, // ON THE WIRE ... not ours to translate; slice 3'. Whole-surface, seam needs a spike. | 5 |
| R-118 | P3 | STILL-TRUE-SMALL | FIX: Only statfs the mount when s.devicePresent(d.MountPath) is true (else leave capacity zero/unknown); put statfsCapacity behind a seam var for the test. — felhom-agent internal/localapi/disks.go:401 'if total, used, okc := statfsCapacity(d.MountPath); okc {' — no device-presence guard on the union path; devicePresent exists (disks.go:985) and is used just above (:381) for BoundUnderParent. | 6 |
| R-121 | P3 | FIXED-BY-LATER-WORK | 3d7a2761 (hub v0.135.0, R-530/R-604 'boxes left behind listed and alarmed'): felhom.eu hub/internal/osupdates/service.go:79 'EventAgentBehind = "agent_behind" // warning, operator' with :180 'AgentBehindAfter: a box runs an agent older than the vouched one this long → an operator alarm' (7 d window, the staleness window the row asked for). | 5 |
| R-126 | P3 | STILL-TRUE-SMALL | FIX: Skip IsNetwork() paths in the export-destination list and refuse them in isValidDrivePath for the export POST (keep scanning for import if wanted, via a separate list). — felhom-controller controller/internal/web/handler_export.go:377-386 storageDriveList() appends every s.settings.GetStoragePaths() entry with no IsNetwork() filter; the predicate exists at controller/internal/settings/setting | 6 |
| R-127 | P3 | STILL-TRUE-NOT-SMALL | Leg (a) still true: grep 'data_key: true' in app-catalog-felhom.eu templates → only adventurelog, dawarich, homebox, papra, sparkyfitness; n8n N8N_ENCRYPTION_KEY, wanderer POCKETBASE_ENCRYPTION_KEY, calcom CALENDSO_ENCRYPTION_KEY, bookstack APP_KEY unflagged (templates/n8n/.felhom.yml:38 etc.). Leg (b) (regenerated DB password vs restored PGDATA) needs a design choice. Leg (a) alone is a ~45-min c | 6 |
| R-130 | P3 | STILL-TRUE-SMALL | FIX: Take the cheap honest branch: rename to RECOMMENDED_MIN_LVM_GIB and reword the warning to 'below the recommended …' (making it refuse would change install behaviour and needs a ruling). — felhom.eu scripts/felhom-host-install.sh:348 'HARD_MIN_LVM_GIB=120 # a useful appliance won't fit below this on local-lvm' and :1760 '... // log_warn "local-lvm free ~${free_gib} GiB < hard min ${HARD_MIN_ | 4 |
| R-132 | P3 | UNCHECKED | Whether HUB_PW was rotated is out-of-band operator state; not visible in source. | 1 |
| R-136 | P3 | STILL-TRUE-SMALL | FIX: Introduce a const sessionCookieName = "__Host-hub_session" and use it at all five sites (Path=/, Secure, no Domain already hold). Every operator logs in once more; plain-HTTP browser access stops (Basic auth unaffected). — felhom.eu hub/internal/web/server.go:857 'Name: "hub_session",' and readers at server.go:806, :896, :918 and apps.go:351. | 4 |
| R-137 | P3 | STILL-TRUE-NOT-SMALL | felhom-controller controller/internal/cloudflare/waf.go:18 'globalRuleDesc = "[felhom-geo] Global"', :21 'appRuleDescPrefix = "[felhom-geo] app:"' — still not namespaced. Two-repo M change. | 3 |
| R-138 | P3 | STILL-TRUE-NOT-SMALL | felhom-controller controller/internal/infra/infra.go:157-159 writes CF_DNS_API_TOKEN when d.CFAPIToken != ""; no shared-zone guard in hub (grep shared.zone: none). Needs a policy decision first; no shared zone exists today. | 4 |
| R-179 | P3 | STILL-TRUE-SMALL | FIX: In uninstall step 4c, before the umount loop: stop+disable every mnt-felhom\x2ddrives-*.automount/.mount unit, rm their files from /etc/systemd/system, daemon-reload (tolerate-absent; still never umount -l/-f). — felhom.eu scripts/felhom-host-install.sh uninstall section :1121-1157 handles felhom-shared-parent and umounts under /mnt/felhom-drives, but grep 'x2ddrives/automount' → no hit: the | 6 |
| R-180 | P3 | STILL-TRUE-SMALL | FIX: In the same pre-flight block, die (byo) / die (appliance) if ARCHIVE_STORAGE is not in PVE_STORAGES, with a message naming --acl-storages. — felhom.eu scripts/felhom-host-install.sh:1800 'if pvesm status --storage "$ARCHIVE_STORAGE" ...' checks existence only; PVE_STORAGES=(local local-lvm felhom-pbs) at :322; no ARCHIVE_STORAGE ∈ PVE_STORAGES assertion. | 5 |
| R-190 | P3 | NOT-WORTH-IT | PICK close-as-accepted: A storage permission vanished once on demo-felhom in August and nobody knows why. Since agent 0.124.1 the agent puts it back by itself and mails the operator when it happens. | 4 |
| R-200 | P3 | FIXED-BY-LATER-WORK | The remaining half (customer-facing recovery-code form: yell → R form → preview) shipped as the recovery screen: felhom-controller 636c51e 'R-193: the recovery screen — unlocking, and only unlocking (v0.200.0)'; controller/internal/web/templates/recovery.html:82 '