Commit Graph
732 Commits
Author SHA1 Message Date
Linus Rath 8a3351bbc9 fix: refuse an oversized plugin approval upload before reading it 2026-10-26 15:15:58 +01:00
Linus Rath 42117da498 fix: stop replaying a stored credential the mail server refused, so a stale session cannot get the webmail banned (GHSA-g6c7-r7wq-xrm2) 2026-10-26 15:00:56 +01:00
Linus Rath ae897b42a4 fix: make the impersonation handoff really clear the previous account list and ignore ?impersonated=1 links from elsewhere 2026-10-26 14:58:31 +01:00
Linus Rath eb2787bcc9 fix: end admin sessions on sign-out and when the admin password changes 2026-10-26 14:52:04 +01:00
Linus Rath 121d2d5e31 fix: stop buffering up to 100 MB of every unauthenticated request body before routing 2026-10-26 14:52:04 +01:00
Linus Rath 08969fde67 fix: stop reading a mail server's answer past a size limit in the JMAP, WebDAV, push preview and agenda routes 2026-10-26 14:52:04 +01:00
Linus Rath 07e6ecce1a fix: show a plain new-mail notification instead of another login's message when two signed-in logins have the same account id 2026-10-26 14:52:04 +01:00
Linus Rath 885ecdaa07 fix: keep the server's path prefix in the CalDAV addresses shown in calendar settings 2026-10-26 14:52:04 +01:00
Linus Rath e6c911899c fix: refuse a session secret under 32 characters in the setup wizard, which broke admin sign-in afterwards 2026-10-26 11:48:39 +01:00
Linus Rath fa3e76652f fix: keep plugin credentials of a bare-name token sign-in under the account it resolved to 2026-10-26 11:36:57 +01:00
Linus Rath 5bd03d175d fix: show all-day events on their own day in the Calendar Agenda for viewers west of the server's time zone 2026-10-26 11:33:38 +01:00
Linus Rath b9fc9bc9c0 fix: stop synced settings from piling up a new file for every extra slash after the server address 2026-10-26 11:33:38 +01:00
Linus Rath 01a1dc47a6 fix: load push notification previews when the webmail reaches the mail server on an internal address 2026-10-26 11:33:37 +01:00
Linus Rath 1fc44b4813 fix: show the push notification for mail in an account shared into another signed-in login 2026-10-26 11:33:37 +01:00
Linus Rath 9ed3354550 fix: send a password and TOTP sign-in to the server the user typed, not the default one 2026-10-26 11:33:37 +01:00
Linus Rath 680742c3ef fix: end a password and TOTP sign-in without remember me with the browser session 2026-10-26 11:33:37 +01:00
Linus Rath ec0fed19cc fix: stop reading a marketplace bundle download once it passes the package size limit 2026-10-26 11:29:37 +01:00
Linus Rath cb51847ab3 fix: refuse plugin approval requests while user plugins or their review are turned off (GHSA-qc44-275p-gqw9) 2026-10-26 11:29:36 +01:00
Linus Rath cf2c27157d Merge branch 'main' into feat/stalwart-1.0
# Conflicts:
#	components/contacts/contacts-app.tsx
#	components/email/__tests__/composer-discard.test.tsx
#	components/email/calendar-invitation-banner.tsx
#	components/email/email-composer.tsx
#	components/mail/mail-app.tsx
#	components/pro/pro-compose-tab-body.tsx
#	components/pro/pro-email-tab-body.tsx
#	components/ui/__tests__/avatar.test.tsx
#	components/ui/avatar.tsx
#	hooks/use-mailbox-drop.ts
#	lib/__tests__/calendar-alerts.test.ts
#	lib/__tests__/jmap-calendar-tasks.test.ts
#	lib/__tests__/jmap-send-threading.test.ts
#	lib/demo/demo-client.ts
#	lib/demo/fixtures/calendars.ts
#	lib/jmap/client-interface.ts
#	lib/jmap/client.ts
#	lib/web-push.ts
#	stores/__tests__/contact-store.test.ts
#	stores/__tests__/email-store-thread-key.test.ts
#	stores/calendar-store.ts
#	stores/contact-store.ts
#	stores/email-store.ts
2026-10-26 10:14:12 +01:00
Linus Rath e38e326efb perf: load plugin frames as a plain page instead of a Next app
Every plugin iframe loaded /plugin-sandbox, a force-dynamic Next page.
Each frame then fetched, parsed and hydrated Next's client router on top
of React and the runtime, and the server rendered the page once per
frame, one after another when a dozen plugins started together.
Sandboxed frames have opaque origins, so the browser's code cache never
helps, and they run on the host page's main thread: with 12 plugins
the frames took 2.5-3 s to come up after the app had loaded.

The sandbox routes now return a small HTML page with the UI kit's
stylesheet and the runtime as an ES module, both built ahead of time:

- `scripts/build-plugin-sandbox.mjs` bundles the runtime with esbuild
  and compiles `plugin-kit.css` with the app's Tailwind setup into
  `public/plugin-sandbox-assets/`, with a manifest. Named Tabler imports
  are pointed at the icons' own files, so the full icon set stays in a
  chunk that only loads for an icon name the kit doesn't ship.
