From c6a75ce775f49e0441fa8989a6877e25fb81c5aa Mon Sep 17 00:00:00 2001 From: Mikhail Yenuchenko Date: Sun, 16 Aug 2026 21:44:20 +0300 Subject: [PATCH] docs: add DMARC report mockups and fold add-domain into lists Domains and Inbound keep the add field in the list card. The DMARC candidate hub drills into a domain roll-up and a parsed aggregate report, including a third-party fail. The running panel is unchanged. Co-Authored-By: Cursor --- .cursor/rules/panel-ui-system.mdc | 2 +- CHANGELOG.md | 5 ++ docs/assets/panel-ui/app.html | 3 + docs/assets/panel-ui/dmarc-domain.html | 88 +++++++++++++++++++++ docs/assets/panel-ui/dmarc-report-fail.html | 88 +++++++++++++++++++++ docs/assets/panel-ui/dmarc-report.html | 88 +++++++++++++++++++++ docs/assets/panel-ui/dmarc.html | 81 +++++++++++++------ docs/assets/panel-ui/domain.html | 2 +- docs/assets/panel-ui/domains.html | 13 +-- docs/assets/panel-ui/inbound.html | 19 ++--- docs/assets/panel-ui/index.html | 7 +- docs/assets/panel-ui/mock.css | 6 +- docs/assets/panel-ui/system.css | 1 + docs/assets/panel-ui/system.html | 8 +- 14 files changed, 361 insertions(+), 50 deletions(-) create mode 100644 docs/assets/panel-ui/dmarc-domain.html create mode 100644 docs/assets/panel-ui/dmarc-report-fail.html create mode 100644 docs/assets/panel-ui/dmarc-report.html diff --git a/.cursor/rules/panel-ui-system.mdc b/.cursor/rules/panel-ui-system.mdc index 06b8a32..8bd512f 100644 --- a/.cursor/rules/panel-ui-system.mdc +++ b/.cursor/rules/panel-ui-system.mdc @@ -12,7 +12,7 @@ Do not copy `internal/web/view/templates` into mockups. Do not mark `
` as Compose screens from `stack`, `pair`, `measure`, `fill`, `field-row`, `actions-row`: - Two peer jobs → `pair` (one child shrinks to `measure`). -- Tables/logs/DNS → `fill` (nowrap + overflow-x on the card). +- Tables/logs/DNS → `fill` (nowrap + overflow-x on the card). Add-to-list is a `measure` row inside that card, not a second card above it. - Confirm/login/user form → `measure`. - Host ‖ Type and two equal inputs → `field-row` (shared grid row, not two `.code` paddings). - Save + Delete → `actions-row` inside the card; never submit inside `
` and danger after `
`. diff --git a/CHANGELOG.md b/CHANGELOG.md index 38d7ac5..c8f112d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,11 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version Regions are `stack` / `pair` / `measure` / `fill`; Host ‖ Type is `field-row`; Save + Delete is `actions-row`. Shared chrome is `shell.js`. +- docs: panel UI mockups — add-domain sits in the list card (Domains and + Inbound); DMARC candidate screens drill into a domain roll-up and a + parsed aggregate report (aligned vs third-party fail), not a hub-only + summary. + ## [1.3.0] - 2026-08-14 Security and quality after 1.2.5: domain-admin send-log authorization, diff --git a/docs/assets/panel-ui/app.html b/docs/assets/panel-ui/app.html index e9c5195..23cb394 100644 --- a/docs/assets/panel-ui/app.html +++ b/docs/assets/panel-ui/app.html @@ -28,6 +28,9 @@ "inbound-backup": "inbound-backup.html", "inbound-delete": "inbound-delete.html", dmarc: "dmarc.html", + "dmarc-domain": "dmarc-domain.html", + "dmarc-report": "dmarc-report.html", + "dmarc-report-fail": "dmarc-report-fail.html", help: "help.html" }; var h = location.hash.replace(/^#/, ""); diff --git a/docs/assets/panel-ui/dmarc-domain.html b/docs/assets/panel-ui/dmarc-domain.html new file mode 100644 index 0000000..2c41e09 --- /dev/null +++ b/docs/assets/panel-ui/dmarc-domain.html @@ -0,0 +1,88 @@ + + + + + +example.com — DMARC — SelfPost mockups + + + + + +
+
+

example.com candidate

+ ← All DMARC reports + ← Back to example.com +
+
+
+

Last 7 days pass

+

98% aligned. Tightening p= looks reasonable.

+

Domain DNS and rua=

+
+
+

Third-party senders

+

google.com / 66.102.0.0/20 failed SPF and DKIM 6 times. Everyone else is this relay.

+
+
+
+
+

Reports

+ + + + + + + + + + + + + + + + + + + + +
ReceivedReporterWindowPassFail
2026-08-15 06:12google.com14 Aug4126View
2026-08-14 06:08google.com13 Aug3902View
+ +
+
+
+
+

Sources · last 7 days

