Commit Graph
3257 Commits
Author SHA1 Message Date
Linus Rath 489a2b2f5f test: give the thread row test's auth store the state the plugin actions read 2026-10-28 10:20:15 +01:00
Linus Rath 41b0afff4b test: expect the organisation lock note on a theme mode the admin locked 2026-10-28 10:20:15 +01:00
Linus Rath a535bbbaf6 chore: translate the organisation features into every language 2026-10-28 09:53:16 +01:00
Linus Rath ae098a6e12 docs: add recovering deleted items to the changelog #1319 2026-10-28 09:18:07 +01:00
Linus Rath 5d90a850bd Merge branch 'feat/org-recovery' into feat/org-features
# Conflicts:
#	components/email/email-list.tsx
2026-10-28 09:17:56 +01:00
Linus Rath 5ebc47dbe6 docs: add shared tags to the changelog 2026-10-28 09:15:29 +01:00
Linus Rath 272083399c Merge branch 'feat/org-tags' into feat/org-features
# Conflicts:
#	lib/admin/restriction-keys.ts
#	lib/jmap/client.ts
2026-10-28 09:15:17 +01:00
Linus Rath f1a666777b Merge branch 'feat/org-features' into feat/org-recovery 2026-10-28 09:08:49 +01:00
Linus Rath 68756cd088 test: answer the paged archive calls in the recovery spec and check the Trash link stays away from an empty archive #1319 2026-10-28 09:08:44 +01:00
Linus Rath 4d846cfc91 fix: read the whole deleted items archive newest first and only for the account shown #1319
Stalwart's x:ArchivedItem/query without calculateTotal scans ids
ascending, stops at 5000 and only then reverses them, so the newest
items of a large archive never showed, and admin accounts got every
account's items. The review of the branch also found gaps around
account switches, restores and focus.

- Read the archive in pages of 500 with calculateTotal, newest first,
  stop at a whole page older than the days limit, and offer
  "Show older" after 2000 items; detection asks for one item.
- Send the accountId filter and fall back without it on
  unsupportedFilter; keep only items of the account, never one without
  an account id.
- Ask nothing until config and policy are loaded and the policy is the
  current account's; the later check after a refusal is forced.
- Show the Trash link only when the archive holds a message inside the
  days limit; the Settings page shows whenever the server has the
  feature and says that archiving must be on in Stalwart.
- Restore: notFound leaves the list with a note, forbidden hides the
  page, results for another account are dropped, the button keeps focus.
- Forget what servers said at a full sign-out.
2026-10-28 09:08:44 +01:00
Linus Rath 44eeb6aa65 docs: add shared templates to the changelog 2026-10-28 09:04:03 +01:00
Linus Rath da37d96449 test: cover per-tag saves, the group tag view and the delete warning on phones 2026-10-28 09:01:47 +01:00
Linus Rath 3a03bc363b Merge branch 'feat/org-templates' into feat/org-features 2026-10-28 09:01:42 +01:00
Linus Rath 26d9fadc50 feat: count shared tags per group and open their tag view in that group only 2026-10-28 08:58:23 +01:00
Linus Rath 7f751e7de2 fix: offer the tags of the selection's account in the context menu, like the toolbar 2026-10-28 08:58:19 +01:00
Linus Rath 33ca8efb0f fix: keep shared tags safe when members edit at once or the server fails
The first version wrote the whole tag list on every change, guessed a
group when the server wouldn't say, and treated a failed read like a
server without metadata. Now:

- Definitions are a map by tag id under `tags`, and each change patches
  one tag (`metadata/org.bulwarkmail.tags/tags/<id>`), so two members
  adding tags at once both keep theirs. Fields and colors this version
  doesn't know survive. The `{ list }` and bare-array shapes are still
  read and converted by the first save.
- Shared tags appear only for confirmed group principals. A failed
  principal lookup keeps the user's own tags and asks again later.
- "No metadata advertised" (0.16) and "the read failed" are separate.
  A failed read keeps the last good tags; a failed save keeps the change,
  says so, and sends it with the next good read after the client's
  pause.
