Commit Graph
6 Commits
Author SHA1 Message Date
mixemeandClaude Sonnet 5 d2dffc2e9a docs: center the readme logo and set its display width
test / test (push) Has been cancelled
Markdown's image syntax carries neither alignment nor size, so the stamp
rendered flush left at its intrinsic 330px. A centred `<p>` with an
`<img width>` is the usual way around that on GitHub, and survives its
HTML sanitiser.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 22:46:40 +03:00
mixemeandClaude Opus 5 c70c115224 feat(panel): move a delivery's details onto its own page
The delivery log now lists what identifies a message and nothing else —
time, sender, recipient, subject, status — and links each row to
/deliveries/{id}, which carries the rest: the sending domain, the
application it was submitted under, the Postfix queue id to search the
system log for, and when the status was last reported. Domain and
application were a column each; they were the widest thing in the table
after the addresses and repeat down every filtered page, and they remain
the log's two filters. Back returns to the page and filters the row was
opened from, rebuilt from the log's own parameters only.

Subjects are now decoded for display as well as on the way in. The milter
has decoded them since 8add005, but the rows it wrote before that still
hold the raw =?utf-8?Q?...?= header, and those are the ones an operator is
most likely to still be reading. The decoder moves to internal/mailhdr,
shared by the milter and the panel; it is idempotent, so a row decoded
once passes through unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 22:43:07 +03:00
mixemeandClaude Sonnet 5 795e945888 feat(panel): show each domain's DNS status in the domain list
The list gave no hint which domains still needed records published — the
verdict lived only on the domain page, one click away per domain. Each row
now carries a badge with the worst of that domain's DKIM, SPF and DMARC
checks, in the panel's shared ok/warn/error/unknown vocabulary, linking to
that domain's DNS status card.

The checks run concurrently across the listed domains: each carries its own
timeout, so in series a dead resolver would multiply that wait by the number
of domains and the list would look hung. They share the checker's cache with
the domain page, so a repeat view costs no lookups and opening a domain
after the list is free.

A domain whose DKIM key cannot be read stays "unknown" rather than being
reported as misconfigured — the missing half of the comparison is this
server's, not the domain's.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 22:33:06 +03:00
mixemeandClaude Opus 5 ad991dea4b style(panel): give the navigation column's mark the column's full width
The mark kept the 110px it had as part of the bar, which was all there was
room for in a row; in a column it ended halfway across, sharing an edge with
nothing below it. At the column's width its edges line up with the page
entries, and the SVG's own inset puts the drawn mark on the entries' icons.
The width/height attributes carry the file's real proportions so the column
still reserves the right height before the SVG loads.

Where the column lies back down into a bar, the mark returns to the compact
size: at full width it would take a row to itself above the entries.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 22:30:21 +03:00
mixemeandClaude Sonnet 5 a8e28e1921 fix(panel): open an application's panels under its row of controls
test / test (push) Has been cancelled
Mode and rate limit were <details>, so each opened where its own toggle sat
and split the row of four controls in two, pushing New password and Delete
below a block of fields. The toggle is now a hidden checkbox with its label
drawn as the button and the panel is the last child of the row, so the
controls keep their places and the fields are laid out beneath all of them.
Pure CSS, so it still works with JavaScript blocked, as the disclosure did.

The panel buttons take back the form spacing the compact row style zeroes
out, and Save limit and Remove limit share one row: two posts mean two
forms, so the first button is bound to its form by the form attribute
instead of sitting inside it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 22:23:39 +03:00
mixemeandClaude Sonnet 5 db56fcc3f3 fix(panel): keep the import password field hidden until a file is chosen
test / test (push) Has been cancelled
The field was revealed whenever no file was selected, so the import card
opened asking for a password it had no use for yet. Hide it in that case
too; an unrecognised extension still reveals it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 22:12:05 +03:00