Files
felhom.eu/documentation/audits/DIAG-backup-missed-2026-07-26.md
T
Claude Code add5b9bbbb docs(audits): R-80 DIAG — expected_backup_missed root-caused to in-memory agent backup store
Read-only diagnostic. No fix applied.

Verdict: FALSE ALARM for demo-felhom + demo-hp, true-but-premature for
drill-r50. Fired ONCE (2026-07-26 03:00 UTC), not nightly. No real
external customer notified.

Root cause: felhom-agent/internal/backup/store.go is in-memory by design;
an agent restart empties the host-report 'backups' array until the next
backup runs. The R-50 island migration restarted the fleet on 2026-07-25
12:44 UTC, opening an ~18h blind window that the 03:00 UTC deadline check
fell into. Hub's assessBackupFreshness reads the empty array as 'no
backup exists'.

Separate real finding: the PBS/offsite-DR tier has no schedule at all
(local_backup_target=local, no jobs.cfg) — demo-felhom has one snapshot
from 07-18, demo-hp has zero since pbs_dr was applied 07-21.
2026-07-26 09:59:35 +02:00

29 KiB
Raw Blame History

DIAG — expected_backup_missed on demo-felhom / demo-hp / drill-r50 (2026-07-26)

Class: read-only diagnostic (R-80). Nothing was fixed, triggered, cleared or restarted. Author: Claude Code, DooPlex. Window investigated: 2026-05-30 → 2026-07-26 09:55 UTC.


0. Headline

The alarm is a FALSE ALARM for 2 of 3 customers, and premature for the third. It did not fire nightly — it fired exactly once, at 2026-07-26 03:00 UTC. No real external customer received anything.

Root cause (H2, empty-array variant): the agent's backup record store is in-memoryfelhom-agent/internal/backup/store.go:15, whose own doc-comment says "In-memory (lost on restart; the cadence re-populates)". An agent restart wipes it, so the host-report emits backups: [] until the next backup runs. The hub's assessBackupFreshness reads an empty array as no backup exists.

Trigger: the R-50 island migration restarted felhom-agent fleet-wide on 2026-07-25 ~12:4112:44 UTC (agent v0.96.0). Backups run on a ~24 h cadence; the next one landed 07-26 07:03 UTC. The 03:00 UTC deadline check fell inside that ~18 h blind window.

The one genuinely bad finding, unrelated to the alarm text: the PBS / offsite-DR tier has no schedule at all. demo-felhom's felhom-offsite datastore holds exactly one snapshot (2026-07-18); demo-hp has pbs_dr applied since 07-21 and zero snapshots ever. See §7.

The premise that ~7.3 days of staleness predates the 07-25 channel outage is correct but misleading: the 176 h figure is the age of the PBS snapshot, reached only as a fallback once the vzdump array went empty. Local vzdump was never 7 days stale — it ran on 07-24, 07-25 and 07-26.


1. D0 — access inventory

Target Reachable Path User Passwordless sudo Notes
DooPlex (this host) local kisfenyo hosts hub, hub DB, k3s, local PBS
Hub (k3s felhom-system) sudo kubectl pod hub-9496fd7c9-kfpkx, image felhom-hub:0.74.0
Hub DB kubectl cp → scratchpad, sqlite3 -readonly 113 MB copy; live DB never opened writable
PVE demo-felhom (N100) ssh felhom-pve (Tailscale 100.70.170.35) root n/a (is root) full journal + pvesm
PVE demo-hp (t740) ssh demo-hpPermission denied (publickey,password) no baked key. Break-glass root exists in hub host_recoverynot used, per scope ("do not escalate or hunt for credentials")
PVE drill-r50 (host drill-r50-0a4f9a) no SSH alias configured NOT COLLECTED
PBS felhom-offsite (ep0/Hetzner, via wg 10.77.0.1) ⚠️ indirect read through PVE storage client + agent verify loop no direct PBS API/root; free space + prune/GC history NOT COLLECTED
Guest 9201 (demo-felhom) ssh felhom-pve "pct exec 9201 …" root n/a not needed for this diagnosis
DooPlex-local PBS felhom-spike local, sudo leftover spike store, newest snapshot 2026-07-10 — not the live offsite datastore

