Skip to content

fix(auth)!: always emit locally stored session as initial session - #1214

Merged
grdsdev merged 2 commits into
mainfrom
guilhermesouza/sdk-1489-auth-remove-emitlocalsessionasinitialsession-always-emit-the
Aug 18, 2026
Merged

grdsdev merged 2 commits into
mainfrom
guilhermesouza/sdk-1489-auth-remove-emitlocalsessionasinitialsession-always-emit-the

Conversation

@grdsdev

@grdsdev grdsdev commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Removes emitLocalSessionAsInitialSession (AuthClient.Configuration, AuthClient.init, SupabaseClientOptions.AuthOptions) — the behavior it used to gate behind true is now the only behavior.
  • .initialSession now always fires immediately with whatever session is stored locally, with a best-effort refresh in the background if it's expired. Previously it fired only after attempting to refresh the local session, collapsing "merely expired" and "refresh token invalid" into the same emitted session and adding a network round-trip delay to every launch.
  • Removes the now-unreachable reportIssue runtime warning that told developers to opt in early.
  • Adds a V3_MIGRATION.md entry (compile error for explicit emitLocalSessionAsInitialSession: callers, silent behavior change otherwise — check session.isExpired in .initialSession handlers).

See #822 for the original discussion. Tracked in SDK-1489.

Test plan

  • swift build --target Auth --target Supabase
  • swift test --filter AuthTests (240 tests passing)
  • ./scripts/spell-check.sh
  • ./scripts/format.sh

`.initialSession` used to fire only after attempting to refresh the
locally stored session, collapsing "merely expired" and "refresh
token invalid" into the same emitted session and delaying every
launch on a network round-trip. Remove the
`emitLocalSessionAsInitialSession` opt-in flag and make that
corrected behavior the only one: the initial session is now emitted
immediately, with a best-effort refresh in the background if
expired.

See #822 (SDK-1489).
@grdsdev
grdsdev requested a review from a team as a code owner August 14, 2026 12:52
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f074a2ce-1ba4-4fdf-99c1-f581edd34bb4

📥 Commits

Reviewing files that changed from the base of the PR and between af6c8bd and 4a61a8a.

📒 Files selected for processing (1)
  • Sources/Auth/AuthClient.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • Sources/Auth/AuthClient.swift

📝 Walkthrough

Summary by CodeRabbit

  • Behavior Changes

    • Authentication now emits the locally stored session immediately, including when no session exists.
    • Expired sessions are refreshed asynchronously after the initial session event.
    • Check session.isExpired before treating the initial session as valid.
  • Breaking Changes

    • Removed the emitLocalSessionAsInitialSession authentication option and related initializer parameters.
  • Documentation

    • Updated migration guidance to reflect the new initial-session behavior and configuration changes.

Walkthrough

The SDK now emits .initialSession immediately with the locally stored session, including nil when no session exists. Expired sessions refresh asynchronously. The emitLocalSessionAsInitialSession option was removed from authentication configuration, initializers, and Supabase client options. Tests and migration guidance now reflect the new event order and require callers to check session.isExpired.

Sequence Diagram(s)

sequenceDiagram
  participant AuthClient
  participant LocalSession
  participant TokenRefresh
  AuthClient->>LocalSession: Read current session
  AuthClient->>AuthClient: Emit initialSession
  AuthClient->>TokenRefresh: Refresh expired session asynchronously
Loading

Merge Risk: ⚪ Minimal · up to 4a61a

This change makes locally stored sessions available immediately and removes the opt-in configuration, with migration guidance for callers. No actionable merge-blocking risk remains beyond normal checks and review.

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coveralls

coveralls commented Aug 14, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 31802847872

Warning

Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes.
Quick fix: rebase this PR. Learn more →

Coverage decreased (-0.8%) to 85.466%

Details

  • Coverage decreased (-0.8%) from the base build.
  • Patch coverage: 2 uncovered changes across 1 file (9 of 11 lines covered, 81.82%).
  • 95 coverage regressions across 5 files.

Uncovered Changes

File Changed Covered %
Sources/Auth/AuthClientConfiguration.swift 2 0 0.0%
Total (3 files) 11 9 81.82%

Coverage Regressions

