Skip to content

feat!: rename the gotrue package to supabase_auth - #1697

Merged
spydon merged 3 commits into
mainfrom
breaking/rename-gotrue-to-supabase-auth
Aug 13, 2026
Merged

feat!: rename the gotrue package to supabase_auth#1697
spydon merged 3 commits into
mainfrom
breaking/rename-gotrue-to-supabase-auth

Conversation

@spydon

@spydon spydon commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

What

Renames the auth client package from gotrue to supabase_auth, its library entrypoint from gotrue.dart to supabase_auth.dart, and the public types that carried the old name.

The service this package talks to has been called Supabase Auth for years, and gotrue is a name users no longer recognize. The other clients already moved: supabase-py ships supabase_auth and supabase-js ships @supabase/auth-js.

Class renames

The old names are replaced with the Auth prefix the rest of the package already uses (AuthException, AuthResponse, AuthState, AuthClientOptions), which is also what auth-js prefers.

Before After
GoTrueClient AuthClient
GoTrueAdminApi AuthAdminApi
GoTrueAdminCustomProvidersApi AuthAdminCustomProvidersApi
GoTrueAdminMFAApi AuthAdminMFAApi
GoTrueAdminOAuthApi AuthAdminOAuthApi
GoTrueAdminPasskeyApi AuthAdminPasskeyApi
GoTrueMFAApi AuthMFAApi
GoTrueOAuthApi AuthOAuthApi
GoTruePasskeyApi AuthPasskeyApi
GotrueAsyncStorage AuthAsyncStorage
SharedPreferencesGotrueAsyncStorage SharedPreferencesAuthAsyncStorage

The two supabase_flutter extensions on the auth client follow: GoTrueClientSignInProvider becomes AuthClientSignInProvider, GoTrueClientPasskey becomes AuthClientPasskey.

Other changes

  • packages/gotrue moved to packages/supabase_auth, with name: supabase_auth in the pubspec and the repository link updated. Source files named after the old package are renamed to match their classes, for example src/gotrue_client.dart to src/auth_client.dart.
  • supabase depends on supabase_auth instead of gotrue. supabase_flutter reaches it transitively, so neither package's own dependency list gains an entry.
  • supabase_flutter/lib/src/flutter_go_true_client_options.dart is renamed to flutter_auth_client_options.dart. The class inside was already FlutterAuthClientOptions.
  • Two private fields in SupabaseClient had collided under the new naming, so the traced client handed to AuthClient is now _authApiHttpClient, distinct from the _authHttpClient that injects the JWT into the other service clients.
  • All 110 GoTrue-prefixed symbol entries in sdk-compliance.yaml are updated. No capability statuses change, this is a rename only.
  • Root pubspec.yaml, the test/pana workflow package lists and coverage carryforward, the issue-form library dropdown, the issue label mapping, READMEs, AGENTS.md and MIGRATION.md all use the new name. The label mapping keeps the old gotrue key so existing reports still land on the auth label.
  • MIGRATION.md gains a v2 to v3 section with the dependency rename, the import rename and the full class rename table.

Deliberately unchanged

  • The X-Client-Info header still reports gotrue-dart. auth-js likewise still sends gotrue-js, and changing it would break continuity in server-side telemetry.
  • The gotrue_meta_security field in captcha payloads is a server wire contract.
  • supabase/config.toml, seed.sql and the 20240101000002_gotrue_reset.sql migration refer to the actual auth server and its schema.
  • The supabase/gotrue docker image name in the test workflow's image-cache grep.

Test env keys

The auth test suite reads optional .env overrides. Each one now accepts a SUPABASE_AUTH_-prefixed key and still honours the old GOTRUE_ key, so existing local .env files keep working:

New Still accepted
SUPABASE_AUTH_URL GOTRUE_URL
SUPABASE_AUTH_TOKEN GOTRUE_TOKEN
SUPABASE_AUTH_SERVICE_ROLE_TOKEN GOTRUE_SERVICE_ROLE_TOKEN

