From a08f407dc8d7058e9ead17463c3cd91153bf3f51 Mon Sep 17 00:00:00 2001 From: sneak Date: Fri, 2 Oct 2026 06:09:21 +0000 Subject: [PATCH] watcher: startup notification no longer says every endpoint works (closes #230) The startup notification ended "All notification channels are working.", but it is written once and handed to every notification endpoint before any delivery has succeeded or failed, so the claim was never checked and was false whenever one endpoint refused it. It now says only that it is a test sent to every configured notification endpoint. The startup notification test checks the whole message. Model: opus-5-5 --- TODO.md | 2 ++ internal/watcher/watcher.go | 8 +++++--- internal/watcher/watcher_test.go | 13 +++++++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/TODO.md b/TODO.md index 927a598..69b5628 100644 --- a/TODO.md +++ b/TODO.md @@ -19,6 +19,8 @@ trial run of the finished image: https://git.eeqj.de/sneak/dnswatcher/issues/149 # Completed Steps +- 2026-10-02: the startup notification no longer says every notification + endpoint works; it says it is a test sent to each of them (closes #230). - 2026-10-02: a resolver test that reads one record type from a nameserver's answer asks again when that type is missing from it (closes #218). - 2026-10-02: a plain `docker build .` of a clone stamps its tag or short diff --git a/internal/watcher/watcher.go b/internal/watcher/watcher.go index bcee203..4bb3579 100644 --- a/internal/watcher/watcher.go +++ b/internal/watcher/watcher.go @@ -1049,8 +1049,9 @@ func (w *Watcher) saveState() { // maybeSendTestNotification sends a startup status notification // after the first full scan completes, if SEND_TEST_NOTIFICATION -// is enabled. The message is clearly informational ("all ok") -// and not an error or anomaly alert. +// is enabled. The message is informational, not an error or anomaly +// alert. It is written before it reaches any endpoint, so it claims +// nothing about whether the endpoints work. func (w *Watcher) maybeSendTestNotification(ctx context.Context) { if !w.config.SendTestNotification { return @@ -1062,7 +1063,8 @@ func (w *Watcher) maybeSendTestNotification(ctx context.Context) { "dnswatcher has started and completed its initial scan.\n"+ "Monitoring %d domain(s) and %d hostname(s).\n"+ "Tracking %d port endpoint(s) and %d TLS certificate(s).\n"+ - "All notification channels are working.", + "This is a test notification, sent to every configured "+ + "notification endpoint.", len(snap.Domains), len(snap.Hostnames), len(snap.Ports), diff --git a/internal/watcher/watcher_test.go b/internal/watcher/watcher_test.go index b527cb1..f82ca27 100644 --- a/internal/watcher/watcher_test.go +++ b/internal/watcher/watcher_test.go @@ -866,18 +866,27 @@ func TestSendTestNotification_ViaRun(t *testing.T) { notifications := deps.notifier.getNotifications() + // No names are configured, so every count is 0. + wantMessage := "dnswatcher has started and completed its initial scan.\n" + + "Monitoring 0 domain(s) and 0 hostname(s).\n" + + "Tracking 0 port endpoint(s) and 0 TLS certificate(s).\n" + + "This is a test notification, sent to every configured " + + "notification endpoint." + found := false for _, n := range notifications { if n.Priority == "success" && - n.Title == "✅ dnswatcher startup complete" { + n.Title == "✅ dnswatcher startup complete" && + n.Message == wantMessage { found = true } } if !found { t.Errorf( - "expected startup test notification, got: %v", + "expected startup test notification with message %q, got: %v", + wantMessage, notifications, ) }