26-Jun-2026 — handle revoked Gmail tokens and coalesce push syncs ref #278

build 721commit e2670d1


Revoked-token handling

When a connected Gmail mailbox is revoked (the 7-day refresh-token expiry that happens while the Google Cloud OAuth consent screen is still in Testing), the Mail settings panel now:

Both links target the project derived from the OAuth client ID, so they resolve to the correct project per environment.

Push-sync concurrency guard

The Pub/Sub push handler fired pollConnection per push with no concurrency guard, so a burst of pushes (e.g. after a reconnect, or whenever a mailbox is busy) ran many full mailbox syncs at once - each holding decoded message bodies and attachment buffers in memory. On a 512MB machine this drove RSS into the OOM ceiling and saturated the single vCPU, tripping the health check and taking the site down.

A per-connection single-flight guard (syncConnectionCoalesced) now runs at most one sync per mailbox at a time, and any pushes arriving during a sync collapse into a single trailing rerun so nothing is missed. The poll timer already had an equivalent guard; this brings the push path in line and keeps inbox work within the 512MB budget.

Alias derivation refactor and tests

The role-to-mailbox alias derivation is consolidated into a single pure function, deriveAliasesFrom, that both derivedAliases and derivedAliasesForConnection now delegate to, removing the duplicated role-alias mapping that existed in each. A new mocha spec (inbox-aliases.spec.ts) covers the derivation behaviours (single catch-all, custom forward email with case normalisation, multiple recipients resolving on the first, import-all general aliases, and unmatched roles) plus the message-to-role matching helpers, so regressions in inbox routing are caught.