# アクセスルール（RLS）

このプラットフォームで最もよく間違えるところです。**エラーにならず空のリストが返ってくるため**、間違えたことに気づきません。

## 必ず知っておくこと

新しく作ったテーブルは、アクセスルールが**有効な状態**で作られ、ルールは**ひとつもありません**。
ルールがなければ、そのテーブルは誰にも見えません。エラーではなく空の配列が返ってきます。

```sql
create table notes (id uuid primary key default gen_random_uuid(), body text);
-- 今、公開キーで select すると: []  （エラーではない）
```

## ロール名

プロジェクトごとに異なります。固定の `anon`/`authenticated` ではありません。
`list_policies` が、そのプロジェクトの実際のロール名を3つ教えてくれます。

| ロール | 誰か |
|---|---|
| `<ref>_anon` | ログインしていない人 |
| `<ref>_authenticated` | ログインしている人 |
| `<ref>_service_role` | サーバー。ルールをすべて迂回します |

**Supabase向けに書いたSQLはそのまま実行できます(Supabase名の変換)。** run_sql、query_sql、apply_migrations、コンソールのSQLエディター、`oneend db push`では、
`public.`、`auth.`、`storage.`を`app_<ref>.`、`auth_<ref>.`、`stor_<ref>.`に、`to`/`from`の後の`anon`、`authenticated`、`service_role`をこのプロジェクトのロールに変換して実行します。
名前を指す文字列(`'public.orders'::regclass`、`to_regclass('public.orders')`、`'public'::regnamespace`)のスキーマも変換します。
何を変換したかは応答の`translated`にあります。それ以外の文字列とコメントは変換せず、直接接続(psql)も変換しません。
すべての実行は search_path が `app_<ref>, auth_<ref>, public, extensions` の状態で動くので、スキーマを付けない `create table orders` や `'orders'::regclass` もこのプロジェクトのものを指します。

## よくあるルール3つ

```sql
-- 誰でも読めるように
create policy "public read" on notes for select to <ref>_anon using (true);

-- ログインした本人の行だけ
create policy "own rows" on notes for all to <ref>_authenticated
  using (user_id = auth_<ref>.uid());

-- ログインした人は書けるが、他人の名前では書けないように
create policy "insert own" on notes for insert to <ref>_authenticated
  with check (user_id = auth_<ref>.uid());
```

`using` は読むときに、`with check` は書くときに確認されます。insert に `using` だけを付けると、誰も書けません。

## 確認のしかた

`list_policies` でルールを確認し、`read_rows` で公開キーから実際に見えるかを確かめてください。
テーブルを作ったりルールを変えたりした後は、`get_advisors` で RLS が無効なテーブルや誰でも書けるルールなどの問題がないかを確認してください。

アプリが起動するたびに実行する SQL(Figma Make の kv_store など)では、インデックスに名前を付けて `if not exists` を使ってください: `create index if not exists kv_store_x_key_idx on kv_store_x (key text_pattern_ops);`。名前のない `create index on …` は実行するたびに同じインデックス(`_idx1`、`_idx2`…)をもう一つ作り、書き込みのたびにそのすべてを更新します。`get_advisors` の duplicate_index が、1つだけ残す `drop index` を一緒に示します。

ルールを作ったのにまだ空なら、ロール名が間違っている可能性が最も高いです。

---

https://end.blackall.ai/docs/access-rules?lang=ja
