mcpField
P
prisma-next-supabase

prisma-next-supabase

github.com/prismaデータ・データベース411678 回インストール9 週間前に更新
リポジトリ

prisma-next-supabase について

Prisma Next を Supabase に接続する開発者向けのスキルです。契約の設定、RLS ポリシー、ロールに紐づくクエリを扱い、クエリ実行前にロールを明示して JWT を検証します。

主な機能

  1. 01Supabase 外部契約の合成
  2. 02RLS ポリシーの定義
  3. 03auth.users への外部キー参照
  4. 04ロールに紐づくクエリ実行
  5. 05ユーザー JWT の検証
  6. 06Supabase 内部テーブルの読み取り

活用シーン

  1. 01アプリケーションテーブルへの RLS 設定
  2. 02モデルから auth.users への関連付け
  3. 03ユーザーまたは匿名ロールでのクエリ
  4. 04service_role による auth.* テーブルの読み取り

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/prisma/prisma-next --skill prisma-next-supabase

インストール後、Claude Code で/prisma-next-supabaseを入力して読み込まれたか確認します。

詳細

Prisma Next — Supabase

データコントラクトを編集すれば、あとは Prisma にお任せください。

このスキルでは、Prisma Next を Supabase プロジェクトでエンドツーエンドに使用する方法を扱います。Supabase 拡張パックの組み合わせ、コントラクトから Supabase 所有のテーブルを参照する方法、行レベルセキュリティ(RLS)ポリシーの作成、supabase() ランタイムを使ったロールに紐づくクエリの実行について説明します。

使用する場面

  • ユーザーが Supabase プロジェクトを持っている(または作成を希望している)場合に、Prisma Next を接続するとき。
  • ユーザーがテーブルに RLS ポリシー(policy_select、@@rls、auth.uid())を設定したいとき。
  • ユーザーがリクエストごとにロールを紐づけたいとき(asUser(jwt)、asAnon()、asServiceRole())。
  • ユーザーが auth.users への外部キー(スペースをまたぐ FK)を設定したいとき。
  • ユーザーが管理者として Supabase 内部テーブル(auth.*、storage.*)を読み取りたいとき。
  • ユーザーが次の内容に言及している場合:supabase、RLS、行レベルセキュリティ、ポリシー、anon、authenticated、service_role、auth.users、auth.uid()、JWT、jwtSecret、jwksUrl、SUPABASE.JWT_INVALID、RoleBoundDb、セッションプーラー。

使用しない場面

  • 一般的なコントラクトの編集(モデル、フィールド、リレーション)→ prisma-next-contract。
  • Supabase 以外の db.ts 接続、ミドルウェア、終了処理 → prisma-next-runtime。
  • 一般的なクエリの形式(フィルタリング、include、集計)→ prisma-next-queries — ここにある内容は、ロールに紐づく db にもすべて適用されます。
  • マイグレーションの計画や適用 → prisma-next-migrations。

