diff --git a/docs/audit-2026-10-12.md b/docs/audit-2026-10-12.md index d213627..c949f38 100644 --- a/docs/audit-2026-10-12.md +++ b/docs/audit-2026-10-12.md @@ -898,7 +898,7 @@ those after it move up one patch number each. 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 +- [x] **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 @@ -910,7 +910,8 @@ those after it move up one patch number each. `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 + *Done 2026-10-14:* `31c2b50`. +- [x] **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 @@ -918,7 +919,9 @@ those after it move up one patch number each. 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, + *Done 2026-10-14:* `55aef6e`; a key given twice makes the check defer, + as it makes Postfix refuse the table. +- [x] **Queue lifetimes read as Postfix reads them** (A-8, B-PQ1, B-PQ10, B-PQ11): expiry is one qmgr line per message, `: 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 @@ -927,30 +930,38 @@ those after it move up one patch number each. 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): + *Done 2026-10-14:* `0ed03b2`, with the next line. +- [x] **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, + *Done 2026-10-14:* `0ed03b2`. +- [x] **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 + *Done 2026-10-14:* `c8f6697`; the match stays case-insensitive, now with + its reason from the source (D-S20). +- [x] **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 + *Done 2026-10-14:* `463d4ff`; the renamed file is read for a minute + after the switch. +- [x] **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** + *Done 2026-10-14:* `e174537`; cleanup takes port 25's limit when it is + larger than main.cf's; Postfix refuses the address literal at RCPT. - [ ] **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 diff --git a/docs/roadmap.md b/docs/roadmap.md index 43160a9..045c5ad 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -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`) | 31/81 | [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`) | 38/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