個人でWebサイトやアプリを作っています(屋号は sesebox です)。tsumoru、nami、ぶーかつなど、いくつかのアプリのデータベースに Supabase を使っています。
2026年9月23日、Supabaseから全プロジェクトのアカウント宛てに、こんな件名のメールが届きました。
New tables in public need explicit grants from October 30
10月30日から、public スキーマに新しく作るテーブルには、明示的な GRANT が必要になるというお知らせです。自分のプロジェクトへの影響を確かめて、マイグレーション(テーブルを作るSQL)の書き方を変えたので、まとめておきます。
※内容はSupabaseからのメールと、そこにあった公式ディスカッションの案内に基づいています。まだ10月30日前なので、実際に permission denied を踏んだわけではありません。
何が変わるのか
Supabaseでは、public スキーマにテーブルを作ると、これまでは自動でData API(supabase-js やRESTから触れる入口)に公開されていました。
これが10月30日以降は、自動では公開されなくなります。 権限(GRANT)を付けないままだと、supabase-js などから触ったときに permission denied のエラーになる、という内容でした。
| 10月30日より前に作ったテーブル | 10月30日以降に作るテーブル | |
|---|---|---|
| 今の権限 | そのまま動く(何もしなくてよい) | GRANTが無いとAPIから見えない |
新規プロジェクトや、supabase db reset で作り直した場合も対象、とのことでした。
GRANTとRLSは別物
ここで混乱しやすいので、整理しておきます。
- GRANT:そのロール(anon・authenticatedなど)に、そのテーブルを触る権限そのものを与える
- RLS(Row Level Security):権限があるロールのうち、どの行を見せるかを絞る
つまり、
- GRANTで「触っていい」という入口を開ける
- RLSで「見えていい行」だけに絞る
という2段階です。RLSを設定しただけでは足りず、GRANTも別に必要になります。 「RLSを書いたから大丈夫」ではなくなります。
自分のマイグレーションに足したもの
新しくテーブルを作るときは、同じSQLファイルにGRANT文を足すことにしました。
create table public.example (
id uuid primary key default gen_random_uuid(),
user_id uuid not null,
created_at timestamptz not null default now()
);
-- RLSは従来どおり有効にする
alter table public.example enable row level security;
-- ★ここが新しく必要になる部分
grant select on public.example to anon;
grant select, insert, update, delete on public.example to authenticated;
grant select, insert, update, delete on public.example to service_role;
ポイントは、ロールごとに、そのテーブルで何をさせるかを決めて書くことです。
-
authenticated:ログイン済みのユーザー。アプリから読み書きさせるなら付ける -
service_role:サーバー側の管理用。ふだんはこちらだけで触る設計にしているテーブルもある -
anon:ログインしていない人。読ませたくないテーブルには付けない
私のアプリには「ログインしていない人には一切読ませない」テーブルがあります。そういうテーブルは anon への grant を書かないのが正解です。全部にコピペで3行付けると、本来閉じておきたい入口を開けてしまうので注意が必要です。
確認のしかた
GRANTの状態は、SQLで確認できます。
select grantee, privilege_type
from information_schema.role_table_grants
where table_schema = 'public' and table_name = 'example'
order by grantee, privilege_type;
テーブルを作った直後に、想定した行だけが出ているかを見れば、付け忘れや付けすぎに気づけます。
いつから何をすればいいか
| やること | |
|---|---|
| 今あるテーブル | 何もしなくてよい(今の権限のまま動く) |
| 10月30日以降に作るテーブル | マイグレーションに grant を書く |
| 過去のマイグレーションSQL | 触らなくてよい。ただし流用するときは、GRANTが入っているかを見る |
私は「新しいテーブルを作るSQLには、grant を必ず一緒に書く」という手順書の1行を足しました。あとから気づくより、作るときにセットで書くほうが確実だからです。
まとめ
- 10月30日から、
publicに作る新しいテーブルは自動でAPIに公開されない - 今あるテーブルには影響しない
- GRANT(触っていいか)とRLS(どの行を見せるか)は別物。両方いる
- 新しいテーブルのSQLに
grantを書く。読ませたくないロールには付けない -
information_schema.role_table_grantsで、付いている権限を確認できる
アプリごとにSupabaseを使っているので、こういう仕様変更のお知らせは、メールが来たときに手順書へ書いておくのが安心です。
作っているものの一覧は sesebox.dev に置いています。