v0.137.0: guard empty-email notification save (prevents alert-delivery wipe)

Saving the notifications form with a blank email box while events are enabled
wiped the customer's hub-side alert address (SyncPreferences pushed empty) —
the 2026-07-15 demo incident. settingsNotificationsHandler now refuses that
save before SetNotificationPrefs + hub sync, re-renders a Hungarian error, and
repaints the submitted checkboxes. Empty email + zero events (clear-all) still
proceeds. Tests + red-proof (remove guard -> stored email wiped to empty).
This commit is contained in:
2026-07-15 19:40:01 +02:00
parent 0ef6648e12
commit c124d0adf2
4 changed files with 201 additions and 0 deletions
+22
View File
@@ -1,5 +1,27 @@
## Changelog
### v0.137.0 — empty-email notification save guard (data-loss fix) (2026-07-15)
Fixes a silent alert-delivery wipe demonstrated on the demo customer on 2026-07-15: saving the
Értesítések form with a **blank e-mail box while events were still enabled** dropped an empty
`Email` into the prefs AND pushed it to the hub (`SyncPreferences`), overwriting the customer's
provisioning-seeded alert address — the "Kedves Ügyfél!" delivery path went dark until it was
restored by hand in 6D (P3-DELIVERY).
- **`web/handlers.go` `settingsNotificationsHandler`:** after computing the trimmed email + enabled
events, a guard refuses the save when `email == "" && len(enabledEvents) > 0` — it returns
**before** `SetNotificationPrefs` and **before** any hub sync, re-rendering the page with a
Hungarian error ("Adj meg egy értesítési e-mail címet …") and repainting the just-submitted
checkboxes (an overlay on `notificationsPageData`'s `NotificationPrefs`, render-only). Enabled
events with no address is a purely destructive state reachable only via the bug. The legitimate
**empty-email + ZERO events** clear-all still proceeds (the empty hub push is correct there).
- **Deliberately NOT** an HTML `required` attr on the input — `required` is unconditional and would
block the legitimate clear-all case; the server-side guard is the correct, precisely-conditional
floor. `SyncPreferences` / the hub side / the seed-migration are untouched.
- **Tests (`web/notifications_guard_test.go`):** guard-fires (stored email survives — the wipe is
prevented; red-proofed: remove the guard → the email is wiped to `""`), legitimate clear-all
proceeds, normal save persists. Real temp-file `Settings` (non-hollow: asserts stored state).
### v0.136.0 — `.fab` exclusion scoping: classes in the manual export (Task 4) (2026-07-15)
Task 4 — the `.fab` column of the matrix (architecture §2; the SQ5 exclusion-scoping verdict + Viktor