supabase

supabase

熱門

當執行任何涉及 Supabase 的任務時使用。觸發條件:Supabase 產品(Database、Auth、Edge Functions、Realtime、Storage、Vectors、Cron、Queues);客戶端函式庫與 SSR 整合(supabase-js、@supabase/ssr)在 Next.js、React、SvelteKit、Astro、Remix 中;驗證問題(登入、登出、session、JWT、cookie、getSession、getUser、getClaims、RLS);Supabase CLI 或 MCP 伺服器;schema 變更、遷移、安全稽核、Postgres 擴充套件(pg_graphql、pg_cron、pg_vector)。

2259星標
166分支
更新於 2026/5/27
SKILL.md
readonlyread-only
name
supabase
description

當執行任何涉及 Supabase 的任務時使用。觸發條件:Supabase 產品(Database、Auth、Edge Functions、Realtime、Storage、Vectors、Cron、Queues);客戶端函式庫與 SSR 整合(supabase-js、@supabase/ssr)在 Next.js、React、SvelteKit、Astro、Remix 中;驗證問題(登入、登出、session、JWT、cookie、getSession、getUser、getClaims、RLS);Supabase CLI 或 MCP 伺服器;schema 變更、遷移、安全稽核、Postgres 擴充套件(pg_graphql、pg_cron、pg_vector)。

Supabase

核心原則

1. Supabase 變動頻繁 — 實作前務必查閱 changelog 與最新文件。
請勿依賴訓練資料中的 Supabase 功能。函式簽章、config.toml 設定與 API 慣例在不同版本間可能有所變更。

首先,擷取 https://supabase.com/changelog.md(輕量摘要索引 — 非大量下載),掃描與你的任務相關的 breaking-change 標籤,並依循連結頁面處理任何適用的變更。接著使用下列文件存取方法查閱相關主題。

2. 驗證你的工作。
實作任何修正後,執行測試查詢以確認變更生效。未經驗證的修正視為不完整。

3. 從錯誤中恢復,不要重複嘗試。
若某種方法在 2-3 次嘗試後仍失敗,請停止並重新思考。嘗試不同方法、查閱文件、更仔細檢查錯誤,並在可行時檢閱相關日誌。Supabase 的問題不一定能透過重複相同指令解決,答案也不一定在日誌中,但在繼續前檢查日誌通常是值得的。

4. 將資料表暴露給 Data API: 根據使用者的 Data API 設定,新建立的資料表可能不會自動透過 Data (REST) API 暴露。若發生此情況,需要明確授予 anonauthenticated 角色存取權限。

請注意,這與 RLS 不同,RLS 控制的是資料表可存取後哪些_資料列_可見,而非資料表本身是否可存取。

當使用者回報 SQL 建立的資料表意外無法存取時,請檢查其 Data API 設定,以及角色是否已透過明確的 GRANT SQL 獲得存取權限。授予公開(anon/authenticated)存取權限時,務必同時啟用 RLS。完整設定流程請參閱將資料表暴露給 Data API

5. 暴露 schema 中的 RLS。
在任何暴露的 schema(預設包含 public)中的每個資料表上啟用 RLS。這在 Supabase 中至關重要,因為當 anon/authenticated 角色擁有存取權限時,暴露 schema 中的資料表可透過 Data API 存取(請參閱將資料表暴露給 Data API)。對於私有 schema,建議將 RLS 作為深度防禦。啟用 RLS 後,建立符合實際存取模型的政策,而非讓每個資料表都使用相同的 auth.uid() 模式。