+ + + + + + +
SourcePassFailDisposition
203.0.113.10 (this relay)8020none
google.com / 66.102.0.0/2008none
+ +
+
+
+ + + diff --git a/docs/assets/panel-ui/dmarc-report-fail.html b/docs/assets/panel-ui/dmarc-report-fail.html new file mode 100644 index 0000000..ccfee61 --- /dev/null +++ b/docs/assets/panel-ui/dmarc-report-fail.html @@ -0,0 +1,88 @@ + + + + + +google.com report — alerts.example.com — SelfPost mockups + + + + + +
+
+

google.com · 14 Aug

+

+ alerts.example.com + 88 pass + 19 fail +

+ ← All DMARC reports +
+
+
+

Report

+
+
Reportergoogle.com
+
Report id3178944098765432109
+
Window2026-08-14 00:00 – 2026-08-15 00:00 UTC
+
Received2026-08-15 04:40 UTC
+
Contactnoreply-dmarc-support@google.com
+
+
+
+

Published policy

+
+
Domainalerts.example.com
+
p / sp / pctnone / none / 100
+
adkim / aspfr / r
+
ruadmarc@mail.example.org
+
+

A third-party source is not in SPF or DKIM. Do not tighten p= until that sender is gone or aligned.

+
+
+
+
+

Records

+ + + + + + + + + + + + + + + + + + + + +
SourceCountDispositionSPFDKIMHeader from
203.0.113.10 (this relay)88nonepasspassalerts.example.com
198.51.100.80 (unknown)19nonefailfailalerts.example.com
+
    +
  • +
    + this relay · 88pass + 203.0.113.10 · SPF pass · DKIM pass +
    +
  • +
  • +
    + unknown · 19fail + 198.51.100.80 · SPF fail · DKIM fail +
    +
  • +
+

Parsed from the aggregate XML. Forensic (ruf=) samples are not stored.

+
+
+
+ + + diff --git a/docs/assets/panel-ui/dmarc-report.html b/docs/assets/panel-ui/dmarc-report.html new file mode 100644 index 0000000..fb376d7 --- /dev/null +++ b/docs/assets/panel-ui/dmarc-report.html @@ -0,0 +1,88 @@ + + + + + +google.com report — example.com — SelfPost mockups + + + + + +
+
+

google.com · 14 Aug

+

+ example.com + 412 pass + 6 fail +

+ ← Back to example.com +
+
+
+

Report

+
+
Reportergoogle.com
+
Report id3178944012345678901
+
Window2026-08-14 00:00 – 2026-08-15 00:00 UTC
+
Received2026-08-15 06:12 UTC
+
Contactnoreply-dmarc-support@google.com
+
+
+
+

Published policy

+
+
Domainexample.com
+
p / sp / pctnone / none / 100
+
adkim / aspfr / r
+
ruadmarc@mail.example.org
+
+

p=none does not affect delivery. Failures here are forwarding through Google, not this relay.

+
+
+
+
+

Records

+ + + + + + + + + + + + + + + + + + + + +
SourceCountDispositionSPFDKIMHeader from
203.0.113.10 (this relay)412nonepasspassexample.com
66.102.1.44 (google.com)6nonefailfailexample.com
+
    +
  • +
    + this relay · 412pass + 203.0.113.10 · SPF pass · DKIM pass +
    +
  • +
  • +
    + google.com · 6fail + 66.102.1.44 · SPF fail · DKIM fail +
    +
  • +
+

Parsed from the aggregate XML. Forensic (ruf=) samples are not stored.

+
+
+
+ + + diff --git a/docs/assets/panel-ui/dmarc.html b/docs/assets/panel-ui/dmarc.html index c4c2b9b..a7478b5 100644 --- a/docs/assets/panel-ui/dmarc.html +++ b/docs/assets/panel-ui/dmarc.html @@ -13,39 +13,76 @@

DMARC reports candidate

-

Aggregate reports SelfPost accepted for rua=. Forensic (ruf=) is out of scope.

+

Aggregate reports SelfPost accepted for rua=. Forensic (ruf=) is out of scope. Open a report for the parsed XML — not a dashboard.

-
+

Ingest ok

-

Last report 6 hours ago. 14 kept, 0 parse failures this week.

-
-
-

example.com pass

-

98% aligned last 7 days. Tightening p= looks reasonable.

-
-
-
-
-

alerts.example.com fail

-

A third-party sender is not in SPF/DKIM. See sources.

-
+

Last report 6 hours ago. Port 25 accepts only the configured report address.

+
+
+

This week

+

14 kept, 0 parse failures. Older summaries are pruned.

+
-

Sources · last 7 days

+

Recent reports

- + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +
DomainSourcePassFailDisposition
ReceivedDomainReporterWindowPassFail
example.com203.0.113.10 (this relay)4122none
example.comgoogle.com / 66.102.0.0/2006none
alerts.example.com203.0.113.10 (this relay)880none
alerts.example.comunknown / 198.51.100.80019none
2026-08-15 06:12example.comgoogle.com14 Aug4126View
2026-08-15 04:40alerts.example.comgoogle.com14 Aug8819View
2026-08-14 06:08example.comgoogle.com13 Aug3902View
+

