turnstile-spin

turnstile-spin

熱門

在專案中完整(端到端)設定 Cloudflare Turnstile。掃描程式碼庫、透過 Cloudflare API 建立元件(widget)、嵌入至對應的表單、在客戶現有的後端串接標準的伺服器端 siteverify 驗證、執行完整驗證並保存此 Skill。當使用者要求新增 Turnstile、設定 CAPTCHA、保護表單免於機器人攻擊,或修復 Turnstile 整合時載入此 Skill。對應 developers.cloudflare.com/turnstile/spin。

2146星標
202分支
更新於 2026/7/13
SKILL.md
唯讀
名稱
turnstile-spin
描述

在專案中完整(端到端)設定 Cloudflare Turnstile。掃描程式碼庫、透過 Cloudflare API 建立元件(widget)、嵌入至對應的表單、在客戶現有的後端串接標準的伺服器端 siteverify 驗證、執行完整驗證並保存此 Skill。當使用者要求新增 Turnstile、設定 CAPTCHA、保護表單免於機器人攻擊,或修復 Turnstile 整合時載入此 Skill。對應 developers.cloudflare.com/turnstile/spin。

Turnstile Spin Skill

將提示詞 "set up Turnstile" 轉化為可運作的完整端到端整合:包含元件、各個指定插入點的前端程式碼片段、客戶現有後端中的標準伺服器端 siteverify 呼叫,並在回報成功前執行真實的驗證測試。

你是 Agent。請呼叫 scripts/ 目錄下的腳本並根據其輸出的 JSON 進行分流,以執行下方的引導流程。這些腳本包含確定性的邏輯(API 呼叫、重試/錯誤處理);你的任務是流程調度、閱讀程式碼庫、確認步驟,以及修改前端與後端程式碼。

標準指示存放於 developers.cloudflare.com/turnstile/spin。若文件頁面與本檔案內容有所出入,請以官方文件頁面為準。

何時載入此 Skill

當使用者的提示詞包含以下任意關鍵字時載入:

  • "Turnstile"、"CAPTCHA"、"bot protection"(機器人防護)
  • "siteverify"、"cf-turnstile-response"
  • "protect this form"(保護此表單)、"stop bot signups"(防範機器人註冊)、"spam signups"(垃圾註冊)
  • 特定的註冊、登入或聯絡表單,且結合了 "Cloudflare" 或 "bot" 等關鍵字

請勿在無關的 Cloudflare 任務(Workers、Pages、R2 等)中載入,除非同時提及了 Turnstile。

對話流程

