e2e: a negative case passes only on its own refusal (audit stage 0)
sendResult.refusedAt(stage, code, text) and replyIs(err, code, text):
nil only for the server's reply with that code and text at that stage;
a reset, a timeout or another reply is described for the failure.
- level 1: only anvil's "450 4.7.1 Error: too much mail from", only after
a message of the loop was accepted. Held to that, it failed twice on
the stand, each time for a real reason:
1. waitForSMTPSReady took a TCP connect for readiness; Docker's port
proxy accepts before Postfix listens and then resets - the reset
once taken for the limit. It now waits for the TLS 220 greeting.
2. the first message then got "553 ... not owned by user l1app": an
smtpd idle from before the panel's postfix reload took the
connection with the old sender_login_maps. The level-1 limit had
never been what the case saw. The first message now waits (15 s at
most) for the map, failing at once on any other refusal.
Now: "level-1 limit tripped on attempt 51/60: 450 4.7.1 Error: too
much mail from 10.77.0.1".
- level 2: 451 4.7.1 at MAIL, and both MAIL FROM of one connection.
- sender mismatch: 553 at RCPT, "not owned by user".
- no AUTH and the relay case: 554 "Client host rejected: Access
denied" at RCPT; the relay case's comment claimed
reject_unauth_destination, which on 465 comes after the client
restriction - port 25 holds "554 Relay access denied".
- port 25: 550 5.1.1 for unknown recipients and report addresses.
- panel down: a 4xx reply (textproto), not just text starting with 4.
The product side (a second after an application is saved when its first
message can get 553) is written in the audit plan, not changed. Audit plan
line ticked with what was found, roadmap 7/61. No CHANGELOG line: tests only.
Evidence: make e2e on the test server for this tree, exit 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -563,7 +563,7 @@ has already run is never edited — the next file is added; the published
|
||||
development.md that the image is rebuilt after each Go patch release
|
||||
(`golang:1.26-bookworm` floats, so a rebuild suffices). — **Haiku**
|
||||
- [x] The four `staticcheck` items. — **Haiku**
|
||||
- [ ] **A negative e2e case passes only on the refusal it is about** (owner,
|
||||
- [x] **A negative e2e case passes only on the refusal it is about** (owner,
|
||||
2026-10-14; seen, not found by the audit). `negative_level1_ratelimit`
|
||||
sends up to sixty messages and waits for one to be refused; it once
|
||||
passed on "limit tripped on attempt 1/60" when the connection was reset
|
||||
@@ -573,6 +573,23 @@ has already run is never edited — the next file is added; the published
|
||||
came. Then every other negative case of the suite is read for the same
|
||||
mistake - any failure taken for the expected refusal - and held to its
|
||||
own reply code. - **Opus**
|
||||
*Done 2026-10-14; what the stand showed:* `waitForSMTPSReady` took a TCP
|
||||
connect for readiness, and Docker's port proxy accepts before Postfix
|
||||
listens - that was the reset; it now waits for the TLS greeting. Held to
|
||||
anvil's `450`, the case then failed on its first message: `553 … not owned
|
||||
by user l1app`, an smtpd process from before the panel's `postfix reload`
|
||||
still holding the old `sender_login_maps` - so the level-1 limit had never
|
||||
been the refusal the case saw. The first message now waits (at most 15 s)
|
||||
for the map; the limit trips at 51/60 with `450 4.7.1 Error: too much mail
|
||||
from`. In the product this is a second or so after an application is
|
||||
saved in which its first message can get a permanent 553; not worth a
|
||||
change (an application is configured after it is created, not within the
|
||||
second). The other cases are held to `451 4.7.1` (level 2, both MAIL FROM
|
||||
of one connection), `553` at RCPT (sender mismatch), `554 … Client host
|
||||
rejected` at RCPT (no AUTH, and the relay case, whose comment claimed
|
||||
`reject_unauth_destination` - on 465 the client restriction comes first;
|
||||
port 25 holds `554 … Relay access denied`), `550 5.1.1` (port 25 unknown
|
||||
recipients), any `4xx` reply (panel down).
|
||||
|
||||
### Stage 1 — mail that is shown wrong (H3, H2, M12, M13) → `2.5.0`
|
||||
|
||||
|
||||
+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 | agreed (2026-10-12: stage 0 first, then 1+2; the rest after) | 6/61 | [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 | agreed (2026-10-12: stage 0 first, then 1+2; the rest after) | 7/61 | [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