The URL lookup moved into a getAuthUrl(env) helper in test/utils.dart, next to the existing token helpers, instead of being repeated in ten test files.

Version

The package is set to 3.0.0-dev.1 by hand rather than by the versioning workflow, because the first release under a new name has to be published manually before pub.dev knows the package. 3.0.0 continues the 2.27.1 line the package had as gotrue, and dev is both the preid the v2 prereleases used (gotrue-v2.0.0-dev.1) and melos' default, so the rest of the packages line up on 3.0.0-dev.N when the v3 prerelease is cut. supabase's pin on the auth client moves with it.

Follow-up outside this repo

Publishing supabase_auth and marking gotrue as discontinued on pub.dev, pointing at the new name, has to happen at release time.

Testing

  • dart analyze clean across the workspace.
  • dart test -j 1 passes in packages/supabase_auth (458 tests) and packages/supabase (134 tests) against the local Supabase stack.
  • flutter test passes in packages/supabase_flutter (76 tests).
  • dart format -l 80 --set-exit-if-changed reports no changes.
  • The three supabase/sdk compliance checks pass locally: validate-compliance, check-drift (no stale registrations from the renames) and check-api-symbols against an origin/main base extraction (every renamed symbol is registered under its new name).

Note on merge order

This is rebased on main and overlaps with #1696 (the supabase to supabase_dart rename) in the workflow package lists, the issue templates, AGENTS.md and the MIGRATION.md insertion point. Whichever merges second needs a conflict pass.

Resolves #1695
Part of #1278

SDK-1467

Summary by CodeRabbit

  • New Features
    • Introduced the Supabase Auth package with updated authentication APIs, storage providers, and Flutter integrations.
    • Added custom OAuth/OIDC provider models, JWT/JWK handling, and standardized authentication error codes.
  • Documentation
    • Updated migration guidance, examples, package references, licensing, and changelog information.
  • Refactor
    • Renamed legacy authentication classes and extensions to consistent Auth terminology across the SDK.
  • Tests
    • Updated coverage and test utilities for the renamed APIs and authentication URL configuration.

@spydon
spydon requested a review from a team as a code owner August 12, 2026 12:55
@coderabbitai

coderabbitai Bot commented Aug 12, 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ea35c461-233f-471b-90c0-d87ee63ae362

📥 Commits

Reviewing files that changed from the base of the PR and between f752c38 and f401b53.

📒 Files selected for processing (2)
  • MIGRATION.md
  • packages/supabase_auth/test/client_test.dart
🚧 Files skipped from review as they are similar to previous changes (2)
  • MIGRATION.md
  • packages/supabase_auth/test/client_test.dart

📝 Walkthrough

Walkthrough

The PR renames the Dart authentication package from gotrue to supabase_auth. It updates public GoTrue* APIs to Auth* names, integrates the renamed package with Supabase and Flutter, adds authentication models and test mocks, and updates repository automation and documentation.

Changes

Supabase Auth package rename

Layer / File(s) Summary
Package rename and API migration
packages/supabase_auth/..., packages/supabase/..., packages/supabase_flutter/...
The package metadata, exports, client APIs, storage types, request options, authentication models, Supabase integration, and Flutter integration now use supabase_auth and Auth* names.
Validation and test support
packages/supabase_auth/test/..., packages/supabase_flutter/test/...
Tests use AuthClient and Supabase Auth URL helpers. New HTTP mocks cover OTP, passkey, Web3, retry, refresh-token, and response scenarios.
Repository references and release tooling
.github/..., AGENTS.md, README.md, MIGRATION.md, pubspec.yaml, sdk-compliance.yaml
Repository workflows, workspace configuration, migration guidance, documentation, and SDK compliance references use the renamed package and APIs.

Estimated code review effort: 4 (Complex) | ~60 minutes

Mergeability Score: ⚪ Minimal · up to f401b