6. 安全檢查清單。
在處理任何涉及 auth、RLS、view、儲存或使用者資料的 Supabase 任務時,請執行此檢查清單。這些是 Supabase 特有的安全陷阱,會默默產生漏洞:

  • Auth 與 session 安全

    • 切勿在基於 JWT 的授權決策中使用 user_metadata 宣告。 在 Supabase 中,raw_user_meta_data 可由使用者編輯,且可能出現在 auth.jwt() 中,因此不適合用於 RLS 政策或任何其他授權邏輯。請改用 raw_app_meta_data / app_metadata 儲存授權資料。
    • 刪除使用者不會使現有的存取 token 失效。 請先登出或撤銷 session,對敏感應用程式保持較短的 JWT 過期時間,並在嚴格要求下,對敏感操作驗證 session_idauth.sessions
    • 若使用 app_metadataauth.jwt() 進行授權,請記住 JWT 宣告在使用者 token 刷新前不一定是最新的。
  • API 金鑰與客戶端暴露

    • 切勿在公開客戶端中暴露 service_role 或 secret key。 前端程式碼請優先使用 publishable key。舊版 anon 金鑰僅供相容性使用。在 Next.js 中,任何 NEXT_PUBLIC_ 環境變數都會傳送至瀏覽器。
  • RLS、view 與特權資料庫程式碼

    • View 預設繞過 RLS。 在 Postgres 15 及以上版本,使用 CREATE VIEW ... WITH (security_invoker = true)。在較舊版本的 Postgres 中,請撤銷 anonauthenticated 角色對 view 的存取權限,或將其置於未暴露的 schema 中來保護 view。
    • 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),請將函式保留在未暴露的 schema 中,務必在函式本體中加入 auth.uid() 檢查,並在變更後執行 supabase db advisors
  • 儲存存取控制

    • 儲存 upsert 需要 INSERT + SELECT + UPDATE。 僅授予 INSERT 允許新上傳,但檔案取代(upsert)會默默失敗。你需要三者皆備。
  • 相依性與供應鏈安全

    • 安裝 Supabase 套件(supabase-js@supabase/ssrsupabase-py 等)時,務必鎖定套件版本並提交 lockfile。 完整檢查清單請參閱 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(無 token),表示伺服器正常運作。逾時或「連線被拒絕」則表示可能已關閉。

  2. 檢查 .mcp.json 組態:
    確認專案根目錄有有效的 .mcp.json,且包含正確的伺服器 URL。若缺少,請建立一個指向 https://mcp.supabase.com/mcp 的檔案。

  3. 驗證 MCP 伺服器:
    若伺服器可連線且 .mcp.json 正確,但工具仍不可見,則使用者需要進行驗證。Supabase MCP 伺服器使用 OAuth 2.1 — 請告知使用者在他們的 agent 中觸發驗證流程,在瀏覽器中完成驗證,然後重新載入 session。

Supabase 文件

在實作任何 Supabase 功能前,請先找到相關文件。請依優先順序使用以下方法:

  1. MCP search_docs 工具(優先 — 直接回傳相關片段)
  2. 以 markdown 格式擷取文件頁面 — 任何文件頁面皆可透過在 URL 路徑後加上 .md 來擷取。
  3. 針對 Supabase 特定主題進行網路搜尋,當你不知道該查閱哪個頁面時。

建立與提交 Schema 變更

若要進行 schema 變更,請使用 execute_sql(MCP)或 supabase db query(CLI)。 這些指令會直接在資料庫上執行 SQL,而不會建立遷移歷史記錄,因此你可以自由迭代,並在準備好時產生乾淨的遷移。

請勿使用 apply_migration 來變更本地資料庫 schema — 它每次呼叫都會寫入遷移歷史記錄,這意味著你無法迭代,且 supabase db diff / supabase db pull 會產生空白或衝突的 diff。若使用它,你將被困在第一次嘗試時傳入的任何 SQL 中。

準備好提交變更至遷移檔案時:

  1. 執行 advisorssupabase db advisors(CLI v2.81.3+)或 MCP get_advisors。修正任何問題。
  2. 檢閱上述安全檢查清單,若你的變更涉及 view、函式、觸發器或儲存。
  3. 產生遷移supabase db pull <descriptive-name> --local --yes
  4. 驗證supabase migration list --local

參考指南