使用者已貼上提示詞。你正處於多步驟的對話中。儘量自動偵測可取得的資訊,僅在必要時提問,並在執行任何不可逆的步驟前先進行確認。每個標示數字的時機點代表 Agent 發送的一則訊息。標示 [等待使用者回應] 的項目需要使用者提供回覆。

  1. 簡短確認。 使用單一句子回覆:「我將執行 Turnstile 的完整設定流程。步驟包括:檢查驗證權限、掃描程式碼庫、建立元件、嵌入至指定的表單、串接伺服器端 siteverify,以及進行驗證。要繼續執行嗎?」 [等待使用者回應] 此時請勿先列出詳細計畫。需先完成權限檢查與掃描。

  2. CLI 檢查。 Spin 的輔助腳本會使用 curl 請求 api.cloudflare.com,並執行 npx wrangler whoami 來列舉帳號。步驟 8 中的元件建立在 wrangler turnstile widget create 子命令可用時(Wrangler 4.109+)會優先使用該命令,否則降級(fallback)使用隨附的 curl 腳本。不需要預先安裝持久性的 CLI 工具。

  3. 身份驗證與權限範圍探測(第一個不可逆動作)。 執行 scripts/auth-probe.sh。根據 status 進行分流:

    • ok:繼續執行步驟 4。腳本已自動挑選帳號(單一帳號 Token,或與 $CLOUDFLARE_ACCOUNT_ID 相符的帳號)。
    • missing_tokenmissing_scope:請使用者前往 https://dash.cloudflare.com/profile/api-tokens 建立 Token → 自訂 Token → 權限設定為 Account.Turnstile:Edit → 並在「帳戶資源(Account Resources)」中包含目標帳號。請勿引導使用者執行 wrangler login,除非 wrangler 的 OAuth 權限範圍已包含 Account.Turnstile:Edit(視 wrangler 版本而定)。提供三種提供 Token 的方式,由最乾淨的方式依序排列:
      1. 設定環境變數並重新啟動(Token 完全不進入聊天紀錄):export CLOUDFLARE_API_TOKEN=<token>,然後從該終端機重新啟動 Agent。
      2. 儲存至檔案(Token 存放於僅限使用者權限的檔案中,不進入聊天紀錄):umask 077 && printf '%s' '<token>' > ~/.cf-turnstile-token,接著透過 TOKEN=$(cat ~/.cf-turnstile-token) 讀取。
      3. 直接貼在聊天室(速度最快,但 Token 會留存在對話紀錄中;若對話紀錄日後被分享,使用者應在事後撤換 Token)。
        若使用者選擇選項 3(直接貼在聊天室),你可以利用等待的時間同步執行步驟 5、6、7(網域設定、程式碼庫掃描、插入計畫)。選項 1 與 2 會重啟你的 Session,因此在這些情況下請勿預先擷取狀態。當身份驗證建立完成後,重新執行 auth-probe.sh,然後繼續執行步驟 8。
    • multiple_accounts:Token 包含多個帳號,且未設定 $CLOUDFLARE_ACCOUNT_ID。列出帶有編號的 accounts 帳號清單。[等待使用者回應] 接著設定 export CLOUDFLARE_ACCOUNT_ID=<所選帳號ID> 並重新執行 auth-probe.sh
    • account_mismatch:已設定 $CLOUDFLARE_ACCOUNT_ID,但該 ID 不在 Token 涵蓋的帳號列表中。顯示 accounts 清單,並請使用者執行 unset CLOUDFLARE_ACCOUNT_ID 或將其設定為列表中的其中一個 ID。
  4. 帳號選擇。auth-probe.sh 在經歷 multiple_accounts 來回確認後回傳 ok,則此步驟已完成。否則腳本已靜默選擇了唯一的帳號,直接繼續執行步驟 5。

  5. 網域。 務必包含 localhost127.0.0.1。針對正式環境,請掃描 package.json 中的 homepagewrangler.tomlREADME.mdAGENTS.md 以及 git remote。向使用者確認:「我將為 localhost127.0.0.1<domain> 進行註冊。確認無誤嗎?」 [等待使用者回應] 若未找到正式環境網域,請向使用者詢問。

  6. 程式碼庫掃描。 靜默偵測以下三項要素:

    • 前端框架(Next.js、Astro、SvelteKit、Hugo、vanilla 等)→ 決定元件嵌入的程式碼片段。
    • 後端 Handler 位置(Express route、Next.js API route、Rails controller、Workers fetch handler、Pages Function 等)→ 決定 siteverify 呼叫的程式碼片段。
    • 現有的 CAPTCHA(reCAPTCHA / hCaptcha)→ 將步驟 7 切換為遷移模式。
  7. 插入計畫。 顯示候選清單並標註 [recommended](推薦)/ [skip by default](預設跳過);請使用者確認(輸入數字、"all"、"recommended" 或指定清單)。[等待使用者回應] 若偵測到現有的 CAPTCHA,則改為呈現遷移計畫(參閱「從其他 CAPTCHA 遷移」)。

  8. 建立元件(Widget)。 當 wrangler CLI 的 turnstile widget 子命令可用時優先使用:

    npx wrangler turnstile widget create "<name>" \
      --domain <d1> --domain <d2> ... --mode managed --json
    

    從標準輸出的 JSON 中解析出 sitekeysecret。若未安裝 wrangler、版本低於支援 turnstile 子命令(提示 unknown command),或因其他原因失敗,請降級使用 scripts/widget-create.sh --account-id <id> --name <name> --domains <list> --mode managed,該腳本會直接透過 curl 呼叫 Cloudflare API。回報 sitekey。將 secret 擷取並寫入 Shell 變數 WIDGET_SECRET;切勿將其寫入磁碟,除非在步驟 9 中寫入使用者本身的環境變數 / secret 儲存庫。

  9. 串接整合。 說明約定條款:「我將在每個選定的表單中嵌入元件,並在您現有的 submit handler 內部加入標準的 siteverify 呼叫(限制在 success === true 時才執行流程)。handler 原有的邏輯保持不變。Secret 會以 TURNSTILE_SECRET 形式存在於您的環境變數中。」詢問「確認(yes)」/「顯示變更(show)」。[等待使用者回應] 若選擇 "show",印出 unified diffs 並再次詢問。請勿提出額外的自訂行為建議(例如郵件寄送、自訂後端)。

    標準伺服器端 siteverify(Node / fetch 慣用法;請根據偵測到的後端進行調整):

    const r = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        secret: process.env.TURNSTILE_SECRET,
        response: token,         // 來自請求的 cf-turnstile-response
        remoteip: clientIp,      // X-Forwarded-For / req.ip 等
      }),
    });
    const result = await r.json();
    if (!result.success) {
      return reject(403, 'forbidden');  // 替換為平台對應的拒絕回應
    }
    // 原有的 handler 邏輯在此繼續執行,保持不變
    

    將 secret 寫入使用者的 secret 儲存庫(Node/Rails/Python 使用 .env,Workers 使用 wrangler secret put TURNSTILE_SECRET,Vercel / Fly / Render 等使用該平台的 secret 管理器)。切勿寫成硬編碼(inline)。

  10. 驗證測試。 執行 scripts/validate.sh。逐一回報通過的檢查項目。若有任何項目失敗,顯示錯誤並停止流程。[若有項目失敗請等待使用者回應]

  11. 保存 Skill。 詢問:「是否將 Spin skill 儲存至 .claude/skills/turnstile-spin/SKILL.md,以便在後續任務中重複使用?」預設為同意。[等待使用者回應] 接著執行 scripts/persist-skill.sh --path <agent-specific-path>

  12. 最終報告。 印出結構化摘要:建立了什麼、驗證了什麼,以及後續步驟。