This PR renames the authentication package and public API for the next major version; the migration guidance and compatibility details are included, and no actionable merge-blocking risk remains after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant SupabaseClient
  participant AuthClient
  participant AuthFetch
  participant SupabaseAuthService
  SupabaseClient->>AuthClient: initialize authentication client
  AuthClient->>AuthFetch: build and send AuthRequestOptions
  AuthFetch->>SupabaseAuthService: issue authentication request
  SupabaseAuthService-->>AuthFetch: return authentication response
  AuthFetch-->>AuthClient: resolve response
  AuthClient-->>SupabaseClient: expose AuthClient through auth getter
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary breaking change: renaming the gotrue package to supabase_auth.
Linked Issues check ✅ Passed The PR implements the package, entrypoint, import, documentation, and public identifier renames required by issue #1695.
Out of Scope Changes check ✅ Passed The changes support the package rename, including code, tests, workflows, documentation, migration guidance, and SDK compliance updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch breaking/rename-gotrue-to-supabase-auth

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.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 4

🧹 Nitpick comments (3)
packages/supabase_auth/lib/src/types/custom_oauth_provider.dart (1)

12-15: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

fromString throws StateError for unknown server values.

firstWhere has no orElse. CustomOAuthProvider.fromJson calls fromString on the raw provider_type field for every admin API response (line 187). If the server introduces a new provider type, listProviders and getProvider throw a bare StateError instead of an AuthException. Callers that catch AuthException do not handle it.

Throw a typed error, or add an explicit unknown value.

Based on learnings: "Applies to packages/{gotrue,postgrest,realtime_client,storage_client}/lib/**/*.dart : Preserve each package's established exception hierarchy and error-handling behavior, including retry logic where applicable."

