feat(mail): add governed JMAP mailbox sync and search
Module Package Release / publish-packages (push) Successful in 12s
Module Package Release / publish-packages (push) Successful in 12s
This commit is contained in:
+32
-20
@@ -23,12 +23,12 @@ See also [Mail protocol roadmap](MAIL_PROTOCOL_ROADMAP.md) and the Campaign
|
||||
|
||||
Mail owns:
|
||||
|
||||
- reusable SMTP/IMAP profile definitions, dedicated legacy POP3 sources, and scope;
|
||||
- encrypted SMTP/IMAP/POP3 credentials and safe credential replacement;
|
||||
- reusable SMTP/IMAP/JMAP profile definitions, dedicated legacy POP3 sources, and scope;
|
||||
- encrypted SMTP/IMAP/JMAP/POP3 credentials and safe credential replacement;
|
||||
- effective profile policy and visibility/authorization decisions;
|
||||
- connection tests and protocol adapters;
|
||||
- SMTP send and IMAP append operations exposed to consumers;
|
||||
- read-only mailbox folder/message access, bounded indexes, and encrypted
|
||||
- read-only IMAP/JMAP mailbox folder/message access, bounded indexes, and encrypted
|
||||
pending-review records imported from legacy POP3 sources; and
|
||||
- the transport sanitization boundary and throttling behavior. A general
|
||||
Mail-owned provider-attempt/diagnostic ledger remains planned.
|
||||
@@ -94,7 +94,7 @@ deactivating a profile may scrub Mail-owned credentials as described below.
|
||||
### Profile
|
||||
|
||||
A profile is a reusable, named delivery identity with optional SMTP and IMAP
|
||||
configuration. It can additionally own a dedicated POP3 endpoint for an
|
||||
configuration and one or more opt-in JMAP mailbox endpoints. It can additionally own a dedicated POP3 endpoint for an
|
||||
explicit legacy-import workflow. It has a stable id, lifecycle state, scope,
|
||||
owner context, and non-secret connection metadata. Passwords are write-only
|
||||
encrypted values and are never returned through list/read/capability responses.
|
||||
@@ -114,14 +114,14 @@ operation: using, testing, managing, and managing secrets are separate rights.
|
||||
### Policy
|
||||
|
||||
Mail policy controls approved profile ids, which lower scopes may define
|
||||
profiles, allowed/denied hosts and addressing patterns, credential inheritance,
|
||||
profiles, allowed/denied SMTP/IMAP/JMAP hosts and addressing patterns, credential inheritance,
|
||||
and lower-level limits. The effective result is assembled from applicable
|
||||
system, tenant, user/group, and campaign context. Denials and locked parent
|
||||
limits cannot be relaxed by a lower scope.
|
||||
|
||||
### Transport identity and revision
|
||||
|
||||
Mail owns opaque random revisions for relevant SMTP/IMAP identity and
|
||||
Mail owns opaque random revisions for relevant SMTP/IMAP/JMAP identity and
|
||||
configuration. They are concurrency tokens, not deterministic hashes that a
|
||||
consumer could use to guess a host or account. Credentials are excluded. A
|
||||
consumer can freeze these revisions at build time and ask Mail to require the
|
||||
@@ -164,7 +164,7 @@ new idempotency key and links it to the prior command.
|
||||
2. Choose from the profiles visible and authorized for the current tenant,
|
||||
owner, group, and task context. Never enter or copy a profile id manually
|
||||
when the UI can present a picker.
|
||||
3. Review the safe summary: name, scope, active state, SMTP/IMAP availability,
|
||||
3. Review the safe summary: name, scope, active state, SMTP/IMAP/JMAP availability,
|
||||
and policy-relevant sender identity. Credentials and raw provider internals
|
||||
are not visible.
|
||||
4. Save the reference in the consuming module. If ownership or policy changes,
|
||||
@@ -177,7 +177,7 @@ permission.
|
||||
### Test a profile
|
||||
|
||||
An authorized profile test verifies connection and authentication for the
|
||||
selected active/visible SMTP or IMAP profile using Mail-owned credentials. The
|
||||
selected active/visible SMTP, IMAP, or JMAP profile using Mail-owned credentials. The
|
||||
consumer-use path evaluates effective Mail policy separately. Use a
|
||||
non-production provider and mailbox first. A successful connection test does
|
||||
not prove policy authorization for a later Campaign context, deliverability,
|
||||
@@ -194,9 +194,13 @@ ordinary consumers to bypass reusable profiles.
|
||||
### Read a mailbox
|
||||
|
||||
The current mailbox UI and API are read-only. An authorized user can list IMAP
|
||||
folders, page through messages, and inspect a bounded full message. Folder
|
||||
names are parsed and quoted defensively; Sent-folder discovery uses provider
|
||||
flags and common names. The list exposes the provider's `Seen` flag as a
|
||||
or JMAP folders, page through messages, and inspect a bounded full message.
|
||||
IMAP folder names are parsed and quoted defensively; Sent-folder discovery uses
|
||||
provider flags and common names. JMAP discovers the Session and Mail account,
|
||||
uses `Mailbox/get` hierarchy and roles, runs text search with `Email/query`, and
|
||||
uses `Email/get` for bounded summaries/details. `Email/changes` exposes a
|
||||
bounded incremental cursor; an expired state tells the caller to perform a full
|
||||
refresh. The list exposes the provider's `Seen`/`$seen` state as a
|
||||
read/unread indicator without changing it. It also labels whether the current
|
||||
page came directly from the provider, from the bounded mailbox index, or from
|
||||
an index while a refresh is in progress, including the index timestamp when
|
||||
@@ -210,9 +214,16 @@ silently interpreted as an empty message.
|
||||
|
||||
Mailbox access requires both `mail:mailbox:read` and `mail:profile:use`. It must
|
||||
not mutate read/unread, delete, move, or reply state. Message responses are
|
||||
bounded by the deployment response policy; ordinary UI should avoid loading a
|
||||
bounded by the endpoint response/body policy; ordinary UI should avoid loading a
|
||||
whole large mailbox or attachment merely to show a list.
|
||||
|
||||
JMAP is opt-in per server endpoint. Its authenticated Session URL is governed
|
||||
by `jmap_hosts`; an advertised API URL on another origin fails closed unless
|
||||
that origin is explicitly listed for the endpoint. Bearer tokens or Basic
|
||||
credentials are stored only in Mail credential envelopes. This slice does not
|
||||
send through JMAP, mutate provider state, download attachment binaries, or add
|
||||
calendar/contact/thread features.
|
||||
|
||||
### Import a legacy POP3 mailbox
|
||||
|
||||
POP3 is available only for bounded migration from a legacy server that cannot
|
||||
@@ -299,21 +310,21 @@ the deletion in the audit log.
|
||||
|
||||
The configured Help Center exposes **Create a custom Mail profile** only when
|
||||
the current actor has broad or self-service profile-write authority and the
|
||||
effective user-scope policy permits user profiles. It states the active SMTP/IMAP hostname
|
||||
effective user-scope policy permits user profiles. It states the active SMTP/IMAP/JMAP hostname
|
||||
allow-list groups and deny rules, plus the actor's separate credential, test,
|
||||
use, and approval requirements. The Settings task creates in the current
|
||||
account's user scope. Grant `mail:profile:write_own` for self-service;
|
||||
`mail:profile:write` remains broad profile administration authority.
|
||||
|
||||
1. Choose the narrowest suitable scope and a stable, descriptive name/slug.
|
||||
2. Configure SMTP, optional IMAP, TLS mode, account identity, standard folder
|
||||
2. Configure SMTP and optional IMAP, or add an optional JMAP Session endpoint after creating the profile. Set TLS mode, account identity, standard folder
|
||||
mappings, and timeouts. Folder discovery proposes provider-visible Inbox,
|
||||
Sent, Drafts, Trash, Archive, and Junk names without mutating the mailbox.
|
||||
Sender/envelope/recipient constraints belong to
|
||||
effective Mail policy; Campaign rate limits remain delivery configuration.
|
||||
3. Enter credentials only in the dedicated credential fields. Returned profile
|
||||
data indicates whether credentials are configured without returning them.
|
||||
4. Save and run SMTP/IMAP tests against a non-production target.
|
||||
4. Save and run SMTP/IMAP/JMAP tests against a non-production target.
|
||||
5. Verify the effective policy for every intended consumer context.
|
||||
6. Communicate changes that alter the non-secret transport identity; prepared
|
||||
consumer snapshots will deliberately stop until rebuilt.
|
||||
@@ -325,7 +336,7 @@ credential replacement never depends on reading the old cleartext value back.
|
||||
|
||||
Profile deletion is immediate for Mail-owned secrets and audit evidence:
|
||||
|
||||
1. Mail clears both encrypted SMTP and IMAP passwords in the same transaction.
|
||||
1. Mail clears encrypted SMTP, IMAP, JMAP, and POP3 credential envelopes in the same transaction.
|
||||
2. It deactivates the remaining non-secret tombstone state so historical stable
|
||||
references can fail safely rather than resolve to another profile.
|
||||
3. When owned encrypted secrets existed, it emits
|
||||
@@ -346,7 +357,7 @@ Effective policy is contextual. Administrators should document:
|
||||
|
||||
- which profile ids are approved globally or for a tenant;
|
||||
- whether tenant, user, group, or campaign-scoped profiles may be created;
|
||||
- allowed and denied SMTP/IMAP hosts;
|
||||
- allowed and denied SMTP/IMAP/JMAP hosts;
|
||||
- permitted From, envelope sender (including bounce address), and envelope
|
||||
recipient-domain patterns;
|
||||
- whether SMTP/IMAP credentials inherit from the reusable profile; and
|
||||
@@ -499,7 +510,7 @@ mandatory release gate.
|
||||
|
||||
Security invariants:
|
||||
|
||||
- Decrypted SMTP/IMAP passwords never cross the Mail capability/API boundary.
|
||||
- Decrypted SMTP/IMAP passwords and JMAP/POP3 credentials never cross the Mail capability/API boundary.
|
||||
- Password fields are write-only and encrypted at rest; safe responses expose
|
||||
configuration state, not values.
|
||||
- Consumers persist stable profile references, not transport copies.
|
||||
@@ -556,8 +567,9 @@ Before claiming a Mail composition is production-ready:
|
||||
semantics (`govoplan-mail#16`).
|
||||
- Final Campaign **test / single send / single resend** semantics; those are a
|
||||
Campaign business-action contract built on Mail transport operations.
|
||||
- JMAP mailbox synchronization/search; it is preferred only after the IMAP MVP
|
||||
is stable.
|
||||
- JMAP provider-side mutation, submission, push, thread, calendar, contact,
|
||||
attachment-binary, and automatic background-sync support; read-only mailbox
|
||||
synchronization/search is implemented on the stable IMAP mailbox contract.
|
||||
- Expanding POP3 beyond the implemented explicit legacy download/import
|
||||
workflow; it has no folder, flag, search, or synchronization contract.
|
||||
- A full mail client with compose/reply/move/delete/read-state mutation.
|
||||
|
||||
Reference in New Issue
Block a user