From e81ad613aec6ed685a7f19df1cf108cbd8f02f3a Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Fri, 18 Sep 2026 17:06:20 +0200 Subject: [PATCH] v0.256.1: the push log says whether a household sentence was attached (R-558) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found while trying to PROVE v0.256.0 on a live box: there was nothing to look at. The box logs the Hungarian message only, the hub logs the Hungarian message only, and the payload is inside TLS - so "did the box attach a second sentence?" was unanswerable from either end. That is the fork in the diagnosis when an English household reports a Hungarian mail. [INFO] Event pushed: app_deployed (info) [+household(en)] — Alkalmazás ... [INFO] Event pushed: app_deployed (info) [hu-only] — Alkalmazás ... The sentence itself is not logged: it is the same sentence twice and one copy is already on the line. Pinned in both languages. A feature whose only failure mode is "the wrong language arrived" needs an observable that says which branch was taken. Without one, every diagnosis is a guess. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- CHANGELOG.md | 20 +++++++++ .../internal/notify/message_customer_test.go | 44 +++++++++++++++++++ controller/internal/notify/notifier.go | 12 ++++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f40679e..f39f5c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +## v0.256.1 — the push log says whether a household sentence was attached (2026-09-18, R-558) + +**MinAgent: 0.131.0** (unchanged). One log line, no behaviour change. + +Found while trying to PROVE v0.256.0 on a live box: there was nothing to look at. `Event pushed:` logs +the Hungarian message only, the hub logs the Hungarian message only, and the payload is inside TLS — +so "did the box attach a second sentence?" was unanswerable from either end. That is the fork in the +diagnosis when an English household reports a Hungarian mail, and it had no observable. + +``` +[INFO] Event pushed: app_deployed (info) [+household(en)] — Alkalmazás telepítve: PrivateBin +[INFO] Event pushed: app_deployed (info) [hu-only] — Alkalmazás telepítve: PrivateBin +``` + +The sentence itself is not logged — it is the same sentence twice and one copy is already on the +line. Pinned by `TestPushLogNamesWhetherAHouseholdSentenceWasAttached` in both languages. + +**The general form: a feature whose only failure mode is "the wrong language arrived" needs an +observable that says which branch was taken. Without one, every diagnosis is a guess.** + ## v0.256.0 — the box sends its own sentence in the household's language (2026-09-18, R-558 Part B) **MinAgent: 0.131.0** (unchanged). **Needs hub v0.118.0+**, which shipped first and tolerates a box diff --git a/controller/internal/notify/message_customer_test.go b/controller/internal/notify/message_customer_test.go index 3fe1d58..957ea98 100644 --- a/controller/internal/notify/message_customer_test.go +++ b/controller/internal/notify/message_customer_test.go @@ -3,9 +3,12 @@ package notify import ( "io" "log" + "net/http" + "net/http/httptest" "path/filepath" "strings" "testing" + "time" "gitea.dooplex.hu/admin/felhom-controller/internal/i18n" "gitea.dooplex.hu/admin/felhom-controller/internal/settings" @@ -167,3 +170,44 @@ func TestUntranslatableTailIsKeptInBothLanguages(t *testing.T) { t.Errorf("the English sentence is wrong: %q (hu %q)", en, hu) } } + +// The push log says WHETHER a household sentence was attached. +// +// It is the only observable an operator has. The hub logs the Hungarian message only, and the +// payload itself is inside TLS — so without this line, "did the box send a second sentence?" is +// unanswerable from either end, which is exactly the question a mis-languaged mail raises. +func TestPushLogNamesWhetherAHouseholdSentenceWasAttached(t *testing.T) { + for _, tc := range []struct { + lang, want, notWant string + }{ + {"en", "+household(en)", "hu-only"}, + {"hu", "hu-only", "+household"}, + } { + var buf strings.Builder + sett, err := settings.Load(filepath.Join(t.TempDir(), "s.json"), log.New(io.Discard, "", 0)) + if err != nil { + t.Fatal(err) + } + if err := sett.SetLanguage(tc.lang); err != nil { + t.Fatal(err) + } + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + defer srv.Close() + + n := New(srv.URL, "k", "c1", sett, log.New(&buf, "", 0), false) + n.NotifyAppDeployed("privatebin", "PrivateBin") + // PushEvent's send is a goroutine; wait for the line rather than sleeping a fixed time. + for i := 0; i < 200 && !strings.Contains(buf.String(), "Event pushed"); i++ { + time.Sleep(10 * time.Millisecond) + } + got := buf.String() + if !strings.Contains(got, tc.want) { + t.Errorf("%s: the push log does not say %q:\n%s", tc.lang, tc.want, got) + } + if strings.Contains(got, tc.notWant) { + t.Errorf("%s: the push log says %q:\n%s", tc.lang, tc.notWant, got) + } + } +} diff --git a/controller/internal/notify/notifier.go b/controller/internal/notify/notifier.go index 64a50ad..1a49cad 100644 --- a/controller/internal/notify/notifier.go +++ b/controller/internal/notify/notifier.go @@ -326,7 +326,17 @@ func (n *Notifier) pushEventBoth(eventType, severity, message, messageCustomer s if n.debug { n.logger.Printf("[DEBUG] PushEvent: %s pushed OK (HTTP %d)", eventType, resp.StatusCode) } - n.logger.Printf("[INFO] Event pushed: %s (%s) — %s", eventType, severity, message) + // The household half is named, not printed. An operator asking "why did my English + // customer get a Hungarian mail?" needs to know whether the BOX attached a second + // sentence at all — that is the fork in the diagnosis, and without it the answer is + // invisible on both sides of the wire (the hub logs only the Hungarian, and the + // payload is inside TLS). The sentence itself is not logged: it is the same sentence + // twice, and one copy is already on the line. + household := "hu-only" + if messageCustomer != "" { + household = "+household(" + n.boxLang() + ")" + } + n.logger.Printf("[INFO] Event pushed: %s (%s) [%s] — %s", eventType, severity, household, message) n.recordHistory(eventType, severity, message, resp.StatusCode, "") return }