Stalwart does no BIMI, so sender icons were only ever favicons, which
anyone controls for any domain. The webmail server now does the
receiver side itself at /api/bimi, and avatars ask it only for
messages whose own Authentication-Results say dmarc=pass for the exact
From domain.
- `lib/bimi/`: DMARC policy check (quarantine or reject, pct=100, the
parent domain's sp and p for subdomains), the assertion record with
fallback to the parent domain, mark certificate validation (chain to
pinned DigiCert, GlobalSign and SSL.com VMC roots, BIMI key purpose,
validity, SAN, SCTs present, CRL revocation, logo from the logotype
extension), SVG Tiny PS checks and rendering to PNG, caching
- logos backed only by the DNS record show by default; the admin
setting "Require a mark certificate" (`BIMI_REQUIRE_CERTIFICATE`)
limits them to VMC and CMC backed ones
- a check mark beside the sender's name for certificate-backed logos
- avatars try contact photo, BIMI logo, plugin avatar, favicon; the
sender warning shield still wins, and logos follow the sender icons
setting and the no-third-party-traffic mode
- the two-label public suffix list moved to `lib/root-domain.ts`
SCT signatures are not verified and only the default selector is used.
Admins write an HTML and a plain-text signature with placeholders on
Organisation > Signatures, per scope. Users fill in the details it asks
for once, under Settings > Account. Without a lock it is the default for
addresses without a signature of their own; locked or hidden, it
replaces every signature.
- `lib/org-signature.ts` fills the templates: values escaped, lines whose
placeholders are all empty dropped
- the composer applies it right before the plugin signature, so new mail,
replies, forwards, re-opened drafts, plain text and identity swaps all
take it the way they take an identity signature; quick reply too
- a send finaliser puts a locked signature back once when it was deleted
- the identity editor shows the filled-in signature read-only with "Set
by your organisation" when locked, and no editor when hidden
- `signatureDetails` is a synced setting
A new feature gate, tagsAboveSharedEnabled (default off, so the sidebar
keeps its order), lists the Tags section above the shared mailboxes
instead of below them. With many shared mailboxes expanded, the tags
otherwise end up out of sight. In Mountain View the tags then follow the
Labels list directly, also when More is open.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The admin drew its own copy of the rail, with a logo and only the app
links, next to a sidebar that signed out from its footer. It now renders
the webmail's NavigationRail (desktop and phone), which needs the
translation, theme and tour providers under /admin, so the admin layout
loads the message catalog itself; the rail marks Admin as the current
app for password admins too. The sidebar footer carries the admin
session links and the same about footer as the settings. Plugin and
theme rows and the detail header show the extension's icon from the
directory listing instead of a generic one, and a plugin's own settings
move to the bottom of its page, after availability, permissions and
versions.
The old panel kept its active tab in a store, so every page sat at
/admin, the sidebar duplicated the webmail rail by hand, and each page
was a stack of boxed cards with their own save buttons. Plugin settings
were only reachable through a gear icon in a row of five.
- one catch-all route for the whole panel; pages switch through
history.pushState, so `/admin/plugins/<id>`, the back button, bookmarks
and connector links all work without a route transition
- sidebar laid out like the user settings: back to mail, search over
pages and their sections, two group headings, change password and
sign out at the bottom; the phone shows a list, then the page
- pages use SettingsSection rows instead of nested cards, with one page
header, one flash message and one save bar at the bottom (Discard,
Save, Ctrl+S); the unsaved-changes prompt still guards leaving
- plugins and themes are lists of rows with a toggle each; a row opens
the extension's own page with its settings, force-on, permissions,
kept versions and removal
- overview shows stat tiles, server facts and recent activity
- old `/admin?tab=x` links redirect; the tab store is gone and the
connector registry resolves admin links to the page URL
- `NEXT_TURBOPACK_ROOT` overrides the Turbopack root so `next dev` runs
from a worktree with a junctioned node_modules
The marketplace now talks to the extension directory's v2 API only. The
detail page lists every version, previews the one picked, installs it,
and refuses a version the publisher withdrew unless the admin confirms,
or one outside the Bulwark range it supports. The listing gains sort, an
Installed view and an updates strip fed by the directory's updates check,
with notices for advisories, deprecations and suspensions.
A self-hosted directory older than 2026-10-14 has no v2 API and no
longer works with the marketplace.