diff --git a/documentation/backlog/OPEN-ITEMS.md b/documentation/backlog/OPEN-ITEMS.md index 06751ec..91f2be5 100644 --- a/documentation/backlog/OPEN-ITEMS.md +++ b/documentation/backlog/OPEN-ITEMS.md @@ -39,7 +39,11 @@ State: `BLOCKED` · `READY` · `WAITING-ON-OPERATOR` · `WATCHING`. Every row ha | **F-REBOOT** | ~~A guest rebooted during its backup does not come back — shutdown completes, start never happens, no self-heal; 9m47s total appliance outage with every alarm silent~~ | **SHIPPED + PROVEN-LIVE** (agent v0.107.0, 2026-07-28) | — | 60 s guest-power watchdog; `onboot` is the deliberate-stop discriminator (already the stale-lock path's, and what `pve-guests` consults), retry bounded 3x/1m-2m-4m then escalates once. Live on demo-hp: **120 s unattended** vs the incident's 587 s with a human; Scenario B proven (an `onboot:0` guest left stopped) | — | | **F-LEAK** | ~~A failed restore-test cannot destroy its own scratch guest (403 `VM.Allocate`); the 10-slot VMID band shrinks silently~~ | **SHIPPED + PROVEN-LIVE** (agent v0.110.0 + host-install v1.21.0, 2026-07-28) | — | **Three attempts, two refuted live.** (1) Pool adoption: `PUT /pools/{pool}` also needs `VM.Allocate` on the VM — membership cannot bootstrap its own authority. (2) Per-path `/vms/990000..990009` ACLs: work, but PVE's destroy calls `remove_vm_access` (`LXC.pm:906`) which deletes every ACL at `/vms/` — **consumed by the op it authorises**, one use per slot. (3) SHIPPED: 4th root-fenced exception, band enforced in sudoers **literally** (`pct destroy 99000[0-9] --purge`) + in code + at the caller; API destroy still tried first. Live: band PERMITTED, `9201`/`9100`/`9999`/`990010`/`1` REFUSED, and `pct start 990000` REFUSED too | — | | **F-OBS** | ~~`deadapp-check` leaves NO positive observable on a default (info-level) box — "no alarms" was indistinguishable from "never ran"~~ | **SHIPPED + PROVEN-LIVE** (controller v0.180.0 + agent v0.109.0, 2026-07-28) | — | INFO summary every 20th scan carrying scans/evaluated/down. **Agent v0.109.0 fixes the same shape in the guest-power watchdog shipped hours earlier in v0.107.0** — it logged only at startup and when it acted, so its health could be read only from absence | — | -| **E-2** | Drive-role machinery around the moved vzdump target: backup-target role on `StoragePath`, wizard assignment (never by transport/`removable`), no automatic roles, stickiness, `felhom-host-install.sh` creating the target **+ its `FelhomAgentStore` ACL**, absent-target policy, retention/space on a shared drive, honest single-drive label, remaining fleet migration | **READY (M)** | — | Architecture change PROVEN by hand on both demo boxes 2026-07-28 (`runbooks/RUNBOOK-vzdump-target-move-2026-07-29.md`); this is the machinery around a proven thing. Flips matrix row 4 | CC | +| **E-2** | **IN PROGRESS 2026-07-29.** SHIPPED: hub v0.81.0 (`backup_target_absent`/`_restored` in allowedEventTypes + Hungarian customerMessages, 3 tests, red-proofed) and controller Part 1 (`StoragePath.BackupTarget` role + `SetBackupTarget`/`ClearBackupTarget`, 5 invariant tests, red-proof C). **REMAINING: Part 2 installer Case A/B, Part 3 the offer + the agent-side move, Part 4 the degraded banner, Part 5 the controller half of the signal, red-proofs E/F, live validation.** | **READY (M) — partially shipped** | — | **Phase 0 inverted the emphasis: the installer has NO drive-enrollment step (`/mnt/felhom-drives` is agent-installed at runtime), so at install time the common case is system-drive-only and Part 3 (drive added later) is the PRIMARY path, not Case A.** Scope + rationale: `runbooks/RUNBOOK-vzdump-target-move-2026-07-29.md` §7. Flips matrix row 4 | CC | +| **E-2a** | **The target move needs a root-fenced wrapper — the agent cannot do it.** Creating a PVE `dir` storage needs `Datastore.Allocate` at `/storage` and the ACL grant needs `Permissions.Modify`; the agent holds neither by design (blast-radius containment), and its sudoers is a literal-argument `Cmnd_Alias` model with **no `pvesm` and no `pveum`**. The established pattern is a guarded wrapper (`felhom-mkfs-guarded`, `felhom-pbs-apply` — the latter already has the exact `grant ` dual-grant verb E-2 needs) | READY (M) | blocks E-2 Part 3 | Add `felhom-backup-target-apply` (create-dir-storage with `is_mountpoint 1` + grant) + its literal sudoers rule + installer install step, then the agent endpoint. **Do NOT widen the agent's PVE role instead** | CC | +| **E-2b** | **`NotifyStorageDisconnected`/`NotifyStorageReconnected` are defined and called NOWHERE** — a drive going absent emits no event on any channel. Detection works (`SetDisconnected`, apps stopped, `[WARN]` log, UI badge); the notification is dead code. Verified against the gitignored-`cmd/` trap with a positive control | **READY (S) — real silence** | — | Fifth instance of seam-built-but-never-wired. Hub side is fully plumbed already (allowedEventTypes + Hungarian message + DefaultEnabledEvents), so wiring needs **no hub change**. A backup-target-only drive has no apps to stop → today it is entirely silent | CC | +| **E-2c** | **E-1 put the whole-guest backups on a drive the customer can self-serve eject.** `RoleForStorage` returns `RoleUserData` for a `local-dir` on a non-system device, so `POST /disks/eject` permits ejecting `/mnt/nvme-1tb` / `/mnt/hdd_1` — now the backup targets | READY (S) | — | Do NOT simply reclassify the drive `RoleBackup`: on both demo boxes it is ALSO the enrolled user-data drive, so that would block legitimate ejects (over-correction). Guard the eject specifically when the mount is the assigned backup target, and make it surface the consequence | CC | +| **PETI** | **`peti-felhom` deliberately NOT migrated.** Its whole-guest backup still shares a device with its guest, so a drive failure there is **offsite-only recovery** | **ACCEPTED RISK — parked** | operator's next visit (tester reinstalling from scratch) | **Accepted until the reinstall; re-evaluate if that slips past ~2026-09-01.** Do not migrate, do not touch | operator | | **R-109** | **The DR recipe records no backup target.** It lists every storage's name/type/content but never which one holds the local archives — and each demo box now carries TWO `content=backup` dir storages, `felhom-backup` (live) and `local` (frozen 2026-07-28 archives) | READY (XS) | — | Add the resolved `BackupTarget()` to the host-half. Third recipe-completeness defect beside R-105/R-106 | CC | | **R-89** | Retention as a per-customer **commercial** policy on the hub | READY (increment 2) | — | Policy object + reconciler → ep0 prune job; keep box tokens write-only | CC | | **R-92** | Hub PBS-DR gauge is 0.1 GB-granular — small deltas unverifiable | READY (XS) | — | Widen precision when retention becomes customer-visible | CC |