docs: sessions, accounts, trusted senders, conversations, themes and the new reader

README: what the webmail now does, the architecture roles, a short guide with the
shortcuts, testing with a real database, and an honest list of what is not
finished. New docs/WEBMAIL.md as the reference for each feature and for the
colour system. OPERATIONS: sessions and trusted senders. DEPLOYMENT: the
two-step release as API calls, and what to expect when upgrading. MAILBOX-CORE:
the conversation invariants and migrations 0015 to 0018.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas RayanandClaude Sonnet 5.5 committed 2026-10-23 06:24:36 -03:00
1 parent c00134f2eb
commit 58d6f8e9e2
5 files changed
+471 -17

No files matched your search

+50 -4
View File
@@ -132,6 +132,47 @@ DELETE FROM mfa_totp WHERE mailbox_id = (SELECT id FROM mailboxes WHERE email_ad
DELETE FROM mfa_recovery_codes WHERE mailbox_id = (SELECT id FROM mailboxes WHERE email_address = 'them@example.com');
```
### Sessions
A webmail session lasts 30 days and is renewed once it is a day old; the
console's lasts 8 hours and is never renewed. The sessions a person holds are
listed in Settings, where each can be signed out; a password change or reset
revokes every other one, and a reset revokes all of them. To end every session
of an account from the database:
```sql
UPDATE web_sessions SET revoked_at = NOW()
WHERE mailbox_id = (SELECT id FROM mailboxes WHERE email_address = 'user@example.com')
AND revoked_at IS NULL;
```
Renewal retires the old token after a two-minute grace rather than at once
(its `revoked_at` is briefly in the future), so a session list can show two rows
for a moment after a renewal. Rotating `JWT_SECRET` signs everyone out, webmail
and console alike.
Each account signed in on a browser also has a `lm_acct_<mailbox id>` cookie.
They are only the browser's own copy of its sessions: revoking a session on the
server makes that account drop out of the switcher the next time it is listed.
### Trusted senders
`trusted_senders (mailbox_id, address)` holds what each person has trusted. It
is part of the database backup and nothing else needs backing up for it. To see
or remove a mailbox's entries:
```sql
SELECT address, created_at FROM trusted_senders
WHERE mailbox_id = (SELECT id FROM mailboxes WHERE email_address = 'user@example.com');
DELETE FROM trusted_senders WHERE mailbox_id = '<id>' AND address = 'x@example.org';
```
A trusted sender's mail is rescued from Junk only when it proves where it came
from (DMARC passed, or SPF passed for the From domain); see
[docs/WEBMAIL.md](WEBMAIL.md#trusted-senders). If a trusted sender's mail still
lands in Junk, look at the `Authentication-Results` header on it: a message
without that proof is deliberately left in Junk.
## Delivery
The outbound queue lives in Postgres, so it survives a restart of anything. The
@@ -175,10 +216,15 @@ disagree — most often because a record was edited by hand.
Rspamd holds its state in Redis and its thresholds in `system_config`, editable
from the admin console. The defaults reject at 15, tag at 6 and greylist at 4.
A message the filter routes to `Junk` is filed there; one over the reject
threshold is refused during the SMTP session, so the sender is told. Nothing is
accepted and silently discarded — a silent discard loses legitimate mail with
nobody aware of it.
A message the filter routes to `Junk` is filed there, unless the mailbox trusts
the sender and the message proves it came from them (see
[Trusted senders](#trusted-senders)); one over the reject threshold is refused
during the SMTP session, so the sender is told. Nothing is accepted and
silently discarded — a silent discard loses legitimate mail with nobody aware
of it.
"Not spam" in the webmail trusts the sender; it does not train Rspamd. To teach
the filter, use Rspamd's own learning (`rspamc learn_ham`) or its web interface.
## Rotating a DKIM key