- `npm run build`, `npm run dev`, the Dockerfile and the perf-guard
  workflow run it before `next build`.
- `lib/plugin-sandbox/sandbox-document.ts` writes the page; proxy.ts
  still sets the sandbox CSP and the script carries its nonce.
- The assets are served from public/ with CORS and immutable caching.

A frame on an idle page is ready in 255 ms instead of 362 ms, eleven at
once in 1.0 s instead of 2.1 s.
2026-10-25 02:01:47 +01:00
Jacob ZeitzandClaude Opus 5.5 96526c1b41 feat: admin policy gate to list the Tags above the shared mailboxes
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>
2026-10-24 08:54:23 +02:00
Linus Rath 310f910a6a fix: hand a mobile sign-in to the app when the browser was already signed in 2026-10-22 08:02:08 +02:00
Linus Rath 416e59fa54 fix: give the admin panel the real navigation rail, extension icons and the plugin settings last
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.
2026-10-20 15:38:55 +02:00
Linus Rath 10b4d2a9db feat: rework the admin panel around a settings-style sidebar and one URL per page
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
2026-10-20 15:16:05 +02:00
Linus Rath 391ed6c018 Merge branch 'fix/security-audit-2026-10' 2026-10-19 12:58:50 +02:00
Linus Rath 9f3441c783 fix: accept both fetch response types in the capped feed reader 2026-10-19 01:36:16 +02:00
Linus Rath 546f34f47e fix: cap concurrent upstream favicon fetches 2026-10-19 01:32:29 +02:00
Linus Rath d13aada077 fix: bound how many CalDAV probes one discovery request can make 2026-10-19 01:32:29 +02:00
Linus Rath 703a15663f fix: keep the extension directory URL off private addresses 2026-10-19 01:32:25 +02:00
Linus Rath 71036c1812 fix: validate the marketplace version and refuse a silent downgrade on update 2026-10-19 01:32:24 +02:00
Linus Rath 5632097971 fix: type the capped feed reader and the invitation sender lookup 2026-10-19 01:32:23 +02:00
Linus Rath 0b01a2d066 fix: ask before handing a sign-in to the mobile app and only to its own callback link 2026-10-19 01:22:19 +02:00
Linus Rath 044c98e6d2 fix: cap the size of a synced settings blob 2026-10-19 01:15:04 +02:00
Linus Rath c0b6519136 fix: stop reading a calendar feed at the size cap instead of buffering it whole 2026-10-19 01:15:04 +02:00
Linus Rath e6064f3476 fix: only connect and proxy plugin credentials that a plugin known to the server declares 2026-10-19 01:07:50 +02:00
Linus Rath 31326c7daf fix: keep OAuth client secrets and the session secret out of the admin audit log, config API and dashboard writes 2026-10-19 00:50:16 +02:00
Linus Rath f91b214719 fix: key synced settings on the account a token login resolves to, not on a bare claimed name 2026-10-19 00:45:11 +02:00
Linus Rath 89ef4d14f2 fix: budget failed sign-ins per client and forward the client address to the mail server 2026-10-19 00:43:00 +02:00
Linus Rath 38c983a886 fix: open the mention card on click and show on hover that the chip is clickable 2026-10-19 00:38:01 +02:00
Linus Rath 8da659fd8c feat: install any version from the marketplace and show updates, withdrawn versions and advisories
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.
2026-10-19 00:09:39 +02:00
Linus Rath dd0da783c6 feat: keep replaced plugin and theme versions and roll back to them 2026-10-19 00:08:10 +02:00
Linus Rath dc837c25f2 feat: let an install link name the extension version to offer in the marketplace 2026-10-19 00:07:04 +02:00
Linus Rath fbae8acfb8 feat: turn @mentions into chips with a hover card 2026-10-18 17:52:11 +02:00
Linus Rath f3482ce020 fix: remember restored sign-ins only when the restoring account is remembered 2026-10-18 14:39:59 +02:00
Linus Rath 100da43991 Merge pull request #1247 from lucamzanon/feat/account-archive-passwords
feat: optionally keep mailbox passwords in the account list backup
2026-10-18 14:34:31 +02:00
Linus Rath 58eff0e879 Merge pull request #1258 from HOLOEYE-JZ/feat/archive-feature-gate
feat: admin policy gate to turn off archiving #1257
2026-10-18 14:29:27 +02:00
Linus Rath 8e7245b26c feat: let the theme policy set and lock the color mode #1280 2026-10-18 13:46:49 +02:00
Linus Rath 4adbad25f6 feat: end the provider session through a configured logout URL #1279 2026-10-18 13:46:48 +02:00
Linus Rath b811ad93cb fix: use the theme's sans font for the whole app #1278 2026-10-18 13:46:47 +02:00
Linus Rath 8583c9efef feat: hide the version from the connector probe when the login page hides it #896 2026-10-17 19:18:21 +02:00