package api import ( "testing" "gitea.dooplex.hu/admin/felhom-hub/internal/notify" ) // R-158 / R-167 (D-c) — the per-app Tier-1 recovery-unit capture failure alert. // // A new event type is a PAIR of registers, and each half fails differently: // - missing from allowedEventTypes → POST /event returns 400 and the event VANISHES (R-97a); // - missing from operatorOnlyEvents → it is delivered TO THE CUSTOMER, in raw English, about a // failure they can take no action on. // // The second is the quiet one — delivery "works", so nothing looks broken. It is also the defect // v0.78.0 actually shipped: adding a type to allowedEventTypes and ASSUMING that made it // operator-only. `FormatCustomerEmail` treats a missing customerMessages entry as a fallback to the // raw message, not a block, and the only customer gate is configuration. Both halves are pinned // here, in the same test, because fixing one and not the other is the realistic mistake. func TestRecoveryUnitCaptureFailedIsAllowlistedAndOperatorOnly(t *testing.T) { const et = "recovery_unit_capture_failed" if !allowedEventTypes[et] { t.Fatalf("%s must be in allowedEventTypes, or POST /event 400s and a per-app Tier-1 backup "+ "failure reaches no hub channel at all — which is the R-158 gap, un-fixed", et) } if !notify.IsOperatorOnly(et) { t.Fatalf("%s is allowlisted but NOT in notify.operatorOnlyEvents — the customer would be "+ "emailed about a recovery-unit capture failure they can take no action on. Adding a type "+ "to allowedEventTypes does NOT make it operator-only; that was the v0.78.0 defect "+ "(corrected in v0.79.0/R-97c) and this is the same mistake one event later", et) } } // The customer's half of D-c must NOT be operator-only — a fill warning is precisely the alert a // customer CAN act on (free space, delete files, add a drive). Pinned in the same file as its // operator sibling so the routing decision is read as one thing, which is what D-c is. func TestFillWarningReachesTheCustomer(t *testing.T) { for _, et := range []string{"disk_warning", "disk_critical"} { if !allowedEventTypes[et] { t.Fatalf("%s must stay in allowedEventTypes — it is the customer fill warning the "+ "controller emits from v0.191.0 (R-167)", et) } if notify.IsOperatorOnly(et) { t.Fatalf("%s is in operatorOnlyEvents — the customer would never be warned that their "+ "disk is filling, which is the whole customer half of decision D-c", et) } } }