- Push reloads wait for 5 s of quiet and skip the echo of our own save;
  a returning tab reloads definitions only, and the scan for unnamed tags
  runs once per sign-in and then at most every 30 minutes.
- The editor names its buttons after the tag, shows the delete warning
  and 44 px buttons on phones, returns focus to the edit button, and
  asks for Inbox rights only for confirmed groups.
2026-10-28 08:58:11 +01:00
Linus Rath 9d9a50e407 test: cover migrating a browser's templates and hidden personal templates against the test servers 2026-10-28 08:33:05 +01:00
Linus Rath e82679c3dc fix: name the admin section for deleted mail Recover deleted items, as users see it 2026-10-28 08:30:11 +01:00
Linus Rath dfa37ee311 fix: take the browser's templates into the account as soon as its synced settings have loaded 2026-10-28 08:29:03 +01:00
Linus Rath 2ed87b2b7f docs: add the team inbox plugin and the new plugin APIs to the changelog 2026-10-28 08:28:38 +01:00
Linus Rath 08f25506d4 Merge branch 'feat/org-teaminbox' into feat/org-features 2026-10-28 08:26:48 +01:00
Linus Rath b6d49aac4f test: check that the team inbox badge names bob where the server shares names 2026-10-28 08:25:02 +01:00
Linus Rath 23f67a5e72 fix: keep plugin chips named by their filter, draw the team icons at once and pass attributes to icons still loading 2026-10-28 08:16:52 +01:00
Linus Rath c00c7080a1 fix: give plugins the directory only with their own permission, and only confirmed team mailboxes
- `directory:read` for api.user.findPeople, with at least 3 characters,
  at most 20 ids, 20 results and 10 lookups a minute, in the directory
  of the account the call names; one load in flight per client.
- Plugins hear `group` only for accounts the server confirmed are group
  principals; the policy's fallback stays for the admin's scopes.
- The email.* keyword methods refuse $draft, $junk, $notjunk and
  $phishing.
- A plugin keeps at most 4 KB in a mailbox and reads it 30 times a
  minute; the email:write consent text says others in a team mailbox
  can read it.
- email.updateKeywords also changes the rows of expanded conversations.
2026-10-28 08:16:52 +01:00
Linus Rath 7f06ed7637 Merge branch 'feat/org-features' into feat/org-tags
# Conflicts:
#	lib/admin/restriction-keys.ts
2026-10-28 08:14:39 +01:00
Linus Rath fcd9930e4a test: cover recovering deleted items against the test servers #1319 2026-10-28 08:08:34 +01:00
Linus Rath 23ad598896 fix: shorten the Trash line that leads to Recover deleted items so it fits the list 2026-10-28 08:08:33 +01:00
Linus Rath 9304557819 fix: look up another signed-in account for the external mail checks only when an admin turned them on 2026-10-28 08:07:55 +01:00
Linus Rath f1bcba6222 fix: start merging the browser's template list from the sync driver, not at import 2026-10-28 07:53:54 +01:00
Linus Rath 2a5f6fc6f0 test: cover expired tombstones and a lone queued deletion at sign-out 2026-10-28 07:48:49 +01:00
Linus Rath 11d92549f4 fix: remember for the tab whether the server offers deleted item recovery, so a reload doesn't ask again 2026-10-28 07:43:33 +01:00
Linus Rath 61d4e02e38 test: keep the Trash link out of a shared Trash without an account id 2026-10-28 07:39:00 +01:00
Linus Rath 62bed18fe8 Merge branch 'feat/org-features' into feat/org-teaminbox 2026-10-28 07:38:25 +01:00
Linus Rath 88f20e1ab0 fix: never lose personal templates to a deletion, a clock or a settings load elsewhere
The first version took a template missing from the account's Inbox
metadata as deleted, skipped the browser's own list once the account
held anything, wrote the marker before the settings blob had loaded,
and let a round overwrite edits made while it ran. Each of these could
drop templates, or bring deleted ones back.

