New OPERATOR-ONLY event type recovery_unit_capture_failed (controller v0.191.0, R-158): in allowedEventTypes AND notify.operatorOnlyEvents. Deliberately not a reuse of backup_failed, which carries customer copy and sits in the controller's DefaultEnabledEvents — reusing it would email the customer in Hungarian about a failure they cannot act on. R-158's own proposal said backup_failed; D-c overrides it. disk_warning/disk_critical lose their generic customerMessages entries. Both were allowlisted, copy'd, default-enabled and checkbox'd with NO producer anywhere; controller v0.191.0 becomes that producer and sends a DYNAMIC Hungarian message naming the drive and its free space. FormatCustomerEmail prefers the entry over the message, so keeping a static entry would discard the label and the byte figures — the same reason offbox_enlarge_blocked and disk_health_degraded have none. The deletion is pinned by a test. New notify.IsOperatorOnly so the api package can pin BOTH registers of a new event type in ONE test; allowlisted-but-not-operator-only is invisible when they are checked separately, and it is the defect v0.78.0 shipped. The register itself stays unexported. REUSE.md's "new event type" extension point rewritten: it told readers to always add a customerMessages entry, which is wrong for operator-only types and harmful for dynamic-message ones. Tests 574 -> 579. Red-proof: removing the operatorOnlyEvents entry shows the customer being emailed; the skipped/operator_only row is asserted as a positive observable.
This commit is contained in:
@@ -189,7 +189,12 @@
|
||||
|
||||
## 5. Extension points (where new features plug in)
|
||||
|
||||
- **New event type**: add to `allowedEventTypes` (hub/internal/api/handler.go ~L1063) **and** `customerMessages` (hub/internal/notify/templates.go) **and** the customer-prefs default list if customer-notifiable. Missing the first = controller POST 400s (the known gotcha).
|
||||
- **New event type — THREE registers, and which ones depend on the AUDIENCE.** Always: `allowedEventTypes` (hub/internal/api/handler.go) — missing it means the controller's POST 400s and the event vanishes (the known gotcha). Then decide the audience and stop guessing from the other registers:
|
||||
- **Operator-only** → add to `notify.operatorOnlyEvents` (hub/internal/notify/dispatcher.go) and give it **no** `customerMessages` entry. **Allowlisting alone does NOT make a type 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. v0.78.0 asserted the opposite in a comment and shipped the defect (R-97c). Examples: `whole_guest_backup_failed`, `recovery_unit_capture_failed`.
|
||||
- **Customer-facing with a STATIC message** → add a `customerMessages` entry (hub/internal/notify/templates.go) and the controller's `settings.DefaultEnabledEvents` if it should be on by default.
|
||||
- **Customer-facing with a DYNAMIC message** (the producer builds Hungarian text carrying names/numbers) → deliberately **no** `customerMessages` entry: `FormatCustomerEmail` PREFERS the entry over the message, so adding one silently discards the specifics. Examples: `offbox_enlarge_blocked`, `disk_health_degraded`, and since v0.89.0 `disk_warning`/`disk_critical`.
|
||||
- Pin BOTH registers in ONE test (hub/internal/api/recovery_unit_event_test.go is the model) — fixing one and not the other is the realistic mistake, and `notify.IsOperatorOnly` exists so the api package can assert it.
|
||||
- **A type in these registers with no PRODUCER is inert.** `disk_warning`/`disk_critical` were allowlisted, copy'd, default-enabled and checkbox'd from early on, and nothing in any repo emitted them until controller v0.191.0 — grep for an emitter before assuming a type works.
|
||||
- **New monitor checker**: copy hub/internal/monitor/staleness.go (§2 pattern); wire in hub/cmd/hub/main.go with an `EventNotifyFunc`; severity must be warning/error/critical to notify.
|
||||
- **New API route**: switch in `api.ServeHTTP` (handler.go ~L139); auth helper first line.
|
||||
- **New web page/action**: switch in `web.ServeHTTP` (server.go ~L182) — non-GET gets CSRF automatically; template into hub/internal/web/templates/ (embedded FS, parsed in `web.New`); new helpers into the funcMap (server.go ~L67).
|
||||
|
||||
Reference in New Issue
Block a user