docs/assumptions-2026-10-14.md gets its second half: every entry of the inventory settled in the source of the version the image runs, with the citation now beside it in the code. 559 verdicts (the documents' claims that repeat one another answered once): 415 hold, 77 hold in part, 55 do not hold, 12 need a measurement on the stand. The plan's heuristics line is done; what the sources contradict becomes fourteen lines of stage 2c, worst first: rspamd signs a forged verdict for a client it counts as local; the sender check takes any key of the sender map where Postfix takes the first; expiry, the forced-expire flag and Postfix's time units; refusals and recipients matched by what Postfix really writes; postlogd after a rename; inbound mail over 10 MB refused by cleanup; master outside supervisord's reach; sasldb written in place; Health showing a socket file and a certificate Postfix does not serve; the Origin check refusing every POST where Sec-Fetch-Site is missing; two processes migrating at once; certbot's symlinks; the documents; and the measurements. Roadmap 31/81. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+1695
-1
File diff suppressed because it is too large
Load Diff
+107
-1
@@ -873,7 +873,7 @@ those after it move up one patch number each.
|
||||
shared files of lines (`from-lines-passed.txt`, `from-lines-other.txt`)
|
||||
are kept: the second one's test becomes "never signed for {other}"
|
||||
rather than "refused". - **Opus**
|
||||
- [ ] **The heuristics review: every assumption about another component,
|
||||
- [x] **The heuristics review: every assumption about another component,
|
||||
answered from its source** (owner, 2026-10-14: "нам нужно полное ревью
|
||||
кода на предмет всей этой эвристики. Её не должно там, где можно
|
||||
посмотреть код и ответить точно и однозначно" and "в коде таких наших
|
||||
@@ -893,6 +893,112 @@ those after it move up one patch number each.
|
||||
window), the smtpd that outlives a reload (measured, not understood), the
|
||||
NOQUEUE line's fields (two fixtures carry a sasl_username= Postfix does
|
||||
not write, one presented as seen on the stand). - **Opus**
|
||||
*Done 2026-10-14:* the register holds 621 entries and their answers; the
|
||||
citations are in the code (`ce363f4`, `b113e72`, `599149b`, `ad3d834`).
|
||||
What the sources contradict is fixed by the lines below, each named by
|
||||
its register entries; the measurements the sources cannot replace are
|
||||
the last of them.
|
||||
- [ ] **Forged filter verdicts signed** (C-R7, B-R1): rspamd 3.11.1's
|
||||
milter_headers skips its verdict routines - nothing removed, nothing
|
||||
added - for a client in `local_addrs` or an authenticated one
|
||||
(`skip_local`, `skip_authenticated`, both on by default), while the
|
||||
custom signature routine runs for every message; a sender on a private
|
||||
address, or every sender when Docker's proxy shows the bridge gateway,
|
||||
gets his own `X-Spamd-Result` signed. Both set to false; a dev trial in
|
||||
a throwaway rspamd 3.11.1 (`rspamc --ip 10.0.0.5` with a forged header)
|
||||
shows it removed and rspamd's own added. The image tag pinned to
|
||||
`3.11.1` (C-R12); the from-rules take the envelope only,
|
||||
`extract_from = "smtp"` (C-R4); the dead `prefilter = true` lines go
|
||||
(C-R5). - **Opus**
|
||||
- [ ] **The sender map read as Postfix reads it** (B-PS1): Postfix takes the
|
||||
owners of the first key `mail_addr_find()` finds - the address, then
|
||||
without its extension, then `@domain` - not any key that lists the
|
||||
login; today an application holding `@domain` may put in `From:` an
|
||||
address a list-mode application of the same domain owns, which Postfix
|
||||
refuses it as envelope sender. First key wins; tests with a list and a
|
||||
wildcard application on one domain. The map parser reads continuation
|
||||
lines and blank-separated owners as Postfix does (B-PS4). - **Opus**
|
||||
- [ ] **Queue lifetimes read as Postfix reads them** (A-8, B-PQ1, B-PQ10,
|
||||
B-PQ11): expiry is one qmgr line per message, `<id>: from=<..>,
|
||||
status=expired, returned to sender`, without `to=` - the tailer maps it
|
||||
to every open row of that id, closed as bounced, and the dead
|
||||
per-recipient `expired` case goes; `postqueue -p` marks a forced-expired
|
||||
message `#`, which the listing parser keeps; a bare number in a time
|
||||
parameter takes the parameter's own default unit (d for the lifetimes, h
|
||||
for delay_warning_time) and `conv_time()` reads one number and one unit.
|
||||
- **Opus**
|
||||
- [ ] **Refusals matched by what Postfix writes** (A-21, A-23, A-15, A-24):
|
||||
smtpd's `milter-reject` line carries `sasl_username=` - the refusal is
|
||||
matched on the login too, so two applications behind one address sending
|
||||
as one sender are told apart; `sasl_username=` ends at a comma
|
||||
(`sasl_sender=` may follow); cleanup's `to=` is the last recipient only,
|
||||
which the rows built from it say; the `IPv6:` trim goes. - **Opus**
|
||||
- [ ] **Recipients matched by what Postfix writes** (B-G5, D-S20, A-9,
|
||||
A-31): go-milter hands the address without brackets and parameters, so
|
||||
`cleanAddress` cuts no blank; Postfix keeps a recipient's case, so the
|
||||
match is exact; a rewritten recipient is matched by `orig_to=`; a
|
||||
recipient given twice is one row (cleanup drops the duplicate). Tests
|
||||
through go-milter's own client. - **Opus**
|
||||
- [ ] **The log tailer's rotation and stamps** (A-33, A-12): postlogd writes
|
||||
to the renamed file until `postfix reload`, so the old file is drained
|
||||
for a while after the switch, not once; no Postfix writes the ISO stamp
|
||||
`isoStampRe` was made for - it goes, and the fixtures take the syslog
|
||||
stamp Postfix 3.7 writes. - **Opus**
|
||||
- [ ] **Inbound mail over 10 MB** (C-P31): cleanup runs with main.cf's
|
||||
`message_size_limit`, never set, so 10240000 bytes, whatever port 25's
|
||||
`-o` says - a 12 MB message to the inbound relay is accepted through
|
||||
DATA and then refused 552. cleanup gets the largest listener limit; e2e
|
||||
sends 12 MB inbound. And `local_transport = error:...` (C-P8): an
|
||||
address literal of the container's own address is local today.
|
||||
- **Opus**
|
||||
- [ ] **Supervision as supervisord does it** (C-P42, C-V5, C-V6, C-V10,
|
||||
B-U2, C-P34): master leaves the shell's process group, so stopping the
|
||||
program never stops Postfix - the wrapper traps TERM and runs `postfix
|
||||
stop`; `startsecs` above the milter wait for Postfix and 1 for logrotate
|
||||
so a failure reaches FATAL (logrotate's not taking the container down);
|
||||
postfix-reload rests in EXITED after a run; a reload's exit status is
|
||||
read, not assumed; the dead set-permissions branch goes. e2e: restart
|
||||
of the program, stop of the container. - **Opus**
|
||||
- [ ] **sasldb written in place** (C-S3, C-Q3): Cyrus opens sasldb2 without
|
||||
a Berkeley DB environment, so without locks, and `saslpasswd2` writes in
|
||||
place; an AUTH or a backup during a change can read it torn. The panel
|
||||
writes a copy and renames it, and the backup reads it under the same
|
||||
lock. - **Opus**
|
||||
- [ ] **Health says what is served** (A-38, A-65, D-P1, D-P3): a socket file
|
||||
is not a listener - unix sockets are dialled as inet ones are; the
|
||||
certificate shown is the one Postfix serves (`postconf -h
|
||||
smtpd_tls_cert_file`), with a renewal waiting named; the wording of
|
||||
"Postfix defers mail" and of Required TLS (mockup first). - **Opus**
|
||||
- [ ] **The panel in browsers without Sec-Fetch-Site** (D-B3, D-B13): under
|
||||
`Referrer-Policy: no-referrer` a form POST carries `Origin: null`, which
|
||||
the origin check refuses - every POST, sign-in included, fails in Safari
|
||||
before 16.4 and over plain HTTP at a name; `same-origin` instead, with a
|
||||
header test and one POST on the stand. A shown-once secret is blanked on
|
||||
`pagehide`; `Pragma` goes. - **Opus**
|
||||
- [ ] **Two processes opening an old database** (D-S3): `user_version` is
|
||||
read outside the transaction, so the panel and dmarc-ingest can both
|
||||
run one migration; `_txlock=immediate` and the version re-read inside
|
||||
it; a test with two concurrent opens behind a held lock. - **Opus**
|
||||
- [ ] **Certificates from certbot** (C-A1, C-Q4, D-guide:258, :291, :722):
|
||||
certbot's `live/` files are relative links into `archive/`, so mounting
|
||||
`live/<host>` alone, or linking `certs` to it, leaves Postfix without a
|
||||
certificate and the backup without it. The deploy fragments mount
|
||||
`/etc/letsencrypt` read-only and point the paths into it; the backup
|
||||
follows a link under `certs/` to a regular file. - **Opus**
|
||||
- [ ] **The rest of what the sources contradict** (C-M7 `<pct>0</pct>`,
|
||||
C-E2 the e2e zone serial, C-D1 a release gate comparing the image's
|
||||
package versions with the ones cited, C-K8/K9 and the comments the
|
||||
answers name), and **the documents**: every claim of architecture.md,
|
||||
security.md and guide.md the answers find false or partly true is
|
||||
rewritten as the answers propose (D-arch, D-sec, D-guide). - **Sonnet**
|
||||
- [ ] **What only the stand can answer** (A-43, C-K5, C-M8, C-X1, D-S7,
|
||||
D-B16 and the document claims marked so): postlog's set-gid in the
|
||||
image; the client address Postfix sees through Docker's port publishing
|
||||
over IPv4 and IPv6; the largest DMARC report received; the public keys
|
||||
of an ECDSA pair as the reload hook compares them; the longest write
|
||||
against busy_timeout at the retention limit; the favicon each browser
|
||||
takes. Each measured, dated and written beside the code it settles.
|
||||
- **Opus**
|
||||
- [ ] Docs and wording: help topic sender-check and guide § Who an
|
||||
application may send as (mockup first), security.md § Mail path,
|
||||
CHANGELOG. - **Sonnet**
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ in `git log` and [CHANGELOG.md](../CHANGELOG.md).
|
||||
| from-header-binding | Hold a message's `From:` header against the application that sends it | shipped `2.4.0` | 9/9 | [plans/from-header-binding.md](plans/from-header-binding.md) |
|
||||
| panel-redesign | Panel redesign (accepted mockups, design contract) | shipped `2.0.0` | 27/27 | [plans/panel-redesign.md](plans/panel-redesign.md) |
|
||||
| schema-squash | Squash SQLite migrations into a 2.x baseline | built in panel-redesign (stage 1) | — | [plans/panel-redesign.md](plans/panel-redesign.md) |
|
||||
| audit-2026-10-12 | Follow-ups of the 2026-10-12 full-tree code audit, seven stages | in progress (stage 0 shipped `2.4.2`, stages 1+2 `2.5.0`, 2b `2.5.1`; next stage 2c → `2.5.2`) | 30/66 | [audit-2026-10-12.md](audit-2026-10-12.md) |
|
||||
| audit-2026-10-12 | Follow-ups of the 2026-10-12 full-tree code audit, seven stages | in progress (stage 0 shipped `2.4.2`, stages 1+2 `2.5.0`, 2b `2.5.1`; next stage 2c → `2.5.2`) | 31/81 | [audit-2026-10-12.md](audit-2026-10-12.md) |
|
||||
|
||||
**Recommended order** (not binding; owner, 2026-10-09: feature order follows
|
||||
development convenience): **panel-redesign** shipped as `2.0.0` (2026-10-11) and
|
||||
|
||||
Reference in New Issue
Block a user