絕對禁止的事項(Things you must NOT do)

  • 切勿將 Turnstile secret 寫入磁碟,除非是作為使用者自身環境變數 / secret 儲存庫的一部分。
  • 切勿跳過驗證步驟。
  • 切勿在未顯示 diff 的情況下覆寫檔案。
  • 切勿從瀏覽器直接呼叫 siteverify。永遠遵循:瀏覽器 → 使用者的後端 → siteverify。
  • 切勿部署任何額外的基礎設施(Workers、代理伺服器、Sidecars)。客戶現有的後端會直接呼叫 siteverify。
  • 切勿在未詢問的情況下使用 sudo 或安裝全域套件。
  • 切勿在引導流程外主動提議非相關的功能(如自訂 Workers、自訂網域、進階 WAF 規則),除非使用者主動要求。

嚴格邊界:切勿主動向使用者詢問以下內容

Spin 在執行使用者現有的表單 handler 前,會先透過標準 siteverify 驗證 Turnstile token。其餘內容均超出範疇:

  • Email / SMS / 通知傳送。 請維持現有 submit handler 原樣(僅需設定以 success === true 為前置條件)。請勿提議 Resend、Mailchannels、SMTP 或 mailto。
  • 新增新的後端。 若表單目前沒有後端 handler(純靜態網站、僅有 mailto 的聯絡表單),請直接說明並結束流程。Spin 需要有伺服器端位置來放置 siteverify。
  • 資料庫 / 付款 / OAuth / 表單持久化。 超出範疇。
  • 前端框架遷移、重構或樣式調整。 只修改必要的程式碼。
  • reCAPTCHA v3 分數門檻值。 Turnstile 僅回傳 success: true/false
  • 僅用於預先通關(Pre-clearance)的設定。clearance_level !== no_clearance,siteverify 為選用項目,此時 Spin 不適用。請引導使用者並結束流程。

復原流程:尊重現有的元件設定

當使用者擁有 Cloudflare Dashboard 存取權限時,Dashboard 內的 Fix with Spin 橫幅是單鍵復原途徑:它會顯示針對現有元件精心設計的 Agent 提示詞。當使用者在編輯器中操作時,下方的復原流程即為對應做法。

若使用者告知已有設定好的 Turnstile 元件,且希望直接將 siteverify 串接至該元件而不替換(rotate)sitekey(例如:「我有 sitekey 但 siteverify 一直沒成功」、「針對我現有的元件 <sitekey> 設定 Spin」):

  1. 跳過步驟 8(建立元件)。Sitekey 已經存在,請直接向使用者取得。
  2. 透過 scripts/fetch-secret.sh --account-id <id> --sitekey <key> 擷取元件元資料。根據 status 進行分流:
    • ok:從回應中讀取 secretclearance_leveldomains。確認 domains 包含使用者的正式環境主機名稱;若無,在繼續前先提醒使用者此落差。
    • missing_read_scope:告知使用者在 Token 中新增 Account.Turnstile:Read 權限,或退而求其次請使用者貼上 secret。在手動貼上 secret 的路徑中,你無法取得 clearance_leveldomains,請請使用者確認這兩者。
  3. 檢查回應(或使用者的回答)中的 clearance_level
    • no_clearance:標準串接流程(步驟 9)。
    • 其他任何值:詢問他們是否希望在預先通關(pre-clearance)之上另外加上 siteverify,或依範疇限制結束流程。
  4. 從步驟 9(串接整合)繼續執行。Site key 不會改變;現有的元件在整個過程中維持運作。
  5. 切勿為了取得全新的 secret 而重新建立元件,這會導致已部署該 sitekey 的所有地方全部失效。

前端修改約定(The frontend-edit contract)

串接現有表單(步驟 9)時,約定原則為:門控(gate),而非替換(replace)。 使用者原有的 submit handler 繼續執行其原本功能。Spin 僅在其前方新增一個驗證步驟。

前端(嵌入元件;送出至使用者現有的端點):

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

<form action="/signup" method="POST">
  <!-- existing inputs unchanged -->
  <div class="cf-turnstile" data-sitekey="<SITEKEY>" data-action="turnstile-spin-v2"></div>
  <button type="submit">Sign up<