Drafts were always created in the primary account, so a message composed as
a group identity sat in the member's own Drafts while its Sent copy (since the
previous commit) went to the group.
- createDraft takes { accountId, previousDraftAccountId }: the draft goes to
the account that owns the From identity (resolveSendAccountId, now public
and briefly caching the identity lists for autosave), and the replaced
version is destroyed in the account it lives in.
- The composer tracks draftAccountId next to draftId (save, re-resolve of
attachment blobs, send, discard, stashed state), since draft ids are only
unique within one account.
- sendEmail destroys the sent draft in options.draftAccountId; discarding
(inline and Pro tab) deletes it there, through the identity's login.
- Re-opening a draft from a group/shared Drafts folder (or a stamped
aggregate row) keeps its account.
- resolveSendAccountId is optional on IJMAPClient; without it drafts stay in
the primary account.
- Tests: client unit tests for draft placement / replacement / send cleanup,
E2E spec 18 draft cases (autosave + send, discard).
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.
The demo user becomes Nora Lindqvist, engineering lead at Meridian Labs,
in the week of a product launch. The fixtures tell one story across mail,
contacts, calendar, tasks and files, and exercise the features the
screenshots and the public demo should show:
- a second, mail-only login (her personal domain) and the shared Support
mailbox delegated to the work account, so the account switcher, the
shared section and the merged inbox have real content
- raw headers the way Stalwart writes them: the sender check fails on
the phishing mail, newsletters carry a one-click unsubscribe, one mail
asks for a read receipt, and spam scores show in the details
- an iMIP invitation with a served .ics, an event waiting for the answer
on the calendar, and RSVP patches applied in the demo client
- @mentions as mailto links in a received mail, a verification code
twelve minutes old, nested folders, named tags on the mail, contact
groups, a scheduled message and tasks switched on
- every attachment and file backed by real bytes under public/demo,
generated by `scripts/demo-assets/generate.mjs`; contact photos are
bundled portraits instead of requests to randomuser.me
- folder counts computed from the mail instead of hand-kept numbers
Demo login seeds the tags, templates and merged-inbox settings once per
device and switches the cross-account gate on for the session; "Reset"
restores them. `bulwark-demo-simulate=off` in localStorage stops the
simulated incoming mail for screenshot runs.