Each row is one aggregate XML SelfPost parsed. Domain names open the roll-up for that sending domain.

diff --git a/docs/assets/panel-ui/domain.html b/docs/assets/panel-ui/domain.html index 80a472b..3c75277 100644 --- a/docs/assets/panel-ui/domain.html +++ b/docs/assets/panel-ui/domain.html @@ -125,7 +125,7 @@
v=DMARC1; p=none; rua=mailto:dmarc@mail.example.org
-

Open DMARC reports for this domain.

+

Open DMARC reports for this domain.

diff --git a/docs/assets/panel-ui/domains.html b/docs/assets/panel-ui/domains.html index a96d19b..4c41a02 100644 --- a/docs/assets/panel-ui/domains.html +++ b/docs/assets/panel-ui/domains.html @@ -11,21 +11,16 @@

Domains

-
+
-

Add a sending domain

-
- +

Domains

+ +
-
-
-
-
-

Domains

diff --git a/docs/assets/panel-ui/inbound.html b/docs/assets/panel-ui/inbound.html index 9519d9a..07e15e7 100644 --- a/docs/assets/panel-ui/inbound.html +++ b/docs/assets/panel-ui/inbound.html @@ -14,21 +14,16 @@

Inbound 1.x

Backup-MX / forwarder. Accepts on port 25 only for listed domains. Recipients are either an allow-list or any address at that domain. Off by default in Compose.

-
-
-

Add inbound domain

-
- -
- - -
- -
-

Forwarding

+
+ +
+ + +
+
DomainDNSSelectorApps
diff --git a/docs/assets/panel-ui/index.html b/docs/assets/panel-ui/index.html index fd76f9e..c35e09c 100644 --- a/docs/assets/panel-ui/index.html +++ b/docs/assets/panel-ui/index.html @@ -80,7 +80,7 @@

Domain-admin

Аварийный телефон

diff --git a/docs/assets/panel-ui/mock.css b/docs/assets/panel-ui/mock.css index ede9a48..e194093 100644 --- a/docs/assets/panel-ui/mock.css +++ b/docs/assets/panel-ui/mock.css @@ -184,6 +184,9 @@ body.page-inbound-domain .n-inbound, body.page-inbound-backup .n-inbound, body.page-inbound-delete .n-inbound, body.page-dmarc .n-dmarc, +body.page-dmarc-domain .n-dmarc, +body.page-dmarc-report .n-dmarc, +body.page-dmarc-report-fail .n-dmarc, body.page-backup .n-backup, body.page-users .n-users, body.page-user-form .n-users, @@ -515,7 +518,8 @@ meter { width: 5rem; height: 0.7rem; vertical-align: middle; margin-right: 0.4re .phone-list { display: none; list-style: none; margin: 0; padding: 0; } .phone-list li { border-bottom: 1px solid var(--border); } -.phone-list a { +.phone-list a, +.phone-list .item { display: grid; grid-template-columns: 1fr auto; gap: 0.15rem 0.7rem; padding: 0.75rem 0.1rem; text-decoration: none; color: var(--fg); } diff --git a/docs/assets/panel-ui/system.css b/docs/assets/panel-ui/system.css index 5877fd0..f4cf77a 100644 --- a/docs/assets/panel-ui/system.css +++ b/docs/assets/panel-ui/system.css @@ -18,6 +18,7 @@ .fill { width: 100%; max-width: var(--ops-max); min-width: 0; } .fill > .card { margin-top: 0; } .fill .card:has(table) { overflow-x: auto; } +.card > .measure { margin-bottom: 1rem; } /* Two peer jobs. One child → reading measure (domain-admin Settings). Never a full-width lonely card on an ops page. */ diff --git a/docs/assets/panel-ui/system.html b/docs/assets/panel-ui/system.html index e460c82..02a4f62 100644 --- a/docs/assets/panel-ui/system.html +++ b/docs/assets/panel-ui/system.html @@ -242,8 +242,8 @@ - - + + @@ -253,6 +253,10 @@ + + + +
DomainDNSUpstreamRecipientsTLS
stack: overall → pair очередь‖TLS → pair milters‖PTR → inbound если есть → pair machine‖processes → configuration. На карточках остаются числа и Detail.
Domains / Deliveries / log / queuefill таблица. Добавление домена — measure или узкая карточка над таблицей, не растянутый инпут.Domains / Inbound / Deliveries / log / queuefill таблица. Добавление домена — поле в той же карточке списка (measure внутри, не вторая карточка и не инпут на 90rem).
DomainInbound domain fill MX DNS → pair upstream ‖ MX to publish → pair recipients ‖ danger
DMARChub: pair ingest ‖ this week, затем fill список отчётов. Домен: roll-up (pair 7 days ‖ third-party, fill reports + sources). Один XML: просмотрpair report ‖ policy, fill records. Не дашборд, не ruf=.
Backup pair full backup ‖ import