- scripts/image_runtime.py: Node / Python Brotli / brotlicffi / apk / dpkg read from an image's registry config and
layers (no pull; HEAD for the nightly digest; zstd via the zstd program where present; quay.io, index.docker.io).
- security_watch.py: a „runtime" source (security_watch_runtimes.json), cached by digest in state.json (154 images,
filled on DooPlex tonight); ghcr.io tag lists are paged; the DooPlex group (own block, homelab next-step).
- dooplex_inventory.py + documentation/security-watch/dooplex-workloads.txt (89 images, homelab-manifests 5aeec8d).
- Tests W10–W12 (58 checks) + test_image_runtime.py (13), each red-proved.
- audits/http2shell-2026-10-27: the Home Assistant lane walk (proven), HOMELAB-LIST.md (19 to update), the run log.
- 08 §11 design line; 09 §3 decision 276 (HA monthly = same main version; decided by CC unattended).
- 08 §10: built (controller 5bd03ad, hub 7e57e824, commit only); putback_pending as on the wire; as-built notes
- audits/d53-held-apps-2026-10-26: live proof on 9202 against a test hub (3-min grace), red-proofs, teardown
- R-1291 BUILT (not released); R-1298 filed (9202's orphan holds + PrivateBin leftover)
- test_gate_decoys.py: the register-shape cases also run the script and assert its exit code — R-1297's decoy 2
showed an inert main() passed every case (9 cases red with it now)
- audits/r1297-ci-trim-2026-10-26: runners, times, decoys
- script_tests_gate.py: test_gate_decoys / test_due_checks_gate / dooplex-offsite run on a CI branch push only
when one of their paths changed (FELHOM_CHANGED_FILES); no list, an empty or unreadable list = every suite
- gates.yml: nightly schedule 03:20 UTC; the list is set only for push:refs/heads/*; a trimmed commits array
(total_commits > listed) is an unknown list
- test_repo_gates.py and test_due_checks_gate.py group G drive the real runner with GATES narrowed to their
labels, instead of the whole gate set a second time (130 s each in CI)
- red-proved: filter cases, workflow pins (old gates.yml), inert run_gate, unregistered due-checks
On 2026-10-19 09:24 the public path to Gitea failed once and the sidecar exited (max-failures defaults to 0).
Anonymous in-cluster fetch proven first (main and installer-v1.34.0 resolve to the public hashes).
The alarm step built its link from GITHUB_SERVER_URL, which on this runner
is the in-cluster Gitea address, and from the run NUMBER, which Gitea 1.26
reads as a run id first (felhom.eu /actions/runs/1116 opened run id 1116 =
run number 613). Now https://gitea.dooplex.hu + GITHUB_RUN_ID, and the link
is printed into the job log as ALARM-LINK. Same change in all four repos.
Rebuilt sizing-data.json; data cache-bust v5; SIZING.md table and the pinned test cases moved
with it. Before/after: audits/day-2026-10-18/P6-before-after.md.
Live on demo-hp (--rotate-recovery-only): vault time moved, new value 200, old 401. Harness 52/0;
the R1145 cases fail against HEAD. Publishes only with the next installer tag.
Hub: the R-120 golden guard judges only a CHANGED golden selection; offsite_snapshots_vanished /
_unexplained (operator-only, hub-origin) on the 07:10 listing; internal/accesslog writes path-only
lines to /data/access-log, 90 days. Installer: --rotate-recovery-only runs step 4b alone (rides
the next installer tag). 03: the orphan check runs after a failed backup (agent 6545ccc). 02: the
allow-list is empty, appdata_folders (controller v0.329.0). All red-proofed.
- hub: `app_definition_refused` in allowedEventTypes + operatorOnlyEvents (controller v0.328.0's catalog
allow-list refusal); SaveHostRecoveryCredential moves set_at on a re-vault (found live: both rotated hosts
kept their first vault's time); the daily key audit also lists the box's restic snapshots/ read-only over the
login the hub already holds and logs count/newest/oldest (no alarm yet).
- installer (main only, rides the next tag): --uninstall removes /usr/local/sbin/felhom-thin-check (agent
v0.159.0's bundle file); test_hostinstall.py knows it.
- runbook whole-guest-backup-orphan-thin.md: the human repair the agent's new orphan finding points to.
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
workflow_dispatch with input force_alarm (default false). A dispatch-only
step prints the RESEND_API_KEY length (never the key) and, when forced,
fails so the alarm step sends its real mail, subject marked FORCED TEST.
Push runs are unchanged: the step is skipped, the subject is the old one.
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
FELHOM_WORKSPACE (set by felhom-controller's runner) names where the sibling repos are; the worktree's own
main clone is skipped. Unset: unchanged. Test red-proved both ways.
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
- documentation/audits/prowlarr-2026-10-15/: bench (update test proven, C3 failed as it must, soak 7.6 %,
volume-persistence CLEAN, official-image check), 9202 runs 1-3 (run 1's bump emptied the drill .felhom.yml — a
test-tool bug, fixed; run 3 re-proved the step and backup -> remove -> restore with the full template), tools.
- website: a Prowlarr card on both apps pages; every stated count 62 -> 63, the media group 19 -> 20; sizing.json +
sizing-data.json carry Prowlarr (41/44 MB, onboarding), the sizing test and SIZING.md table moved to 63 apps.
- OPEN-ITEMS: R-1057 (a restore of a removed gated app returns without the gate, even from a backup made before the
setup — measured on 9202); R-1036 notes the count and that wger/plant-it are hidden/abandoned.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
- 15-media-library.md §10: what the box does on each drive event, per app, with the measured call; the guards
that ARE needed and the ones that are NOT (K1: nothing lost while a drive is gone).
- Evidence K4 (dead-drive check: mountinfo `shutdown`, stat unreliable), K5 (restart), K6 (unclaimed Plex),
K7 (old Sonarr/Radarr repair on the bench), K8 (hub received the drive-return events and mailed none), K9 (files identical).
- nightly-rotation.md runs scripts/https_only_check.py first every night; scripts/CHANGELOG.md entry.
- STATUS, CONTEXT (decisions 244-246), REPORT-night-2026-10-14.md.
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
Fetch, pull --ff-only, then refuse unless clean and HEAD == origin/main; the
commit label is read after the pull. Test with a stub docker: 6 cases; the
old script gets 5 wrong. Evidence for the catalog gate unclean-boot-images.