build, deploy, inbound, dmarc, backup, e2e: cite the source of what they rely on (assumptions part C)

Comments only, no behaviour changed. Each main.cf/master.cf parameter the
build sets, the wrapper's and the reload hook's reliance on Postfix 3.7.11
(postfix-script, master.5, postconf.5, cleanup_init.c, smtpd_peer.c,
README_FILES), supervisor 4.2.5 (process.py, options.py, events.rst),
logrotate 3.21.0, OpenDKIM's config, Cyrus SASL's sasldb, rspamd 3.11.1
(milter_headers.lua, multimap, the map watcher), Docker Compose, CoreDNS
and certbot now say where that is written. Measurements already there stay
measurements ("date not recorded" where none was); hand-composed fixtures
say so.

Contradictions left for their own commits: C-P31 cleanup's size limit,
C-P42 master outside supervisor's signal, C-V5/V6 startsecs, C-V10,
C-S3/Q3 sasldb written in place, C-Q4/A1 certbot's symlinks, C-R7 rspamd
skips local clients but the signature routine does not, C-P8, C-R4, C-R12,
C-M7, C-E2, C-K8/K9, C-D1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-14 19:39:21 +03:00
co-authored by Claude Opus 5.5
parent ad3d834392
commit 599149bf83
39 changed files with 417 additions and 59 deletions
+17 -1
View File
@@ -33,6 +33,12 @@ type ListStore interface {
// line, and the filter (rspamd, deploy/antispam/rspamd/multimap.conf) rereads
// a file when it changes. Which list wins when both match is the filter's
// configuration: deny.
//
// rspamd 3.11.1, src/libserver/maps/map.c: a file map is watched with libev's
// ev_stat (inotify, or a stat poll every map_watch_interval x
// map_file_watch_multiplier = 30 s, conf/options.inc), so a change takes
// effect within that, not at once; docs.rspamd.com/configuration/maps asks
// for the atomic rename atomicfile.Write does.
type Lists struct {
store ListStore
dir string
@@ -157,7 +163,10 @@ func (l *Lists) sync() error {
}
// Values were validated on the way in; this is the writer's own guard
// against a row that got into the table some other way. In a map file a
// newline ends the entry, whitespace starts its value and # a comment.
// newline ends the entry, whitespace starts its value and # a comment
// (rspamd 3.11.1, src/libserver/maps/map_helpers.c,
// rspamd_parse_kv_list()). An IP map takes bare v4 and v6 addresses and
// CIDR networks (docs.rspamd.com/configuration/maps, IP maps).
if err := configsafe.Token("filter list entry", e.Value, " \t\r\n#"); err != nil {
return err
}
@@ -165,6 +174,8 @@ func (l *Lists) sync() error {
}
// The filter runs under another user in another container: the directory
// and the files are readable by anyone. They hold addresses, not secrets.
// (The rspamd image runs as uid 11333: rspamd-docker v3.11.1+3,
// Dockerfile, USER 11333:11333.)
if err := os.MkdirAll(l.dir, 0o755); err != nil {
return fmt.Errorf("create %s: %w", l.dir, err)
}
@@ -297,6 +308,11 @@ func normalizeNote(raw string) (string, error) {
// refuses with a message, which the log tailer files as the reply of a
// rejected row. An allow rule adds a symbol named after the kind of entry,
// which the journal milter keeps in the verdict of an accepted row.
//
// rspamd 3.11.1: the deny message reaches Postfix as the milter reply "554
// 5.7.1 <message>" (src/libserver/milter.c, rspamd_milter_send_task_results());
// src/plugins/lua/milter_headers.lua, routine x-spamd-result, writes each
// symbol as "%s(%.2f)[%s]" - name, score, options.
const (
denyReplyMark = "this server's deny list"
allowMark = "SELFPOST_ALLOW_"
+3
View File
@@ -314,6 +314,9 @@ func TestListsUsage(t *testing.T) {
t.Fatal(err)
}
}
// The rows below are composed by hand. Their replies and verdicts follow
// rspamd 3.11.1's forms: "Spam message rejected" is the proxy's default
// reject_message (conf/worker-proxy.inc).
// hour 1: the address and its domain are both on the deny list, and both fit.
row("Spammer@Evil.Example", "192.0.2.9", store.SpamDecisionReject, store.SpamEngineRspamd, denied)
// hour 2: another address of the domain.