- An export now pauses a revoked integration only if its row is
unchanged since the export read it, using the trigger-maintained
updatedAt column as the row version. If the user reconnected in the
meantime, the stale failure no longer disables the fresh credentials
or asks the user to reconnect again. updateExportStatus now reports
whether a row was written.
- The backup status store ignores a response overtaken by a newer
refresh, or by the status being flagged, cleared or set directly, so
a slow response can't overwrite newer state.
- Unit tests cover the whole integration repository, the guarded pause
and stale status responses. Coverage thresholds are raised to the
new baseline.
Google answers a revoked or expired refresh token with invalid_grant.
Every save then retried the dead token, and reconnecting never cleared
the old error, so it kept showing on Backup Settings afterwards.
- The Google Drive and Dropbox OAuth callbacks clear lastError when a
provider is reconnected.
- An invalid_grant, or a missing refresh token, now pauses the
integration with a readable "reconnect" message instead of retrying
it on every catch update. Other failures still retry as before.
- A banner on every page and an alert on the Pokédex page point to
Backup Settings, which shows a "Reconnect needed" badge. The Pokédex
page re-checks backup status after each export, because saving a
catch record also exports on the server and may pause a provider
first.
- Offline sync status and the "Save all artwork" link move from every
page to a new /offline-guide page, linked from the user menu and the
home and welcome pages. Only the offline read-only banner stays
sitewide.
- Unit tests cover every export path and the backup status store. BDD
covers revocation and reconnecting for both providers, and the
offline guide. The mock provider can now reject token refreshes, and
mock control calls fail loudly if a stale mock is reused. Coverage
thresholds are raised to the new baseline.