Masked email decisions before implementation: storage, start state, rate config, who administers (ME-7a, ME-15, ME-19)
This commit is contained in:
@@ -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).
|
||||||
|
|||||||
Reference in New Issue
Block a user