From ca89e70d531a20cc3c157e913ff02e055e34314c Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Mon, 5 Oct 2026 22:51:58 +0200 Subject: [PATCH] R-585 (part): three producers follow the household's language db_dump_failed, the off-box backup_failed and offbox_enlarge_blocked (whose sentence IS the household's mail - no hub customerMessages entry) now take facts and push a bundle key, so an English household reads English. Hungarian bytes unchanged (go-parity). Added to convertedProducers. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- controller/cmd/controller/main.go | 9 +++------ controller/internal/i18n/locales/en.json | 3 +++ controller/internal/i18n/locales/hu.json | 3 +++ .../internal/notify/message_customer_test.go | 4 ++++ controller/internal/notify/notifier.go | 18 ++++++++++++++---- controller/scripts/i18n_go_keys.json | 3 +++ 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/controller/cmd/controller/main.go b/controller/cmd/controller/main.go index 50392b2..d90317a 100644 --- a/controller/cmd/controller/main.go +++ b/controller/cmd/controller/main.go @@ -1144,7 +1144,7 @@ func main() { dbDumpLeg := withLeg(nightchain.LegDBDump, func(ctx context.Context) error { err := backupMgr.RunDBDumps(ctx) if err != nil { - notifier.NotifyDBDumpFailed("Adatbázis mentés sikertelen", err.Error()) + notifier.NotifyDBDumpFailed(err.Error()) } else { notifier.NotifyDBDumpCompleted(notify.DBDumpDetails{}) } @@ -1248,8 +1248,7 @@ func main() { if err != nil { // F-DIAG: a distinct message per cause, and the detail SANITISED — a raw err.Error() // carries the sftp:user@host:/path repo reference off the box. - notifier.NotifyBackupFailed("Off-box (NAS) mentés sikertelen", - backupMgr.OffsiteFailureMessage(err, dur)) + notifier.NotifyOffboxBackupFailed(backupMgr.OffsiteFailureMessage(err, dur)) } }) // R-203 (operator half): a completed off-site run could NOT capture a directory an app declares @@ -1360,9 +1359,7 @@ func main() { // triggered by the engine (only NEW blocks notify), so the hub's per-event-type cooldown suffices — // no controller-side timer (the hub owns cooldown). backupMgr.SetOffboxEnlargeBlockedNotifier(func(stack string, estBytes int64, usedGB, quotaGB int) { - notifier.NotifyOffboxEnlargeBlocked(fmt.Sprintf( - "A(z) %s teljes távoli mentése (~%s) túllépné a tárhelykeretet (%d/%d GB). A konfiguráció és az adatbázis továbbra is mentésre kerül; nagyobb kerethez vedd fel velünk a kapcsolatot.", - stack, appbackup.HumanizeBytes(estBytes), usedGB, quotaGB)) + notifier.NotifyOffboxEnlargeBlocked(stack, appbackup.HumanizeBytes(estBytes), usedGB, quotaGB) // R-585 }) // v0.142.0 offsite-repo continuity: push a hub event on the orphaned/reset transitions (once per // transition — the Manager guards nightly re-fire). Operator-visible on the customer page. diff --git a/controller/internal/i18n/locales/en.json b/controller/internal/i18n/locales/en.json index e8ec504..acccb11 100644 --- a/controller/internal/i18n/locales/en.json +++ b/controller/internal/i18n/locales/en.json @@ -1430,6 +1430,9 @@ "event.crossdrive_completed": "Second backup copy finished: %s", "event.crossdrive_failed": "Second backup copy failed: %s", "event.db_dump_completed": "Database backup finished", + "event.db_dump_failed": "Database backup failed", + "event.offbox_backup_failed": "Off-box (NAS) backup failed", + "event.offbox_enlarge_blocked": "The full remote backup of %s (~%s) would go over the storage quota (%d/%d GB). The configuration and the database are still backed up; contact us for a larger quota.", "event.disaster_recovery_completed": "Disaster recovery finished (%d succeeded, %d failed)", "event.disaster_recovery_started": "Disaster recovery started (%d app(s))", "event.health_critical": "System health is critical (was: %s)", diff --git a/controller/internal/i18n/locales/hu.json b/controller/internal/i18n/locales/hu.json index ac88841..744094b 100644 --- a/controller/internal/i18n/locales/hu.json +++ b/controller/internal/i18n/locales/hu.json @@ -1421,6 +1421,9 @@ "event.crossdrive_completed": "Másodlagos mentés elkészült: %s", "event.crossdrive_failed": "Másodlagos mentés sikertelen: %s", "event.db_dump_completed": "Adatbázis mentés elkészült", + "event.db_dump_failed": "Adatbázis mentés sikertelen", + "event.offbox_backup_failed": "Off-box (NAS) mentés sikertelen", + "event.offbox_enlarge_blocked": "A(z) %s teljes távoli mentése (~%s) túllépné a tárhelykeretet (%d/%d GB). A konfiguráció és az adatbázis továbbra is mentésre kerül; nagyobb kerethez vedd fel velünk a kapcsolatot.", "event.disaster_recovery_completed": "Katasztrófa helyreállítás befejezve (%d sikeres, %d sikertelen)", "event.disaster_recovery_started": "Katasztrófa helyreállítás elindítva (%d alkalmazás)", "event.health_critical": "Rendszer állapot kritikus (volt: %s)", diff --git a/controller/internal/notify/message_customer_test.go b/controller/internal/notify/message_customer_test.go index 957ea98..6cbf071 100644 --- a/controller/internal/notify/message_customer_test.go +++ b/controller/internal/notify/message_customer_test.go @@ -62,6 +62,10 @@ func convertedProducers() []struct { n.NotifyHealthChange("ok", nil, nil) }}, {"db_dump_completed", func(n *Notifier) { n.NotifyDBDumpCompleted(DBDumpDetails{}) }}, + // R-585: three of the six producers that sent Hungarian only. + {"db_dump_failed", func(n *Notifier) { n.NotifyDBDumpFailed("pg_dump: exit 1") }}, + {"backup_failed_offbox", func(n *Notifier) { n.NotifyOffboxBackupFailed("a NAS nem elerheto") }}, + {"offbox_enlarge_blocked", func(n *Notifier) { n.NotifyOffboxEnlargeBlocked("immich", "120 GB", 80, 100) }}, {"controller_updated", func(n *Notifier) { n.NotifyControllerUpdated("0.255.0", "0.256.0", true) }}, {"controller_update_failed", func(n *Notifier) { n.NotifyControllerUpdated("0.255.0", "0.256.0", false) }}, {"controller_started", func(n *Notifier) { n.NotifyControllerStarted("0.256.0", nil) }}, diff --git a/controller/internal/notify/notifier.go b/controller/internal/notify/notifier.go index ac7ecd1..cf9f630 100644 --- a/controller/internal/notify/notifier.go +++ b/controller/internal/notify/notifier.go @@ -483,8 +483,17 @@ func (n *Notifier) NotifyBackupRunFailures(message string, d BackupRunFailuresDe // body). NOTE: the event type "offbox_enlarge_blocked" must be added to the hub's allowedEventTypes + // customerMessages for delivery (a hub-side task, flagged — until then the hub 400s/drops it and the // in-dashboard LastWarning + /backups/remote note carry the message). -func (n *Notifier) NotifyOffboxEnlargeBlocked(message string) { - n.PushEvent("offbox_enlarge_blocked", "warning", message, nil) +// +// R-585: it takes the FACTS, not a finished sentence, so the sentence follows the household's language — +// this type has no customerMessages entry on the hub, so its sentence IS the household's mail. +func (n *Notifier) NotifyOffboxEnlargeBlocked(stack, estimate string, usedGB, quotaGB int) { + n.pushEventMsg("offbox_enlarge_blocked", "warning", "event.offbox_enlarge_blocked", nil, stack, estimate, usedGB, quotaGB) +} + +// NotifyOffboxBackupFailed is the off-box (NAS / off-site) run's failure — a `backup_failed` event whose +// headline follows the household's language (R-585). detail is the sanitised cause (OffsiteFailureMessage). +func (n *Notifier) NotifyOffboxBackupFailed(detail string) { + n.pushEventMsg("backup_failed", "error", "event.offbox_backup_failed", BackupDetails{Error: detail}) } // (NotifyBackupCompleted removed 2026-06-16 — the backup_completed event had no callers @@ -493,8 +502,9 @@ func (n *Notifier) NotifyOffboxEnlargeBlocked(message string) { // below are still emitted and consumed.) // NotifyDBDumpFailed sends a DB dump failure event. -func (n *Notifier) NotifyDBDumpFailed(message, errMsg string) { - n.PushEvent("db_dump_failed", "error", message, DBDumpDetails{Error: errMsg}) +// R-585: the headline is a bundle key, so it follows the household's language; errMsg is the cause. +func (n *Notifier) NotifyDBDumpFailed(errMsg string) { + n.pushEventMsg("db_dump_failed", "error", "event.db_dump_failed", DBDumpDetails{Error: errMsg}) } // NotifyDBDumpCompleted sends a DB dump success event. diff --git a/controller/scripts/i18n_go_keys.json b/controller/scripts/i18n_go_keys.json index 615e2ca..16cc114 100644 --- a/controller/scripts/i18n_go_keys.json +++ b/controller/scripts/i18n_go_keys.json @@ -1093,6 +1093,9 @@ "event.health_degraded": "Rendszer állapot romlott (volt: %s)", "event.health_recovered": "Rendszer állapot helyreállt: %s (volt: %s)", "event.db_dump_completed": "Adatbázis mentés elkészült", + "event.db_dump_failed": "Adatbázis mentés sikertelen", + "event.offbox_backup_failed": "Off-box (NAS) mentés sikertelen", + "event.offbox_enlarge_blocked": "A(z) %s teljes távoli mentése (~%s) túllépné a tárhelykeretet (%d/%d GB). A konfiguráció és az adatbázis továbbra is mentésre kerül; nagyobb kerethez vedd fel velünk a kapcsolatot.", "event.controller_updated": "Controller frissítve: %s → %s", "event.controller_update_failed": "Controller frissítés sikertelen: %s → %s", "event.controller_started": "Controller elindult (%s)",