send log: rows belong to a domain by id (audit L12, 0008)
A domain user's log, the message page, a domain's statistics, the level-2 count and the notifier's refusal count picked send-log rows by domain name, so a domain deleted and re-added under its old name showed its earlier mail to the next assignee and went on counting it. Migration 0008 (not run on the live database yet, so extended here): send_log.domain_id and inbound_spam_log.inbound_domain_id, REFERENCES ... ON DELETE SET NULL, filled once by name from the registry as it is at migration time, each with an (id, created_at) index. - Writes: InsertQueued / InsertRejected set domain_id to the domain of the row's login (loginDomainID) - the journal milter and the sender check's refusal rows both go through them; the inbound journal sets inbound_domain_id from the inbound domain's name at insert. - Reads: SendLogFilter.DomainIDs (was Domains, by name) and InboundSpamFilter.DomainIDs are the scope; the global role still reads everything. The message page checks row.DomainID against the user's domains. DomainSendStats and CountMessages keep their name argument and select domain_id = (SELECT id FROM domains WHERE name = ?). The notifier joins send_log.domain_id to the domain and its application. - DMARC reports stay by name on purpose (a report is about the DNS name). Tests: store - scope by ids; a re-added domain's log, level-2 count and statistics hold its own row only, the global log both; inbound scope by ids. Handlers - the new assignee gets 404 for the old row's page and does not see it in the log, the global role sees both. Tests that wrote rows for a login that is no application now register it (a row is a domain's through its application). Schema at 0008 with the two columns and indexes. schema-migrations row 8, CHANGELOG [Unreleased], audit plan line ticked, roadmap 19/62. Evidence: go vet ./... clean; go test ./... ok locally but for the two Windows-only tests; the server run follows before the push. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,3 +9,20 @@
|
||||
-- (case-sensitive) stays: SQLite cannot change a column's collation without
|
||||
-- rebuilding the table, and this index is the stricter rule.
|
||||
CREATE UNIQUE INDEX idx_applications_login_nocase ON applications (login COLLATE NOCASE);
|
||||
|
||||
-- A send-log row belongs to a domain by its id, not its name (audit L12; the
|
||||
-- owner, 2026-10-12). A domain deleted and added again under its old name
|
||||
-- used to show the earlier rows to whoever it was assigned to next. The id is
|
||||
-- the domain of the login the row was written for; a row of a domain deleted
|
||||
-- since - and every row older than this migration whose domain is gone - is
|
||||
-- NULL and nobody's but the global role's. The name stays for display and for
|
||||
-- the global view. Filled once from the registry as it is now.
|
||||
ALTER TABLE send_log ADD COLUMN domain_id INTEGER REFERENCES domains(id) ON DELETE SET NULL;
|
||||
UPDATE send_log SET domain_id = (SELECT d.id FROM domains d WHERE d.name = send_log.domain);
|
||||
CREATE INDEX idx_send_log_domain_id_created_at ON send_log (domain_id, created_at);
|
||||
|
||||
-- The inbound journal follows the same rule, so the two logs do not follow two
|
||||
-- (security.md's accepted risk of the inbound log, struck).
|
||||
ALTER TABLE inbound_spam_log ADD COLUMN inbound_domain_id INTEGER REFERENCES inbound_domains(id) ON DELETE SET NULL;
|
||||
UPDATE inbound_spam_log SET inbound_domain_id = (SELECT d.id FROM inbound_domains d WHERE d.name = inbound_spam_log.inbound_domain);
|
||||
CREATE INDEX idx_inbound_spam_log_domain_id_created_at ON inbound_spam_log (inbound_domain_id, created_at);
|
||||
|
||||
Reference in New Issue
Block a user