docs: draw the roadmap's screens in the panel design
test / test (push) Canceled after 0s

Four screens for open roadmap items, all built from existing components:
Inbound > Filter lists (allow / deny, where the maps go) and an adjusted
Inbound > Log (client, decision, engine and reason, Allow / Deny sender)
for inbound-antispam-panel; Inbound > Quarantine, list and held message
with Release beside a danger-zone Discard, for inbound-quarantine; and
Server > Preflight, a verdict postmark over a table of checks with a
"what to do" column and a test e-mail form, for preflight.

A mockup is the target look, not a decision to build: each item keeps
its status, and quarantine's open questions stay open - the mockup only
assumes answers to them. The paths join the plan's Routes table, the
quarantine and preflight plans link their mockups, and the components
page maps the quarantine decision to a tag. 33 screens; lint clean.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
mix
2026-09-21 22:07:39 +03:00
co-authored by Claude Fable 5.1
parent 5e0adb2de5
commit 2f7b5d95c3
45 changed files with 991 additions and 42 deletions
+15 -9
View File
@@ -13,7 +13,7 @@ design itself is drawn and accepted:
| Artefact | Role |
|---|---|
| [docs/assets/panel-redesign/panel/](../assets/panel-redesign/index.html) | 29 screens — **the** reference for what each page looks like |
| [docs/assets/panel-redesign/panel/](../assets/panel-redesign/index.html) | 33 screens — **the** reference for what each page looks like |
| [panel/components.html](../assets/panel-redesign/panel/components.html) | every component in every state — the only parts a page may be built from |
| [panel/outlines.json](../assets/panel-redesign/panel/outlines.json) | the component skeleton of each screen, generated from the mockups |
| [panel/check.py](../assets/panel-redesign/panel/check.py) | the contract as a program; its rules are ported to Go tests below |
@@ -93,6 +93,8 @@ only.
| Inbound: domain (upstream, recipients), log | all domains | assigned inbound domains |
| Add / delete a domain, either direction | yes | no |
| Queues, either direction | yes | no, until the queue is a filterable table |
| Inbound › Quarantine | all domains | assigned inbound domains |
| Inbound › Filter lists, Server › Preflight | yes | no — the lists are instance-wide |
| Account, Help | yes | yes |
- New table `user_inbound_domains (user_id, inbound_domain_id)`, mirroring
@@ -115,6 +117,7 @@ list, an action under the thing it changes.
|---|---|---|
| overview | `GET /overview` | `/status` |
| health | `GET /server/health` · `POST …/recheck` · `POST …/reload` | tables of `/status` · `/status/recheck` · `/reload` |
| preflight | `GET /server/preflight` · `POST …/preflight/run` · `POST …/preflight/test-email` | — (preflight; its plan says `/preflight`) |
| out-domains | `GET, POST /outbound/domains` | `/domains` |
| out-domain | `GET /outbound/domains/{id}` · `POST …/dns-recheck` | `/domains/{id}` |
| out-domain-settings | `GET /outbound/domains/{id}/settings` · `POST …/settings/reports` · `…/settings/ratelimit` · `…/settings/ratelimit/recalc` · `…/settings/export` | cards of `/domains/{id}` · `…/dmarc` · `…/ratelimit` · `…/ratelimit/recalc` · `…/export` |
@@ -127,6 +130,8 @@ list, an action under the thing it changes.
| in-domains · in-domain | `GET, POST /inbound/domains` · `GET /inbound/domains/{id}` · `POST …/dns-recheck`, `…/upstream`, `…/recipients` | `/inbound` · `/inbound/{id}/…` |
| in-domain-delete | `GET, POST /inbound/domains/{id}/delete` | `/inbound/{id}/delete` |
| in-log · in-queue | `GET /inbound/log` · `GET /inbound/queue` | — (new, see below) |
| in-quarantine · in-quarantine-message | `GET /inbound/quarantine` · `GET …/quarantine/{id}` · `POST …/{id}/release` · `POST …/{id}/discard` | — (inbound-quarantine) |
| in-filter-lists | `GET, POST /inbound/filter-lists` · `POST …/filter-lists/{id}/delete` | — (inbound-antispam-panel) |
| system-log | `GET /server/log` | `/system-log` |
| backup | `GET, POST /server/backup` · `POST /server/backup/import` | `/backup` · `POST /domains/import` |
| users · user · user-delete | `/server/users` · `…/new` · `…/{uid}` · `…/{uid}/delete` | `/users/…` |
@@ -174,17 +179,18 @@ shell, and its menu entry is hidden if the page does not exist.
## Room for roadmap items
The mockups draw today's features plus the four rows above. The other open
roadmap items are **not drawn yet**; each has a place, and none needs a new
component or layout. A feature's screens are drawn mockup-first in this system
(`panel/src/`, `build.py`, `check.py --write`) as the first step of that
feature's own plan — not invented during its implementation.
The mockups draw today's features, the four rows above, and the screens of
the open roadmap items — none of them needed a new component or layout. A
mockup of a feature is its target look, not a decision to build it: each item
keeps its own status and plan. From here on a feature's screens are drawn
mockup-first in this system (`panel/src/`, `build.py`, `check.py --write`) as
the first step of that feature's plan — not invented during implementation.
| Roadmap item | Where it lands | Built from | Drawn |
|---|---|---|---|
| inbound-antispam-panel (agreed, `1.10.0`) | journal = **Inbound › Log** (add client IP and engine to the mockup's columns; `quarantine` joins the decisions); lists = new **Inbound › Filter lists**, global-only because the lists are instance-wide | list layout: add form + table, `status_tag`, filter form in `box_head` | log: yes, to be adjusted · lists: **no** |
| inbound-quarantine (candidate) | new **Inbound › Quarantine**, list + detail with *Release* / *Discard* | list layout; detail like `out-message` with `facts`, `log_pane`, a `sp-danger-zone` box for Discard | **no** |
| preflight (candidate) | new **Server › Preflight**, next to Health: Health is what runs now, Preflight is the deeper on-demand installation check with a test e-mail form | `postmark` verdict, a table of checks with `status_tag`, `facts`, one form box | **no** |
| inbound-antispam-panel (agreed, `1.10.0`) | journal = **Inbound › Log** (add client IP and engine to the mockup's columns; `quarantine` joins the decisions); lists = new **Inbound › Filter lists**, global-only because the lists are instance-wide | list layout: add form + two tables, `status_tag`, filter form in `box_head`; the log links *Allow / Deny sender* to the lists | `in-log`, `in-filter-lists` |
| inbound-quarantine (candidate) | new **Inbound › Quarantine**, list + detail with *Release* / *Discard* | list layout; detail like `out-message` with `facts`, `log_pane` for headers only, Release beside a `sp-danger-zone` Discard | `in-quarantine`, `in-quarantine-message` — the open questions of its plan (where mail lives, what release means, retention, RBAC) stay open; the mockup assumes SelfPost-held mail, release to upstream, 14 days, delegated like the rest of Inbound |
| preflight (candidate) | new **Server › Preflight**, next to Health: Health is what runs now, Preflight is the deeper on-demand installation check with a test e-mail form | `postmark` verdict, a table of checks with `status_tag` and a *What to do* column, one form box for the test e-mail | `preflight` |
| csrf-tokens | no screen; every form gains a hidden field — forms are rendered through one helper so the token cannot be forgotten | — | n/a |
| template-data-typing | no screen; the component partials are the natural first users of typed data | — | n/a |
| structured-logging, contributing, review follow-ups | none | — | n/a |