Undelete: deleted accounts are kept for their period, hold their addresses, and are restored or destroyed through inbuxa:DeletedAccount (UD-15 to UD-17a)

With archiveDeletedAccountsFor set, a destroyed account's record is kept in
the fork subspace with its id, its DestroyAccount task is due at the end of
the period, and its shares are suspended both ways. Its addresses can't be
taken by new accounts, aliases, lists or masks. inbuxa:DeletedAccount/get
lists kept accounts to server and tenant administrators; /set restores one
with a new password (same id, task cancelled, shares reinstated) or destroys
it now. The destroy task also clears undelete's own records.
Acceptance test 14; test 16 written as the ignored undelete_compat.
This commit is contained in:
2026-09-18 21:35:48 -07:00
parent 0a2c29e8fd
commit ecbdfd533b
21 changed files with 1357 additions and 6 deletions
+1 -1
View File
@@ -277,7 +277,7 @@ is written.
|---|---|---|---|
| 1 | Multi-tenancy | Tenants with their own domains, admins, quotas and queue visibility | Needed for anybody hosting mail for others. ihasmail already has a Tenants screen. Built 2026-09-18 in `crates/features`; status in `features/multi-tenancy.md`. |
| 2 | Masked email | Per-sender disposable addresses that deliver to the account | Existing addresses must keep delivering (§3.4). Built 2026-09-18 in `crates/features`; status in `features/masked-email.md`. |
| 3 | Undelete | Deleted mail held for a set period and restorable | Existing archived items must stay restorable. Spec: `features/undelete.md`. |
| 3 | Undelete | Deleted mail held for a set period and restorable | Existing archived items must stay restorable. Built 2026-09-18 in `crates/features`; status in `features/undelete.md`. |
| 4 | Branding and templates | Operator logo, and the text of calendar alarm and invitation emails | INBUXA's branding is the default. Spec: `features/branding-and-templates.md`. |
| 5 | AI spam classification | An optional model's opinion as one spam signal, and a Sieve function that asks a model | Local and auditable model only: no hosted API by default. Spec: `features/ai-spam-classification.md`. |
| 6 | Monitoring history, live tracing, alerts | Stored metrics and traces, a live trace view, and threshold alerts | ihasmail's dashboard shows them. Spec: `features/monitoring.md`. |
+28
View File
@@ -265,6 +265,34 @@ Stalwart-facing (SPEC.md §5).
16. **(compat)** Archived items already held at INBUXA read back unchanged
through `x:ArchivedItem` after cutover, and restore.
## Implementation status
Built 2026-09-18 from this spec, clean-room, under the multi-tenancy hand-off
brief's rules. The rules live in `crates/features` (`inbuxa-features`, module
`undelete`); the JMAP glue in `crates/jmap/src/inbuxa/`, with the deleted
account object type in `crates/jmap-proto/src/object/inbuxa_deleted_account.rs`;
restoring in `crates/services/src/task_manager/`; upstream files carry hooks
marked `inbuxa:`. Acceptance tests 1 to 15 pass as
`tests/src/system/undelete.rs`, with `/changes` and the `/query` filters.
- **UD-1 to UD-17a:** built.
- **ihasmail changes** belong to ihasmail-inbuxa and aren't part of this
repository.
- **Test 16 (compat)** is written as `undelete_compat`, ignored, and unrun
until a copy of INBUXA's data with archived items made on it is provided.
Its doc comment says how to run it.
- **Known limits, not requirements of this spec:**
- A kept account holds the addresses it had under its domain's names at
deletion. A domain renamed while it's kept doesn't move the hold.
- The hold is checked when accounts, aliases, mailing lists and masks are
created or changed through `x:`. A mask made through Fastmail's API
isn't checked; its random address makes a clash unlikely.
- A restored user keeps its other credentials (app passwords, API keys,
its one-time-password setup) as they were; only the password is new.
- Restoring needs `sysAccountCreate` and the right to grant everything the
account holds, so a tenant administrator can't bring back an account
with more than it could create.
## Observed
Settled on 2026-09-18 against INBUXA's live Enterprise server (Stalwart