Skip to content

fix(mobile): harden push/auth flows and notification release setup#97

Merged
dhairyashiil merged 28 commits into
mainfrom
devin/1780004741-push-auth-cache-hardening
Jun 2, 2026
Merged

fix(mobile): harden push/auth flows and notification release setup#97
dhairyashiil merged 28 commits into
mainfrom
devin/1780004741-push-auth-cache-hardening

Conversation

@dhairyashiil
Copy link
Copy Markdown
Member

@dhairyashiil dhairyashiil commented May 28, 2026

Summary

Mobile release hardening for Companion push notifications, auth/refresh handling, persisted query cache ownership, and notification build setup.

This PR started as push/auth/cache hardening and now also includes the final mobile release fixes found during device/build testing: Android Firebase config loading through EAS secrets, Android notification channel setup, iOS notification handler deprecation cleanup, booking action auth UX, dev-only app-review prompt suppression, and removal of temporary debug logs.

What Changed

Push notifications

  • Persist successful app-push registration state on device: token, deviceId, platform, region, userId, and timestamp.
  • Deregister from persisted state on logout instead of relying only on in-memory refs.
  • Handle registration/logout races with auth-generation checks, pending deregistration records, capped pending queue, and best-effort cleanup while the bearer is still valid.
  • Create the Android notification channel before requesting/registering for notifications.
  • Remove deprecated Expo shouldShowAlert usage in favor of shouldShowBanner / shouldShowList.

Auth and session safety

  • Keep auth refresh/failure callbacks installed across logout and same-session relogin.
  • Add single-flight refresh so parallel 401s do not trigger competing refreshes or accidentally log out a valid session.
  • Add auth session generation/epoch checks so stale refreshes, stale login flows, and stale requests cannot apply after logout/account switch.
  • Add runAuthTransition() to serialize short auth-marker storage mutations without holding the lock across network I/O.
  • Install the OAuth refresh handler before profile fetch, so a recoverable /me 401 can refresh instead of logging the user out.
  • Treat booking-action 401 after a refresh retry as endpoint authorization failure, not a whole-app logout.

Query cache isolation

  • Add owner metadata to persisted React Query cache: { region, userId }.
  • Restore cache only when the stored owner matches the current authenticated owner.
  • Clear in-memory and persisted cache on logout/login/account-switch paths.
  • Refuse ownerless cache writes until the current user id is known.

Booking action UX and logs

  • Keep confirm/reject buttons visible, but show user-facing unauthorized messages when the signed-in user is not allowed to confirm/reject the booking.
  • Remove temporary booking-action and widget debug logs added during investigation.
  • Suppress app-store-review prompt in dev to avoid noisy HMR-related warnings.

Release/build setup

  • Bump mobile app version to 1.0.8.
  • Load Android google-services.json from the GOOGLE_SERVICES_JSON EAS file secret via app.config.js.
  • Ignore local google-services.json in Git and EAS upload paths so the Firebase config is not committed to the public repo.

Important Context

  • Strong cross-region global revocation is still out of scope because US/EU deployments have separate databases and separate KV/Redis by design. This PR implements best-effort mobile cleanup and same-region/session safety, not new shared global infra.
  • A push registration POST that finishes after logout has already cleared the bearer can no longer be deleted from the device immediately because the DELETE would 401. The app parks/drains what it can, and backend same-device dedup/cleanup remains the server-side safety net.
  • Android push delivery also depends on EAS credentials being configured with an FCM V1 service account key and the GOOGLE_SERVICES_JSON file secret. Those credentials are not committed in this PR.

Verification

Local checks run on this branch:

  • bun --filter mobile typecheck
  • bun --filter mobile lint:react-compiler
  • git diff --check
  • GOOGLE_SERVICES_JSON=./google-services.json bunx expo config --json
  • GOOGLE_SERVICES_JSON=./google-services.json bunx expo export --platform android

Manual/device checks performed during release testing:

  • iOS build succeeded after regenerating the iOS provisioning profile with Push Notifications entitlement.
  • Android FCM V1 credential was added in EAS credentials.
  • Android device push notification registration/delivery was confirmed after Firebase/EAS setup.
  • Booking confirm/reject unauthorized-user path was validated and changed to user-facing errors instead of logging the user out.

Reviewer Checklist

  • OAuth login survives app restart and access-token refresh.
  • A 401 from a forbidden booking action does not log out the app.
  • Logout during in-flight push registration does not leave active local state behind.
  • Same-device relogin/account switch does not reuse another user's persisted query cache.
  • Android production builds have GOOGLE_SERVICES_JSON configured as an EAS file secret and FCM V1 credentials assigned.

Link to Devin session: https://app.devin.ai/sessions/a3bc1b9f3e3845ef8f795f2509c8a72d
Requested by: @dhairyashiil

@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@vercel
Copy link
Copy Markdown

vercel Bot commented May 28, 2026

Deployment failed with the following error:

You don't have permission to create a Preview Deployment for this Vercel project: cal-companion-mcp.

View Documentation: https://vercel.com/docs/accounts/team-members-and-roles

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

- write cal_auth_user_id in loginFromWebSession so web-session users keep persisted cache
- treat backend 404 on unregister as already-gone (region-aware) and clear stale record
- resolve a differing previous push registration before overwriting it
- add safe, PII-free logs (region, userId, deviceId, token hash) to push cleanup paths
@vercel
Copy link
Copy Markdown

vercel Bot commented May 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
cal-companion-chat Ignored Ignored Jun 1, 2026 9:35pm

Request Review

…registration races

Addresses parallel-review findings:
- #1/#2: add a monotonic auth generation (epoch) bumped on clearAuth and every
  new login. Refreshes discard their result if the epoch changed mid-flight, and
  401 retries abort instead of replaying a stale request under a new identity.
- #3: loginFromWebSession now clears the query cache before flipping auth state
  so a previous user's in-memory cache can't be re-persisted under the new owner.
- #4: a registration that completes after logout/switch is not persisted as the
  active record; it is parked for retry instead of leaving a live subscription.
- #5: compare the full {token,userId,region,deviceId} tuple and keep unresolved
  prior registrations in a retry queue instead of clobbering the single slot.
…ion lock; pre-POST generation check for push registration
@devin-ai-integration devin-ai-integration Bot changed the title fix(mobile): durable push registration, single-flight token refresh, identity-scoped query cache fix(mobile): harden auth/refresh/cache/push against cross-session races (epoch guard + auth-transition lock) May 29, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

…lock, region-safe cache envelope, pending-queue cap
@dhairyashiil dhairyashiil marked this pull request as ready for review May 29, 2026 22:19
@dhairyashiil dhairyashiil enabled auto-merge (squash) May 29, 2026 22:25
cubic-dev-ai[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread apps/mobile/hooks/use-push-notifications.ts
@cubic-dev-ai
Copy link
Copy Markdown
Contributor

cubic-dev-ai Bot commented Jun 1, 2026

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

@dhairyashiil dhairyashiil changed the title fix(mobile): harden auth/refresh/cache/push against cross-session races (epoch guard + auth-transition lock) fix(mobile): harden push/auth flows and notification release setup Jun 2, 2026
Copy link
Copy Markdown
Contributor

@volnei volnei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dhairyashiil dhairyashiil merged commit c74c026 into main Jun 2, 2026
10 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants