panel-notifications: schema and store

Migration 0004_notifications.sql, DDL only: users.notify, a user's own
switch, on by default; notify_state, one row per subject the panel has
written about (dns:<domain>, cert, queue, limit:<domain>:<login>), so that
each thing is said once and a restart says nothing again.

Store: the instance switch as a settings key, on unless turned off;
SetUserNotify; NotifyRecipients - global users for everything, domain users
for the domains on their list or all of them, only with an e-mail and their
switch on, a shared mailbox once; the state's get, set, delete and list by
prefix; LimitRefusalsSince, the mail refused under a level-2 limit per domain
and application.

Nothing is sent yet. Checked on Windows: go vet clean, go test
./internal/store passes with the schema test at user_version 4. The page
guards fail from the design commit 87fa0a4 until the pages are built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-12 15:48:56 +03:00
co-authored by Claude Opus 5.5
parent 87fa0a4381
commit 06ad174fb9
9 changed files with 421 additions and 17 deletions
@@ -0,0 +1,28 @@
-- Notifications: the panel writes to its users when something needs them
-- (panel-notifications, 2.3.0). DDL only; nothing existing changes, and every
-- user starts with notifications on.
-- A user's own switch, on Account. It decides nothing by itself: a user is
-- written to when it is on, the profile has an e-mail and the instance switch
-- (settings key "notifications") is on.
ALTER TABLE users ADD COLUMN notify INTEGER NOT NULL DEFAULT 1 CHECK (notify IN (0, 1));
-- What the panel has already said, so that it says each thing once and a
-- restart announces nothing again. One row per subject:
-- dns:<domain> a sending domain's records
-- cert the TLS certificate
-- queue a message older than three days
-- limit:<domain>:<login> a level-2 limit that refused mail
-- phase is where the subject stands ("pending": seen wrong, not yet said;
-- "open": said; for the certificate, the threshold last said). count is the
-- checks in a row that agree with the phase's direction, mark what the phase
-- refers to (the certificate's expiry), since when it began, sent_at when the
-- last message about it went out.
CREATE TABLE notify_state (
key TEXT PRIMARY KEY,
phase TEXT NOT NULL,
count INTEGER NOT NULL DEFAULT 0,
mark TEXT NOT NULL DEFAULT '',
since TEXT NOT NULL,
sent_at TEXT NOT NULL DEFAULT ''
);