Commit Graph
258 Commits
Author SHA1 Message Date
admin 844f19f11e fill watch: one warning per filesystem (R-1371) — committed, not released
gates / gates (push) Successful in 31s
On a box whose guest has one data volume the two built-in fill targets, "/"
(the controller's overlay on the Docker data volume) and /mnt/sys_drive, are one
filesystem. The target list was de-duplicated by path only, so one fill would
send two warnings under two names.

fillTargets now keeps one target per filesystem; the first stays (app area,
system area, drives). The identity is system.FilesystemKey, not st_dev alone:
inside the container "/" is an overlay with its own device number, so an
overlay path takes the device of a Docker-kept file on the data-root
(/etc/hostname, /etc/hosts, /etc/resolv.conf). Measured read-only on demo-hp
9201/9202 and the N100 on 2026-11-10.

Tests: TestR1371_* (3), TestFilesystemKey_* (2). Red seen three times.
No version, no image, no floor: it waits for a release session.

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-11-10 14:18:36 +01:00
adminandClaude Opus 5.5 27360d6abe v0.351.0 (unreleased): old -rc controller images and old infra images are deleted (decision 56 amended, decision 285)
gates / gates (push) Successful in 31s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-11-09 10:23:06 +01:00
admin 37644458c7 R-1348: the mail of an interrupted put-back names a restore, not an off-site run (seen on the live proof); changelog: R-1347, R-1348 proven live on 9202. Commit only.
gates / gates (push) Successful in 32s
2026-11-03 01:12:19 +01:00
admin c4b6844d34 Traefik v3.7.17 (GHSA-xv5x-242w-7hf7); R-1347 a restore forgets the update-held flag; R-1348 a failed put-back at start-up mails; R-1339, R-1351, R-1323 truthful start-up lines and one lock over FileBrowser's compose. Commit only.
gates / gates (push) Successful in 29s
2026-11-02 23:14:16 +01:00
admin b69e90bdad D65 = A: the busy file the agent reads before an operator reboot, and the household's 'Felhom support restarted your box' line; R-1350: a hold clear records the wanted stop so no app_start_failed follows it
gates / gates (push) Successful in 32s
2026-10-29 16:24:40 +01:00
admin 99fac06aa7 R-1340 second producer: a restore_mixed hold's Why() names the cause from its record (found live on rc.1: the hub's Held apps line said off-site/database for a local restore with no database) — test red first
gates / gates (push) Successful in 30s
2026-10-29 14:35:07 +01:00
admin 6077ac0083 R-1343 fallback: the box command's own settings.json edit (no controller running) goes through the same clear door, so a waiting put-back is dropped from the marker there too — test red first
gates / gates (push) Successful in 30s
2026-10-29 12:59:41 +01:00
admin 5b3b541602 clear_hold (D64 = B) + the box command through the running controller (R-1343), R-1340, R-1341 — tests red first; commit only
gates / gates (push) Successful in 31s
- clear_hold: a fifth verb in the closed operator-action list; lifts a hold of any reason in the RUNNING
  controller (memory + settings.json together), forgets the update's held flag, drops a waiting put-back
  from the app-stop marker (copy kept). Refused on a bad name or no hold. No new event type.
- --clear-restore-hold asks the running controller over <data dir>/ctl/hold.sock (unix, 0600, peer uid
  checked, no TCP); edits settings.json only when no controller answers, and says so (in-guest restart).
- R-1340: the operator's HELD STOPPED mail is built from the hold record (restore kind, mixed cause,
  failed put-back step, database replay or not, kept copy) — never the option-C database story by default.
