hub v0.55.0: accept offbox_enlarge_blocked event (Task 3a-fix delivery chain)
allowedEventTypes gains offbox_enlarge_blocked (was 400 at ingestion, dropping the customer email). Deliberate NON-change: no customerMessages entry — the static map would discard the controller's dynamic two-number Hungarian message (templates.go:129 fallback is correct). event_test acceptance + 400 red-proof; templates_offbox_test locks the raw-message fallback. manifest bumped to :0.55.0.
This commit is contained in:
@@ -1,5 +1,22 @@
|
||||
# Felhom Hub — Changelog
|
||||
|
||||
## v0.55.0 — accept the offbox_enlarge_blocked event (Task 3a-fix delivery chain) (2026-07-15)
|
||||
|
||||
The controller (v0.134.1) sends an `offbox_enlarge_blocked` warning when an app's enlarged offsite
|
||||
push is refused by the quota gate (config+DB still saved). This closes the **ingestion** link of its
|
||||
delivery chain.
|
||||
|
||||
- **`internal/api/handler.go`:** `offbox_enlarge_blocked` added to `allowedEventTypes` — the event was
|
||||
400-rejected before (the customer email was dropped at ingestion). Acceptance case +
|
||||
400-red-proof added to `internal/api/event_test.go`.
|
||||
- **Deliberate NON-change:** NO `customerMessages` entry. `FormatCustomerEmail` (`templates.go:129`)
|
||||
gives the static per-type message PRIORITY over the raw message, so a static entry would DISCARD
|
||||
the controller's dynamic two-number Hungarian text (estimate + quota). The documented fallback (raw
|
||||
message survives) is the correct path; locked by a new `internal/notify/templates_offbox_test.go`
|
||||
assertion. `internal/notify/dispatcher.go` and the customer `EnabledEvents` whitelist are unchanged
|
||||
here — the controller side (v0.134.1) owns `DefaultEnabledEvents` + the prefs migration + the
|
||||
settings checkbox.
|
||||
|
||||
## v0.54.0 — operator login password changeable from the UI (2026-07-13)
|
||||
|
||||
The hub login password was previously settable ONLY by editing the `auth.password_hash` field in
|
||||
|
||||
@@ -78,6 +78,25 @@ func TestHandleEvent_UnknownEventTypeRejected(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Scenario D (controller v0.134.1): offbox_enlarge_blocked is an accepted controller-pushed type —
|
||||
// the enlarge-blocked notification's delivery chain starts at hub ingestion. Red-proof: removing the
|
||||
// allowlist entry makes this 400 (the pre-fix behavior that dropped the customer email).
|
||||
func TestHandleEvent_OffboxEnlargeBlockedAccepted(t *testing.T) {
|
||||
h, st := newEventTestHandler(t)
|
||||
|
||||
rr := do(h, http.MethodPost, "/event", "ckey", eventBody("warning", "offbox_enlarge_blocked"))
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200 (offbox_enlarge_blocked must be allowlisted); body=%s", rr.Code, rr.Body.String())
|
||||
}
|
||||
evs, err := st.GetRecentEvents("c1", 10)
|
||||
if err != nil {
|
||||
t.Fatalf("GetRecentEvents: %v", err)
|
||||
}
|
||||
if len(evs) != 1 || evs[0].EventType != "offbox_enlarge_blocked" {
|
||||
t.Errorf("stored = %+v, want exactly one offbox_enlarge_blocked event", evs)
|
||||
}
|
||||
}
|
||||
|
||||
// Auth: no bearer at all is a 401 and stores nothing.
|
||||
func TestHandleEvent_Unauthorized(t *testing.T) {
|
||||
h, st := newEventTestHandler(t)
|
||||
|
||||
@@ -1434,6 +1434,10 @@ var allowedEventTypes = map[string]bool{
|
||||
"backup_integrity_failed": true,
|
||||
"crossdrive_completed": true,
|
||||
"crossdrive_failed": true,
|
||||
// controller v0.134.1 — enlarged offsite push refused by the quota gate (warning; the controller's
|
||||
// dynamic Hungarian message is customer-grade — deliberately NO customerMessages entry, which would
|
||||
// discard the numbers (templates.go:129 priority)).
|
||||
"offbox_enlarge_blocked": true,
|
||||
"storage_disconnected": true,
|
||||
"storage_reconnected": true,
|
||||
"disk_warning": true,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package notify
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFormatCustomerEmail_OffboxEnlargeBlockedRawMessageSurvives locks in the deliberate non-change
|
||||
// (Task 3a-fix): offbox_enlarge_blocked has NO customerMessages entry, so FormatCustomerEmail falls
|
||||
// back to the controller's raw dynamic Hungarian message (templates.go:129) — the two-number text
|
||||
// (estimate + quota) reaches the customer intact. A static customerMessages entry would DISCARD it.
|
||||
func TestFormatCustomerEmail_OffboxEnlargeBlockedRawMessageSurvives(t *testing.T) {
|
||||
// exactly the shape the controller sends (NotifyOffboxEnlargeBlocked).
|
||||
raw := "A(z) immich teljes távoli mentése (~42.0 GB) túllépné a tárhelykeretet (20/50 GB). " +
|
||||
"A konfiguráció és az adatbázis továbbra is mentésre kerül; nagyobb kerethez vedd fel velünk a kapcsolatot."
|
||||
|
||||
// guard: the map must NOT gain an entry for this type (the trap).
|
||||
if _, ok := customerMessages["offbox_enlarge_blocked"]; ok {
|
||||
t.Fatal("offbox_enlarge_blocked must have NO customerMessages entry (it would discard the dynamic numbers)")
|
||||
}
|
||||
|
||||
subject, body := FormatCustomerEmail("c1", "offbox_enlarge_blocked", "warning", raw, "")
|
||||
for _, want := range []string{"~42.0 GB", "20/50 GB"} {
|
||||
if !strings.Contains(body, want) {
|
||||
t.Errorf("email body must carry the dynamic figure %q (raw message survived): %s", want, body)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(subject, "túllépné a tárhelykeretet") {
|
||||
t.Errorf("subject must carry the raw message, got %q", subject)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -125,7 +125,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: hub
|
||||
image: gitea.dooplex.hu/admin/felhom-hub:0.54.0
|
||||
image: gitea.dooplex.hu/admin/felhom-hub:0.55.0
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
|
||||
Reference in New Issue
Block a user