Provider Lanes Need Account Scope

Provider lanes need account scope

When a local daemon wraps a remote provider, "background" and "foreground"
are not enough. The useful boundary is often the provider account.

A sync loop, a manual sync, and an archive mutation may enter through different
commands, but they all touch the same upstream account state. If they run
through the provider at the same time, they can race. If one gets stuck, the
others can wait forever. If the lock is global, a broken account can punish a
healthy one.

The rule

Serialize provider work at the smallest provider-truth boundary.

For email, that boundary is the account. A background sync for personal and
an archive mutation for personal should share a lane. A broken consulting
account should not block personal.

The shape

The lane protects provider truth. It is not a general-purpose background-work
queue.

Mxr example

In Mxr v0.5.61, AppState::acquire_provider_operation creates a
per-account tokio::sync::Mutex. The background sync loop, manual mxr sync,
and mail mutations all acquire it before provider work.

The important details are boring and load-bearing:

That fixed the shape where opening mxr could start sync, stale provider work
could wedge the account, and later archive/read mutations appeared to work
locally before provider truth brought the messages back.

2026-06-24 validation found the late edge worth remembering: snooze restore is
provider work too. It may be triggered by time instead of a fresh user command,
but it still mutates upstream account state and must use the same account lane.

Where this generalizes

Any local-first client with remote providers hits this eventually: mail,
calendars, music, issue trackers, cloud storage, CRM sync, anything with a
local cache and upstream mutations.

The question is not "should I add a lock?" The better question is "what remote
truth is this operation allowed to monopolize?" Scope the lane there, put a
timeout around it, and keep unrelated accounts or workspaces out of the blast
radius.

Code grounding

Validated against Mxr v0.5.61:

See also