Skip to content

Commit d4e2370

Browse files
grdsdevclaude
andauthored
feat: rename anon key → publishable key, service role key → secret key (#1360)
* feat: rename anon key to publishable key and service role key to secret key Renames all references to align with Supabase's updated key naming convention: - `anonKey` parameter → `publishableKey` in Supabase.initialize() and _init() - `supabaseAnonKey` → `supabasePublishableKey` (internal parameter) - `ANON_KEY` / `SUPABASE_ANON_KEY` → `PUBLISHABLE_KEY` / `SUPABASE_PUBLISHABLE_KEY` in examples, docs, and infra config - `service_role` key references in doc comments → `secret` key - Test variables `anonToken` → `publishableToken` in gotrue tests JWT role claims (`'role': 'service_role'`) are left unchanged as they are internal backend values unrelated to the key naming convention. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: deprecate anonKey instead of hard-removing it, revert ANON_KEY env var rename - Keep anonKey as @deprecated in Supabase.initialize() so existing callers continue to compile; they receive a deprecation warning pointing to publishableKey. An assert enforces that at least one of the two is supplied. - Revert ANON_KEY → PUBLISHABLE_KEY in docker-compose: the storage binary reads ANON_KEY by name, renaming it silently breaks the service. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: apply dart format to changed files Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: rename publishableKey to supabaseKey in public API The key passed to Supabase.initialize() can be either a publishable key (anon) or a secret key depending on the use case, so the parameter name should not imply a specific key type. Aligns with SupabaseClient which already uses supabaseKey as its positional argument. - Rename publishableKey parameter -> supabaseKey in Supabase.initialize() - Update deprecated anonKey message to reference supabaseKey - Update all call sites in tests, examples, docs, and CHANGELOG - Revert internal gotrue test variable names back to anonToken (they represent the anonymous JWT, unrelated to the public API rename) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: rename _init param supabasePublishableKey to supabaseKey, use SUPABASE_PUBLISHABLE_KEY in example Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: publishableKey for flutter package, supabaseKey for dart package; revert CHANGELOG edits - Supabase.initialize() (supabase_flutter): rename supabaseKey → publishableKey. Flutter apps are client-side and should always use the publishable (anon) key, matching the label shown on the Supabase dashboard. - SupabaseClient (supabase): keep supabaseKey as-is. The dart package is used in both client and server contexts, so the generic name is appropriate. - Add a note to SupabaseClient doc distinguishing publishable vs secret usage. - Revert all CHANGELOG modifications — historical entries should not be refactored. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 13349c8 commit d4e2370

15 files changed

Lines changed: 64 additions & 53 deletions

File tree

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ For integration testing, you may want to point to a local Supabase instance:
196196
```dart
197197
await Supabase.initialize(
198198
url: 'http://localhost:54321',
199-
anonKey: 'your-local-anon-key',
199+
publishableKey: 'your-local-supabase-key',
200200
);
201201
```
202202

packages/functions_client/lib/src/functions_client.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class FunctionsClient {
8383
/// final fetchClient = FetchClient(mode: RequestMode.cors);
8484
/// await Supabase.initialize(
8585
/// url: supabaseUrl,
86-
/// anonKey: supabaseKey,
86+
/// publishableKey: supabaseKey,
8787
/// httpClient: fetchClient,
8888
/// );
8989
/// ```

packages/gotrue/lib/src/gotrue_admin_api.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class GoTrueAdminApi {
5959

6060
/// Creates a new user.
6161
///
62-
/// This function should only be called on a server. Never expose your `service_role` key on the client.
62+
/// This function should only be called on a server. Never expose your `secret` key on the client.
6363
///
6464
/// Requires either an email or phone
6565
Future<UserResponse> createUser(AdminUserAttributes attributes) async {
@@ -75,11 +75,11 @@ class GoTrueAdminApi {
7575
return UserResponse.fromJson(response);
7676
}
7777

78-
/// Delete a user. Requires a `service_role` key.
78+
/// Delete a user. Requires a `secret` key.
7979
///
8080
/// [id] is the user id of the user you want to remove.
8181
///
82-
/// This function should only be called on a server. Never expose your `service_role` key on the client.
82+
/// This function should only be called on a server. Never expose your `secret` key on the client.
8383
Future<void> deleteUser(String id) async {
8484
validateUuid(id);
8585
final options = GotrueRequestOptions(headers: _headers);
@@ -92,7 +92,7 @@ class GoTrueAdminApi {
9292

9393
/// Get a list of users.
9494
///
95-
/// This function should only be called on a server. Never expose your `service_role` key on the client.
95+
/// This function should only be called on a server. Never expose your `secret` key on the client.
9696
///
9797
/// The result is paginated. Use the [page] and [perPage] parameters to paginate the result.
9898
Future<List<User>> listUsers({int? page, int? perPage}) async {

packages/gotrue/lib/src/gotrue_admin_oauth_api.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class GoTrueAdminOAuthApi {
6565
/// Lists all OAuth clients with optional pagination.
6666
/// Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
6767
///
68-
/// This function should only be called on a server. Never expose your `service_role` key in the browser.
68+
/// This function should only be called on a server. Never expose your `secret` key in the browser.
6969
Future<OAuthClientListResponse> listClients({
7070
int? page,
7171
int? perPage,
@@ -88,7 +88,7 @@ class GoTrueAdminOAuthApi {
8888
/// Creates a new OAuth client.
8989
/// Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
9090
///
91-
/// This function should only be called on a server. Never expose your `service_role` key in the browser.
91+
/// This function should only be called on a server. Never expose your `secret` key in the browser.
9292
Future<OAuthClientResponse> createClient(
9393
CreateOAuthClientParams params,
9494
) async {
@@ -107,7 +107,7 @@ class GoTrueAdminOAuthApi {
107107
/// Gets details of a specific OAuth client.
108108
/// Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
109109
///
110-
/// This function should only be called on a server. Never expose your `service_role` key in the browser.
110+
/// This function should only be called on a server. Never expose your `secret` key in the browser.
111111
Future<OAuthClientResponse> getClient(String clientId) async {
112112
validateUuid(clientId);
113113

@@ -125,7 +125,7 @@ class GoTrueAdminOAuthApi {
125125
/// Updates an existing OAuth client.
126126
/// Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
127127
///
128-
/// This function should only be called on a server. Never expose your `service_role` key in the browser.
128+
/// This function should only be called on a server. Never expose your `secret` key in the browser.
129129
Future<OAuthClientResponse> updateClient(
130130
String clientId,
131131
UpdateOAuthClientParams params,
@@ -147,7 +147,7 @@ class GoTrueAdminOAuthApi {
147147
/// Deletes an OAuth client.
148148
/// Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
149149
///
150-
/// This function should only be called on a server. Never expose your `service_role` key in the browser.
150+
/// This function should only be called on a server. Never expose your `secret` key in the browser.
151151
Future<OAuthClientResponse> deleteClient(String clientId) async {
152152
validateUuid(clientId);
153153

@@ -165,7 +165,7 @@ class GoTrueAdminOAuthApi {
165165
/// Regenerates the secret for an OAuth client.
166166
/// Only relevant when the OAuth 2.1 server is enabled in Supabase Auth.
167167
///
168-
/// This function should only be called on a server. Never expose your `service_role` key in the browser.
168+
/// This function should only be called on a server. Never expose your `secret` key in the browser.
169169
Future<OAuthClientResponse> regenerateClientSecret(String clientId) async {
170170
validateUuid(clientId);
171171

packages/supabase/example/web/main.dart

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'package:web/web.dart' as web;
55

66
void main() {
77
const supabaseUrl = 'YOUR_SUPABASE_URL';
8-
const supabaseKey = 'YOUR_ANON_KEY';
8+
const supabaseKey = 'YOUR_SUPABASE_KEY';
99
final supabase = SupabaseClient(supabaseUrl, supabaseKey);
1010

1111
final element = web.document.querySelector('#output') as web.HTMLDivElement;
@@ -16,10 +16,8 @@ void main() {
1616

1717
void exampleUsage(SupabaseClient supabase) async {
1818
// query data
19-
final data = await supabase
20-
.from('countries')
21-
.select()
22-
.order('name', ascending: true);
19+
final data =
20+
await supabase.from('countries').select().order('name', ascending: true);
2321
print(data);
2422

2523
// insert data
@@ -76,15 +74,13 @@ void exampleUsage(SupabaseClient supabase) async {
7674
print('upload response : $storageResponse');
7775

7876
// Get download url
79-
final urlResponse = await supabase.storage
80-
.from('public')
81-
.createSignedUrl('example.txt', 60);
77+
final urlResponse =
78+
await supabase.storage.from('public').createSignedUrl('example.txt', 60);
8279
print('download url : $urlResponse');
8380

8481
// Download text file
85-
final fileResponse = await supabase.storage
86-
.from('public')
87-
.download('example.txt');
82+
final fileResponse =
83+
await supabase.storage.from('public').download('example.txt');
8884
print('downloaded file : ${String.fromCharCodes(fileResponse)}');
8985

9086
// Delete file

packages/supabase/lib/src/supabase_client.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import 'counter.dart';
1414
/// Creates a Supabase client to interact with your Supabase instance.
1515
///
1616
/// [supabaseUrl] and [supabaseKey] can be found on your Supabase dashboard.
17+
/// Pass the `publishable` (anon) key for client-side usage or the `secret`
18+
/// key for trusted server-side environments.
1719
///
1820
/// You can access none public schema by passing different [schema].
1921
///

packages/supabase_flutter/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void main() async {
2727
2828
await Supabase.initialize(
2929
url: SUPABASE_URL,
30-
anonKey: SUPABASE_ANON_KEY,
30+
publishableKey: SUPABASE_KEY,
3131
);
3232
3333
runApp(MyApp());

packages/supabase_flutter/example/lib/main.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import 'package:flutter/material.dart';
22
import 'package:supabase_flutter/supabase_flutter.dart';
33

44
Future<void> main() async {
5-
await Supabase.initialize(url: 'SUPABASE_URL', anonKey: 'SUPABASE_ANON_KEY');
5+
await Supabase.initialize(
6+
url: 'SUPABASE_URL', publishableKey: 'SUPABASE_PUBLISHABLE_KEY');
67
runApp(const MyApp());
78
}
89

packages/supabase_flutter/lib/src/supabase.dart

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ class Supabase {
5252
/// This must be called only once. If called more than once, an
5353
/// [AssertionError] is thrown
5454
///
55-
/// [url] and [anonKey] can be found on your Supabase dashboard.
55+
/// [url] and [publishableKey] can be found on your Supabase dashboard.
56+
/// Use the `publishable` (anon) key here — never the secret key in a
57+
/// Flutter app.
5658
///
5759
/// You can access none public schema by passing different [schema].
5860
///
@@ -76,7 +78,11 @@ class Supabase {
7678
/// If [debug] is set to `true`, debug logs will be printed in debug console. Default is `kDebugMode`.
7779
static Future<Supabase> initialize({
7880
required String url,
79-
required String anonKey,
81+
String? publishableKey,
82+
@Deprecated(
83+
'Use publishableKey instead. anonKey will be removed in a future major version.',
84+
)
85+
String? anonKey,
8086
Map<String, String>? headers,
8187
Client? httpClient,
8288
RealtimeClientOptions realtimeClientOptions = const RealtimeClientOptions(),
@@ -86,6 +92,12 @@ class Supabase {
8692
Future<String?> Function()? accessToken,
8793
bool? debug,
8894
}) async {
95+
assert(
96+
publishableKey != null || anonKey != null,
97+
'Either publishableKey or anonKey must be provided.',
98+
);
99+
final effectiveKey = publishableKey ?? anonKey!;
100+
89101
if (_instance._isInitialized) {
90102
_log.info('Supabase is already initialized. Skipping reinitialization.');
91103
return _instance;
@@ -120,7 +132,7 @@ class Supabase {
120132
}
121133
_instance._init(
122134
url,
123-
anonKey,
135+
effectiveKey,
124136
httpClient: httpClient,
125137
customHeaders: headers,
126138
realtimeClientOptions: realtimeClientOptions,
@@ -193,7 +205,7 @@ class Supabase {
193205

194206
void _init(
195207
String supabaseUrl,
196-
String supabaseAnonKey, {
208+
String supabaseKey, {
197209
Client? httpClient,
198210
Map<String, String>? customHeaders,
199211
required RealtimeClientOptions realtimeClientOptions,
@@ -208,7 +220,7 @@ class Supabase {
208220
};
209221
client = SupabaseClient(
210222
supabaseUrl,
211-
supabaseAnonKey,
223+
supabaseKey,
212224
httpClient: httpClient,
213225
headers: headers,
214226
realtimeClientOptions: realtimeClientOptions,

packages/supabase_flutter/test/auth_test.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ void main() {
4646

4747
await Supabase.initialize(
4848
url: supabaseUrl,
49-
anonKey: supabaseKey,
49+
publishableKey: supabaseKey,
5050
debug: false,
5151
authOptions: FlutterAuthClientOptions(
5252
localStorage: mockStorage,
@@ -67,7 +67,7 @@ void main() {
6767
() async {
6868
await Supabase.initialize(
6969
url: supabaseUrl,
70-
anonKey: supabaseKey,
70+
publishableKey: supabaseKey,
7171
debug: false,
7272
authOptions: FlutterAuthClientOptions(
7373
localStorage: MockEmptyLocalStorage(),
@@ -94,7 +94,7 @@ void main() {
9494

9595
await Supabase.initialize(
9696
url: supabaseUrl,
97-
anonKey: supabaseKey,
97+
publishableKey: supabaseKey,
9898
debug: false,
9999
authOptions: FlutterAuthClientOptions(
100100
localStorage: corruptedStorage,
@@ -112,7 +112,7 @@ void main() {
112112

113113
await Supabase.initialize(
114114
url: supabaseUrl,
115-
anonKey: supabaseKey,
115+
publishableKey: supabaseKey,
116116
debug: false,
117117
authOptions: FlutterAuthClientOptions(
118118
localStorage: emptyStorage,

0 commit comments

Comments
 (0)