Highest value per unit of work. Ships alone and fixes ghost messages for single-engine users today.
Sync is a forward-only {uidnext}:* high-water mark and fetch_and_persist only ever calls save_email. Nothing observes deletion, so any message moved or removed by another client — including the user's own phone or webmail — becomes a permanent local ghost.
Replace it with CollectionSync::enumerate_changes(collection, since) -> {upserts, removals, next_token}. removals is the entire fix.
The ladder — selected per mailbox, not per account
STATUS/LIST-STATUS gate, then ESEARCH UID-set diff
Exchange, Yahoo
4
Full resync
last resort
Gmail has CONDSTORE but no QRESYNC; Exchange has neither.NOMODSEQ is a mailbox property (RFC 7162 §3.1.2.2), so detection must be per mailbox.
Notes
QRESYNC never signals modseq expiry — RFC 7162 §3.2.6 makes a too-old modseq a large VANISHED, not an error. full_resync_required is always client-derived (UIDVALIDITY mismatch, NOMODSEQ, HIGHESTMODSEQ regression).
Sync state is structured: (uidvalidity, highestmodseq, known-uid-set, seq-match-sample).
Keep a periodic full UID-set reconciliation even on rung 1.
Generalize folder_sync_state to collection_sync_state(account_id, collection_id, token).
Depends on #387, #388. Testable against #384 (all three server profiles).
**Highest value per unit of work. Ships alone and fixes ghost messages for single-engine users today.**
Sync is a forward-only `{uidnext}:*` high-water mark and `fetch_and_persist` only ever calls `save_email`. Nothing observes deletion, so any message moved or removed by another client — including the user's own phone or webmail — becomes a permanent local ghost.
Replace it with `CollectionSync::enumerate_changes(collection, since) -> {upserts, removals, next_token}`. **`removals` is the entire fix.**
### The ladder — selected per *mailbox*, not per account
| Rung | Mechanism | Providers |
| --- | --- | --- |
| 1 | QRESYNC `SELECT (QRESYNC …)` → `VANISHED` | Fastmail/Cyrus, Dovecot |
| 2 | CONDSTORE `UID FETCH 1:* (FLAGS) (CHANGEDSINCE n)` + periodic UID-set diff | **Gmail** |
| 3 | `STATUS`/`LIST-STATUS` gate, then ESEARCH UID-set diff | **Exchange**, Yahoo |
| 4 | Full resync | last resort |
**Gmail has CONDSTORE but no QRESYNC; Exchange has neither.** `NOMODSEQ` is a mailbox property (RFC 7162 §3.1.2.2), so detection must be per mailbox.
### Notes
- QRESYNC **never signals modseq expiry** — RFC 7162 §3.2.6 makes a too-old modseq a large `VANISHED`, not an error. `full_resync_required` is always client-derived (UIDVALIDITY mismatch, `NOMODSEQ`, HIGHESTMODSEQ regression).
- Sync state is structured: `(uidvalidity, highestmodseq, known-uid-set, seq-match-sample)`.
- Keep a periodic full UID-set reconciliation even on rung 1.
- Generalize `folder_sync_state` to `collection_sync_state(account_id, collection_id, token)`.
Depends on #387, #388. Testable against #384 (all three server profiles).
Design: [ADR 0002](https://github.com/KofTwentyTwo/nuncio/blob/dev/docs/adr/0002-multi-engine-sync-model.md) · [review evidence](https://github.com/KofTwentyTwo/nuncio/blob/dev/docs/reviews/2026-08-10-multi-engine-design-review.md) (PR #385)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Highest value per unit of work. Ships alone and fixes ghost messages for single-engine users today.
Sync is a forward-only
{uidnext}:*high-water mark andfetch_and_persistonly ever callssave_email. Nothing observes deletion, so any message moved or removed by another client — including the user's own phone or webmail — becomes a permanent local ghost.Replace it with
CollectionSync::enumerate_changes(collection, since) -> {upserts, removals, next_token}.removalsis the entire fix.The ladder — selected per mailbox, not per account
SELECT (QRESYNC …)→VANISHEDUID FETCH 1:* (FLAGS) (CHANGEDSINCE n)+ periodic UID-set diffSTATUS/LIST-STATUSgate, then ESEARCH UID-set diffGmail has CONDSTORE but no QRESYNC; Exchange has neither.
NOMODSEQis a mailbox property (RFC 7162 §3.1.2.2), so detection must be per mailbox.Notes
VANISHED, not an error.full_resync_requiredis always client-derived (UIDVALIDITY mismatch,NOMODSEQ, HIGHESTMODSEQ regression).(uidvalidity, highestmodseq, known-uid-set, seq-match-sample).folder_sync_statetocollection_sync_state(account_id, collection_id, token).Depends on #387, #388. Testable against #384 (all three server profiles).
Design: ADR 0002 · review evidence (PR #385)