工具 / RLS 转换器

Supabase RLS 转换器

在浏览器中把 Supabase 行级安全转换为纯 Postgres。你的 SQL 不会离开此页面。

完全在浏览器中运行(WebAssembly)。你粘贴或添加的 SQL 不会被上传:页面只下载一次转换器,其余都在本地完成。

目标
输出约定

策略改为使用读取事务级设置的 app.* 访问函数。数据库不再需要知道 JWT 的存在。

角色模型

在 CapyDB 上,应用以表所有者身份连接,因此会强制启用行级安全(FORCE)。分离角色需要 CREATE ROLE,而 CapyDB 的数据库角色没有这个权限。

用户 ID 类型

如果用户 ID 不是 UUID(例如 Clerk 的 user_... ID),请选择 text。

01

转换哪些内容

Supabase 的 RLS 是标准的 CREATE POLICY,加上只有 Supabase 提供的上下文:auth.uid() 和 auth.jwt()、anon、authenticated 和 service_role 角色,以及注入到每个请求中的 JWT。把项目困在 Supabase 上的是这一层上下文,而不是策略本身。

转换器会整体迁移这一层,让你的策略在纯 Postgres 上运行,并继续承担同样的授权工作。

  • -auth.uid()、auth.jwt()、auth.role() 和 auth.email() 变成读取事务级设置的访问函数,每个 JWT 声明都有自己的设置。
  • -TO anon 和 TO authenticated 变成谓词,service_role 变成一条同样能通过限制性策略的服务通道。
  • -FOR ALL 策略按命令拆分,default auth.uid() 之类的列默认值会被改写。
  • -报告列出应用现在需要向数据库提供的设置,这就是你的集成清单。

02

两种约定

默认的 Vanilla 是纯 Postgres 的惯用做法:应用验证调用方,并在每个事务中设置带类型的事实(app.user_id、app.org_id)。数据库中没有任何东西需要了解 JWT。

Supabase 兼容模式用于原样迁移:通过读取 request.jwt.claims 的 auth.* 适配层,策略几乎可以原样迁移。它的服务通道是声明中的 role:只在原本使用服务密钥的服务端代码中设置 "role": "service_role"。

两种约定在 CapyDB 上都使用单一角色模型:由数据库单元的所有者连接,强制启用行级安全(FORCE),无需创建任何角色。

03

它不会猜测的内容

凡是无法机械迁移的内容,都会写进报告,而不是错误地转换:

  • -引用 auth.users 的策略:这张表留在 Supabase;请先把需要的列迁移过来。
  • -Supabase 托管 schema(如 storage 和 realtime)上的策略。
  • -调用 auth.* 的函数体,以及依赖它们的策略。
  • -向 FORCE 表写入的 SECURITY DEFINER 函数(它们不再绕过行级安全),并附上修复方法。通过 EXECUTE 的写入无法检测。

04

任何内容都不会离开浏览器

转换器是编译为 WebAssembly 的 capyrls。页面只以静态文件的形式获取一次;你的 SQL 从文本框和所选文件中读取,在页面内转换,再以下载的形式交给你。

无需账号,不上传,也不记录你粘贴的内容。如果不想使用浏览器,同样的引擎也可以在 CLI 中运行。

05

命令行中的同一个转换器

capydb migrate rls 会对你的代码仓库运行这个转换器,或者以最准确的方式,直接对运行中的 Supabase 数据库运行。capyrls 采用 MIT 许可,适用于任何 Postgres 目标。

# from your repo (finds supabase/migrations) or straight from the live database
$ capydb migrate rls
$ capydb migrate rls --source-url "$SUPABASE_DIRECT_URL" --uid-type text

# standalone, MIT, any Postgres
$ go install github.com/capydatabase/capyrls/cmd/capyrls@latest
$ capyrls convert supabase/migrations