Masked email decisions before implementation: storage, start state, rate config, who administers (ME-7a, ME-15, ME-19)

This commit is contained in:
2026-09-18 16:09:57 -07:00
parent e109cf86ae
commit edfb357cb1
+19 -3
View File
@@ -76,6 +76,12 @@ stays byte-for-byte what upstream wrote:
- **Tombstones**: every address ever issued, including destroyed ones, so an - **Tombstones**: every address ever issued, including destroyed ones, so an
address is never issued twice. address is never issued twice.
**Decision** (2026-09-18) on where: one new data-store subspace owned by the
fork (`X`), with its own SQL table, included in backup and restore. It also
holds an index from address to mask, since upstream's record doesn't index
`email`, and a per-account change log for `/changes`. Masks written before
the fork are indexed on first start.
## One state, two APIs ## One state, two APIs
Fastmail and upstream disagree about what "disabled" means. inbuxa-server Fastmail and upstream disagree about what "disabled" means. inbuxa-server
@@ -126,6 +132,10 @@ accepted, which is the fact `enabled` reports.
still works when it doesn't. Expired masks aren't removed automatically. still works when it doesn't. Expired masks aren't removed automatically.
- **ME-7.** Arriving mail sets `lastMessageAt`, and moves a `pending` mask to - **ME-7.** Arriving mail sets `lastMessageAt`, and moves a `pending` mask to
`enabled`. `enabled`.
- **ME-7a.** **Decision** (2026-09-18): a mask created through the Fastmail
API starts `pending` unless the create sets `state`. One created through
upstream's `x:` API, which ihasmail and existing clients use, starts
`enabled` and is never removed automatically.
- **ME-8.** A `pending` mask with no mail within 24 hours of creation is - **ME-8.** A `pending` mask with no mail within 24 hours of creation is
removed, per Fastmail's rule, and tombstoned. It's hidden from ihasmail's removed, per Fastmail's rule, and tombstoned. It's hidden from ihasmail's
list while pending, as Fastmail's own interface hides it. list while pending, as Fastmail's own interface hides it.
@@ -169,7 +179,9 @@ accepted, which is the fact `enabled` reports.
`disabled`. A create past it fails with `overQuota`. 0 turns creation off. `disabled`. A create past it fails with `overQuota`. 0 turns creation off.
- **ME-15.** Create-rate limit per account, as Fastmail's API allows: past it, - **ME-15.** Create-rate limit per account, as Fastmail's API allows: past it,
create fails with `rateLimit`. **Decision**: 50 an hour per account, create fails with `rateLimit`. **Decision**: 50 an hour per account,
configurable. configurable. **Decision** (2026-09-18) on where: the environment variable
`INBUXA_MASKED_EMAIL_CREATE_RATE` (creates per hour, default 50, 0 for no
limit), read at startup, until the fork has a settings object of its own.
- **ME-16.** `createdBy` is set by the server from the authenticated client's - **ME-16.** `createdBy` is set by the server from the authenticated client's
name (the OAuth client's name once SPEC.md §5.2 is in place). Fastmail's API name (the OAuth client's name once SPEC.md §5.2 is in place). Fastmail's API
treats it as server-set. Upstream's API accepts and stores a client-supplied treats it as server-set. Upstream's API accepts and stores a client-supplied
@@ -185,7 +197,10 @@ accepted, which is the fact `enabled` reports.
destroy. Its role needs the `sysMaskedEmail*` permissions, which the default destroy. Its role needs the `sysMaskedEmail*` permissions, which the default
user role carries: an ordinary account holds all five (observed 7). user role carries: an ordinary account holds all five (observed 7).
- **ME-19.** An administrator with the same permissions can manage another - **ME-19.** An administrator with the same permissions can manage another
account's masks, for support. A tenant administrator can manage only masks account's masks, for support. **Decision** (2026-09-18) on who counts as
one: at server level, a principal holding `impersonate`; in a tenant, one
holding `sysAccountUpdate`, for accounts in its own tenant only. Either
also needs the matching `sysMaskedEmail*` permission. A tenant administrator can manage only masks
owned by accounts in its tenant (multi-tenancy MT-1). owned by accounts in its tenant (multi-tenancy MT-1).
## The two APIs ## The two APIs
@@ -236,7 +251,8 @@ Stalwart-facing (SPEC.md §5).
## Acceptance tests ## Acceptance tests
1. Create with no arguments: gets a unique address on the account's primary 1. Create with no arguments: gets a unique address on the account's primary
domain, state `pending` in the Fastmail API and `enabled: true` in `x:`. domain. Through the Fastmail API it's `pending`, and reads `enabled: true`
in `x:`. Through `x:` it's `enabled` in both (ME-7a).
2. Mail to a pending mask: delivered, state becomes `enabled`, 2. Mail to a pending mask: delivered, state becomes `enabled`,
`lastMessageAt` set (ME-7). `lastMessageAt` set (ME-7).
3. Pending mask with no mail for 24 hours: removed and tombstoned (ME-8). 3. Pending mask with no mail for 24 hours: removed and tombstoned (ME-8).