- handlers/authz.go: domainIDSet removed, nothing called it (U1000). - handlers_outbound_pages_test.go: two refusals whose status code was assigned and never read (SA4006) now check it is 400 - a custom DMARC report mode without an address, export passwords that differ. - view/pages_test.go: !strings.Contains for a missing box (S1003). - Audit plan line ticked, roadmap 6/61. No CHANGELOG line: nothing an operator sees changes. staticcheck ./... clean afterwards. Evidence on the test server: see the previous commit (same tree run). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -562,7 +562,7 @@ has already run is never edited — the next file is added; the published
|
|||||||
- [x] **Toolchain and deps**: `modernc.org/sqlite`, `x/crypto`, `x/sys`; note in
|
- [x] **Toolchain and deps**: `modernc.org/sqlite`, `x/crypto`, `x/sys`; note in
|
||||||
development.md that the image is rebuilt after each Go patch release
|
development.md that the image is rebuilt after each Go patch release
|
||||||
(`golang:1.26-bookworm` floats, so a rebuild suffices). — **Haiku**
|
(`golang:1.26-bookworm` floats, so a rebuild suffices). — **Haiku**
|
||||||
- [ ] The four `staticcheck` items. — **Haiku**
|
- [x] The four `staticcheck` items. — **Haiku**
|
||||||
- [ ] **A negative e2e case passes only on the refusal it is about** (owner,
|
- [ ] **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`
|
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
|
sends up to sixty messages and waits for one to be refused; it once
|
||||||
|
|||||||
+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) |
|
| 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) |
|
| 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) |
|
| 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) | 5/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) | 6/61 | [audit-2026-10-12.md](audit-2026-10-12.md) |
|
||||||
|
|
||||||
**Recommended order** (not binding; owner, 2026-10-09: feature order follows
|
**Recommended order** (not binding; owner, 2026-10-09: feature order follows
|
||||||
development convenience): **panel-redesign** shipped as `2.0.0` (2026-10-11) and
|
development convenience): **panel-redesign** shipped as `2.0.0` (2026-10-11) and
|
||||||
|
|||||||
@@ -57,16 +57,3 @@ func domainNameSet(domains []store.Domain) map[string]bool {
|
|||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// domainIDSet is the set of sending domains a principal is limited to; nil
|
|
||||||
// means no limit (the global role, or a domain user with All).
|
|
||||||
func domainIDSet(p auth.Principal) map[int64]bool {
|
|
||||||
if p.IsGlobal() || p.AllDomains {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
m := make(map[int64]bool, len(p.Domains))
|
|
||||||
for _, id := range p.Domains {
|
|
||||||
m[id] = true
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -172,6 +172,9 @@ func TestDomainSettingsRefusalsStayOnTheSettingsPage(t *testing.T) {
|
|||||||
lacks(t, "report address refusal", body, `<b>`)
|
lacks(t, "report address refusal", body, `<b>`)
|
||||||
|
|
||||||
code, body = post(s.h.HandleDomainDMARC, "reports", url.Values{"dmarc_rua_mode": {"custom"}})
|
code, body = post(s.h.HandleDomainDMARC, "reports", url.Values{"dmarc_rua_mode": {"custom"}})
|
||||||
|
if code != http.StatusBadRequest {
|
||||||
|
t.Fatalf("a custom mode without an address = %d", code)
|
||||||
|
}
|
||||||
has(t, "report address refusal", body, `Enter the report address or choose another option.`)
|
has(t, "report address refusal", body, `Enter the report address or choose another option.`)
|
||||||
|
|
||||||
code, body = post(s.h.HandleDomainDMARC, "reports", url.Values{"dmarc_rua_mode": {"hosted"}})
|
code, body = post(s.h.HandleDomainDMARC, "reports", url.Values{"dmarc_rua_mode": {"hosted"}})
|
||||||
@@ -192,6 +195,9 @@ func TestDomainSettingsRefusalsStayOnTheSettingsPage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
has(t, "export refusal", body, `The encryption password must be at least 12 characters.`, `<h1 class="title is-3">Domain settings</h1>`)
|
has(t, "export refusal", body, `The encryption password must be at least 12 characters.`, `<h1 class="title is-3">Domain settings</h1>`)
|
||||||
code, body = post(s.h.HandleExportDomain, "export", url.Values{"encrypt": {"1"}, "password": {"long-enough-password"}, "password_confirm": {"another-one-entirely"}})
|
code, body = post(s.h.HandleExportDomain, "export", url.Values{"encrypt": {"1"}, "password": {"long-enough-password"}, "password_confirm": {"another-one-entirely"}})
|
||||||
|
if code != http.StatusBadRequest {
|
||||||
|
t.Fatalf("export passwords that differ = %d", code)
|
||||||
|
}
|
||||||
has(t, "export refusal", body, `The two passwords do not match.`)
|
has(t, "export refusal", body, `The two passwords do not match.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ func TestHealthShowsEveryCheckAndBothActions(t *testing.T) {
|
|||||||
order := []string{`id="processes"`, `id="sender-check"`, `id="hostname"`, `id="machine"`,
|
order := []string{`id="processes"`, `id="sender-check"`, `id="hostname"`, `id="machine"`,
|
||||||
`id="sockets"`, `id="certificate"`, `id="notification-mail"`, `id="configuration"`}
|
`id="sockets"`, `id="certificate"`, `id="notification-mail"`, `id="configuration"`}
|
||||||
for i := 1; i < len(order); i++ {
|
for i := 1; i < len(order); i++ {
|
||||||
if strings.Index(out, order[i-1]) < 0 || strings.Index(out, order[i]) < strings.Index(out, order[i-1]) {
|
if !strings.Contains(out, order[i-1]) || strings.Index(out, order[i]) < strings.Index(out, order[i-1]) {
|
||||||
t.Errorf("%s does not come after %s", order[i], order[i-1])
|
t.Errorf("%s does not come after %s", order[i], order[i-1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user