Exit-code discipline. stderr was inspected on every rc=0. pvesm status / pvesm list first emitted perl locale warnings to stderr that truncated the read — re-run with LC_ALL=C and stderr captured to a separate file; all three commands rc=0 with empty stderr on the clean run. proxmox-backup-manager namespace list returned rc≠0 (subcommand absent on this PBS version) and proxmox-backup-client list failed with "no password input mechanism available" — neither was retried, because pvesm list felhom-pbs yields the same ground truth via the configured credential.


2. Who the three customers are

customer_id Name Status DR tier Customer notify channel Real external customer?
demo-felhom Demo Ügyfél active 1 doo…@freemail.hu (operator's own mailbox) No — operator demo box (N100)
demo-hp Demo HP active 1 none — operator channel only No — operator demo box (HP t740)
drill-r50 drill-r50 active 0 none — operator channel only No — R-50 drill VM, bound 2026-07-25 09:49 UTC, ~19 h old

No real external customer was notified. The one real external customer in the hub, peti-felhom ("Peti Proxmox", active, dr_tier 0), did not fire today and has no customer_notifications row (operator channel only, always). It is silent because it has no agent host-report at all → deadline.go:176 takes the explicit "legacy/defunct controller-only customer" branch, which deliberately raises no backup alarm.

customer_notifications holds exactly one real row (demo-felhom) plus a _resend-rotation-test stub. So at most one mailbox — the operator's own — can ever receive this event today.


3. D1 — the events, verbatim

3.1 Every expected_backup_missed in the current era (since the 2026-06-16 repoint)

id customer created_at (UTC) sev verbatim message
723 demo-felhom 2026-06-29 03:00:00 error No fresh verified backup: no PBS snapshot or successful backup in the latest host-report
1129 peti-felhom 2026-07-13 03:00:00 error No fresh verified backup: newest backup is 40h0m0s old (limit 26h0m0s)
1203 peti-felhom 2026-07-14 03:00:00 error No fresh verified backup: no PBS snapshot or successful backup in the latest host-report
1275 peti-felhom 2026-07-15 03:00:00 error No fresh verified backup: no PBS snapshot or successful backup in the latest host-report
1803 demo-felhom 2026-07-26 03:00:00 error No fresh verified backup: newest backup is 176h0m0s old (limit 26h0m0s)
1804 demo-hp 2026-07-26 03:00:01 error No fresh verified backup: no PBS snapshot or successful backup in the latest host-report
1805 drill-r50 2026-07-26 03:00:01 error No fresh verified backup: no PBS snapshot or successful backup in the latest host-report

(Rows 339512, 2026-05-30 → 2026-06-16, are the pre-repoint era with the old message No backup completed or failed since midnight — the v0.12.0 CHANGELOG names that as a known daily false alarm, already fixed. Not relevant.)

3.2 Per-customer answers

demo-felhom demo-hp drill-r50
Reason branch fired newest backup is Xh old no PBS snapshot or successful backup no PBS snapshot or successful backup
First occurrence 2026-07-26 03:00:00 UTC 2026-07-26 03:00:01 UTC 2026-07-26 03:00:01 UTC
Total count 1 (this era: 2, incl. 06-29) 1 1
Nightly? No — single occurrence No — single occurrence No — single occurrence
Channels delivered operator and customer operator only operator only
H2 status refuted by string alone → H1/H4/H5 live → D2b decisive live → D2b decisive

The "nightly" premise is refuted. notification_log records exactly one customer-channel send for this event since the 2026-06-16 repoint: id 245, demo-felhom, 2026-07-26 03:00:01, status sent, Hungarian subject text „A mai biztonsági mentés nem készült el a határidőig!" (hub/internal/notify/templates.go:106), body carrying the English reason string No fresh verified backup: newest backup is 176h0m0s old (limit 26h0m0s).

3.3 Co-firing signals in the same window

expected_dbdump_missed: not fired for any of the three (all three emitted db_dump_completed at 00:30 UTC today). host_staleness / node_stale / offsite_stale / pbsdr_*: none on 2026-07-26. The only other events today are agent_channel_unreachable (demo-felhom 06:16, demo-hp 06:19, drill-r50 07:23 — transient) and local_api_endpoint_drift on drill-r50 (07:21, unrelated, see §10).


4. D2 — what the agent reported

Latest host-report per customer (2026-07-26 07:4207:44 UTC), pbs_snapshots and backups verbatim:

demo-felhompbs_snapshots 1 entry, backups 1 entry:

"pbs_snapshots": [{ "namespace":"root","backup_type":"ct","backup_id":"9201",
  "backup_time":"2026-07-18T18:31:06Z","size_bytes":9744319415,
  "owner":"felhom@pbs!demo-felhom","protected":false,"encrypted":true,
  "verify_state":"ok",
  "verify_upid":"UPID:felhom-hetzner:000003D4:000005BE:00000048:6A65ACDA:verify:felhom\\x2doffsite\\x3ans-demo\\x2dfelhom:felhom@pbs!demo-felhom:" }]
"backups": [{ "target_id":"local","vmid":9201,
  "archive":"local:backup/vzdump-lxc-9201-2026_07_26-09_03_19.tar.zst",
  "mode":"snapshot","crash_consistent":true,"size_bytes":5690147837,
  "success":true,"started_at":"2026-07-26T07:03:19Z","duration_seconds":216.556501101,
  "uncovered_volumes":["/etc/felhom-bootstrap","/mnt/felhom-drives"] }]

demo-hppbs_snapshots: [] (0 entries), backups 1 entry:

"backups": [{ "target_id":"local","vmid":9201,
  "archive":"local:backup/vzdump-lxc-9201-2026_07_26-09_06_02.tar.zst",
  "mode":"snapshot","crash_consistent":true,"size_bytes":1476771458,
  "success":true,"started_at":"2026-07-26T07:06:02Z","duration_seconds":76.320400309,
  "uncovered_volumes":["/etc/felhom-bootstrap","/mnt/felhom-drives"] }]

drill-r50pbs_snapshots: [], backups: []. Both empty. No pbs_dr stanza (null).

Note the timing trap: these are the 07:44 reports. At 03:00, when the check ran, all three backups arrays were empty — see §5.

4.1 D2b — the parse check (H2 parse variant)

Agent wire struct: felhom-agent/internal/hub/report.go:27,29Backups []Backup, PBSSnapshots []PBSSnapshot. Emitted values are 2026-07-26T07:03:19Z / 2026-07-18T18:31:06Z — plain RFC3339 with a Z offset. parseBackupTime (deadline.go:107) accepts exactly time.RFC3339. No format mismatch.

H2's parse variant is REFUTED. H2's empty-array variant is the root cause. The two are conflated behind one reason string — see fix #3.

4.2 The mechanism, proven

felhom-agent/internal/backup/store.go:10-19:

"Store holds the agent's LATEST backup result per target … In-memory (lost on restart; the cadence re-populates) and mutex-guarded…"

Collector.collectBackups (internal/hub/collect.go:393) returns []Backup{} when the store is empty. Hub-side, assessBackupFreshness sees !havePBS && !haveVzdump → fires "no PBS snapshot or successful backup"; or, if a stale PBS snapshot survives (demo-felhom), falls through to the age branch and reports the PBS snapshot's age — 176 h.

The alarm cannot distinguish "no backup was taken" from "the agent forgot".


5. D4 — the discriminator: agent-reported vs ground truth

Ground truth gathered read-only on felhom-pve (pvesm list, rc=0, empty stderr — no verify, no prune, no GC, no backup triggered):

PBS  felhom-pbs (datastore felhom-offsite, ns demo-felhom, server 10.77.0.1):
  felhom-pbs:backup/ct/9201/2026-07-18T18:31:06Z   pbs-ct  9744319415  9201     <- ONLY entry

LOCAL local (content=backup):
  local:backup/vzdump-lxc-9100-2026_07_18-18_30_52.tar.zst    612397450  9100
  local:backup/vzdump-lxc-9100-2026_07_20-17_50_57.tar.zst    648549366  9100
  local:backup/vzdump-lxc-9201-2026_07_24-21_12_03.tar.zst   5487897588  9201
  local:backup/vzdump-lxc-9201-2026_07_25-08_30_14.tar.zst   5603727891  9201
  local:backup/vzdump-lxc-9201-2026_07_26-09_03_19.tar.zst   5690147837  9201

5.1 What the check actually saw, night by night (demo-felhom)

The report nearest each 03:00 UTC — this is the decisive table:

Check at Report used backups newest vzdump pbs_snapshots newest Age of newest Fired?
07-19 03:00 07-19 02:45 2026-07-18T18:20:11Z none 8.7 h no correct
07-20 03:00 07-19 11:30 2026-07-18T18:20:11Z none 32.7 h no ⚠️ (see note)
07-21 03:00 07-21 02:55 2026-07-20T06:40:45Z none 20.3 h no correct
07-22 03:00 07-22 02:47 2026-07-21T11:18:24Z 2026-07-18T18:31:06Z 15.7 h no correct
07-23 03:00 07-23 02:59 2026-07-22T17:21:46Z 2026-07-18T18:31:06Z 9.6 h no correct
07-24 03:00 07-24 02:55 2026-07-23T11:41:34Z 2026-07-18T18:31:06Z 15.3 h no correct
07-25 03:00 07-25 02:57 2026-07-24T19:12:03Z 2026-07-18T18:31:06Z 7.8 h no correct
07-26 03:00 07-26 02:59 NONE (array empty) 2026-07-18T18:31:06Z 176 h YES false

07-20 note: the customer was down that morning (node_down 07-19 12:38) and would have been skipped by the staleness.GetState(id) == "down" guard at deadline.go:160. Either way no alarm was raised, and a real backup had run 07-20 06:40.

The deadline check ran every night and was correctly silent on all of them. The 07-26 fire is caused solely by the array going empty. This also refutes any "the scheduler stopped" theory — scheduleDaily (cmd/hub/main.go:677) recomputes the next 05:00 Budapest on every loop iteration and is sound.

5.2 The array-emptying transitions (all three customers)

Only the change-points are shown:

demo-felhom   2026-07-24 19:11:58  nb=0            <- agent restart, refilled 30 min later
              2026-07-25 06:23:55  nb=0            <- agent restart, refilled 15 min later
              2026-07-25 12:44:05  nb=0            <- R-50 restart; STAYS EMPTY across 03:00
              2026-07-26 07:12:xx  nb=1 vzdump=2026-07-26T07:03:19Z   <- self-cleared

demo-hp       2026-07-24 18:46:13  nb=1 vzdump=2026-07-24T18:38:30Z
              2026-07-25 10:22:45  nb=0            <- agent restart, refilled 15 min later
              2026-07-25 12:41:28  nb=0            <- R-50 restart; STAYS EMPTY across 03:00
              2026-07-26 07:12:20  nb=1 vzdump=2026-07-26T07:06:02Z   <- self-cleared

drill-r50     2026-07-25 09:50:55  nb=0 npbs=0     <- never had a backup; still nb=0

The two earlier restarts (07-24 19:11, 07-25 06:23) also emptied the array, but a backup followed within 30 minutes, so no 03:00 boundary was crossed. The R-50 restart is the one that landed in the blind window.

5.3 Verdict per customer

Customer Agent said PBS/local ground truth Verdict
demo-felhom backups: [] at 03:00; PBS 07-18 vzdump ran 07-24 21:12, 07-25 08:30, 07-26 09:03 CEST (3 archives retained, retention=3); PBS 1 snapshot, verify_state ok H2 — FALSE ALARM. Local tier fully healthy. PBS tier genuinely stale (§7), but that is a different fault than the message implies
demo-hp backups: [], pbs_snapshots: [] at 03:00 vzdump 07-25 10:23, 07-26 07:06 UTC both success:true; PBS 0 snapshots ever H2 — FALSE ALARM. Local tier healthy. PBS tier never ran (§7)
drill-r50 both empty nothing, ever H1 — TRUE but premature. Box bound 2026-07-25 09:49 UTC, ~17 h before the check; no backup was yet due

6. Verdicts on H1H6

Verdict The observation that decided it
H1 genuine backup outage REFUTED for the host/vzdump tier; SUPPORTED for the PBS/offsite-DR tier; SUPPORTED-but-premature for drill-r50 pvesm list local shows three retained vzdump archives (07-24, 07-25, 07-26) and the agent journal logs backup: completed … target=local at 09:06:56 CEST today. Conversely pvesm list felhom-pbs returns exactly one snapshot, from 07-18
H2 reporting/parse break SUPPORTED (empty-array variant); REFUTED (parse variant) store.go:15 is in-memory by design; §5.2 shows the array emptying at each agent restart and refilling at the next backup. Timestamps are valid RFC3339 Z, so parseBackupTime never silently drops one
H3 verification failure REFUTED demo-felhom's only snapshot carries verify_state: "ok"; the agent journal logs pbs: verify cycle complete datastore=felhom-offsite snapshots=1 at 02:44 and 08:44 CEST today. demo-hp/drill-r50 have no snapshots to verify
H4 transport REFUTED wg show on felhom-pve: peer 167.233.158.164:443, latest handshake 39 seconds ago, 753.13 MiB rx / 481.85 MiB tx, keepalive 25 s. All three reports carry wireguard.active: true with last_handshake_age_s 3646. pvesm status shows felhom-pbs active
H5 schedule stopped PARTIALLY SUPPORTED The vzdump cadence is alive but its 24 h phase resets on agent restart (BackupCadence() default 24 h, config.go:390), which opened the window. Separately, no PBS schedule has ever existed: backup.local_backup_target = "local" and no /etc/pve/jobs.cfg (§7)
H6 stale host-report REFUTED Latest reports 2026-07-26 07:42:19 / 07:44:41 / 07:44:53 UTC, all agent 0.96.0; 664 / 436 / 96 rows. No host_staleness fired

7. The real finding — the PBS / offsite-DR tier has no schedule

This is not what the alarm text described, and it is the one thing here that is genuinely wrong.

  • felhom-agent's backup runner has exactly one target, resolved by BackupConfig.BackupTarget() (internal/config/config.go:415): local_backup_target if set, else the constant defaultBackupTarget = "felhom-pbs".
  • On demo-felhom, /etc/felhom-agent/agent.json sets "local_backup_target": "local". Therefore no agent-driven backup on that host ever targets felhom-pbs.
  • There is no /etc/pve/jobs.cfg on the host — no PVE-native backup job either.
  • The single PBS snapshot (2026-07-18T18:31:06Z) predates that and was not produced by a recurring job.
  • demo-hp reports pbs_dr: {state:"applied", storage_id:"felhom-pbs", namespace:"demo-hp", applied_at:"2026-07-21T16:35:44Z"} and pbs_snapshots: [] — the DR tier has been "applied" for 5 days and has produced nothing.
  • Today's vzdump was controller-initiated, not cadence-initiated: local-api: backup reached snapshotted (app may resume) vmid=9201 job=backup-9201-1785049399941273219backup: completed … target=local. The agent exposes GET /backup/due with a 24 h cadence (localapi/server.go:92-95) and the in-guest controller drives it.

So the offsite-DR promise is currently unbacked on both demo boxes. Worth its own task; it is not fixable as a one-liner.


8. D7 — timeline

When (UTC) What
2026-06-16 hub v0.12.0 repoints CheckBackupDeadlines from backup_completed events to host-report freshness. This is where the empty-array sensitivity is introduced (assessBackupFreshness, commit 0635640)
2026-07-18 18:20 last vzdump before the PBS snapshot
2026-07-18 18:31:06 the one and only PBS snapshot on demo-felhom. Nothing has been written to felhom-offsite since
2026-07-21 08:39 / 16:35 pbs_dr applied — demo-felhom / demo-hp
2026-07-24 19:11 agent restart → backups empties, refills 19:42 (no 03:00 crossed)
2026-07-25 06:23 agent restart → backups empties, refills 06:38 (no 03:00 crossed)
2026-07-25 09:49 drill-r50 appliance bound — a brand-new customer with no backup history
2026-07-25 12:41 / 12:44 R-50 island-bridge fleet migration — felhom-agent v0.96.0 restarted on every box. systemctl show felhom-agent on felhom-pve: ExecMainStartTimestamp=Sat 2026-07-25 14:44:37 CEST, NRestarts=0. backups empties and stays empty
2026-07-26 00:30 / 01:30 db_dump_completed + crossdrive_completed — app-data tiers healthy
2026-07-26 03:00:0003:00:01 deadline check fires on all three. demo-felhom also mails the customer channel
2026-07-26 07:03 / 07:06 next vzdumps run → arrays repopulate → condition self-clears
2026-07-26 07:15:58 hub pod restarts onto v0.74.0after the alarm, not causal

What changed at the outage start: the R-50 island migration's fleet-wide agent restart on 2026-07-25 12:44 UTC. That is the named, correlated change. Nothing else in the window touches backups.

Host uptime is 3 d 14 h (boot ~2026-07-22 19:14 UTC) — no host reboot in the window; the agent restart was a service restart. hub v0.73.2 was, as stated in the task, a hostInstallVersion string bump never deployed as an artifact (manifests/hub.yaml now pins 0.74.0) — confirmed irrelevant. deadline.go has not been touched since 2026-06-16, so neither 0.73.x nor 0.74.0 changed this logic.


9. D8 — is the customer-facing message accurate?

No, on two independent counts.

The Hungarian template (hub/internal/notify/templates.go:106) is „A mai biztonsági mentés nem készült el a határidőig!""Today's backup was not completed by the deadline!". A customer reads that as all my backups failed.

At the moment it was sent to demo-felhom (2026-07-26 03:00:01):

Tier State at send time Healthy?
Local vzdump (host tier) vzdump-lxc-9201-2026_07_25-08_30_14.tar.zst on disk, 5.6 GB, 20 h old
App-data cross-drive (tier 2) crossdrive_completed 2026-07-26 01:30:06 — 1.5 h before the mail
DB dump db_dump_completed 2026-07-26 00:30:56 — 2.5 h before the mail
PBS / offsite-DR last snapshot 2026-07-18, verify_state: ok genuinely stale
  1. The trigger was an artifact — the local host-tier backup had run and was on disk; the agent had merely forgotten it across a restart.
  2. Even when the signal is true, the scope is wrong — this check covers only the PBS/vzdump host tier. The controller's app-data tiers are separate signals (backup_failed, db_dump_failed, crossdrive_*) and were all green.

Recorded as a finding. Not changed.


10. Proposed fixes — described, NOT applied

# Where Fix Class
1 felhom-agent/internal/backup/store.go (Store, RecordBackup, Backups) Stop losing backup history on restart. Either persist the latest-per-target record to the agent's state dir, or have Collector.collectBackups fall back to querying PVE for the newest archive on the target storage (pvesm list <target> --content backup / the API equivalent) when the store is cold. The query path is arguably better — it is ground truth rather than remembered state, and it would also have surfaced the real PBS gap needs-a-spike (persistence vs query-on-demand is a design call)
2 felhom.eu/hub/internal/monitor/deadline.goassessBackupFreshness Do not alarm on absence of evidence. The function's own doc says "Only POSITIVE evidence of a problem fires an alarm", but !havePBS && !haveVzdump is precisely absence of evidence. Narrow it: empty+empty → unknown, log + operator-only, never the customer channel. Optionally require the condition to persist across ≥2 consecutive daily checks before escalating. This is the same bug shape as the hub v0.73.0 offsite_stale fix (never-ran branch with no time anchor) safe-obvious for the operator-only narrowing; needs-a-spike for a full unknown-state model
3 same file, same function (deadline.go:90) Split the conflated reason string. "no PBS snapshot or successful backup in the latest host-report" currently covers both arrays empty and every timestamp unparseable. Emit distinct strings so the next diagnosis is one query instead of a session safe-obvious
4 felhom.eu/hub/internal/notify/templates.go:106 Narrow the customer copy. Name the host/DR tier explicitly and state that app data is covered by separate alerts, so the message stops implying total backup failure safe-obvious — run scripts/hub_confirm_gate.py + the felhom-ui-design copy rules
5 agent config on both demo hosts + internal/backup/runner.go Wire an actual PBS/offsite-DR schedule (§7). Today local_backup_target: "local" means nothing ever targets felhom-pbs, and the runner supports only one target per run. Decide: second target per run, alternating cadence, or a PVE backup job needs-a-spike — this is the real defect and the largest piece of work
6 customer_notifications for demo-felhom RECOMMENDATION — operator decision, deliberately NOT applied. enabled_events currently includes expected_backup_missed. Given that the check demonstrably false-alarms on any agent restart and the copy overstates scope, consider removing expected_backup_missed from that list until fixes 14 land. The operator channel keeps full visibility. Mitigating factor: the only subscribed mailbox is the operator's own, so the blast radius today is zero — this can wait for the proper fix operator's call

Suppression urgency: LOW. The condition self-cleared at 07:03 UTC, no real external customer is subscribed, and the alarm requires an agent restart in the backup blind window to recur.


11. Not collectable

Item Why What access would be needed
demo-hp host-level: agent journal, wg show, agent.json backup stanza, PBS attempt logs ssh demo-hpPermission denied (publickey,password); break-glass root exists in hub host_recovery/demo-hp-bb76ea but was not used per scope a baked SSH key, or explicit authorisation to use the break-glass credential
drill-r50 host-level (host drill-r50-0a4f9a) no SSH alias configured; host not identified beyond the report an SSH route to that host
PBS server side: felhom-offsite free space, prune/GC job history, per-namespace usage no direct API/root on the ep0/Hetzner PBS; local proxmox-backup-client has no password input mechanism PBS API token or root on the PBS box
Hub logs from 03:00 today the hub pod restarted at 07:15:58 UTC onto v0.74.0; kubectl logs only reaches back to then, and there is no previous-container log a log sink outside the pod
Whether a datastore-full condition contributed pvesm status reports felhom-pbs Total/Used/Available all 0 KiB while Status=active — see §12 PBS-side status

12. Observations — noticed, not acted on

  1. pvesm status reports felhom-pbs with Total = Used = Available = 0 KiB, yet Status active and pvesm list works. Either the PBS storage plugin isn't returning usage over the wg link, or the datastore genuinely reports nothing. Worth a look when §7 is picked up — a full datastore is a classic silent-write-refusal cause, and this reading cannot currently rule it out.
  2. customer_notifications.updated_at for demo-felhom = 2026-07-26 07:17:54 — that row was touched today, after the alarm. Flagging in case the operator already adjusted something; I did not change it and did not investigate further.
  3. drill-r50 is emitting local_api_endpoint_drift (07:21 today): controller.yaml=192.168.0.176:8443 bootstrap.json=169.254.253.1:8443 (pin agrees: true), plus agent_channel_unreachable. Unrelated to this diagnosis, but live and probably R-50 fallout.
  4. agent_channel_unreachable fired on demo-felhom (06:16) and demo-hp (06:19) today and recovered. The task's framing treated the 07-25 channel outage as a possible cause; it is not — §5.1 shows backups ran normally throughout it. Coincidence confirmed.
  5. The DooPlex-local PBS datastore felhom-spike (/mnt/5_hdd/backup/demo-felhom, the only entry in datastore.cfg) is a leftover spike store with snapshots up to 2026-07-10. It is not the live offsite datastore — that is felhom-offsite on felhom-hetzner, reached over wg at 10.77.0.1. Easy to confuse when hunting PBS ground truth on this host.
  6. restore_test_cadence_seconds: 0 in the agent config → RestoreTestCadence() maps 0 to the 24 h default, so restore tests should be running; restore_tests was not examined in this pass.
  7. The pre-repoint era (2026-05-30 → 06-16) shows this same event false-alarming daily on peti-felhom and demo-felhom for a different reason, fixed in v0.12.0. Combined with the v0.73.0 offsite_stale fix, this is the third false-alarm in the same monitor family — all three from treating "no signal" as "bad signal". Fix #2 addresses the class, not just the instance.

13. What was NOT done (prime directive compliance)

No backup was run, triggered or tested. No PBS verify, prune or GC. No agent, hub, PBS or wg-felhom restart. No alert cleared, acknowledged or muted. No notification preference or channel setting changed. No schedule, timer or config file edited. No code changed, no version bumped.

The hub DB was copied out (kubectl cp) and every query ran against the copy with sqlite3 -readonly; the live /data/hub.db was never opened writable. All host commands were listings (pvesm list, pvesm status, wg show, systemctl show, journalctl).

The staleness measurement is intact: as of this writing the newest felhom-offsite snapshot is still 2026-07-18T18:31:06Z.