D62: restore copies kept 30 days, listed with their date, deletable by hand (typed name, never a needed copy, operator event); D63: a test-build-only fault switch for the R-1256 H4/H5 live proofs — tests red first
gates / gates (push) Successful in 33s
gates / gates (push) Successful in 33s
This commit is contained in:
1 parent
a815b37fbd
commit
e3fce09d96
24 files changed
+1992
-11
No files matched your search
@@ -0,0 +1,34 @@
|
||||
package notify
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// D62 — restore_copy_deleted: info (the hub's vocabulary), the operator message only (no household sentence — the hub
|
||||
// bars the type from customers too), and the details carry who, app, the restore's date and the size.
|
||||
func TestD62_RestoreCopyDeletedEvent(t *testing.T) {
|
||||
n := &Notifier{}
|
||||
var et, sev, msg, cust string
|
||||
var det []byte
|
||||
n.pushFn = func(eventType, severity, message, customer string, details interface{}) {
|
||||
et, sev, msg, cust = eventType, severity, message, customer
|
||||
det, _ = json.Marshal(details)
|
||||
}
|
||||
n.NotifyRestoreCopyDeleted(RestoreCopyDeletedDetails{App: "vikunja", RestoreAt: "2026-10-29T08:00:00Z", SizeBytes: 4096,
|
||||
Who: "the household (dashboard sign-in) from 192.168.0.5", Path: "/x/backups/restore-undo/vikunja/20261029T080000Z"})
|
||||
if et != "restore_copy_deleted" || sev != "info" || cust != "" {
|
||||
t.Fatalf("type=%q severity=%q customer=%q", et, sev, cust)
|
||||
}
|
||||
for _, want := range []string{"vikunja", "2026-10-29T08:00:00Z", "4096", "the household"} {
|
||||
if !strings.Contains(msg, want) {
|
||||
t.Fatalf("message %q lacks %q", msg, want)
|
||||
}
|
||||
}
|
||||
for _, want := range []string{`"app":"vikunja"`, `"restore_at":"2026-10-29T08:00:00Z"`, `"size_bytes":4096`, `"who":"the household`} {
|
||||
if !strings.Contains(string(det), want) {
|
||||
t.Fatalf("details %s lack %s", det, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1585,6 +1585,25 @@ func (n *Notifier) NotifyAppDefinitionRefused(app, detail string) {
|
||||
n.pushEventBoth("app_definition_refused", "warning", msg, "", AppDefinitionRefusedDetails{App: app, Refused: detail})
|
||||
}
|
||||
|
||||
// RestoreCopyDeletedDetails is restore_copy_deleted's record: who deleted which app's copy, the restore it protected,
|
||||
// and its size.
|
||||
type RestoreCopyDeletedDetails struct {
|
||||
App string `json:"app"`
|
||||
RestoreAt string `json:"restore_at"` // RFC 3339, UTC
|
||||
SizeBytes int64 `json:"size_bytes"`
|
||||
Who string `json:"who"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
// NotifyRestoreCopyDeleted (D62, operator 2026-10-29): the household deleted a restore copy with „Törlés most" before
|
||||
// its 30 days. Info, operator-only on the hub (registered in both of its lists, hub D62): an audit line for support,
|
||||
// never a household mail. Pinned by TestD62_RestoreCopyDeletedEvent.
|
||||
func (n *Notifier) NotifyRestoreCopyDeleted(d RestoreCopyDeletedDetails) {
|
||||
msg := fmt.Sprintf("%s: the restore copy from before the restore of %s (%d bytes) was deleted by hand — %s. That restore can no longer be undone from this box.",
|
||||
d.App, d.RestoreAt, d.SizeBytes, d.Who)
|
||||
n.pushEventBoth("restore_copy_deleted", "info", msg, "", d)
|
||||
}
|
||||
|
||||
// healthSeverity is the event severity a health status would be sent at (R-647): the disabled path
|
||||
// names what it drops, and "warn" is a health STATUS, not a severity the hub knows.
|
||||
func healthSeverity(status string) string {
|
||||
|
||||
Reference in new issue
Block a user