supabase

supabase

热门

在执行任何涉及 Supabase 的任务时使用。触发条件:Supabase 产品(数据库、认证、边缘函数、实时功能、存储、向量、定时任务、队列);客户端库和 SSR 集成(supabase-js、@supabase/ssr)在 Next.js、React、SvelteKit、Astro、Remix 中;认证问题(登录、登出、会话、JWT、Cookie、getSession、getUser、getClaims、RLS);Supabase CLI 或 MCP 服务器;模式变更、迁移、安全审计、Postgres 扩展(pg_graphql、pg_cron、pg_vector)。

2259Star
166Fork
更新于 2026/5/27
SKILL.md
readonly只读
name
supabase
description

在执行任何涉及 Supabase 的任务时使用。触发条件:Supabase 产品(数据库、认证、边缘函数、实时功能、存储、向量、定时任务、队列);客户端库和 SSR 集成(supabase-js、@supabase/ssr)在 Next.js、React、SvelteKit、Astro、Remix 中;认证问题(登录、登出、会话、JWT、Cookie、getSession、getUser、getClaims、RLS);Supabase CLI 或 MCP 服务器;模式变更、迁移、安全审计、Postgres 扩展(pg_graphql、pg_cron、pg_vector)。

Supabase

核心原则

1. Supabase 频繁变更——在实施前请对照更新日志和当前文档进行验证。
不要依赖训练数据中的 Supabase 功能。函数签名、config.toml 设置和 API 约定在不同版本间会发生变化。

首先,获取 https://supabase.com/changelog.md(一个轻量级的摘要索引——不是繁重的拉取),扫描与你的任务相关的 breaking-change 标签,并按照链接页面处理任何适用的变更。然后使用下面的文档访问方法查找相关主题。

2. 验证你的工作。
在实施任何修复后,运行一个测试查询以确认更改生效。未经验证的修复是不完整的。

3. 从错误中恢复,不要循环。
如果一种方法在尝试 2-3 次后失败,停下来重新考虑。尝试不同的方法,检查文档,更仔细地检查错误,并在可用时查看相关日志。Supabase 的问题并不总是通过重试相同命令来解决,答案也不总是在日志中,但在继续之前,日志通常值得检查。

4. 将表暴露给数据 API: 根据用户的数据 API 设置,新创建的表可能不会自动通过数据(REST)API 暴露。如果是这种情况,需要显式授予 anonauthenticated 角色访问权限。

注意,这与 RLS 不同,RLS 控制的是表可访问后哪些_行_可见,而不是表是否可访问。

当用户报告 SQL 创建的表意外不可访问时,检查他们的数据 API 设置以及是否通过显式的 GRANT SQL 授予了角色访问权限。在授予公共(anon/authenticated)访问权限时,始终启用 RLS。有关完整设置工作流程,请参见将表暴露给数据 API

5. 暴露模式中的 RLS。
在任何暴露模式(默认包括 public)的每个表上启用 RLS。这在 Supabase 中至关重要,因为暴露模式中的表在 anon/authenticated 角色具有访问权限时,可以通过数据 API 访问(参见将表暴露给数据 API)。对于私有模式,建议使用 RLS 作为纵深防御。启用 RLS 后,创建与实际访问模型匹配的策略,而不是默认每个表都使用相同的 auth.uid() 模式。

