70 lines
4.6 KiB
Markdown
70 lines
4.6 KiB
Markdown
# REPORT — Cleanup bundle: email-wipe guard + carried hygiene — controller v0.137.0
|
||
|
||
## Summary
|
||
|
||
Four closing-the-loop items from the backup-redesign arc + 6D. One code fix (Part 1, shipped
|
||
v0.137.0), three operational/doc items executed inline.
|
||
|
||
## Part 1 — empty-email notification save guard (CODE, v0.137.0) — SHIPPED
|
||
|
||
**Problem:** `settingsNotificationsHandler` dropped a trimmed-empty `notification_email` into the
|
||
prefs and pushed it to the hub (`SyncPreferences`), overwriting the customer's provisioning-seeded
|
||
alert address — a customer saving any notification change with a blank email field silently wiped
|
||
their own hub-side alert delivery (the 2026-07-15 demo incident, restored by hand in 6D
|
||
P3-DELIVERY).
|
||
|
||
**Fix:** after computing the trimmed email + enabled events, refuse the save when
|
||
`email == "" && len(enabledEvents) > 0` — return **before** `SetNotificationPrefs` and any hub sync,
|
||
re-render with the Hungarian error `"Adj meg egy értesítési e-mail címet – bekapcsolt
|
||
értesítésekhez szükséges egy cím, ahova küldhetjük őket."`, and repaint the just-submitted
|
||
checkboxes (render-only overlay on `notificationsPageData`'s `NotificationPrefs`). The legitimate
|
||
empty-email + **zero** events clear-all still proceeds. `SyncPreferences` / the hub / the
|
||
seed-migration are untouched. Deliberately **no** HTML `required` attr (it is unconditional and
|
||
would block the legitimate clear-all — the server-side guard is the precisely-conditional floor).
|
||
|
||
**Tests + red-proof (`web/notifications_guard_test.go`, real temp-file Settings):** guard-fires
|
||
(stored email survives the refused save), legitimate clear-all proceeds, normal save persists.
|
||
Red-proof: neutering the guard → the stored email is wiped to `""` (the incident) → the test fails.
|
||
Full `go build/vet/test ./...` green.
|
||
|
||
**Deploy + live:** built + pushed `felhom-controller:0.137.0`, deployed to guest 9201 (Up, healthy;
|
||
`selfupdate: Current version 0.137.0 is up to date`). The protected asset is confirmed present — the
|
||
demo customer's notification email `nagyfenyvesi.viktor@gmail.com` is set. The authenticated UI
|
||
click-through needs the customer-owned claim password (CC does not hold it), so the server-side guard
|
||
is validated by the endpoint-equivalent unit test + red-proof (the CLAUDE.md live-validation proxy).
|
||
|
||
## Part 2 — duplicate recovery-unit cleanup (HYGIENE) — 1 removed, 3 STOPPED
|
||
|
||
Recovery units are `<drive>/backups/primary/<app>/`; the controller's tie-break selects the newest by
|
||
manifest `CreatedAt`, else dir mtime (`backup/offbox.go:558-607`, first-in-order wins on a CreatedAt
|
||
tie). On `felhom-flash`:
|
||
- **Removed** `/mnt/felhom-drives/felhom-flash/backups/primary/immich` (44M) — CreatedAt
|
||
`2026-06-23T10:02:35Z` vs the live `felhom-usb` copy `2026-07-15T17:41:20Z` → **confirmed older**,
|
||
never selected. Prefix asserted (`*/felhom-flash/backups/primary/*`) before `rm -rf`.
|
||
- **STOPPED** (not deleted): `felhom-flash` **audiobookshelf, komga, romm** — their manifest CreatedAt
|
||
is **identical** to the `felhom-usb` copy (`2026-06-23T10:02:35Z`), so the controller's tie-break is
|
||
drive-order-dependent and I cannot confirm the flash copy is the non-selected/older one. Per the
|
||
STOP discipline, left for a manual byte-identity check / disposition (not this micro-task).
|
||
|
||
## Part 3 — campaign6 orphaned autofs (OPERATOR ACTION) — safe clear attempted, left for Viktor
|
||
|
||
`/mnt/felhom-drives/campaign6` is a bare empty leftover directory (`nobody:nogroup`) — **not** a live
|
||
mount (not a mountpoint, absent from the mount table, no autofs config / systemd unit / fstab entry).
|
||
A safe non-disruptive `rmdir` (refuses non-empty dirs + mountpoints) was **refused with Permission
|
||
denied** even as root (an autofs-ghost / immutable artifact). No live mount was disturbed (mount count
|
||
89→89; all 8 drive mounts intact). Not escalated to `chattr`/force (beyond a safe clear). **Left for
|
||
Viktor's demo-host reboot window** — CC did not reboot.
|
||
|
||
## Part 4 — 6D audit doc tag (DOC) — committed
|
||
|
||
Added the matching track-only disposition line to the campaign6 autofs LOW finding in
|
||
`felhom.eu/documentation/audits/CAMPAIGN-6D-2026-07-15.md` (consistency with the duplicate-recovery
|
||
LOW). Commit `dee72cd`.
|
||
|
||
## Queue after this bundle
|
||
- **Pending operator (Viktor):** campaign6 autofs clears on the next demo-host reboot; the tied-CreatedAt
|
||
`felhom-flash` audiobookshelf/komga/romm duplicates await a manual disposition.
|
||
- **Deliberately not here** (correctly deferred): Peti-return runbook (hardware-gated); P4-DEEP timing +
|
||
P-TIER2 deep-4 (pre-broad-launch resilience); agent 0.88 publish (6D P-DAY0 shows the manifest already
|
||
vouches 0.88/golden-0.136 — likely closeable, verify separately).
|