Now the marker entry `org.bulwarkmail.templates` holds tombstones
(90 days, at most 8 KB, oldest dropped first) and only a tombstone
deletes; a missing entry is uploaded again. Every round merges the
browser's list in when it is this account's, each version once, minus
what a newer tombstone deleted. While settings sync hasn't loaded the
account's settings, the list isn't used and no marker is written; a
blob that loads later is merged into the account's copy. The settings
blob drops its templates only once the marker is on the server. Without
settings sync the list goes into the first account that answers only.
A round that saw changes while it ran plans again against the server as
it left it. An answer without the metadata property counts as
unsupported. Changes move `updatedAt` past the previous value, dateless
synced templates get a fixed early date, and ids that don't fit a
metadata key get a new id derived from the old one. Queued changes go
out before an account signs out; a full sign-out keeps unsent templates
and deletions.

Team templates are written only if the entry is still the version the
edit started from ("Changed by someone else"), never carry Bcc, and a
refusal is told apart by Stalwart's error type. The template manager's
lists are a real tab list with arrow keys and 44 px row buttons on
phones.
2026-10-28 07:34:25 +01:00
Linus Rath 4aa4606b84 fix: give plugins no personal templates when the admin hid them 2026-10-28 07:34:23 +01:00
Linus Rath 63d64bba13 fix: show who a template addresses before inserting it and suggest the account's own categories 2026-10-28 07:34:05 +01:00
Linus Rath a6af7bc8f1 feat: let admins limit or hide recovering deleted items per domain or group #1319 2026-10-28 07:27:55 +01:00
Linus Rath ba6e6af014 feat: recover deleted items from Stalwart's archive #1319 2026-10-28 07:27:47 +01:00
Linus Rath 8d8bc26602 test: check that the team inbox names are kept in the team Inbox on Stalwart v1.0.0 2026-10-28 07:19:08 +01:00
Linus Rath 97d686b916 test: check that the 1.0 test build was asked for shared tags and stayed online 2026-10-28 07:18:16 +01:00
Linus Rath 5efcca2315 test: cover the team inbox plugin's assignment, filters and phone menu against the test servers 2026-10-28 07:16:53 +01:00
Linus Rath a049282cc0 test: check live edits and the unified inbox for shared tags 2026-10-28 07:15:14 +01:00
Linus Rath a19d95c4bb test: cover shared tags in group mailboxes against the test servers 2026-10-28 07:10:42 +01:00
Linus Rath 528450db61 fix: name the edit button of a shared tag after the tag, not the list 2026-10-28 07:10:42 +01:00
Linus Rath b5e92ba176 Merge branch 'feat/org-features' into feat/org-templates
# Conflicts:
#	lib/admin/restriction-keys.ts
2026-10-28 07:10:25 +01:00
Linus Rath 9f7e875faf docs: add delegates to the changelog 2026-10-28 06:49:14 +01:00
Linus Rath 3d8a0cfd0b feat: let admins lock shared tags per domain or group 2026-10-28 06:46:04 +01:00
Linus Rath 2944ead665 test: check that the 1.0 test build drops the metadata request and the app stays online 2026-10-28 06:45:12 +01:00
Linus Rath b049b6f470 feat: share tag names and colours in group mailboxes #1310 2026-10-28 06:43:46 +01:00
Linus Rath a69d7eee33 feat: let plugins work with team mailboxes: list filters, row badge icons, account info and message conditions
What the team inbox plugin needs, kept general for other plugins:

- `api.ui.setListFilters`: keyword filters drawn as chips in the list
  header of the folders they apply to (by account kind and folder
  role). A chip the user turns on is ANDed into the folder's query and
  comes off with one click; a keyword change a filter tests loads the
  list again (ui:message-list).
- Actions get `accounts`, `hasKeyword` and `notKeyword`, so a button
  shows only on messages of group accounts, or of a keyword state; the
  click of message-row-actions and reader-actions carries the message's
  `accountId`.
- `api.email.updateKeywords`: several keywords in one change, through
  the list for a listed message (email:write).
- `api.user.getSelf`, `getMailAccounts` and `findPeople`: the user's own
  account id (Stalwart's principal id), which accounts are group
  accounts, and people from the directory (account:read).
- `api.accountData`: a plugin's own entry in a mail account's shared
  Inbox metadata on Stalwart 1.0 (email:read / email:write).
- Row badges take an `icon`.
2026-10-28 06:39:57 +01:00