♻️ Proposed fix to raise a typed error
   static CustomProviderType fromString(String value) {
-    return CustomProviderType.values.firstWhere((e) => e.name == value);
+    return CustomProviderType.values.firstWhere(
+      (e) => e.name == value,
+      orElse: () => throw FormatException(
+        'Unknown custom provider type: $value',
+      ),
+    );
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/supabase_auth/lib/src/types/custom_oauth_provider.dart` around lines
12 - 15, Update CustomProviderType.fromString to handle unknown provider values
without allowing firstWhere to emit a raw StateError. Raise the package’s
established AuthException type, or return an explicit unknown enum value, so
CustomOAuthProvider.fromJson and its listProviders/getProvider callers preserve
the expected typed error-handling behavior.

Source: Learnings

packages/supabase_auth/CHANGELOG.md (1)

1-3: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a changelog entry for the package rename.

The changelog starts at ## 2.27.1, which is the last gotrue release. It contains no entry for the rename to supabase_auth or for the GoTrue*Auth* symbol renames. A user who reads only this file sees no record of the breaking change. Add an unreleased or v3 section that states the new package name, the discontinued gotrue package, and the renamed public types.

Based on learnings: "Update package changelogs if making notable changes" and "Any change that breaks the public API adds its own section to MIGRATION.md in the same pull request, under the major version it will ship in".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/supabase_auth/CHANGELOG.md` around lines 1 - 3, Add an unreleased or
v3 section before the existing 2.27.1 entry in the package changelog documenting
the rename to supabase_auth, discontinuation of the gotrue package, and public
GoTrue* to Auth* type renames; also add the corresponding breaking-change
guidance under the shipping major version in MIGRATION.md.

Source: Learnings

packages/supabase_auth/test/mocks/otp_mock_client.dart (1)

190-290: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Deduplicate the two phone response builders.

_handlePhoneSignup and _handlePhoneSignInWithPassword produce the same payload. The only difference is user_metadata, which signup fills from requestBody?['data']. Extract one builder that takes the metadata map. This keeps the two mock routes in sync when the response shape changes.

♻️ Proposed shared builder
-  StreamedResponse _handlePhoneSignup(Map<String, dynamic>? requestBody) {
-    final now = DateTime.now().toIso8601String();
-    ...
-  }
-
-  StreamedResponse _handlePhoneSignInWithPassword(
-    Map<String, dynamic>? requestBody,
-  ) {
-    final now = DateTime.now().toIso8601String();
-    ...
-  }
+  StreamedResponse _handlePhoneSignup(Map<String, dynamic>? requestBody) {
+    return _phoneSessionResponse(
+      requestBody,
+      userMetadata: requestBody?['data'] ?? {},
+    );
+  }
+
+  StreamedResponse _handlePhoneSignInWithPassword(
+    Map<String, dynamic>? requestBody,
+  ) {
+    return _phoneSessionResponse(requestBody, userMetadata: {});
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/supabase_auth/test/mocks/otp_mock_client.dart` around lines 190 -
290, Deduplicate the payload construction used by _handlePhoneSignup and
_handlePhoneSignInWithPassword by extracting a shared response builder that
accepts the user metadata map. Have signup pass requestBody?['data'] with the
existing empty-map fallback, and sign-in pass an empty map, while preserving the
current response fields and route behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@MIGRATION.md`:
- Around line 17-22: Update the `gotrue` package status in the migration
documentation to use future tense, indicating discontinuation will occur with
the v3 release rather than implying it has already happened. Keep the existing
package rename and release context unchanged.

In `@packages/supabase_auth/pubspec.yaml`:
- Around line 1-5: Update the package version in pubspec.yaml from 2.27.1 to
3.0.0 so the release publishes supabase_auth as the v3 package.

In `@packages/supabase_auth/test/client_test.dart`:
- Line 516: Wrap the expected OAuth URL in the test assertion by splitting
adjacent string literals so the line stays within 80 characters, while
preserving the exact expected URL value.

In `@packages/supabase_auth/test/provider_test.dart`:
- Line 51: Wrap the changed OAuth URL assertion in the provider test so every
line, including indentation, stays within 80 characters. Split the expected URL
literal or reuse a local prefix without changing the asserted value, then run
dart format.

---

Nitpick comments:
In `@packages/supabase_auth/CHANGELOG.md`:
- Around line 1-3: Add an unreleased or v3 section before the existing 2.27.1
entry in the package changelog documenting the rename to supabase_auth,
discontinuation of the gotrue package, and public GoTrue* to Auth* type renames;
also add the corresponding breaking-change guidance under the shipping major
version in MIGRATION.md.

In `@packages/supabase_auth/lib/src/types/custom_oauth_provider.dart`:
- Around line 12-15: Update CustomProviderType.fromString to handle unknown
provider values without allowing firstWhere to emit a raw StateError. Raise the
package’s established AuthException type, or return an explicit unknown enum
value, so CustomOAuthProvider.fromJson and its listProviders/getProvider callers
preserve the expected typed error-handling behavior.

In `@packages/supabase_auth/test/mocks/otp_mock_client.dart`:
- Around line 190-290: Deduplicate the payload construction used by
_handlePhoneSignup and _handlePhoneSignInWithPassword by extracting a shared
response builder that accepts the user metadata map. Have signup pass
requestBody?['data'] with the existing empty-map fallback, and sign-in pass an
empty map, while preserving the current response fields and route behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 77bfc6b7-5c99-43f9-aa61-e02d50172aef

📥 Commits

Reviewing files that changed from the base of the PR and between 84c7c07 and 1fae5da.

📒 Files selected for processing (102)
  • .github/ISSUE_TEMPLATE/bug_report.yml
  • .github/workflows/label-issues.yml
  • .github/workflows/release-pana.yml
  • .github/workflows/test.yml
  • AGENTS.md
  • MIGRATION.md
  • README.md
  • packages/supabase/lib/src/supabase_client.dart
  • packages/supabase/lib/src/supabase_client_options.dart
  • packages/supabase/lib/supabase.dart
  • packages/supabase/pubspec.yaml
  • packages/supabase_auth/CHANGELOG.md
  • packages/supabase_auth/LICENSE
  • packages/supabase_auth/README.md
  • packages/supabase_auth/analysis_options.yaml
  • packages/supabase_auth/example/README.md
  • packages/supabase_auth/example/main.dart
  • packages/supabase_auth/lib/src/auth_admin_api.dart
  • packages/supabase_auth/lib/src/auth_admin_custom_providers_api.dart
  • packages/supabase_auth/lib/src/auth_admin_mfa_api.dart
  • packages/supabase_auth/lib/src/auth_admin_oauth_api.dart
  • packages/supabase_auth/lib/src/auth_admin_passkey_api.dart
  • packages/supabase_auth/lib/src/auth_client.dart
  • packages/supabase_auth/lib/src/auth_mfa_api.dart
  • packages/supabase_auth/lib/src/auth_oauth_api.dart
  • packages/supabase_auth/lib/src/auth_passkey_api.dart
  • packages/supabase_auth/lib/src/broadcast_stub.dart
  • packages/supabase_auth/lib/src/broadcast_web.dart
  • packages/supabase_auth/lib/src/constants.dart
  • packages/supabase_auth/lib/src/fetch.dart
  • packages/supabase_auth/lib/src/helper.dart
  • packages/supabase_auth/lib/src/types/auth_async_storage.dart
  • packages/supabase_auth/lib/src/types/auth_exception.dart
  • packages/supabase_auth/lib/src/types/auth_response.dart
  • packages/supabase_auth/lib/src/types/auth_state.dart
  • packages/supabase_auth/lib/src/types/custom_oauth_provider.dart
  • packages/supabase_auth/lib/src/types/error_code.dart
  • packages/supabase_auth/lib/src/types/fetch_options.dart
  • packages/supabase_auth/lib/src/types/jwt.dart
  • packages/supabase_auth/lib/src/types/mfa.dart
  • packages/supabase_auth/lib/src/types/passkey.dart
  • packages/supabase_auth/lib/src/types/session.dart
  • packages/supabase_auth/lib/src/types/sign_out_reason.dart
  • packages/supabase_auth/lib/src/types/types.dart
  • packages/supabase_auth/lib/src/types/user.dart
  • packages/supabase_auth/lib/src/types/user_attributes.dart
  • packages/supabase_auth/lib/src/version.dart
  • packages/supabase_auth/lib/supabase_auth.dart
  • packages/supabase_auth/pubspec.yaml
  • packages/supabase_auth/test/admin_delete_user_test.dart
  • packages/supabase_auth/test/admin_list_users_test.dart
  • packages/supabase_auth/test/admin_test.dart
  • packages/supabase_auth/test/client_test.dart
  • packages/supabase_auth/test/custom_http_client.dart
  • packages/supabase_auth/test/custom_oauth_provider_test.dart
  • packages/supabase_auth/test/custom_providers_test.dart
  • packages/supabase_auth/test/fetch_test.dart
  • packages/supabase_auth/test/get_claims_test.dart
  • packages/supabase_auth/test/get_session_test.dart
  • packages/supabase_auth/test/header_isolation_test.dart
  • packages/supabase_auth/test/jwk_test.dart
  • packages/supabase_auth/test/mfa_challenge_mock_test.dart
  • packages/supabase_auth/test/mfa_enroll_test.dart
  • packages/supabase_auth/test/mocks/otp_mock_client.dart
  • packages/supabase_auth/test/mocks/passkey_mock_client.dart
  • packages/supabase_auth/test/mocks/web3_mock_client.dart
  • packages/supabase_auth/test/otp_mock_test.dart
  • packages/supabase_auth/test/passkey_test.dart
  • packages/supabase_auth/test/provider_test.dart
  • packages/supabase_auth/test/refresh_token_race_test.dart
  • packages/supabase_auth/test/src/auth_admin_custom_providers_api_test.dart
  • packages/supabase_auth/test/src/auth_admin_mfa_api_test.dart
  • packages/supabase_auth/test/src/auth_admin_oauth_api_test.dart
  • packages/supabase_auth/test/src/auth_mfa_api_test.dart
  • packages/supabase_auth/test/src/auth_oauth_api_test.dart
  • packages/supabase_auth/test/src/broadcast_web_test.dart
  • packages/supabase_auth/test/src/constants_test.dart
  • packages/supabase_auth/test/src/helper_test.dart
  • packages/supabase_auth/test/src/set_session_test.dart
  • packages/supabase_auth/test/src/token_refresh_race_test.dart
  • packages/supabase_auth/test/src/types/auth_exception_test.dart
  • packages/supabase_auth/test/src/types/mfa_test.dart
  • packages/supabase_auth/test/src/types/passkey_test.dart
  • packages/supabase_auth/test/src/types/session_test.dart
  • packages/supabase_auth/test/src/types/user_attributes_test.dart
  • packages/supabase_auth/test/src/types/user_test.dart
  • packages/supabase_auth/test/utils.dart
  • packages/supabase_auth/test/web3_auth_integration_test.dart
  • packages/supabase_auth/test/web3_auth_test.dart
  • packages/supabase_common/README.md
  • packages/supabase_flutter/README.md
  • packages/supabase_flutter/lib/src/flutter_auth_client_options.dart
  • packages/supabase_flutter/lib/src/local_storage.dart
  • packages/supabase_flutter/lib/src/supabase.dart
  • packages/supabase_flutter/lib/src/supabase_auth.dart
  • packages/supabase_flutter/lib/src/supabase_passkey.dart
  • packages/supabase_flutter/lib/supabase_flutter.dart
  • packages/supabase_flutter/test/local_storage_migration_test.dart
  • packages/supabase_flutter/test/storage_test.dart
  • packages/supabase_flutter/test/widget_test_stubs.dart
  • pubspec.yaml
  • sdk-compliance.yaml

Comment thread MIGRATION.md Outdated
Comment thread packages/supabase_auth/pubspec.yaml
Comment thread packages/supabase_auth/test/client_test.dart Outdated
Comment thread packages/supabase_auth/test/provider_test.dart
spydon added 2 commits August 13, 2026 16:35
BREAKING CHANGE: The auth client is published as supabase_auth instead of
gotrue, and its library entrypoint is supabase_auth.dart. The types that
carried the old name use the Auth prefix the rest of the package already
uses: GoTrueClient is now AuthClient, GoTrueAdminApi is now AuthAdminApi,
GotrueAsyncStorage is now AuthAsyncStorage, and so on for the remaining
admin, MFA, OAuth and passkey API classes.
The renamed package has no history on pub.dev, so its first release has to
be cut by hand instead of by the versioning workflow. 3.0.0-dev.1 continues
the 2.27.1 line the package had as gotrue and matches the -dev preid the v2
prereleases used.
@spydon
spydon force-pushed the breaking/rename-gotrue-to-supabase-auth branch from 1fae5da to f752c38 Compare August 13, 2026 14:46
The guide is for people upgrading this SDK, so what auth-js, supabase-js and
supabase-py ship is beside the point. Also phrases the pub.dev discontinuation
as something that happens when v3 ships rather than something already done,
and wraps the OAuth URL in client_test.dart to stay inside 80 columns.
@spydon
spydon merged commit 563b502 into main Aug 13, 2026
45 checks passed
@spydon
spydon deleted the breaking/rename-gotrue-to-supabase-auth branch August 13, 2026 15:07
spydon added a commit that referenced this pull request Aug 14, 2026
## What

Hotfix for the `gotrue` 2.27.x line, backporting the Wasm
`Session.fromJson` crash fix from #1716.

The base is `release/gotrue-2.27.x`, a maintenance branch cut at the
`gotrue-v2.27.1` tag. It cannot target `main`, because `main` has since
renamed the package to `supabase_auth` (#1697) and renamed the public
API (#1712), so a PR against `main` would read as reverting everything
merged since the tag.

Resolves #1687 for the 2.x line.

## The bug

`Session.fromJson` cast `json['expires_in']` straight to `int?`. That
map does not always come from `jsonDecode`.
`GoTrueClient._mayStartBroadcastChannel` also feeds it payloads that
crossed the JavaScript interop boundary through `dartify()` in
`broadcast_web.dart`, where every JavaScript number arrives as a
`double`.

Under `dart2js` this was invisible, because Dart `int` and `double`
share a JavaScript `Number` at runtime, so `3600.0 as int?` succeeded.
Under `dart2wasm` they are distinct runtime types and the cast throws:

```
TypeError: type 'double' is not a subtype of type 'int?' in type cast
```

The `json.decode(json.encode(dataMap))` round trip in
`broadcast_web.dart` does not rescue this: `3600.0` encodes to
`"3600.0"` and decodes back to a `double`.

Because the throw happened inside the `BroadcastChannel` message
listener, outside the setup `try`/`catch`, the rest of the listener was
skipped. No `_saveSession` or `_removeSession` ran, and
`notifyAllSubscribers` never fired, so receiving tabs silently failed to
synchronize login, logout, and token refresh.

## The fix

`expires_in` is now parsed as `(json['expires_in'] as num?)?.toInt()`,
which accepts `int`, `double`, and `null`. `JwtPayload.fromJson` (`exp`,
`nbf`, `iat`) and `OAuthClientListResponse.fromJson` (`nextPage`,
`lastPage`, `total`) get the same treatment for their numeric fields.

I traced the rest of the reachable surface. `dartify()` is called in
exactly one place in the repository, and the only types built from that
data are `Session`, `User`, `UserIdentity`, and `Factor`.
`User.fromJson` has no numeric fields, its timestamps are ISO 8601
strings, so after this change nothing reachable from the interop
boundary casts to `int`. Everything else in the workspace decodes from a
string through `dart:convert`, where integer literals stay `int` on
every backend.

## Pipeline fixes

The tag this branch is frozen at no longer builds against the current
toolchain, so the second commit carries three unrelated fixes needed to
get a green run. All three were verified to be pre-existing drift rather
than fallout from this change, by comparing against #1717, an equivalent
change on `main` whose run passed minutes apart.

- Flutter stable now ships AGP 9, which rejects the example app's old
Gradle DSL. The example's Gradle configuration is ported from `main`
(AGP 8.13.1 to 9.1.0, Gradle 8.13 to 9.3.1, Kotlin 2.1.20 to 2.4.0). The
example is `publish_to: none`, so nothing published changes.
- `dart analyze --fatal-infos` now reports `use_super_parameters` on
`SupabaseStorageClient`. `main` resolved this as part of the fetch layer
refactor in #1647, which gave `StorageBucketApi` a stored client field.
At this tag the superclass stores nothing, so the local field is still
needed and the lint is suppressed instead of backporting that refactor.
- The compliance workflow validates against `supabase/sdk@main`, whose
canonical capability identifiers keep moving, so a branch frozen at an
old release can never satisfy them. Its `pull_request` trigger is now
scoped to pull requests that target `main`.

## Release notes

`melos version` on this branch proposes `gotrue` 2.27.2, plus `supabase`
2.16.1 and `supabase_flutter` 2.17.2 as dependency cascades. Those
cascades are required, not incidental: the published `supabase` 2.16.0
pins `gotrue: 2.27.1` exactly and `supabase_flutter` 2.17.1 pins
`supabase: 2.16.0` exactly, so publishing `gotrue` alone would reach
nobody using the higher level packages.

Note that `release-tag.yml` only triggers on pushes to `main`, so
merging the version pull request into this maintenance branch will not
create the tags. They need to be pushed manually, or that workflow needs
a `workflow_dispatch` trigger, before `release-publish.yml` can run
against `gotrue-v2.27.2`.

## Testing

- `dart pub get` resolves the workspace cleanly.
- `dart analyze lib test` in `packages/gotrue`: no issues.
- `dart analyze --fatal-infos packages/storage_client`: no issues.
- `dart test test/src/types/session_test.dart
test/src/helper_test.dart`: 57 passing, including two new tests covering
a `double` `expires_in` and `double` `exp`, `nbf`, and `iat`.
- `dart format`: clean.
- The Android build is verified by CI only, it was not built locally.
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.

v3: rename the gotrue package to supabase_auth

3 participants