主な概念

  • パックは external の契約空間です。 @prisma-next/extension-supabase/pack は、Supabase が管理するすべてのもの、すなわち auth スキーマと storage スキーマ、そのネイティブの enum 型、プラットフォームロール(anon、authenticated、service_role)の完全なイントロスペクション生成済み契約を、すべて制御ポリシー external として提供します。extensions 経由で合成すると、移行プランナーはこれらのオブジェクトに対する DDL を一切出力しません(Supabase が管理します)。一方、db verify はライブデータベースにそれらが存在することを確認します。独自のテーブルは通常どおり managed のままです。
  • ロールはパックから取得されるため、自分で宣言する必要はありません。 RLS の roles = [authenticated] 識別子は、合成された契約に対して解決されます。ランタイムの接続先が Supabase 以外の Postgres である場合、verify は不足しているロールを示す not-found の問題で失敗します。よくある「データベースの指定間違い」という設定ミスが、クエリの実行前に検出されます。
  • ランタイムはロール優先です。 supabase() は、トップレベルのクエリ用インターフェースを持たない SupabaseDb を返します。ロールをバインドするまで、db.sql / db.orm はありません。await db.asUser(jwt) / db.asAnon() / db.asServiceRole() は、それぞれ .sql、.orm、.raw、.execute(plan)、.transaction(fn) を公開する RoleBoundDb を返します。これは意図的な設計です。Supabase アプリでは「ロールなし」の実行コンテキストに意味がなく、接続のログインロールをデフォルトにすると、気づかないうちに RLS を回避してしまう危険があるためです。
  • ロールのバインドはミドルウェアの下位で行われ、外部に漏れません。 ロールにバインドされた各クエリは、ユーザーミドルウェアチェーンの下位で set_config('role', …) と set_config('request.jwt.claims', …) を適用し、接続の解放時に RESET ALL を実行する接続上で動作します。Postgres 側の auth.uid() / auth.jwt() はこれらのセッション変数を読み取ります。RLS の適用は Postgres の役割であり、コンテキストのバインドはランタイムの役割です。
  • RLS はポリシーと権限の両方によって適用されます。 ポリシーは行をフィルタリングし、GRANT はテーブルへのアクセスを制御します。Prisma Next はポリシーを作成して移行しますが、権限は作成しません(Prisma Next がまだ対応していないことを参照)。ポリシーがあっても GRANT がないロールでは、行がフィルタリングされるのではなく、権限エラーが発生します。Supabase では、public テーブルにはデフォルト権限によってプラットフォームロールの権限がすでに付与されています。初期状態で実際に不足している権限は、auth.* / storage.* に対する service_role の権限です(ワークフロー — 権限を参照)。
  • JWT 検証は接続取得前に実行され、設定可能です。現在の Supabase プロジェクトには jwksUrl が必要です。 asUser(jwt) は接続を取得する前に(jose を介して)トークンを検証します。検証では jwksUrl に対して署名と有効期限を確認します(非対称署名キー — ES256 で署名する現在の Supabase プロジェクトのデフォルト)。または jwtSecret を使用します(対称 HS256 シークレット — レガシープロジェクトのみ)。両方を指定した場合、またはどちらも指定しなかった場合は、コード SUPABASE.CONFIG_INVALID を持つ構造化エラーが発生します。不正なトークンの場合は、コード SUPABASE.JWT_INVALID と型付きの meta.reason を持つ構造化エラーが発生します。これには、トークンのアルゴリズムと設定されたキーソースの不一致も含まれます(jwtSecret を指定したクライアントに対して ES256 トークンを使うと、問題を示し、jwksUrl に切り替えるよう案内します)。Postgres ロールはトークンの role クレームから決まり、デフォルトは authenticated です。注:supabase status は、ES256 で署名するプロジェクトでも JWT_SECRET を表示します。表示されていても、プロジェクトでそれが使われているとは限りません。
  • auth.* / storage.* への管理者アクセスは、service_role だけが持つ副次的なルートであり、一度限りの権限付与が必要です。 db.asServiceRole().supabase は、パック独自の契約(.sql、.orm、.nativeEnums、.execute)を公開します。このルートは設計上 service_role にのみ存在しますが、実際の Supabase プロジェクトでは service_role に auth.* / storage.* のテーブル権限が一切付与されていません(スキーマの USAGE のみで、テーブル権限を持つのは postgres のみです)。管理者ルートで Supabase 内部のテーブルを読み取る前に、対象を絞った権限を一度付与してください(ワークフロー — 権限を参照)。asUser / asAnon には .supabase がなく、主要な asServiceRole().sql / .orm は引き続き独自の契約の範囲内にとどまります。

ワークフロー — パックを設定に組み込む