- R-1341: the OOM WARN line once per new kill (container, start time, kill count); event unchanged.
2026-10-29 12:49:46 +01:00
admin 652a690e5d R-1342: a restore copy under the stable-start watch is not deletable (D62 gap); an app removed during the watch raises no alarm — tests red first; commit only
gates / gates (push) Successful in 31s
2026-10-29 11:16:13 +01:00
admin e3fce09d96 D62: restore copies kept 30 days, listed with their date, deletable by hand (typed name, never a needed copy, operator event); D63: a test-build-only fault switch for the R-1256 H4/H5 live proofs — tests red first
gates / gates (push) Successful in 33s
2026-10-29 08:50:59 +01:00
admin eed23e7594 R-528: the 30-s OOM scan also reads the host's per-container kernel counter (agent GET /guest/oom-kills)
gates / gates (push) Successful in 32s
A count above 0 in a running container's current run fires the existing app_oom line (source cgroup/docker in the
details), whatever Docker's OOMKilled says. Old agent: 404 back-off; no agent: Docker's flag only.
Tests TestR528_* red first / red-proved. Commit only.
2026-10-28 23:22:46 +01:00
admin 342a394bff R-1256: four restore edges (review round 2 HUNT-1 H4/H5/H6/H8) — each test seen failing first
gates / gates (push) Successful in 31s
H4: a failed definition write in the off-site restore writes the live definition back before the start;
    a failed write-back holds the app (restore_mixed).
H5: a put-back whose stop fails pours nothing, keeps the copy and holds the app (off-site, local, power-cut);
    a failed definition write-back keeps the copy (D20); a failed 'volume rm -f' fails that volume (no merge).
H6: TryBeginRestoreOp/RestoreBusy: check every operation and record the restore in one step under m.mu;
    every web handler and the kept loads begin through it; install-time kept load asks about the mirror too.
H8: SweepUnusedRestoreCopies every 6 h: removes a copy only with no hold, no marker naming it, no restore
    running, and older than 14 days.

