hub v0.71.0: paired recovery mails (F11), prefs seeding at claim + empty-email no-clobber (F12), priority headers + operator test leg (F14-light)

This commit is contained in:
2026-07-22 20:57:29 +02:00
parent 5b35023574
commit c766c8af82
15 changed files with 832 additions and 30 deletions
+23 -1
View File
@@ -199,8 +199,23 @@ func (e *Engine) ResetToUnclaimed(cc *store.CustomerConfig) error {
return nil
}
// defaultSeedEvents is the enabled_events set seeded at claim (v0.71.0, audit F12) — critical-only:
// no node_stale (too chatty), no *_recovered (the recovery pairing gate handles those and never
// consults enabled_events). Viktor may adjust the list at review.
var defaultSeedEvents = []string{
"node_down",
"backup_failed",
"disk_critical",
"host_disk_critical",
"storage_fill_critical",
"offbox_repo_orphaned",
}
// MarkClaimed records a controller-reported successful claim and sends the one-time confirmation
// email on the unclaimed→claimed transition (idempotent — repeated reports are no-ops).
// email on the unclaimed→claimed transition (idempotent — repeated reports are no-ops). On the
// transition it also seeds notification prefs from the registered email (v0.71.0, audit F12) so a
// claimed customer can no longer be silently unnotifiable — insert-if-absent, never overwriting a
// customer-edited row, and never failing the claim (notification plumbing must not gate claiming).
func (e *Engine) MarkClaimed(cc *store.CustomerConfig) error {
transitioned, err := e.Store.MarkClaimed(cc.CustomerID)
if err != nil {
@@ -210,6 +225,13 @@ func (e *Engine) MarkClaimed(cc *store.CustomerConfig) error {
return nil
}
e.logf("[INFO] [claim] customer %s CLAIMED its dashboard (password set by the customer)", cc.CustomerID)
if seeded, err := e.Store.SeedNotificationPrefs(cc.CustomerID, cc.Email, defaultSeedEvents); err != nil {
e.logf("[WARN] [claim] notification-prefs seed for %s failed (claim unaffected): %v", cc.CustomerID, err)
} else if seeded {
e.logf("[INFO] [claim] notification prefs seeded for %s from the registered email (default critical set)", cc.CustomerID)
} else {
e.logf("[INFO] [claim] notification prefs for %s left untouched (row exists or no registered email)", cc.CustomerID)
}
if cc.Email != "" {
if err := e.Mailer.SendClaimEmail(string(EmailClaimed), cc.CustomerID, cc.Email, cc.Domain, ""); err != nil {
e.logf("[WARN] [claim] claimed-confirmation email to %s failed: %v", cc.CustomerID, err)