TRACKING: Spaces Stage B mirror of mailbox mapping
openTRACKING: Spaces Stage B — mirror mailbox mapping to space-permissioned repo
Parent: bug 3726817. Depends on: Issues 1–3 (app DB source-of-truth) + PDS selection (Issue 4).
Goal: Mirror the app-DB mailbox↔DID mapping as at.sovrn.mail.account records in the postmaster’s domain spaces so the “second ATProto account logs in → sees/creates own mailbox + app password, reads via IMAP/JMAP” flow works post-launch. App DB remains source-of-truth until Stage B cutover criteria are met.
Scope (from bug 3726817 proposal + docs/03 §3, docs/04):
- Postmaster-authored at.sovrn.domain.detail (in tenant space) + at.sovrn.mail.account (did, address, status, verifiedAt, in domain space).
- User-authored at.sovrn.mail.service (endpoints only) at first login — untrusted input, schema-validate server-side.
- Identity-change flows: handle-change alias-grace (default 90d), deactivation suspend + 30d retention, deletion teardown (TaskDestroyAccount poll, space purge, syncer cache expiry).
Tasks (bite-sized, in order):
1. Publish lexicon JSON + Go types + validation layer (untrusted-input posture).
2. stalwartsync-adjacent space writer: idempotent upsert of mail.account on mailbox create/reassign (keyed by (did, rkey, cid)).
3. Reconciliation sweep: app-DB ↔ space three-way diff + metrics.
4. Second-login e2e: new DID sees own mailboxes, creates mailbox + app password, reads via IMAP/JMAP.
5. Cutover criteria: when space becomes readable source (post-GA Nov?) — define explicitly, do not cut over at launch.
Acceptance: Second ATProto login e2e passes against spaces-alpha; drift sweep green; no launch blocker — Stage A (Issues 1–3) ships first.
Non-goals: No watcher/firehose work beyond identity/lifecycle (§5 of docs/03); no signup-via-jetstream.