6. 安全检查清单。
在处理任何涉及认证、RLS、视图、存储或用户数据的 Supabase 任务时,请运行此清单。这些是 Supabase 特有的安全陷阱,会静默地创建漏洞:

  • 认证和会话安全

    • 切勿在基于 JWT 的授权决策中使用 user_metadata 声明。 在 Supabase 中,raw_user_meta_data 是用户可编辑的,并且可能出现在 auth.jwt() 中,因此对于 RLS 策略或任何其他授权逻辑来说是不安全的。请改用 raw_app_meta_data / app_metadata 存储授权数据。
    • 删除用户不会使现有的访问令牌失效。 首先登出或撤销会话,对于敏感应用保持 JWT 过期时间短,并且为了严格保证,在敏感操作中根据 auth.sessions 验证 session_id
    • 如果你使用 app_metadataauth.jwt() 进行授权,请记住 JWT 声明在用户令牌刷新之前并不总是最新的。
  • API 密钥和客户端暴露

    • 切勿在公共客户端中暴露 service_role 或密钥。 在前端代码中优先使用可发布的密钥。旧版 anon 密钥仅用于兼容性。在 Next.js 中,任何 NEXT_PUBLIC_ 环境变量都会发送到浏览器。
  • RLS、视图和特权数据库代码

    • 视图默认绕过 RLS。 在 Postgres 15 及以上版本中,使用 CREATE VIEW ... WITH (security_invoker = true)。在旧版本的 Postgres 中,通过撤销 anonauthenticated 角色的访问权限,或将视图放在未暴露的模式中来保护视图。
    • UPDATE 需要 SELECT 策略。 在 Postgres RLS 中,UPDATE 需要先 SELECT 该行。如果没有 SELECT 策略,更新会静默返回 0 行——没有错误,只是没有变化。
    • auth.role() 已弃用——请改用 TO 子句。 Supabase 已弃用 auth.role(),转而直接在策略上使用 TO authenticatedTO anon 指定目标角色。除了弃用之外,auth.role() = 'authenticated' 在启用匿名登录时会静默失效,因为匿名用户携带 authenticated Postgres 角色,无论用户是否真正登录,都会通过检查。
      -- 已弃用(请勿使用)
      create policy "example" on table_name for select
      using ( auth.role() = 'authenticated' );
      
    • 仅使用 TO authenticated 是认证而非授权(BOLA / IDOR)。 仅使用 TO authenticated 只检查角色——它不限制用户可以访问哪些行。正确的模式是将 TO authenticatedUSING 中的所有权谓词结合:
      create policy "example" on table_name for select
      to authenticated
      using ( (select auth.uid()) = user_id );
      
    • UPDATE 策略需要同时包含 USINGWITH CHECK 如果没有 WITH CHECK,用户可以将行的 user_id 重新分配给另一个用户:
      create policy "example" on table_name for update
      to authenticated
      using ( (select auth.uid()) = user_id )
      with check ( (select auth.uid()) = user_id );
      
    • SECURITY DEFINER 函数会绕过 RLS。 SECURITY DEFINER 函数以其创建者的权限运行——通常是具有 bypassrls 的角色(例如 postgres)。切勿添加 SECURITY DEFINER 来解决权限错误;它会静默地移除访问控制而不修复根本原因。请优先使用 SECURITY INVOKER
    • public 中的 SECURITY DEFINER 函数可被所有角色调用。 Postgres 默认对每个新函数授予 PUBLICEXECUTE 权限,因此 public 中的任何 SECURITY DEFINER 函数都是一个公共 API 端点,可由 anonauthenticated(继承自 PUBLIC)调用,无需任何额外授权。当确实需要 SECURITY DEFINER 时(例如,绕过内部查找表上的 RLS),将函数放在未暴露的模式中,始终在函数体内包含 auth.uid() 检查,并在更改后运行 supabase db advisors
  • 存储访问控制

    • 存储的 upsert 需要 INSERT + SELECT + UPDATE。 仅授予 INSERT 允许新上传,但文件替换(upsert)会静默失败。你需要所有三个权限。
  • 依赖和供应链安全

    • 在安装 Supabase 包(supabase-js@supabase/ssrsupabase-py 等)时,始终固定包版本并提交锁定文件。 有关完整清单,请参见 npm 安全指南

对于上述未涵盖的任何安全问题,请获取 Supabase 产品安全索引:https://supabase.com/docs/guides/security/product-security.md

Supabase CLI

始终通过 --help 发现命令——切勿猜测。CLI 结构在不同版本间会发生变化。

supabase --help                    # 所有顶级命令
supabase <group> --help            # 子命令(例如 supabase db --help)
supabase <group> <command> --help  # 特定命令的标志

Supabase CLI 已知陷阱:

  • supabase db query 需要 CLI v2.79.0+ → 使用 MCP execute_sqlpsql 作为后备
  • supabase db advisors 需要 CLI v2.81.3+ → 使用 MCP get_advisors 作为后备
  • 当你需要新的迁移 SQL 文件时,始终先使用 supabase migration new <name> 创建它。切勿自行发明迁移文件名或依赖记忆中的预期格式。

版本检查和升级: 运行 supabase --version 检查。有关 CLI 更新日志和版本特定功能,请查阅 CLI 文档GitHub 发布

Supabase MCP 服务器

有关设置说明、服务器 URL 和配置,请参见 MCP 设置指南

连接问题排查——按顺序执行以下步骤:

  1. 检查服务器是否可达:
    curl -so /dev/null -w "%{http_code}" https://mcp.supabase.com/mcp
    返回 401 是预期的(无令牌),表示服务器正在运行。超时或“连接被拒绝”表示服务器可能已关闭。

  2. 检查 .mcp.json 配置:
    验证项目根目录是否存在有效的 .mcp.json,其中包含正确的服务器 URL。如果缺失,请创建一个指向 https://mcp.supabase.com/mcp 的文件。

  3. 认证 MCP 服务器:
    如果服务器可达且 .mcp.json 正确,但工具不可见,则用户需要进行认证。Supabase MCP 服务器使用 OAuth 2.1——告诉用户在其代理中触发认证流程,在浏览器中完成,然后重新加载会话。

Supabase 文档

在实施任何 Supabase 功能之前,请找到相关文档。按优先级顺序使用以下方法:

  1. MCP search_docs 工具(首选——直接返回相关片段)
  2. 以 Markdown 形式获取文档页面——任何文档页面都可以通过在 URL 路径后附加 .md 来获取。
  3. 针对 Supabase 特定主题进行网络搜索,当你不知道应该查看哪个页面时。

创建和提交模式变更

要进行模式变更,请使用 execute_sql(MCP)或 supabase db query(CLI)。 这些命令直接在数据库上运行 SQL,而不创建迁移历史记录,因此你可以自由迭代,并在准备好时生成干净的迁移。

不要使用 apply_migration 来更改本地数据库模式——它每次调用都会写入迁移历史记录,这意味着你无法迭代,并且 supabase db diff / supabase db pull 会产生空或冲突的差异。如果你使用它,你将受限于第一次尝试时传递的任何 SQL。

准备好提交你的更改到迁移文件时:

  1. 运行顾问supabase db advisors(CLI v2.81.3+)或 MCP get_advisors。修复任何问题。
  2. 如果更改涉及视图、函数、触发器或存储,请检查上面的安全检查清单。
  3. 生成迁移supabase db pull <descriptive-name> --local --yes
  4. 验证supabase migration list --local

参考指南