Calendar OAuth Disconnect — Root Cause Analysis (2026-06-26)
Affected: Sloane appointment scheduling (Oppy Inc), alex@remark.re + ag@oppy.pro calendars, and the comms-api ManagedCalendars connected via the same grant.
Summary
On 2026-06-26 a revoke_access (Google Calendar disconnect) fired for oppy User #2 (alex@remark.re). It POSTed to Google’s token-revoke endpoint — actually revoking the grant at Google — then nulled google_calendar_refresh_token and calendar_id locally. Because oppy and comms-api share the same Google OAuth client (GOOGLE_CALENDAR_CLIENT_ID = 883356951770-qkh…), revoking at Google simultaneously killed comms-api’s calendars connected via alex@remark.re — including ag@oppy.pro, Sloane’s primary appointment calendar. One revoke → both apps dark → the appointment schedule stopped working.
The broken record (oppy users, plaintext columns)
User #2 (auth alex@remark.re), updated 2026-06-26 17:03 UTC:
-
google_calendar_refresh_token= nil (wiped) -
calendar_id= nil (wiped) -
google_calendar= true (still claims connected) -
google_sync_token= present (stale leftover)
Mechanism (confirmed in code)
The only oppy path that nulls that column is revoke_access in app/controllers/api/v{2,3}/scheduler/google_calendars_controller.rb:
- POST
https://oauth2.googleapis.com/revoke, then on success:current_user.update(google_calendar_refresh_token: nil, calendar_id: nil) -
Bug: it does NOT set
google_calendar = false, so the account still shows “connected” with no token → silent failure, no reconnect prompt.
Cross-app cascade (oppy ↔ comms-api)
Same OAuth client id across both apps (verified). comms-api’s 16 ManagedCalendars connected via alex@remark.re (incl. ag@oppy.pro/Sloane, spencer.g, kaitlyn.s, ana.p, michael.p@remarkvisions.com, + group calendars) flipped to status=token_expired in the same window because Google revoked the shared grant.
Recovery
The refresh token was revoked at Google, not just deleted locally — so no valid copy exists in any database (comms-api’s is dead too, same grant). Fix = re-authorize: reconnect Google Calendar in oppy (re-consent → fresh refresh token + re-select calendar_id). That restores the appointment schedule and Sloane.
How widespread
-
oppy: of 313 users with
google_calendar=true, only 3 have a token; 310 are tokenless — but a long-standing accumulation (scattered across 2023; old disconnects). Only User #2 broke on 06-26 — recent + isolated. -
comms-api: 178/213 ManagedCalendars connected; 35
token_expiredacross 8 accounts (grant-specific, not platform-wide).
Engineering follow-ups
-
revoke_accessmust setgoogle_calendar=false(and surface “reconnect”) — fixes the silent-broken state behind the 310 stale flags. - Document/guard the oppy↔comms-api shared-OAuth-client coupling: a disconnect in one app revokes calendars in both.
- Data cleanup: reconcile the 310
google_calendar=true+ no-token users. - Proactive alerting: 7 accounts are fully calendar-dark with no notification.
Verification status
DB facts (nulled token, dates, counts, code path, shared client id) are confirmed. Inferred (strong, consistent): the 06-26 nulling was a revoke_access call that cascaded to comms-api via the shared grant. Unknown: what triggered the revoke (UI click / reconnect-gone-wrong / automated) — recommend a Cloud Logging check for the disconnect-endpoint hit on User #2 on 06-26.