95 previously-covered lines in 5 files lost coverage.

File Lines Losing Coverage Coverage
Sources/Auth/AuthClientConfiguration.swift 45 0.0%
Sources/Helpers/AnyJSON/AnyJSON+Codable.swift 27 17.95%
Sources/Supabase/Types.swift 18 66.67%
Sources/Auth/Types.swift 4 89.89%
Sources/Auth/AuthClient.swift 1 89.12%

Coverage Stats

Coverage Status
Relevant Lines: 10252
Covered Lines: 8762
Line Coverage: 85.47%
Coverage Strength: 43.13 hits per line

💛 - Coveralls

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Capability matrix drift detected

The following capabilities are marked implemented in swift but have no registered symbols to verify:

  • auth.passkey.register_passkey (no symbols list — cannot confirm implementation exists)
  • auth.passkey.sign_in_with_passkey (no symbols list — cannot confirm implementation exists)
  • client.authentication_integration.third_party_auth (no symbols list — cannot confirm implementation exists)
  • client.authentication_integration.cross_client_token_sync (no symbols list — cannot confirm implementation exists)
  • client.authentication_integration.oauth_flow_type (no symbols list — cannot confirm implementation exists)
  • client.authentication_integration.session_url_detection (no symbols list — cannot confirm implementation exists)
  • client.session_management.custom_storage (no symbols list — cannot confirm implementation exists)
  • client.session_management.persist_session (no symbols list — cannot confirm implementation exists)
  • client.request_configuration.global_headers (no symbols list — cannot confirm implementation exists)
  • client.observability.trace_propagation (no symbols list — cannot confirm implementation exists)
  • database.query.select (no symbols list — cannot confirm implementation exists)
  • database.query.schema_selection (no symbols list — cannot confirm implementation exists)
  • database.query.rpc (no symbols list — cannot confirm implementation exists)
  • database.mutate.insert (no symbols list — cannot confirm implementation exists)
  • database.mutate.update (no symbols list — cannot confirm implementation exists)
  • database.mutate.upsert (no symbols list — cannot confirm implementation exists)
  • database.mutate.delete (no symbols list — cannot confirm implementation exists)
  • database.mutate.select_after_mutation (no symbols list — cannot confirm implementation exists)
  • database.using_filters.eq (no symbols list — cannot confirm implementation exists)
  • database.using_filters.neq (no symbols list — cannot confirm implementation exists)
  • database.using_filters.gt (no symbols list — cannot confirm implementation exists)
  • database.using_filters.gte (no symbols list — cannot confirm implementation exists)
  • database.using_filters.lt (no symbols list — cannot confirm implementation exists)
  • database.using_filters.lte (no symbols list — cannot confirm implementation exists)
  • database.using_filters.like (no symbols list — cannot confirm implementation exists)
  • database.using_filters.ilike (no symbols list — cannot confirm implementation exists)
  • database.using_filters.is (no symbols list — cannot confirm implementation exists)
  • database.using_filters.in (no symbols list — cannot confirm implementation exists)
  • database.using_filters.contains (no symbols list — cannot confirm implementation exists)
  • database.using_filters.contained_by (no symbols list — cannot confirm implementation exists)
  • database.using_filters.range_gt (no symbols list — cannot confirm implementation exists)
  • database.using_filters.range_gte (no symbols list — cannot confirm implementation exists)
  • database.using_filters.range_lt (no symbols list — cannot confirm implementation exists)
  • database.using_filters.range_lte (no symbols list — cannot confirm implementation exists)
  • database.using_filters.range_adjacent (no symbols list — cannot confirm implementation exists)
  • database.using_filters.overlaps (no symbols list — cannot confirm implementation exists)
  • database.using_filters.text_search (no symbols list — cannot confirm implementation exists)
  • database.using_filters.match (no symbols list — cannot confirm implementation exists)
  • database.using_filters.not (no symbols list — cannot confirm implementation exists)
  • database.using_filters.or (no symbols list — cannot confirm implementation exists)
  • database.using_filters.raw (no symbols list — cannot confirm implementation exists)
  • database.using_filters.regex (no symbols list — cannot confirm implementation exists)
  • database.using_filters.regex_icase (no symbols list — cannot confirm implementation exists)
  • database.using_filters.is_distinct (no symbols list — cannot confirm implementation exists)
  • database.using_filters.like_all (no symbols list — cannot confirm implementation exists)
  • database.using_filters.like_any (no symbols list — cannot confirm implementation exists)
  • database.using_filters.ilike_all (no symbols list — cannot confirm implementation exists)
  • database.using_filters.ilike_any (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.order (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.limit (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.range (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.single_row (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.strip_nulls (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.format_csv (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.format_geojson (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.max_affected_rows (no symbols list — cannot confirm implementation exists)
  • database.using_modifiers.request_cancellation (no symbols list — cannot confirm implementation exists)
  • database.configuration.auto_retry (no symbols list — cannot confirm implementation exists)
  • functions.invocation.invoke (no symbols list — cannot confirm implementation exists)
  • functions.invocation.set_auth_token (no symbols list — cannot confirm implementation exists)
  • functions.invocation.method_override (no symbols list — cannot confirm implementation exists)
  • functions.invocation.streaming_response (no symbols list — cannot confirm implementation exists)
  • functions.invocation.request_cancellation (no symbols list — cannot confirm implementation exists)
  • realtime.client.connect (no symbols list — cannot confirm implementation exists)
  • realtime.client.disconnect (no symbols list — cannot confirm implementation exists)
  • realtime.client.get_channels (no symbols list — cannot confirm implementation exists)
  • realtime.client.remove_channel (no symbols list — cannot confirm implementation exists)
  • realtime.client.remove_all_channels (no symbols list — cannot confirm implementation exists)
  • realtime.client.connection_state (no symbols list — cannot confirm implementation exists)
  • realtime.client.listen_heartbeats (no symbols list — cannot confirm implementation exists)
  • realtime.client.set_auth_token (no symbols list — cannot confirm implementation exists)
  • realtime.client.channel (no symbols list — cannot confirm implementation exists)
  • realtime.channel.subscribe (no symbols list — cannot confirm implementation exists)
  • realtime.channel.unsubscribe (no symbols list — cannot confirm implementation exists)
  • realtime.channel.broadcast (no symbols list — cannot confirm implementation exists)
  • realtime.channel.broadcast_http (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.postgres_changes (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.subscribe_presence (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.private_channel (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.broadcast_self (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.broadcast_ack (no symbols list — cannot confirm implementation exists)
  • realtime.subscriptions.broadcast_replay (no symbols list — cannot confirm implementation exists)
  • realtime.presence.track (no symbols list — cannot confirm implementation exists)
  • realtime.presence.untrack (no symbols list — cannot confirm implementation exists)
  • realtime.presence.presence_key (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.custom_websocket_transport (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.reconnect_backoff (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.heartbeat_interval (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.access_token_callback (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.deferred_disconnect (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.custom_logger (no symbols list — cannot confirm implementation exists)
  • realtime.configuration.binary_protocol (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.get_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.list_file_buckets (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.update_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.delete_file_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.empty_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.access_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.upload (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.download (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.move (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.copy (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.remove (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.create_signed_url (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.create_signed_urls (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.create_signed_upload_url (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.upload_with_signed_url (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.update_file (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.file_exists (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.file_info (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.copy_cross_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.move_cross_bucket (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.upload_with_metadata (no symbols list — cannot confirm implementation exists)
  • storage.file_buckets.url_cache_nonce (no symbols list — cannot confirm implementation exists)

These may have been renamed, removed, or never registered. Please update the capability matrix.
See: https://github.com/supabase/sdk/blob/main/docs/capability-matrix.md

Avoids creating an unstructured Task on every launch when the locally
stored session is still valid.
// task below, capturing `self` would resurrect this client while it is being deallocated.
let sessionManager = Dependencies.instances.value[clientID]?.sessionManager

Dependencies.instances.withValue { $0.removeValue(forKey: clientID) }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All these warnings would be de-deplicated if #1207 was merged 😉

@grdsdev
grdsdev merged commit 12cfe79 into main Aug 18, 2026
31 of 32 checks passed
@grdsdev
grdsdev deleted the guilhermesouza/sdk-1489-auth-remove-emitlocalsessionasinitialsession-always-emit-the branch August 18, 2026 13:05
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.

3 participants