diff --git a/CHANGELOG.md b/CHANGELOG.md index c0a591b..cdbce4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,14 @@ document is not part of the release. ### Added +- Panel redesign, the roadmap's screens: **Inbound › Filter lists** and the + adjusted **Inbound › Log** (client, decision, engine and reason; *Allow / + Deny sender*) for inbound-antispam-panel, **Inbound › Quarantine** (list and + held message with Release / Discard) for inbound-quarantine, and **Server › + Preflight** for preflight — all from existing components; 33 screens. Their + paths join § Routes; the quarantine and preflight plans link their mockups. + A mockup is the target look, not a decision to build: each item keeps its + status, and quarantine's open questions stay open. - Panel redesign, two owner decisions recorded in `docs/plans/panel-redesign.md`: **no compatibility** — the redesign is `2.0.0`, old paths are removed without redirects, the SQLite migration chain diff --git a/docs/assets/panel-redesign/index.html b/docs/assets/panel-redesign/index.html index c2b7e58..a4ce82b 100644 --- a/docs/assets/panel-redesign/index.html +++ b/docs/assets/panel-redesign/index.html @@ -13,7 +13,7 @@
Direction C (Bulma) was picked as the base: the important things in view, details one or two clicks away. It takes the postal signature of A — the postmark verdict, numbered mono section - heads, the stamp's perforated edge — and the icons of B. Twenty-nine screens and a components page live in + heads, the stamp's perforated edge — and the icons of B. Thirty-three screens and a components page live in panel/. Serve this folder from the repository root: the pages load the panel's own fonts and mark by relative path.
@@ -31,8 +31,10 @@ by domain · one reportInbound · global administrator
+Correct the spam filter by hand: senders it must always let through, and senders it must always turn away. One pair of lists for the whole instance.
+INBOUND_ANTISPAM_MILTER is set.Inbound
What port 25 accepted and what it turned away. Accepts come from the inbound journal, rejects from mail.log.
What port 25 decided about each message, one row per recipient. Accepts come from the inbound journal, rejects from mail.log; the filter's reasons appear when the spam filter is on.
| Time, UTC | From | To | Subject | Action | Reason | ||
|---|---|---|---|---|---|---|---|
| Time, UTC | Client | From | To | Subject | Decision | Why | |
| 09-21 14:00:18 | t.berg@uni.example | dev@lists.example.org | Re: [dev] patch series v3 | forwarded | → mx.internal:25 | ||
| 09-21 13:57:41 | promo@bulk.example | sales@lists.example.org | — | rejected | 550 5.1.1 unknown recipient | ||
| 09-21 13:44:02 | hr@partner.example | jobs@acme.io | Application: backend engineer | deferred | upstream 10.0.4.12 timed out | ||
| 09-21 13:30:55 | noreply@github.example | security@lists.example.org | [advisory] new report | forwarded | → mx.internal:25 | ||
| 09-21 14:00:18 | 192.0.2.77 | t.berg@uni.example | dev@lists.example.org | Re: [dev] patch series v3 | accept | rspamd · score 0.4 | Deny sender |
| 09-21 13:59:02 | 203.0.113.140 | invoice@partner-billing.example | owner@lists.example.org | Outstanding invoice — action required | quarantine | rspamd · score 9.8 · PHISHING, FORGED_SENDER | Review |
| 09-21 13:57:41 | 198.51.100.90 | promo@bulk.example | sales@lists.example.org | — | reject | postfix · 550 5.1.1 unknown recipient | Deny sender |
| 09-21 13:51:30 | 198.51.100.12 | billing@partner.example | owner@lists.example.org | Invoice 2026-0917 | reject | rspamd · score 16.2 · BAYES_SPAM | Allow sender |
| 09-21 13:44:02 | 192.0.2.31 | hr@partner.example | jobs@acme.io | Application: backend engineer | tempfail | selfpost · upstream 10.0.4.12 timed out | |
| 09-21 13:30:55 | 192.0.2.200 | noreply@github.example | security@lists.example.org | [advisory] new report | accept | rspamd · allow list |
invoice@partner-billing.exampleowner@lists.example.orgquarantine
+| Symbol | Score |
|---|---|
| PHISHING | 5.0 |
| FORGED_SENDER | 3.0 |
| HTML_ATTACHMENT | 1.8 |
Received: from mail.partner-billing.example (unknown [203.0.113.140]) by mail.example.org +From: "Partner Billing" <invoice@partner-billing.example> +Reply-To: payments.dept@freemail.example +To: owner@lists.example.org +Subject: Outstanding invoice — action required +Date: Mon, 21 Sep 2026 13:58:57 +0000 +Authentication-Results: spf=fail dkim=none dmarc=fail+
Hands the message to mx.internal:25 unchanged, as if it had just arrived. It leaves the quarantine.
+ +Deletes the message now instead of in 14 days. The sender is not told. This cannot be undone.
+ +Inbound
+Mail the filter found suspicious enough to hold, but not to refuse. Release hands a message to its upstream as if it had just arrived; Discard deletes it. Anything left is deleted after 14 days.
+| Held, UTC | From | To | Subject | Why | Size | Deleted in | |
|---|---|---|---|---|---|---|---|
| 09-21 13:59:02 | invoice@partner-billing.example | owner@lists.example.org | Outstanding invoice — action required | score 9.8 · PHISHING | 48 kB | 14 days | Review |
| 09-20 22:14:40 | no-reply@shipping-update.example | jobs@acme.io | Your parcel could not be delivered | score 8.1 · URL_SHORTENER | 12 kB | 13 days | Review |
| 09-09 07:02:11 | m.ortega@supplier.example | owner@lists.example.org | Fwd: scanned contract (3 attachments) | score 7.4 · MIME_ARCHIVE | 2.9 MB | 2 days | Review |
Server
+Is this installation ready to deliver mail? Run it after the first start, after moving the server, or when receivers start refusing you. Health watches what runs; Preflight checks what the outside world sees.
+| Check | Result | Found | What to do |
|---|---|---|---|
| Reverse DNS | ok | 203.0.113.25 ⇄ mail.example.org | — |
| TLS certificate | warn | Valid for mail.example.org, expires in 12 days | Renewal has not run. Check that port 80 reaches the ACME client and look for acme in the system log. |
| Port 25 | ok | 220 mail.example.org ESMTP | — |
| Ports 465, 587 | ok | TLS handshake, 220 banner on both | — |
| HELO name | ok | mail.example.org | — |
| Proxy headers | ok | Peer 172.18.0.2 is trusted; X-Forwarded-Proto: https | — |
| DKIM signing | ok | inet:127.0.0.1:8891 answers | — |
SPF, DKIM and DMARC records are per domain — each outbound domain shows its own.
+Whether a receiver finally accepted the test message is not tracked; only that it left.
+Inbound · global administrator
+Correct the spam filter by hand: senders it must always let through, and senders it must always turn away. One pair of lists for the whole instance.
+INBOUND_ANTISPAM_MILTER is set.Inbound
What port 25 accepted and what it turned away. Accepts come from the inbound journal, rejects from mail.log.
What port 25 decided about each message, one row per recipient. Accepts come from the inbound journal, rejects from mail.log; the filter's reasons appear when the spam filter is on.
| Time, UTC | From | To | Subject | Action | Reason | ||
|---|---|---|---|---|---|---|---|
| Time, UTC | Client | From | To | Subject | Decision | Why | |
| 09-21 14:00:18 | t.berg@uni.example | dev@lists.example.org | Re: [dev] patch series v3 | forwarded | → mx.internal:25 | ||
| 09-21 13:57:41 | promo@bulk.example | sales@lists.example.org | — | rejected | 550 5.1.1 unknown recipient | ||
| 09-21 13:44:02 | hr@partner.example | jobs@acme.io | Application: backend engineer | deferred | upstream 10.0.4.12 timed out | ||
| 09-21 13:30:55 | noreply@github.example | security@lists.example.org | [advisory] new report | forwarded | → mx.internal:25 | ||
| 09-21 14:00:18 | 192.0.2.77 | t.berg@uni.example | dev@lists.example.org | Re: [dev] patch series v3 | accept | rspamd · score 0.4 | Deny sender |
| 09-21 13:59:02 | 203.0.113.140 | invoice@partner-billing.example | owner@lists.example.org | Outstanding invoice — action required | quarantine | rspamd · score 9.8 · PHISHING, FORGED_SENDER | Review |
| 09-21 13:57:41 | 198.51.100.90 | promo@bulk.example | sales@lists.example.org | — | reject | postfix · 550 5.1.1 unknown recipient | Deny sender |
| 09-21 13:51:30 | 198.51.100.12 | billing@partner.example | owner@lists.example.org | Invoice 2026-0917 | reject | rspamd · score 16.2 · BAYES_SPAM | Allow sender |
| 09-21 13:44:02 | 192.0.2.31 | hr@partner.example | jobs@acme.io | Application: backend engineer | tempfail | selfpost · upstream 10.0.4.12 timed out | |
| 09-21 13:30:55 | 192.0.2.200 | noreply@github.example | security@lists.example.org | [advisory] new report | accept | rspamd · allow list |
invoice@partner-billing.exampleowner@lists.example.orgquarantine
+| Symbol | Score |
|---|---|
| PHISHING | 5.0 |
| FORGED_SENDER | 3.0 |
| HTML_ATTACHMENT | 1.8 |
Received: from mail.partner-billing.example (unknown [203.0.113.140]) by mail.example.org +From: "Partner Billing" <invoice@partner-billing.example> +Reply-To: payments.dept@freemail.example +To: owner@lists.example.org +Subject: Outstanding invoice — action required +Date: Mon, 21 Sep 2026 13:58:57 +0000 +Authentication-Results: spf=fail dkim=none dmarc=fail+
Hands the message to mx.internal:25 unchanged, as if it had just arrived. It leaves the quarantine.
+ +Deletes the message now instead of in 14 days. The sender is not told. This cannot be undone.
+ +Inbound
+Mail the filter found suspicious enough to hold, but not to refuse. Release hands a message to its upstream as if it had just arrived; Discard deletes it. Anything left is deleted after 14 days.
+| Held, UTC | From | To | Subject | Why | Size | Deleted in | |
|---|---|---|---|---|---|---|---|
| 09-21 13:59:02 | invoice@partner-billing.example | owner@lists.example.org | Outstanding invoice — action required | score 9.8 · PHISHING | 48 kB | 14 days | Review |
| 09-20 22:14:40 | no-reply@shipping-update.example | jobs@acme.io | Your parcel could not be delivered | score 8.1 · URL_SHORTENER | 12 kB | 13 days | Review |
| 09-09 07:02:11 | m.ortega@supplier.example | owner@lists.example.org | Fwd: scanned contract (3 attachments) | score 7.4 · MIME_ARCHIVE | 2.9 MB | 2 days | Review |
Server
+Is this installation ready to deliver mail? Run it after the first start, after moving the server, or when receivers start refusing you. Health watches what runs; Preflight checks what the outside world sees.
+| Check | Result | Found | What to do |
|---|---|---|---|
| Reverse DNS | ok | 203.0.113.25 ⇄ mail.example.org | — |
| TLS certificate | warn | Valid for mail.example.org, expires in 12 days | Renewal has not run. Check that port 80 reaches the ACME client and look for acme in the system log. |
| Port 25 | ok | 220 mail.example.org ESMTP | — |
| Ports 465, 587 | ok | TLS handshake, 220 banner on both | — |
| HELO name | ok | mail.example.org | — |
| Proxy headers | ok | Peer 172.18.0.2 is trusted; X-Forwarded-Proto: https | — |
| DKIM signing | ok | inet:127.0.0.1:8891 answers | — |
SPF, DKIM and DMARC records are per domain — each outbound domain shows its own.
+Whether a receiver finally accepted the test message is not tracked; only that it left.
+