controller (unreleased): R-921 check-first pre-check (no stop while another tier's job is in flight); R-922 email_cleared on a household's deliberate clear
gates / gates (push) Successful in 1m0s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-09 12:57:34 +02:00
parent 13eeb484ab
commit ec9b997151
16 changed files with 798 additions and 18 deletions
+22
View File
@@ -622,6 +622,28 @@ type NotificationPrefs struct {
Email string `json:"email,omitempty"`
EnabledEvents []string `json:"enabled_events,omitempty"`
CooldownHours int `json:"cooldown_hours,omitempty"` // default: 6
// EmailCleared (R-922, operator ruling 2026-10-09 option A) marks a DELIBERATE clear: the household
// saved an empty address where one was stored. Every hub push carries it as `email_cleared: true`
// while the address stays empty, so the hub deletes the address it holds — and a push the hub missed
// is repaired by the next one. A box that never had an address never sets it (the hub's no-clobber
// guard must keep protecting a seeded address); a new address drops it. Set only by
// web.settingsNotificationsHandler via ClearedBy. Pinned by internal/web TestR922_*.
EmailCleared bool `json:"email_cleared,omitempty"`
}
// ClearedBy reports whether saving `newEmail` over these stored prefs is (or keeps) a deliberate clear:
// the new address is empty AND the stored one was not — or the stored prefs already record a clear.
func (p *NotificationPrefs) ClearedBy(newEmail string) bool {
if newEmail != "" || p == nil {
return false
}
return p.Email != "" || p.EmailCleared
}
// SyncOnStartup reports whether the startup push should run: an address to restore after a hub DB
// rebuild, or a household clear the hub may not have received yet (R-922).
func (p *NotificationPrefs) SyncOnStartup() bool {
return p != nil && (p.Email != "" || p.EmailCleared)
}
// DefaultEnabledEvents are the events enabled by default for new customers.