コンセプト:パックは Supabase のコントラクト空間を登録するため、コントラクトから参照でき、プランナー/検証ツールは Supabase が何を所有するかを把握できます。この拡張機能にはまだ /control サブパスがないため、ターゲットファサードの defineConfig({ extensions: [...] }) 経由では組み込めません。低レベル設定の extensions に組み込みます(What Prisma Next doesn't do yet を参照)。以下の低レベルインポートは、ファサードのみをインポートするルールに対する意図的な例外であり、この不足によるものです。このブロックは examples/supabase/prisma-next.config.ts をそのまま反映しています。独自に組み立てず、コピーしてください。

// prisma-next.config.ts
import postgresAdapter from '@prisma-next/adapter-postgres/control';
import { defineConfig } from '@prisma-next/cli/config-types';
import postgresDriver from '@prisma-next/driver-postgres/control';
import supabasePack from '@prisma-next/extension-supabase/pack';
import sql from '@prisma-next/family-sql/control';
import { prismaContract } from '@prisma-next/sql-contract-psl/provider';
import postgres from '@prisma-next/target-postgres/control';
import postgresPackRef from '@prisma-next/target-postgres/pack';
import { postgresCreateNamespace } from '@prisma-next/target-postgres/types';

export default defineConfig({
  family: sql,
  target: postgres,
  adapter: postgresAdapter,
  driver: postgresDriver,
  extensions: [supabasePack],
  contract: prismaContract('./src/contract.prisma', {
    output: 'src/contract.json',
    target: postgresPackRef,
    createNamespace: postgresCreateNamespace,
  }),
  migrations: { dir: 'migrations' },
});

ワークフロー — コントラクト:auth.users への FK + RLS ポリシー

コンセプト:モデルは自分の名前空間(public)に配置し、Supabase のモデルはパックの名前空間(auth、storage)に配置します。supabase:auth.AuthUser 型のリレーションフィールドは空間をまたぐ FKです。プランナーは REFERENCES "auth"."users"("id") を出力し、ターゲットテーブルは検証されるだけで、マイグレーションされません。RLS ポリシーは、対象モデルと同じ名前空間にあるトップレベルの policy_<operation> ブロックで、対象モデルには @@rls による明示的な有効化が必要です。examples/supabase/src/contract.prisma をそのまま反映してください。

namespace public {
  model Profile {
    id       Uuid   @id @default(uuid())
    username String
    userId   Uuid   @unique
    user     supabase:auth.AuthUser @relation(fields: [userId], references: [id], onDelete: Cascade)
    @@map("profile")
    @@rls
  }

  // authenticated may read only their own profile.
  policy_select profile_owner_read {
    target = Profile
    roles  = [authenticated]
    using  = "\"userId\"::uuid = auth.uid()"
  }

  // anon may read every profile (a public directory listing).
  policy_select profile_public_read {
    target = Profile
    roles  = [anon]
    using  = "true"
  }

  // authenticated may update only their own profile, and may not
  // reassign it to another owner (WITH CHECK).
  policy_update profile_owner_write {
    target    = Profile
    roles     = [authenticated]
    using     = "\"userId\"::uuid = auth.uid()"
    withCheck = "\"userId\"::uuid = auth.uid()"
  }
}

Uuid コンストラクターは、型の位置でネイティブ UUID ストレージを選択します。従来の @db.Uuid 表記は削除されています。出力する前に、String @db.Uuid というエイリアスまたはフィールドはすべて Uuid に書き換えてください。

各要素:

  • 操作ごとのポリシーブロック:policy_select、policy_insert、policy_update、policy_delete、policy_all。本文は key = value 形式です。target(この名前空間内のモデル)、roles(合成後のコントラクトに対して解決されます。パックは anon/authenticated/service_role を提供します)、using、および(書き込み操作の場合は)withCheck を指定します。同じ (target, operation) に対する複数の許可ポリシーは有効です。Postgres はそれらを OR で評価します。
  • ポリシー対象には @@rls が必須です。 対象モデルに @@rls がない policy_* ブロックは、PSL_EXTENSION_TARGET_MODEL_MISSING_ATTRIBUTE により出力時に失敗します。@@rls があり、ポリシーがないモデルにも意味があります。RLS が有効になり、すべて拒否されます。
  • 述語は SQL 文字列としてそのまま扱われます。 述語内の camelCase の列名は引用符で囲み(\"userId\")、必要に応じてキャストしてください。auth.uid() は uuid を返します。コントラクト内での名前変更によって述語本文が書き換えられることはありません。
  • TS ビルダーとの同等性が確保されています。 @prisma-next/postgres/contract-builder は、policySelect/policyInsert/policyUpdate/policyDelete/policyAll、rlsEnabled(Model)、および role('anon') をエクスポートします。これらは PSL の低レベル表現とキー単位で対応し、出力されるワイヤ名も同一です。ここでは PSL を標準的な方法として示しています。

通常どおり出力してマイグレーションします(prisma-next contract emit の後に prisma-next-migrations を実行します)。プランによって、テーブル、FK、ENABLE ROW LEVEL SECURITY、CREATE POLICY ステートメントが作成されます。auth.* に対する DDL は作成されません。

ワークフロー — supabase() ファクトリーを使った db.ts

コンセプト:標準の postgres() ファクトリーの代わりに、Supabase アプリは拡張機能の /runtime サブパスから supabase() を使ってクライアントを構築します。このファクトリーは非同期です(JWT キーマテリアルを準備し、jwksUrl が設定されている場合は初回の JWKS 取得も行います)。戻り値はロール優先です。

// src/prisma/db.ts
import { supabase } from '@prisma-next/extension-supabase/runtime';
import type { Contract } from './contract.d';
import contractJson from './contract.json' with { type: 'json' };

export const db = await supabase<Contract>({
  contractJson,
  url: process.env['DATABASE_URL'],        // direct Postgres connection — see pitfalls
  jwksUrl: process.env['SUPABASE_JWKS_URL'], // https://<project-ref>.supabase.co/auth/v1/.well-known/jwks.json
  // Legacy HS256 projects use jwtSecret: process.env['SUPABASE_JWT_SECRET'] instead — exactly one of the two.
});

基本設定以外のオプション:middleware(postgres() と同じ合成方法です。prisma-next-runtime を参照してください。ミドルウェアからロールバインディングの set_config 呼び出しが見えることはありません)、poolOptions、pg(url の代わりに BYO の pg.Pool/pg.Client を使用)。終了処理は prisma-next-runtime とまったく同じく await db.close()/await using で行います。同じスクリプトのハングに関するルールが適用されます。

ワークフロー — ロールに紐づけたクエリ

コンセプト:リクエストを実行するロールを紐づけ、返された RoleBoundDb を通じてクエリを実行します。prisma-next-queries のすべてのクエリサーフェスが利用でき、Postgres によって RLS でフィルタリングされます。

// A signed-in user: rows are RLS-scoped to the JWT's auth.uid().
const userDb = await db.asUser(jwt); // async — rejects with code SUPABASE.JWT_INVALID on a bad/expired token
const mine = await userDb.orm.public.Profile.select('id', 'username').all();

// The anon role: sees what anon policies permit.
const listing = await db.asAnon().orm.public.Profile.select('id', 'username').all();

// service_role: BYPASSRLS — sees everything in YOUR contract.
const all = await db.asServiceRole().orm.public.Profile.select('id', 'username').all();

// Writes ride the same surfaces; RLS filters them too. An UPDATE against
// another owner's row affects 0 rows; a withCheck violation raises an error.
const updated = await userDb.orm.public.Profile
  .where({ userId: me })
  .updateAndCount({ username: 'new-name' });

注:asAnon() / asServiceRole() は同期処理で、非同期なのは asUser のみです。マルチネームスペースのコントラクトでは、座標を使ってモデルにアクセスします(orm.public.Profile、sql.public.profile)。詳しくは prisma-next-queries § ネームスペース対応アクセサー を参照してください。RoleBoundDb.transaction(fn) は、ロールに紐づいたセッションで処理をトランザクション内にラップします。

ワークフロー — auth.* / storage.* の管理者読み取り

コンセプト:Supabase 内部テーブルはコントラクトに含まれないため、クエリサーフェスにも含まれません。service_role バインディングにはセカンダリルートがあり、db.asServiceRole().supabase がパッケージのコントラクトサーフェスです。

const admin = db.asServiceRole();

// SQL builder over the pack contract:
const users = await admin.supabase
  .execute(admin.supabase.sql.auth.users.select('id', 'email').build())
  .toArray();

// ORM over the pack contract:
const sessions = await admin.supabase.orm.auth.AuthSession.select('id', 'aal').all();

// Native enum values (e.g. auth.aal_level) come typed:
type AalLevel = (typeof admin.supabase.nativeEnums.auth.AalLevel)['Value'];

管理者ルートには一度だけ GRANT が必要です。 実際の Supabase プロジェクトでは、service_role に auth.* / storage.* のテーブル権限はありません。そのため、初期状態では上記の読み取りは permission denied for table users(sqlState 42501)で失敗します。読み取る対象だけに、必要最小限の権限を付与してください。

GRANT USAGE ON SCHEMA auth TO service_role;
GRANT SELECT ON TABLE auth.users TO service_role;

ほかにも守るべき境界があります。asUser / asAnon に .supabase はありません。管理者ルートには .transaction がありません(プールを共有する別個のコントラクトバウンドランタイムであり、両方のルートにまたがるトランザクションは対象外です)。また、ユーザーの管理(ユーザーの作成、パスワードのリセット)には GoTrue Admin API を優先してください。Supabase 内部スキーマはプラットフォームのアップグレードによって変更される可能性があります。service_role による直接の SQL は、臨時の管理者読み取りに使用します。

ワークフロー — GRANT

コンセプト:RLS ポリシーは通常のテーブル権限に加わる行フィルターです。ポリシーがあっても GRANT のないロールは、行がフィルタリングされるのではなく permission denied になります。Supabase では、次の 2 つの方向を混同しやすいので注意してください。

  • 独自の public テーブルには何も必要ありません。 Supabase では public に対して ALTER DEFAULT PRIVILEGES が設定されているため、prisma-next db init / migrate で作成したテーブルには、ダッシュボードで作成したテーブルと同様に、anon / authenticated / service_role の完全な権限が自動的に継承されます。行を実際に保護するのは RLS ポリシーです。テーブルごとに GRANT を追加したり、理由なくデフォルト権限を狭めたりしないでください。
  • 必要な GRANT は、Supabase 内部テーブルを管理者が読み取るためのものだけです。service_role には auth.* / storage.* のテーブル権限がありません(必要最小限の GRANT USAGE / GRANT SELECT の組み合わせについては、上記の管理者読み取りを参照してください)。

GRANT は Supabase SQL エディターまたは psql から実行します。GRANT が不足している場合、空の結果ではなく permission denied for table …(sqlState 42501)が発生します。

ワークフロー — 実際の Supabase プロジェクトへの接続

コンセプト:ランタイムには、直接接続でき、セッションを扱える Postgres 接続が必要です。ロールの紐づけには、セッションスコープの set_config + RESET ALL を使用します。

  • セッションプーラー(aws-0-<region>.pooler.supabase.com:5432、ユーザー名 postgres.<project-ref>)— あらゆる環境で動作し、IPv4 に対応しています。デフォルトの選択肢です。
  • 直接接続(db.<project-ref>.supabase.co:5432)— 動作しますが、新しいプロジェクトでは IPv6 専用です。IPv4 のみの環境からは DNS / 接続に失敗します。
  • トランザクションプーラー(ポート 6543)— 使用しないでください。 トランザクションプーリングはセッション GUC を壊すため、ロールの紐づけが正しく動作しません。

.env には DATABASE_URL と JWT キーの取得元を設定します。現在のプロジェクトでは SUPABASE_JWKS_URL を使用します。値は https://<project-ref>.supabase.co/auth/v1/.well-known/jwks.json です(ローカルスタックでは http://127.0.0.1:54321/auth/v1/.well-known/jwks.json)。旧式の HS256 プロジェクトでのみ SUPABASE_JWT_SECRET(Project Settings → API → JWT Secret)を使用します。なお、ES256 プロジェクトでも supabase status は JWT_SECRET を出力するため、その存在だけで方式を判断しないでください。JWKS エンドポイント、またはトークンのヘッダー alg を確認してください。

よくある落とし穴

  1. トランザクションプーラー(ポート 6543)を使用する。 セッション GUC のロールバインディングにはセッション対応の接続が必要です。セッションプーラー(5432)または直接接続を使用してください。
  2. supabase status に JWT_SECRET と表示されるため、jwtSecret を設定する。 現在のプロジェクトでは ES256 で署名されます。そのため、asUser はトークンが ES256 であり、クライアントには jwksUrl が必要だと説明する SUPABASE.JWT_INVALID をスローします。SUPABASE_JWKS_URL を設定し、jwtSecret はレガシーな HS256 プロジェクト用にしてください。
  3. 誤った方向に権限を付与する。 public テーブルには権限付与は不要です(Supabase のデフォルト権限でカバーされ、RLS が行を保護します)。必要なのは、service_role による管理者読み取り用の限定的な auth.* の権限ペアです。permission denied(42501)は、結果がフィルタリングされたのではなく、権限付与が不足していることを意味します。
  4. トップレベルの db に db.sql / db.orm があると思い込む。 Supabase の db はロール優先です。ロールをバインドして、RoleBoundDb にクエリを実行してください。
  5. await を忘れる — supabase() ファクトリーと asUser(jwt) の両方に必要です。どちらも非同期ですが、asAnon() / asServiceRole() は非同期ではありません。
  6. asUser / asAnon に .supabase があると思い込む。 auth.* への管理者アクセスは構成上 service_role 専用です。また、service_role であっても、事前に一度だけ限定的な権限付与が必要です。
  7. 対象に @@rls がない policy_* ブロック。 Emit は PSL_EXTENSION_TARGET_MODEL_MISSING_ATTRIBUTE で失敗します。モデルに @@rls を追加してください。
  8. 引用符で囲まれていない camelCase のカラム、または述語内のキャスト漏れ。 述語はそのまま SQL として扱われます。"userId" には引用符が必要です。カラムの型がすでに uuid でない場合は、uuid と auth.uid() を ::uuid キャストを使って比較してください。
  9. jwksUrl と jwtSecret の両方(またはどちらも指定しない)を渡す。 supabase() の Promise は SUPABASE.CONFIG_INVALID で reject されます。非同期ファクトリーのため、設定ミスは同期的な throw ではなく reject として現れます(await / .catch)。
  10. RLS でフィルタリングされた書き込みをエラーとして扱う。 ロールから見えない行に対する UPDATE は0 行に影響するだけで、例外は発生しません。エラーになるのは withCheck 違反のみです。

Prisma Next がまだ対応していないこと

  • 拡張機能に /control サブパスがない — 対象ファサードの defineConfig({ extensions: [...] }) を通じて登録できません。上記のとおり、低レベル設定の extensions を通じて接続します。機能の要望は prisma-next-feedback からお寄せください。
  • GRANT の定義。 テーブル権限は契約の要素ではありません。Supabase アプリに必要な唯一の権限付与(管理者読み取り用の service_role の auth.* 権限ペア)は、SQL エディターまたは psql で一度だけ手動実行します。権限付与を契約で管理したい場合は、prisma-next-feedback からご要望ください。
  • アプリのルートと .supabase 管理者ルートをまたぐトランザクション。 2 つのルートは、1 つのプールを共有する別々の契約バインド済みランタイムです。ルートをまたぐトランザクションには対応していません。
  • 契約要素としてのトリガー / 関数。 サインアップ時にプロフィール行を作成する従来型の auth.users トリガーは、契約内ではなくデータベースに対する生の SQL として定義します。auth.uid() などは、不透明なポリシー述語文字列内でのみ使用します。
  • Supabase Realtime、ストレージへのアップロード、PostgREST / @supabase/supabase-js との相互運用、エッジランタイム。 これらは拡張機能の対象外です。拡張機能は Postgres と直接通信します(Node.js / Bun)。

リファレンスファイル

  • examples/supabase — 設定、契約、db.ts、受け入れテスト、README を含む、実行可能な標準アプリです。
  • packages/3-extensions/supabase/README.md — パッケージレベルのリファレンス(JWT モード、ロールバインディングモデル、未対応の範囲)。
  • packages/3-extensions/supabase/src/runtime/supabase.ts — オプションと型の正式な定義(SupabaseOptions、RoleBoundDb、ServiceRoleDb)。

チェックリスト

  • 低レベルの defineConfig に extensions: [supabasePack] が設定されている(/control サブパスは存在しません)。
  • スペースをまたぐ外部キーが supabase:auth.AuthUser として型指定され、明示的な fields/references(必要に応じて onDelete)が指定されている。
  • ポリシーの対象となるすべてのモデルに @@rls が設定されている。述語ではキャメルケースのカラム名を引用符で囲み、auth.uid() の呼び出しにキャストを適用している。
  • db.ts では await supabase<Contract>({ contractJson, url, jwksUrl | jwtSecret }) を使用している(JWT キーソースは1つだけ)。現在のプロジェクトでは jwksUrl を、レガシーの HS256 でのみ jwtSecret を使用する。
  • クエリは asUser/asAnon/asServiceRole から取得した RoleBoundDb を通して実行している。asUser は await している。
  • auth.*/storage.* の読み取りは、1回限りの最小限の権限付与(GRANT USAGE ON SCHEMA auth と、読み取るテーブルに対する GRANT SELECT)の後、asServiceRole().supabase のみを通して行っている。
  • 独自の public テーブルに対するテーブルごとの権限付与を追加していない。Supabase のデフォルト権限でカバーされ、RLS が保護を担う。
  • 接続はセッション対応である。セッションプーラーまたは直接接続を使用し、6543 のトランザクションプーラーは決して使用しない。
  • /control サブパス、トップレベルの db.sql、サービスロール以外のロールに対する .supabase、またはコントラクト内での権限付与の定義を、誤って作り出していない。

コメント