Commit only; rides the next controller release.
2026-10-28 22:24:16 +01:00
admin b156e4526a fix(R-1298): held-app reports only for installed apps (a restore hold always)
Red-proved. Commit only.
2026-10-26 20:26:44 +01:00
admin 5bd03ad152 feat(D53): the hub learns which apps are held — app_held / app_hold_cleared, daily repeat
gates / gates (push) Successful in 54s
internal/holdreport: one observer of the hold store, ticked every minute; app_held for a new or changed
hold (stack_name, reason, since, why), app_hold_cleared when gone (also while the controller was down:
settings.reported_holds), every hold again daily and at start. Severity info. RestoreHold.Why/WireReason
(holdWhy calls it). 8 tests, red-proved (inert Tick; unwired scheduler line). Commit only (felhom.eu 08 §10).
2026-10-26 18:23:54 +01:00
admin 838c834169 R-1286: a held app says why it is held — each hold reason gets its own sentence in the start gate, the boot sweep and --restore-holds (an unhealthy stop read as a failed restore). Red-proved. Commit only.
gates / gates (push) Successful in 1m28s
2026-10-25 22:05:23 +01:00
admin b5863a96eb R-1288: a restore of a set-aside unit sets the replaced install's unit aside at once, with no alarm. R-1282: the later media restart time is stored and resumed at start, once. Red-proved. Commit only.
gates / gates (push) Successful in 1m26s
2026-10-25 21:37:55 +01:00
admin a79a292d72 R-1261: the line hold holds every running seeder, drops the record of an app removed while held, and puts back the qBittorrent slot it held (alternative speed). Red-proved. Commit only.
gates / gates (push) Successful in 1m29s
2026-10-25 20:38:28 +01:00
admin 935e624f10 D47 follow-up: a set-aside tells the operator once (backup_run_failures, leg unit-set-aside, both identities, own run id). Red-proved. Commit only.
gates / gates (push) Successful in 1m33s
2026-10-25 17:19:08 +01:00
admin 3a1f09d29f Fix A (found live on 9202): the container sampler reads docker inspect JSON — a -f template stopped at 'no entry for key Health' for every app without a healthcheck, so a healthy restore read 'not started'. Commit only.
gates / gates (push) Successful in 1m27s
2026-10-25 17:02:32 +01:00
admin 1ee0353dbd Fix A: the container sampler keeps Docker's stderr in its error (a live run on 9202 logged only 'exit status 1'). Commit only.
gates / gates (push) Successful in 1m24s
2026-10-25 16:56:04 +01:00
admin 7720439440 D49 = A follow-ups: (A) the undo copy is released only after a stable start — 3 min of running, healthy, no restart, one rule for the first verdict and the late-start watch; a watch ends only for a restore begun after it; (B, R-1279) the .fab import downloads first with the restores' D48 helper, before it removes anything. Red-proved. Commit only.
gates / gates (push) Successful in 1m26s
2026-10-25 12:45:33 +01:00
admin 2d71270858 D48: a restore downloads first — every restore path resolves and pulls every image of the definition that will run before the stop, under the image-work lock held until the restore returns; a failed pull refuses with the app untouched (a deleted version and a busy registry read differently), one operator line. Red-proved. Commit only.
gates / gates (push) Successful in 1m26s
2026-10-25 09:38:28 +01:00
admin b680db85cb R-1270 (P2): a restore whose app does not reach running in time is never a success — every restore path returns ErrRestoreNotStarted, the household reads that the data is back but the app has not started yet, one operator alarm; the data stays, the undo copy is kept, a late start turns the record into a success and releases the copy. Red-proved. Commit only.
gates / gates (push) Successful in 1m32s
2026-10-25 09:33:26 +01:00
admin 02daebe9c5 D47 / R-1269 (P2): a new install never writes into an earlier install's backup — every install has an identity (install_id), the unit records it, every unit writer asks first; another install's unit is set aside whole (backups/set-aside/<app>/<stamp>, a D25 kept copy, „Visszaállítás” + „Eltávolítás” on the restore page); a move that fails refuses the write. Red-proved. Commit only.
gates / gates (push) Successful in 1m33s
2026-10-25 09:27:48 +01:00
admin c9b4b82dc7 R-1253 (P2): an export that stops its app refuses while another operation (a restore) holds the app-stop marker — its Undo is never replaced. Commit only.
gates / gates (push) Successful in 1m28s
2026-10-24 20:29:59 +02:00
admin 518a13592d R-1252 (P2): a rejected or absent backup block never deletes second-drive copies — reconcile only on a valid classification; a rejected block is said on the app's status and once a day to the operator (backup_run_failures); kept copies stay kept (H2); Remove drops the kept records it deleted (H9). Commit only.
gates / gates (push) Successful in 1m18s
2026-10-24 20:07:16 +02:00
admin 062f9b41d9 R-1251: sync the restore copy's folders before the marker names it (a cut left undo.json as .tmp on Tester 1); the interrupted-restore record says the put-back waits, not 'run it again'. Commit only.
gates / gates (push) Successful in 1m24s
2026-10-24 19:36:32 +02:00
admin bb2809dc68 R-1251 (P1): a pending put-back blocks every start — a cut restore's copy on an unbound drive waits (a restore hold), is poured back when the drive binds before any start; a failed put-back holds the app (H2); Stop during a restore still puts back (H7). Commit only, unreleased.
gates / gates (push) Successful in 1m18s
2026-10-24 19:07:02 +02:00
admin 046b808792 upwatch: hold a seeding torrent app for one line test, then put its limit back exactly (R-1250)
gates / gates (push) Successful in 1m22s
When the agent waits for quiet and qBittorrent or Transmission runs: record the limit first,
hold at 1 KiB/s, ask the agent for a test on request, put the old limit back (deferred; a
household change during the test stays). Start-up puts back a limit a killed controller left;
the 50 % rule skips while a hold record exists. Commit only.
2026-10-24 13:19:07 +02:00
admin 42cda07b42 v0.342.0 (unreleased): the watch's start line no longer says the line is learnt only from the off-site push
gates / gates (push) Successful in 1m22s
2026-10-24 09:58:13 +02:00
admin ed1011b088 v0.342.0 (unreleased): the upload watch reads the host's weekly line test (GET /host/line-test, agent >= 0.164.0); qBittorrent's limit = 50 % of the TESTED line only (D41), the watch uses the higher of test and push floor, the system page names the source; red-proved
gates / gates (push) Successful in 1m15s
2026-10-24 08:59:57 +02:00
admin a9c1997fbc v0.342.0 (unreleased): the upload and CPU watch — an app that sends or burns far more than its own numbers explain is one operator-only alarm; the line learnt from the off-site push; qBittorrent's default upload limit (never over the household's)
gates / gates (push) Successful in 1m17s
internal/upwatch: exact per-container counters from the Docker Engine API, per-app judging (upload >= max(5 Mbit/s,
25% of the line) for 15 min; CPU >= max(150%, 50% x cores) for 30 min), explainers qBittorrent / Transmission / Plex,
app_unexplained_upload / app_unexplained_cpu + _cleared (hub 0.169.0). The off-site push is sampled once a second
for the line (a lower bound). qBittorrent limit = 50% of the line, the household's limit always wins. 20 red-proofs.
Spike + design: felhom.eu audits/SPIKE-upload-watch-2026-10-23.md, architecture/08 section 9. Not released.
2026-10-23 21:26:09 +02:00
admin 943c517550 Review fixes for 0.340.0: C5 a catch-up releases the whole-guest backup when its backup legs end (red-proved); C3 the R-1187 c refusal text fits an unhealthy app; C6 two comments; C8 README backup.volumes wording; unreleased
gates / gates (push) Successful in 1m40s
2026-10-22 21:25:48 +02:00
admin 66a69d4954 Stray-copy fix: the capped second-drive copy container never outlives the copy — fixed name + label, removed by name on any error (the timeout included), every leftover removed at start before the scheduler and web server; a restore is refused while a copy runs or may still run; --mount (refuses a path the daemon does not see) and the image ID with --pull never (review); red-proved; unreleased
gates / gates (push) Successful in 1m53s
2026-10-22 20:20:35 +02:00
admin d5f88a2182 R-1187 (c): refuse a .fab import over an installed app that is not running (it merged old and bundle data); R-1189 (d): the off-site proof + integrity check run after a catch-up; unreleased
gates / gates (push) Successful in 1m54s
2026-10-22 17:27:56 +02:00
admin 6a17c95815 R-49 (D21 = B): a template may exclude a named volume from every backup (backup.volumes, class excluded) — Immich's model cache; guarded, red-proved; unreleased
gates / gates (push) Successful in 1m50s
2026-10-22 16:21:38 +02:00
admin add310c80a R-1199 reopened: a box with no list of its own reads the household's from the hub and adopts it, pushes its default once only when no household saved one; every push names its source; an empty saved list stays empty; R-1216 (D28 = A): the install page's swap sentence only when host swap is really short (shared case table); unreleased
gates / gates (push) Successful in 1m55s
2026-10-22 12:13:26 +02:00
admin ba22f9b2d9 R-1199: a box whose household never saved its notification choice pushes the default list its page shows at start, so the hub mails by it; unreleased
gates / gates (push) Successful in 1m37s
2026-10-21 23:40:21 +02:00
admin d582feb245 D22: every restore puts the data back exactly on failure and after a power cut (R-1177, R-1195); whole restore asks the unit first (R-1178); no mirror during a restore (R-1180); W22 restore refusals in Hungarian; unreleased
gates / gates (push) Successful in 1m40s
2026-10-21 21:19:46 +02:00
admin 5929b8e345 kept second-drive copies (D25: R-1175, R-1181, R-1179); .fab import keeps the family gate (R-1191); stale restore temp (R-1188 c); the overcommit sentence made true (R-1192); escrow before the floor (R-1176); unreleased
gates / gates (push) Successful in 1m20s
2026-10-21 15:46:10 +02:00
admin 8f5bea0148 R-1182: a finished off-site abandonment closes on the hub's abandon_purge_done (hub v0.163.0 keeps other copies' packages); unreleased
gates / gates (push) Successful in 1m18s
2026-10-21 13:36:12 +02:00
admin 93fb251ea9 R-893 option A (operator D20): a failed off-site restore puts the app's live volumes and definition back exactly and starts it; fit check before the stop; the held sentence made true (R-1169)
gates / gates (push) Successful in 1m11s
2026-10-20 09:17:00 +02:00
admin 15ea002458 v0.335.0: no app stop for a tier the agent will refuse because its host is busy (host_busy pre-check, R-921)
gates / gates (push) Successful in 53s
2026-10-19 20:05:52 +02:00
admin 546eef37bd v0.334.0: a live box refreshes its config with its own hub key (GET /box-config; R-1159, operator D19)
gates / gates (push) Successful in 49s
2026-10-19 15:55:10 +02:00
admin 6d90374f63 v0.328.0: the catalog allow-list — the box refuses container rights a template asks for and the box does not give (R-971, D2 = A)
gates / gates (push) Successful in 45s
internal/privpolicy checks the RENDERED compose (privileged, cap_add, devices, host namespaces, security_opt,
sysctls, volumes_from, build/include/extends, env_file/config files outside the stack dir, aliasing named volumes,
binds outside the box's data roots, the Docker socket, propagation, ${VAR} in a privileged key) against an
allow-list compiled into the controller (one entry: homepage's read-only socket). Asked before every compose
write: the 15-minute sync, the guarded update/ladder step, the install, both settings changes, both restores
(before the stop). A refusal writes nothing, keeps the app on its last good compose, raises the operator-only
event app_definition_refused once per definition and puts one line on the app page. The sync never copies a
template named like a controller infra stack. Structural guard TestAllowList_IsWiredIntoEveryComposeWriter.

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-17 16:34:12 +02:00
admin 6ed223886d R-1112: open the family store when the controller starts
gates / gates (push) Successful in 46s
Found on demo-hp with 0.325.0-rc.1: the store (and so the conversion of an old family.json) opened only on the
first family request; a box nobody visits through a family gate kept the session values. OpenFamilyStore from
main, one INFO line with the count. TestR1112_StartConvertsTheFamilyFile, TestR1112_MainOpensTheFamilyStore,
red-proved.

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-17 09:56:12 +02:00
admin f75b3aa778 v0.324.0: the database password comes back with the data (R-1106, R-127b, R-926); restic 0.19.1 (R-1107); R-1108, R-1065, R-1017; dashboard hardening (R-983, R-976)
gates / gates (push) Successful in 44s
2026-10-16 22:46:00 +02:00
admin fbcc3cf042 Debian 13 runtime with restic 0.18.1 pinned outside the OS; restic assumptions re-proven; felhom-samba 1.2.0 (R-1105, R-972)
gates / gates (push) Successful in 49s
2026-10-16 20:33:57 +02:00
admin f037be7a6a R-970: the box's hub key opens no route; Data tab leftovers; R-1103: the install form's dead branches
gates / gates (push) Successful in 48s
R-970: /api/config, /api/config/hash, /api/config/apply removed (they read and replaced controller.yaml with
every secret, reachable with the box's own hub API key, unsigned; nothing called them). The hub-key Bearer
door on /api/selfupdate/ and /api/geo/ and the matching CSRF exemption are gone; the dashboard keeps using
those with a session. The route table is buildMux, so a test drives the real one.

Data tab: the export password field is autocomplete=new-password with a non-login name; the 2nd copy's
status rows that repeated the form are gone (the no-target reason moves into the form).

R-1103: app_fields.html loses its installed-only branches (no page serves them since R-1095); the tests
that rendered that dead path are retired, their rules asserted on the settings tab (R-694 moved there).

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-16 18:24:00 +02:00
admin 0626b9fc8a v0.317.0: a second copy counts only on a proven different disk; the no-drive install speaks in words (felhom.eu architecture/16, build A)
gates / gates (push) Successful in 46s
Tier-2 and the one-copy notice ask the host agent (POST /disks/same-disk, agent 0.157.0): different +
proven -> made and counted; same disk -> not made (D1); unknown (VM, hidden USB serial) -> made, not
counted, the row says why (D2); a NAS never counts and no longer hides the notice (R-1075). An older
agent keeps the st_dev rule, logged once. D4: a data-folder or media app on a box with no drive is
refused in words with a link to the drives page (R-1068's raw-error half). MinAgent 0.157.0.

Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
2026-10-15 21:21:54 +02:00