• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / supabase-swift / 36541039710
90%

Build:
DEFAULT BRANCH: main
Ran 29 Sep 2026 08:13AM UTC
Jobs 1
Files 136
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

29 Sep 2026 08:10AM UTC coverage: 89.521% (+0.1%) from 89.406%
36541039710

push

github

web-flow
fix(auth): discard a token refresh that outlived its session (#1374)

* fix(auth): discard a token refresh that outlived its session

A refresh that completed after `signOut` — and after another user signed in —
was applied to whatever session was stored at that moment. On success it wrote
the previous user's session back to storage and emitted `.tokenRefreshed` with
it; on a session-cleanup error code it deleted the *new* user's session and
emitted `.signedOut`. Every sub-client resolves its token from that storage, so
a newly signed-in user's requests then carried the previous user's access token.

`signOut` never cancels an in-flight refresh, and `RetryRequestInterceptor`
retries POST, so a `/token` retry can be created after `/logout` has revoked the
token — making the cleanup-error path the certain outcome rather than a rare one.

Guard both mutation sites with a storage snapshot taken before the request:

- `LiveSessionManager.refreshSession` reads storage before any suspension point
  and throws the new `AuthError.refreshDiscarded` instead of committing, if that
  session was cleared or replaced while the request was in flight.
- `APIClient.send`/`handleError` take the session a request was issued for and
  only run session cleanup while that session is still the stored one. This is
  the shared error path for every auth request, so an authorized call in flight
  during a sign-out can no longer sign out whoever signed in after it.
- `inFlightRefresh` is keyed by the refresh token it was started for, so a
  refresh asked for a different token is no longer served another one's result.

The comparison is between two storage reads, not between the caller's input and
storage: `setSession(accessToken:refreshToken:)` refreshes an externally-sourced
token with nothing stored yet, which is a legitimate hydration. This mirrors the
commit guard in supabase-js's `_callRefreshToken`. Swift needs no equivalent of
its `_sessionRemovalEpoch` — the storage acce... (continued)

49 of 49 new or added lines in 3 files covered. (100.0%)

10764 of 12024 relevant lines covered (89.52%)

893110.18 hits per line

Jobs
ID Job ID Ran Files Coverage
1 36541039710.1 29 Sep 2026 08:13AM UTC 136
89.52
GitHub Action Run
Source Files on build 36541039710
  • Tree
  • List 136
  • Changed 5
  • Source Changed 4
  • Coverage Changed 5
Coverage ∆ File Lines Relevant Covered Missed Hits/Line
  • Back to Repo
  • Github Actions Build #36541039710
  • 8de0e62a on github
  • Prev Build on main (#35998349812)
  • Next Build on main (#36557281091)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc