pi-cloudflare 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +67 -0
- package/bin/setup.mjs +103 -0
- package/dist/auth-flow.d.ts +15 -0
- package/dist/auth-flow.d.ts.map +1 -0
- package/dist/auth-flow.js +90 -0
- package/dist/auth-flow.js.map +1 -0
- package/dist/client.d.ts +18 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +47 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +10 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth.d.ts +44 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +135 -0
- package/dist/oauth.js.map +1 -0
- package/dist/proxy.d.ts +29 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +39 -0
- package/dist/proxy.js.map +1 -0
- package/dist/servers.d.ts +19 -0
- package/dist/servers.d.ts.map +1 -0
- package/dist/servers.js +40 -0
- package/dist/servers.js.map +1 -0
- package/dist/token-store.d.ts +23 -0
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +47 -0
- package/dist/token-store.js.map +1 -0
- package/package.json +67 -0
- package/skills/agents-sdk/SKILL.md +221 -0
- package/skills/agents-sdk/references/browse-the-web.md +63 -0
- package/skills/agents-sdk/references/callable.md +92 -0
- package/skills/agents-sdk/references/client-sdk.md +110 -0
- package/skills/agents-sdk/references/codemode.md +110 -0
- package/skills/agents-sdk/references/configuration.md +72 -0
- package/skills/agents-sdk/references/durable-execution.md +51 -0
- package/skills/agents-sdk/references/email.md +146 -0
- package/skills/agents-sdk/references/human-in-the-loop.md +67 -0
- package/skills/agents-sdk/references/mcp.md +188 -0
- package/skills/agents-sdk/references/observability.md +44 -0
- package/skills/agents-sdk/references/queue-retries.md +79 -0
- package/skills/agents-sdk/references/routing.md +75 -0
- package/skills/agents-sdk/references/server-driven-messages.md +63 -0
- package/skills/agents-sdk/references/state-scheduling.md +171 -0
- package/skills/agents-sdk/references/streaming-chat.md +198 -0
- package/skills/agents-sdk/references/think.md +112 -0
- package/skills/agents-sdk/references/voice.md +68 -0
- package/skills/agents-sdk/references/webhooks-push.md +86 -0
- package/skills/agents-sdk/references/workflows.md +132 -0
- package/skills/cloudflare/SKILL.md +248 -0
- package/skills/cloudflare/references/agents-sdk/README.md +89 -0
- package/skills/cloudflare/references/agents-sdk/api.md +190 -0
- package/skills/cloudflare/references/agents-sdk/configuration.md +182 -0
- package/skills/cloudflare/references/agents-sdk/gotchas.md +158 -0
- package/skills/cloudflare/references/agents-sdk/patterns.md +192 -0
- package/skills/cloudflare/references/ai-gateway/README.md +175 -0
- package/skills/cloudflare/references/ai-gateway/configuration.md +111 -0
- package/skills/cloudflare/references/ai-gateway/dynamic-routing.md +82 -0
- package/skills/cloudflare/references/ai-gateway/features.md +96 -0
- package/skills/cloudflare/references/ai-gateway/sdk-integration.md +114 -0
- package/skills/cloudflare/references/ai-gateway/troubleshooting.md +88 -0
- package/skills/cloudflare/references/ai-search/README.md +138 -0
- package/skills/cloudflare/references/ai-search/api.md +87 -0
- package/skills/cloudflare/references/ai-search/configuration.md +88 -0
- package/skills/cloudflare/references/ai-search/gotchas.md +81 -0
- package/skills/cloudflare/references/ai-search/patterns.md +85 -0
- package/skills/cloudflare/references/analytics-engine/README.md +94 -0
- package/skills/cloudflare/references/analytics-engine/api.md +112 -0
- package/skills/cloudflare/references/analytics-engine/configuration.md +112 -0
- package/skills/cloudflare/references/analytics-engine/gotchas.md +85 -0
- package/skills/cloudflare/references/analytics-engine/patterns.md +83 -0
- package/skills/cloudflare/references/api/README.md +66 -0
- package/skills/cloudflare/references/api/api.md +204 -0
- package/skills/cloudflare/references/api/configuration.md +160 -0
- package/skills/cloudflare/references/api/gotchas.md +225 -0
- package/skills/cloudflare/references/api/patterns.md +204 -0
- package/skills/cloudflare/references/api-shield/README.md +44 -0
- package/skills/cloudflare/references/api-shield/api.md +141 -0
- package/skills/cloudflare/references/api-shield/configuration.md +192 -0
- package/skills/cloudflare/references/api-shield/gotchas.md +125 -0
- package/skills/cloudflare/references/api-shield/patterns.md +180 -0
- package/skills/cloudflare/references/argo-smart-routing/README.md +90 -0
- package/skills/cloudflare/references/argo-smart-routing/api.md +240 -0
- package/skills/cloudflare/references/argo-smart-routing/configuration.md +197 -0
- package/skills/cloudflare/references/argo-smart-routing/gotchas.md +111 -0
- package/skills/cloudflare/references/argo-smart-routing/patterns.md +104 -0
- package/skills/cloudflare/references/artifacts/README.md +79 -0
- package/skills/cloudflare/references/artifacts/api.md +128 -0
- package/skills/cloudflare/references/artifacts/configuration.md +92 -0
- package/skills/cloudflare/references/bindings/README.md +122 -0
- package/skills/cloudflare/references/bindings/api.md +203 -0
- package/skills/cloudflare/references/bindings/configuration.md +188 -0
- package/skills/cloudflare/references/bindings/gotchas.md +208 -0
- package/skills/cloudflare/references/bindings/patterns.md +200 -0
- package/skills/cloudflare/references/bot-management/README.md +94 -0
- package/skills/cloudflare/references/bot-management/api.md +169 -0
- package/skills/cloudflare/references/bot-management/configuration.md +163 -0
- package/skills/cloudflare/references/bot-management/gotchas.md +114 -0
- package/skills/cloudflare/references/bot-management/patterns.md +182 -0
- package/skills/cloudflare/references/browser-rendering/README.md +78 -0
- package/skills/cloudflare/references/browser-rendering/api.md +108 -0
- package/skills/cloudflare/references/browser-rendering/configuration.md +78 -0
- package/skills/cloudflare/references/browser-rendering/gotchas.md +88 -0
- package/skills/cloudflare/references/browser-rendering/patterns.md +91 -0
- package/skills/cloudflare/references/c3/README.md +111 -0
- package/skills/cloudflare/references/c3/api.md +71 -0
- package/skills/cloudflare/references/c3/configuration.md +81 -0
- package/skills/cloudflare/references/c3/gotchas.md +92 -0
- package/skills/cloudflare/references/c3/patterns.md +82 -0
- package/skills/cloudflare/references/cache-reserve/README.md +147 -0
- package/skills/cloudflare/references/cache-reserve/api.md +194 -0
- package/skills/cloudflare/references/cache-reserve/configuration.md +169 -0
- package/skills/cloudflare/references/cache-reserve/gotchas.md +132 -0
- package/skills/cloudflare/references/cache-reserve/patterns.md +197 -0
- package/skills/cloudflare/references/containers/README.md +85 -0
- package/skills/cloudflare/references/containers/api.md +187 -0
- package/skills/cloudflare/references/containers/configuration.md +188 -0
- package/skills/cloudflare/references/containers/gotchas.md +178 -0
- package/skills/cloudflare/references/containers/patterns.md +202 -0
- package/skills/cloudflare/references/cron-triggers/README.md +99 -0
- package/skills/cloudflare/references/cron-triggers/api.md +196 -0
- package/skills/cloudflare/references/cron-triggers/configuration.md +180 -0
- package/skills/cloudflare/references/cron-triggers/gotchas.md +199 -0
- package/skills/cloudflare/references/cron-triggers/patterns.md +190 -0
- package/skills/cloudflare/references/d1/README.md +133 -0
- package/skills/cloudflare/references/d1/api.md +196 -0
- package/skills/cloudflare/references/d1/configuration.md +191 -0
- package/skills/cloudflare/references/d1/gotchas.md +98 -0
- package/skills/cloudflare/references/d1/patterns.md +189 -0
- package/skills/cloudflare/references/ddos/README.md +41 -0
- package/skills/cloudflare/references/ddos/api.md +164 -0
- package/skills/cloudflare/references/ddos/configuration.md +93 -0
- package/skills/cloudflare/references/ddos/gotchas.md +107 -0
- package/skills/cloudflare/references/ddos/patterns.md +174 -0
- package/skills/cloudflare/references/do-storage/README.md +75 -0
- package/skills/cloudflare/references/do-storage/api.md +102 -0
- package/skills/cloudflare/references/do-storage/configuration.md +112 -0
- package/skills/cloudflare/references/do-storage/gotchas.md +150 -0
- package/skills/cloudflare/references/do-storage/patterns.md +194 -0
- package/skills/cloudflare/references/do-storage/testing.md +183 -0
- package/skills/cloudflare/references/durable-objects/README.md +185 -0
- package/skills/cloudflare/references/durable-objects/api.md +187 -0
- package/skills/cloudflare/references/durable-objects/configuration.md +160 -0
- package/skills/cloudflare/references/durable-objects/gotchas.md +197 -0
- package/skills/cloudflare/references/durable-objects/patterns.md +201 -0
- package/skills/cloudflare/references/email-routing/README.md +89 -0
- package/skills/cloudflare/references/email-routing/api.md +195 -0
- package/skills/cloudflare/references/email-routing/configuration.md +186 -0
- package/skills/cloudflare/references/email-routing/gotchas.md +196 -0
- package/skills/cloudflare/references/email-routing/patterns.md +229 -0
- package/skills/cloudflare/references/email-workers/README.md +151 -0
- package/skills/cloudflare/references/email-workers/api.md +237 -0
- package/skills/cloudflare/references/email-workers/configuration.md +112 -0
- package/skills/cloudflare/references/email-workers/gotchas.md +125 -0
- package/skills/cloudflare/references/email-workers/patterns.md +102 -0
- package/skills/cloudflare/references/flagship/README.md +59 -0
- package/skills/cloudflare/references/flagship/api.md +390 -0
- package/skills/cloudflare/references/flagship/configuration.md +202 -0
- package/skills/cloudflare/references/flagship/gotchas.md +178 -0
- package/skills/cloudflare/references/flagship/patterns.md +469 -0
- package/skills/cloudflare/references/graphql-api/README.md +147 -0
- package/skills/cloudflare/references/graphql-api/api.md +175 -0
- package/skills/cloudflare/references/graphql-api/configuration.md +118 -0
- package/skills/cloudflare/references/graphql-api/gotchas.md +110 -0
- package/skills/cloudflare/references/graphql-api/patterns.md +225 -0
- package/skills/cloudflare/references/hyperdrive/README.md +82 -0
- package/skills/cloudflare/references/hyperdrive/api.md +143 -0
- package/skills/cloudflare/references/hyperdrive/configuration.md +159 -0
- package/skills/cloudflare/references/hyperdrive/gotchas.md +77 -0
- package/skills/cloudflare/references/hyperdrive/patterns.md +190 -0
- package/skills/cloudflare/references/images/README.md +61 -0
- package/skills/cloudflare/references/images/api.md +96 -0
- package/skills/cloudflare/references/images/configuration.md +211 -0
- package/skills/cloudflare/references/images/gotchas.md +99 -0
- package/skills/cloudflare/references/images/patterns.md +115 -0
- package/skills/cloudflare/references/kv/README.md +89 -0
- package/skills/cloudflare/references/kv/api.md +160 -0
- package/skills/cloudflare/references/kv/configuration.md +144 -0
- package/skills/cloudflare/references/kv/gotchas.md +131 -0
- package/skills/cloudflare/references/kv/patterns.md +196 -0
- package/skills/cloudflare/references/miniflare/README.md +105 -0
- package/skills/cloudflare/references/miniflare/api.md +187 -0
- package/skills/cloudflare/references/miniflare/configuration.md +173 -0
- package/skills/cloudflare/references/miniflare/gotchas.md +160 -0
- package/skills/cloudflare/references/miniflare/patterns.md +181 -0
- package/skills/cloudflare/references/network-interconnect/README.md +99 -0
- package/skills/cloudflare/references/network-interconnect/api.md +199 -0
- package/skills/cloudflare/references/network-interconnect/configuration.md +114 -0
- package/skills/cloudflare/references/network-interconnect/gotchas.md +165 -0
- package/skills/cloudflare/references/network-interconnect/patterns.md +166 -0
- package/skills/cloudflare/references/observability/README.md +88 -0
- package/skills/cloudflare/references/observability/api.md +164 -0
- package/skills/cloudflare/references/observability/configuration.md +169 -0
- package/skills/cloudflare/references/observability/gotchas.md +115 -0
- package/skills/cloudflare/references/observability/patterns.md +105 -0
- package/skills/cloudflare/references/pages/README.md +88 -0
- package/skills/cloudflare/references/pages/api.md +204 -0
- package/skills/cloudflare/references/pages/configuration.md +201 -0
- package/skills/cloudflare/references/pages/gotchas.md +203 -0
- package/skills/cloudflare/references/pages/patterns.md +204 -0
- package/skills/cloudflare/references/pages-functions/README.md +98 -0
- package/skills/cloudflare/references/pages-functions/api.md +143 -0
- package/skills/cloudflare/references/pages-functions/configuration.md +122 -0
- package/skills/cloudflare/references/pages-functions/gotchas.md +94 -0
- package/skills/cloudflare/references/pages-functions/patterns.md +137 -0
- package/skills/cloudflare/references/pipelines/README.md +90 -0
- package/skills/cloudflare/references/pipelines/api.md +124 -0
- package/skills/cloudflare/references/pipelines/configuration.md +155 -0
- package/skills/cloudflare/references/pipelines/gotchas.md +58 -0
- package/skills/cloudflare/references/pipelines/patterns.md +130 -0
- package/skills/cloudflare/references/pulumi/README.md +100 -0
- package/skills/cloudflare/references/pulumi/api.md +200 -0
- package/skills/cloudflare/references/pulumi/configuration.md +198 -0
- package/skills/cloudflare/references/pulumi/gotchas.md +181 -0
- package/skills/cloudflare/references/pulumi/patterns.md +191 -0
- package/skills/cloudflare/references/queues/README.md +96 -0
- package/skills/cloudflare/references/queues/api.md +206 -0
- package/skills/cloudflare/references/queues/configuration.md +144 -0
- package/skills/cloudflare/references/queues/gotchas.md +206 -0
- package/skills/cloudflare/references/queues/patterns.md +220 -0
- package/skills/cloudflare/references/r2/README.md +95 -0
- package/skills/cloudflare/references/r2/api.md +200 -0
- package/skills/cloudflare/references/r2/configuration.md +165 -0
- package/skills/cloudflare/references/r2/gotchas.md +190 -0
- package/skills/cloudflare/references/r2/patterns.md +193 -0
- package/skills/cloudflare/references/r2-data-catalog/README.md +75 -0
- package/skills/cloudflare/references/r2-data-catalog/api.md +122 -0
- package/skills/cloudflare/references/r2-data-catalog/configuration.md +98 -0
- package/skills/cloudflare/references/r2-data-catalog/gotchas.md +55 -0
- package/skills/cloudflare/references/r2-data-catalog/patterns.md +122 -0
- package/skills/cloudflare/references/r2-sql/README.md +64 -0
- package/skills/cloudflare/references/r2-sql/api.md +121 -0
- package/skills/cloudflare/references/r2-sql/configuration.md +50 -0
- package/skills/cloudflare/references/r2-sql/gotchas.md +39 -0
- package/skills/cloudflare/references/r2-sql/patterns.md +118 -0
- package/skills/cloudflare/references/realtime-sfu/README.md +65 -0
- package/skills/cloudflare/references/realtime-sfu/api.md +158 -0
- package/skills/cloudflare/references/realtime-sfu/configuration.md +137 -0
- package/skills/cloudflare/references/realtime-sfu/gotchas.md +133 -0
- package/skills/cloudflare/references/realtime-sfu/patterns.md +174 -0
- package/skills/cloudflare/references/realtimekit/README.md +113 -0
- package/skills/cloudflare/references/realtimekit/api.md +212 -0
- package/skills/cloudflare/references/realtimekit/configuration.md +203 -0
- package/skills/cloudflare/references/realtimekit/gotchas.md +169 -0
- package/skills/cloudflare/references/realtimekit/patterns.md +223 -0
- package/skills/cloudflare/references/sandbox/README.md +96 -0
- package/skills/cloudflare/references/sandbox/api.md +198 -0
- package/skills/cloudflare/references/sandbox/configuration.md +143 -0
- package/skills/cloudflare/references/sandbox/gotchas.md +194 -0
- package/skills/cloudflare/references/sandbox/patterns.md +201 -0
- package/skills/cloudflare/references/secrets-store/README.md +74 -0
- package/skills/cloudflare/references/secrets-store/api.md +200 -0
- package/skills/cloudflare/references/secrets-store/configuration.md +185 -0
- package/skills/cloudflare/references/secrets-store/gotchas.md +97 -0
- package/skills/cloudflare/references/secrets-store/patterns.md +207 -0
- package/skills/cloudflare/references/smart-placement/README.md +138 -0
- package/skills/cloudflare/references/smart-placement/api.md +183 -0
- package/skills/cloudflare/references/smart-placement/configuration.md +196 -0
- package/skills/cloudflare/references/smart-placement/gotchas.md +174 -0
- package/skills/cloudflare/references/smart-placement/patterns.md +183 -0
- package/skills/cloudflare/references/snippets/README.md +68 -0
- package/skills/cloudflare/references/snippets/api.md +198 -0
- package/skills/cloudflare/references/snippets/configuration.md +227 -0
- package/skills/cloudflare/references/snippets/gotchas.md +86 -0
- package/skills/cloudflare/references/snippets/patterns.md +135 -0
- package/skills/cloudflare/references/spectrum/README.md +52 -0
- package/skills/cloudflare/references/spectrum/api.md +181 -0
- package/skills/cloudflare/references/spectrum/configuration.md +194 -0
- package/skills/cloudflare/references/spectrum/gotchas.md +145 -0
- package/skills/cloudflare/references/spectrum/patterns.md +196 -0
- package/skills/cloudflare/references/static-assets/README.md +65 -0
- package/skills/cloudflare/references/static-assets/api.md +199 -0
- package/skills/cloudflare/references/static-assets/configuration.md +186 -0
- package/skills/cloudflare/references/static-assets/gotchas.md +162 -0
- package/skills/cloudflare/references/static-assets/patterns.md +189 -0
- package/skills/cloudflare/references/stream/README.md +114 -0
- package/skills/cloudflare/references/stream/api-live.md +195 -0
- package/skills/cloudflare/references/stream/api.md +199 -0
- package/skills/cloudflare/references/stream/configuration.md +141 -0
- package/skills/cloudflare/references/stream/gotchas.md +130 -0
- package/skills/cloudflare/references/stream/patterns.md +184 -0
- package/skills/cloudflare/references/tail-workers/README.md +89 -0
- package/skills/cloudflare/references/tail-workers/api.md +200 -0
- package/skills/cloudflare/references/tail-workers/configuration.md +176 -0
- package/skills/cloudflare/references/tail-workers/gotchas.md +192 -0
- package/skills/cloudflare/references/tail-workers/patterns.md +180 -0
- package/skills/cloudflare/references/terraform/README.md +102 -0
- package/skills/cloudflare/references/terraform/api.md +178 -0
- package/skills/cloudflare/references/terraform/configuration.md +197 -0
- package/skills/cloudflare/references/terraform/gotchas.md +150 -0
- package/skills/cloudflare/references/terraform/patterns.md +174 -0
- package/skills/cloudflare/references/tunnel/README.md +129 -0
- package/skills/cloudflare/references/tunnel/api.md +193 -0
- package/skills/cloudflare/references/tunnel/configuration.md +157 -0
- package/skills/cloudflare/references/tunnel/gotchas.md +147 -0
- package/skills/cloudflare/references/tunnel/networking.md +168 -0
- package/skills/cloudflare/references/tunnel/patterns.md +192 -0
- package/skills/cloudflare/references/turn/README.md +82 -0
- package/skills/cloudflare/references/turn/api.md +239 -0
- package/skills/cloudflare/references/turn/configuration.md +179 -0
- package/skills/cloudflare/references/turn/gotchas.md +231 -0
- package/skills/cloudflare/references/turn/patterns.md +213 -0
- package/skills/cloudflare/references/turnstile/README.md +99 -0
- package/skills/cloudflare/references/turnstile/api.md +240 -0
- package/skills/cloudflare/references/turnstile/configuration.md +222 -0
- package/skills/cloudflare/references/turnstile/gotchas.md +218 -0
- package/skills/cloudflare/references/turnstile/patterns.md +193 -0
- package/skills/cloudflare/references/vectorize/README.md +133 -0
- package/skills/cloudflare/references/vectorize/api.md +88 -0
- package/skills/cloudflare/references/vectorize/configuration.md +88 -0
- package/skills/cloudflare/references/vectorize/gotchas.md +76 -0
- package/skills/cloudflare/references/vectorize/patterns.md +90 -0
- package/skills/cloudflare/references/waf/README.md +113 -0
- package/skills/cloudflare/references/waf/api.md +202 -0
- package/skills/cloudflare/references/waf/configuration.md +203 -0
- package/skills/cloudflare/references/waf/gotchas.md +204 -0
- package/skills/cloudflare/references/waf/patterns.md +197 -0
- package/skills/cloudflare/references/web-analytics/README.md +141 -0
- package/skills/cloudflare/references/web-analytics/configuration.md +76 -0
- package/skills/cloudflare/references/web-analytics/gotchas.md +82 -0
- package/skills/cloudflare/references/web-analytics/integration.md +60 -0
- package/skills/cloudflare/references/web-analytics/patterns.md +91 -0
- package/skills/cloudflare/references/workerd/README.md +78 -0
- package/skills/cloudflare/references/workerd/api.md +185 -0
- package/skills/cloudflare/references/workerd/configuration.md +183 -0
- package/skills/cloudflare/references/workerd/gotchas.md +139 -0
- package/skills/cloudflare/references/workerd/patterns.md +192 -0
- package/skills/cloudflare/references/workers/README.md +108 -0
- package/skills/cloudflare/references/workers/api.md +195 -0
- package/skills/cloudflare/references/workers/configuration.md +185 -0
- package/skills/cloudflare/references/workers/frameworks.md +197 -0
- package/skills/cloudflare/references/workers/gotchas.md +137 -0
- package/skills/cloudflare/references/workers/patterns.md +198 -0
- package/skills/cloudflare/references/workers-ai/README.md +197 -0
- package/skills/cloudflare/references/workers-ai/api.md +112 -0
- package/skills/cloudflare/references/workers-ai/configuration.md +97 -0
- package/skills/cloudflare/references/workers-ai/gotchas.md +114 -0
- package/skills/cloudflare/references/workers-ai/patterns.md +120 -0
- package/skills/cloudflare/references/workers-for-platforms/README.md +89 -0
- package/skills/cloudflare/references/workers-for-platforms/api.md +196 -0
- package/skills/cloudflare/references/workers-for-platforms/configuration.md +167 -0
- package/skills/cloudflare/references/workers-for-platforms/gotchas.md +134 -0
- package/skills/cloudflare/references/workers-for-platforms/patterns.md +188 -0
- package/skills/cloudflare/references/workers-playground/README.md +127 -0
- package/skills/cloudflare/references/workers-playground/api.md +101 -0
- package/skills/cloudflare/references/workers-playground/configuration.md +163 -0
- package/skills/cloudflare/references/workers-playground/gotchas.md +88 -0
- package/skills/cloudflare/references/workers-playground/patterns.md +132 -0
- package/skills/cloudflare/references/workers-vpc/README.md +127 -0
- package/skills/cloudflare/references/workers-vpc/api.md +202 -0
- package/skills/cloudflare/references/workers-vpc/configuration.md +147 -0
- package/skills/cloudflare/references/workers-vpc/gotchas.md +167 -0
- package/skills/cloudflare/references/workers-vpc/patterns.md +209 -0
- package/skills/cloudflare/references/workflows/README.md +77 -0
- package/skills/cloudflare/references/workflows/api.md +218 -0
- package/skills/cloudflare/references/workflows/configuration.md +152 -0
- package/skills/cloudflare/references/workflows/gotchas.md +90 -0
- package/skills/cloudflare/references/workflows/patterns.md +175 -0
- package/skills/cloudflare/references/wrangler/README.md +135 -0
- package/skills/cloudflare/references/wrangler/api.md +188 -0
- package/skills/cloudflare/references/wrangler/configuration.md +197 -0
- package/skills/cloudflare/references/wrangler/gotchas.md +197 -0
- package/skills/cloudflare/references/wrangler/patterns.md +209 -0
- package/skills/cloudflare/references/zaraz/IMPLEMENTATION_SUMMARY.md +121 -0
- package/skills/cloudflare/references/zaraz/README.md +111 -0
- package/skills/cloudflare/references/zaraz/api.md +112 -0
- package/skills/cloudflare/references/zaraz/configuration.md +90 -0
- package/skills/cloudflare/references/zaraz/gotchas.md +81 -0
- package/skills/cloudflare/references/zaraz/patterns.md +74 -0
- package/skills/cloudflare-email-service/SKILL.md +103 -0
- package/skills/cloudflare-email-service/references/cli-and-mcp.md +125 -0
- package/skills/cloudflare-email-service/references/deliverability.md +285 -0
- package/skills/cloudflare-email-service/references/rest-api.md +184 -0
- package/skills/cloudflare-email-service/references/routing.md +199 -0
- package/skills/cloudflare-email-service/references/sending.md +252 -0
- package/skills/cloudflare-one/SKILL.md +176 -0
- package/skills/cloudflare-one-migrations/SKILL.md +110 -0
- package/skills/durable-objects/SKILL.md +186 -0
- package/skills/durable-objects/references/rules.md +295 -0
- package/skills/durable-objects/references/testing.md +264 -0
- package/skills/durable-objects/references/workers.md +346 -0
- package/skills/sandbox-migrate-to-next/SKILL.md +185 -0
- package/skills/sandbox-next/SKILL.md +91 -0
- package/skills/sandbox-next/references/api-quick-ref.md +94 -0
- package/skills/sandbox-next/references/examples.md +15 -0
- package/skills/sandbox-stable/SKILL.md +110 -0
- package/skills/turnstile-spin/README.md +51 -0
- package/skills/turnstile-spin/SKILL.md +330 -0
- package/skills/turnstile-spin/references/astro.md +199 -0
- package/skills/turnstile-spin/references/hugo.md +114 -0
- package/skills/turnstile-spin/references/nextjs-app.md +261 -0
- package/skills/turnstile-spin/references/nextjs-pages.md +82 -0
- package/skills/turnstile-spin/references/sveltekit.md +191 -0
- package/skills/turnstile-spin/references/vanilla-html.md +157 -0
- package/skills/turnstile-spin/scripts/auth-probe.sh +285 -0
- package/skills/turnstile-spin/scripts/persist-skill.sh +114 -0
- package/skills/turnstile-spin/scripts/validate.sh +137 -0
- package/skills/turnstile-spin/scripts/widget-create.sh +121 -0
- package/skills/turnstile-spin/tests/validation.md +62 -0
- package/skills/workers-best-practices/SKILL.md +127 -0
- package/skills/workers-best-practices/references/review.md +174 -0
- package/skills/workers-best-practices/references/rules.md +467 -0
- package/skills/wrangler/SKILL.md +922 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Persists the canonical Spin skill bundle into the current project.
|
|
3
|
+
|
|
4
|
+
set +x
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
unset CLOUDFLARE_API_TOKEN CF_API_TOKEN CLOUDFLARE_API_KEY CF_API_KEY
|
|
8
|
+
unset CLOUDFLARE_EMAIL CF_API_EMAIL WIDGET_SECRET TURNSTILE_SECRET
|
|
9
|
+
unset WRANGLER_BIN WRANGLER_VERSION
|
|
10
|
+
unset GITHUB_TOKEN GH_TOKEN GITLAB_TOKEN NPM_TOKEN
|
|
11
|
+
|
|
12
|
+
need_arg() {
|
|
13
|
+
if [[ -z "${2-}" || "$2" == --* ]]; then
|
|
14
|
+
echo "persist-skill: missing value for $1" >&2
|
|
15
|
+
exit 2
|
|
16
|
+
fi
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
PATH_ARG=""
|
|
20
|
+
while [[ $# -gt 0 ]]; do
|
|
21
|
+
case "$1" in
|
|
22
|
+
--path) need_arg "$1" "${2-}"; PATH_ARG="$2"; shift 2 ;;
|
|
23
|
+
*) echo "persist-skill: unknown arg $1" >&2; exit 2 ;;
|
|
24
|
+
esac
|
|
25
|
+
done
|
|
26
|
+
|
|
27
|
+
[[ -n "$PATH_ARG" ]] || { echo "persist-skill: --path required" >&2; exit 2; }
|
|
28
|
+
if [[ "$(basename "$PATH_ARG")" != "SKILL.md" ]]; then
|
|
29
|
+
echo "persist-skill: --path must end in SKILL.md for a directory-based skill bundle" >&2
|
|
30
|
+
echo '{"status":"error","reason":"file_target_not_supported"}'
|
|
31
|
+
exit 2
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
for command_name in git python3; do
|
|
35
|
+
command -v "$command_name" >/dev/null 2>&1 || {
|
|
36
|
+
echo "persist-skill: $command_name is required" >&2
|
|
37
|
+
echo "{\"status\":\"error\",\"reason\":\"${command_name}_not_available\"}"
|
|
38
|
+
exit 1
|
|
39
|
+
}
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
PROJECT_ROOT="$(pwd -P)"
|
|
43
|
+
TARGET_DIR="$(python3 -I -c 'import os,sys; print(os.path.realpath(os.path.abspath(sys.argv[1])))' "$(dirname "$PATH_ARG")")"
|
|
44
|
+
if [[ "$TARGET_DIR" != "$PROJECT_ROOT" && "$TARGET_DIR" != "$PROJECT_ROOT/"* ]]; then
|
|
45
|
+
echo "persist-skill: target must be inside the current project" >&2
|
|
46
|
+
echo '{"status":"error","reason":"target_outside_project"}'
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
if [[ -e "$TARGET_DIR" ]] && ! python3 -I -c 'import os,sys; raise SystemExit(0 if not os.listdir(sys.argv[1]) else 1)' "$TARGET_DIR"; then
|
|
50
|
+
echo "persist-skill: target directory is not empty" >&2
|
|
51
|
+
echo '{"status":"error","reason":"target_not_empty"}'
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
if ! TEMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/turnstile-spin-persist.XXXXXX")"; then
|
|
56
|
+
echo "persist-skill: could not create a temporary directory" >&2
|
|
57
|
+
echo '{"status":"error","reason":"temporary_directory_failed"}'
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
trap 'rm -rf "$TEMP_DIR"' EXIT
|
|
61
|
+
|
|
62
|
+
if ! git -c core.hooksPath=/dev/null clone \
|
|
63
|
+
--quiet \
|
|
64
|
+
--depth 1 \
|
|
65
|
+
--filter=blob:none \
|
|
66
|
+
--sparse \
|
|
67
|
+
"https://github.com/cloudflare/skills.git" \
|
|
68
|
+
"$TEMP_DIR/repo"; then
|
|
69
|
+
echo "persist-skill: clone failed" >&2
|
|
70
|
+
echo '{"status":"error","reason":"clone_failed"}'
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
if ! git -C "$TEMP_DIR/repo" -c core.hooksPath=/dev/null sparse-checkout set skills/turnstile-spin; then
|
|
74
|
+
echo "persist-skill: sparse checkout failed" >&2
|
|
75
|
+
echo '{"status":"error","reason":"sparse_checkout_failed"}'
|
|
76
|
+
exit 1
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
SOURCE_DIR="$TEMP_DIR/repo/skills/turnstile-spin"
|
|
80
|
+
if [[ ! -f "$SOURCE_DIR/SKILL.md" ]]; then
|
|
81
|
+
echo "persist-skill: canonical bundle is missing SKILL.md" >&2
|
|
82
|
+
echo '{"status":"error","reason":"skill_missing"}'
|
|
83
|
+
exit 1
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
python3 -I - "$SOURCE_DIR" "$TARGET_DIR" <<'PY'
|
|
87
|
+
import pathlib
|
|
88
|
+
import shutil
|
|
89
|
+
import sys
|
|
90
|
+
|
|
91
|
+
source = pathlib.Path(sys.argv[1])
|
|
92
|
+
target = pathlib.Path(sys.argv[2])
|
|
93
|
+
if target.exists():
|
|
94
|
+
target.rmdir()
|
|
95
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
96
|
+
shutil.copytree(source, target, dirs_exist_ok=False)
|
|
97
|
+
for script in (target / "scripts").glob("*.sh"):
|
|
98
|
+
script.chmod(0o755)
|
|
99
|
+
PY
|
|
100
|
+
|
|
101
|
+
python3 -I - "$PATH_ARG" "$TARGET_DIR" <<'PY'
|
|
102
|
+
import json
|
|
103
|
+
import pathlib
|
|
104
|
+
import sys
|
|
105
|
+
|
|
106
|
+
path_arg, bundle_root = sys.argv[1], pathlib.Path(sys.argv[2])
|
|
107
|
+
scripts = sorted(path.name for path in (bundle_root / "scripts").glob("*.sh"))
|
|
108
|
+
print(json.dumps({
|
|
109
|
+
"status": "ok",
|
|
110
|
+
"path": path_arg,
|
|
111
|
+
"bundle_root": str(bundle_root),
|
|
112
|
+
"scripts": scripts,
|
|
113
|
+
}))
|
|
114
|
+
PY
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Validates a Turnstile widget without placing its secret in arguments,
|
|
3
|
+
# exported environment variables, logs, or temporary files.
|
|
4
|
+
|
|
5
|
+
set +x
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
usage() {
|
|
9
|
+
echo "Usage: printf '%s' \"\$TURNSTILE_SECRET\" | $0 --sitekey <sitekey> --account-id <account-id> --expected-domains '<json-array>'" >&2
|
|
10
|
+
exit 2
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
need_arg() {
|
|
14
|
+
if [[ -z "${2-}" || "$2" == --* ]]; then
|
|
15
|
+
usage
|
|
16
|
+
fi
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
SITEKEY=""
|
|
20
|
+
ACCOUNT_ID=""
|
|
21
|
+
EXPECTED_DOMAINS_JSON=""
|
|
22
|
+
|
|
23
|
+
while [[ $# -gt 0 ]]; do
|
|
24
|
+
case "$1" in
|
|
25
|
+
--sitekey)
|
|
26
|
+
need_arg "$1" "${2-}"
|
|
27
|
+
SITEKEY="$2"
|
|
28
|
+
shift 2
|
|
29
|
+
;;
|
|
30
|
+
--account-id)
|
|
31
|
+
need_arg "$1" "${2-}"
|
|
32
|
+
ACCOUNT_ID="$2"
|
|
33
|
+
shift 2
|
|
34
|
+
;;
|
|
35
|
+
--expected-domains)
|
|
36
|
+
need_arg "$1" "${2-}"
|
|
37
|
+
EXPECTED_DOMAINS_JSON="$2"
|
|
38
|
+
shift 2
|
|
39
|
+
;;
|
|
40
|
+
*) usage ;;
|
|
41
|
+
esac
|
|
42
|
+
done
|
|
43
|
+
|
|
44
|
+
[[ -n "$SITEKEY" && -n "$ACCOUNT_ID" && -n "$EXPECTED_DOMAINS_JSON" ]] || usage
|
|
45
|
+
: "${CLOUDFLARE_API_TOKEN:?CLOUDFLARE_API_TOKEN must be set}"
|
|
46
|
+
API_TOKEN="$CLOUDFLARE_API_TOKEN"
|
|
47
|
+
unset CLOUDFLARE_API_TOKEN
|
|
48
|
+
[[ "$API_TOKEN" =~ ^[A-Za-z0-9_-]+$ ]] || {
|
|
49
|
+
echo "validate: CLOUDFLARE_API_TOKEN has an invalid format" >&2
|
|
50
|
+
exit 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for command_name in curl jq python3; do
|
|
54
|
+
command -v "$command_name" >/dev/null 2>&1 || {
|
|
55
|
+
echo "validate: $command_name is required" >&2
|
|
56
|
+
exit 1
|
|
57
|
+
}
|
|
58
|
+
done
|
|
59
|
+
|
|
60
|
+
if ! jq -e '
|
|
61
|
+
type == "array" and
|
|
62
|
+
length > 0 and
|
|
63
|
+
all(.[]; type == "string" and length > 0)
|
|
64
|
+
' <<<"$EXPECTED_DOMAINS_JSON" >/dev/null; then
|
|
65
|
+
echo "validate: --expected-domains must be a non-empty JSON array of domains" >&2
|
|
66
|
+
exit 2
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
WIDGET_SECRET=""
|
|
70
|
+
IFS= read -r -d '' WIDGET_SECRET || true
|
|
71
|
+
trap 'unset API_TOKEN WIDGET_SECRET WIDGET_API_SECRET WIDGET_RESPONSE SITEVERIFY_RESPONSE' EXIT
|
|
72
|
+
|
|
73
|
+
if [[ -z "$WIDGET_SECRET" || "$WIDGET_SECRET" =~ [[:space:]] ]]; then
|
|
74
|
+
echo "validate: standard input must contain one non-empty secret without whitespace" >&2
|
|
75
|
+
exit 1
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
ACCOUNT_ENCODED="$(python3 -I -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$ACCOUNT_ID")"
|
|
79
|
+
SITEKEY_ENCODED="$(python3 -I -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$SITEKEY")"
|
|
80
|
+
|
|
81
|
+
if ! WIDGET_RESPONSE="$(
|
|
82
|
+
printf 'header = "Authorization: Bearer %s"\n' "$API_TOKEN" |
|
|
83
|
+
curl --disable --config - --fail --silent --show-error \
|
|
84
|
+
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ENCODED/challenges/widgets/$SITEKEY_ENCODED"
|
|
85
|
+
)"; then
|
|
86
|
+
echo "validate: widget metadata lookup failed" >&2
|
|
87
|
+
exit 1
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
if ! printf '%s' "$WIDGET_RESPONSE" | jq -e --arg sitekey "$SITEKEY" --argjson expected "$EXPECTED_DOMAINS_JSON" '
|
|
91
|
+
. as $widget
|
|
92
|
+
| (.success == true) and
|
|
93
|
+
(.result.sitekey == $sitekey) and
|
|
94
|
+
((.result.clearance_level | type) == "string") and
|
|
95
|
+
(.result.clearance_level as $clearance | ["no_clearance", "interactive", "managed", "jschallenge"] | index($clearance) != null) and
|
|
96
|
+
((.result.domains | type) == "array") and
|
|
97
|
+
(all($expected[]; . as $domain | $widget.result.domains | index($domain) != null))
|
|
98
|
+
' >/dev/null; then
|
|
99
|
+
echo "validate: widget sitekey, domains, or clearance level was invalid" >&2
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
if ! WIDGET_API_SECRET="$(printf '%s' "$WIDGET_RESPONSE" | jq -er '.result.secret | select(type == "string" and test("^\\S+$"))')"; then
|
|
104
|
+
echo "validate: widget metadata did not include a valid secret" >&2
|
|
105
|
+
exit 1
|
|
106
|
+
fi
|
|
107
|
+
if [[ "$WIDGET_API_SECRET" != "$WIDGET_SECRET" ]]; then
|
|
108
|
+
echo "validate: secret does not belong to the requested sitekey" >&2
|
|
109
|
+
exit 1
|
|
110
|
+
fi
|
|
111
|
+
unset WIDGET_API_SECRET
|
|
112
|
+
unset WIDGET_RESPONSE
|
|
113
|
+
|
|
114
|
+
if ! SITEVERIFY_RESPONSE="$(
|
|
115
|
+
printf '%s' "$WIDGET_SECRET" |
|
|
116
|
+
python3 -I -c 'import sys,urllib.parse; print(urllib.parse.urlencode({"secret":sys.stdin.read(),"response":"XXXX.DUMMY.TOKEN.XXXX"}),end="")' |
|
|
117
|
+
curl --disable --fail --silent --show-error \
|
|
118
|
+
"https://challenges.cloudflare.com/turnstile/v0/siteverify" \
|
|
119
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
120
|
+
--data-binary @-
|
|
121
|
+
)"; then
|
|
122
|
+
echo "validate: dummy-token siteverify request failed" >&2
|
|
123
|
+
exit 1
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
if ! jq -e '
|
|
127
|
+
(.success == false) and
|
|
128
|
+
((.["error-codes"] | type) == "array") and
|
|
129
|
+
((.["error-codes"] | index("invalid-input-response")) != null) and
|
|
130
|
+
((.["error-codes"] | index("invalid-input-secret")) == null)
|
|
131
|
+
' <<<"$SITEVERIFY_RESPONSE" >/dev/null; then
|
|
132
|
+
echo "validate: siteverify did not confirm the widget secret" >&2
|
|
133
|
+
exit 1
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
unset WIDGET_SECRET SITEVERIFY_RESPONSE
|
|
137
|
+
echo '{"status":"ok","metadata_check":"ran","dummy_siteverify":"ran"}'
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Creates a Turnstile widget without writing credentials or the response to disk.
|
|
3
|
+
|
|
4
|
+
set +x
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
need_arg() {
|
|
8
|
+
if [[ -z "${2-}" || "$2" == --* ]]; then
|
|
9
|
+
echo "widget-create: missing value for $1" >&2
|
|
10
|
+
exit 2
|
|
11
|
+
fi
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
MODE="managed"
|
|
15
|
+
ACCOUNT_ID=""
|
|
16
|
+
NAME=""
|
|
17
|
+
DOMAINS=""
|
|
18
|
+
|
|
19
|
+
while [[ $# -gt 0 ]]; do
|
|
20
|
+
case "$1" in
|
|
21
|
+
--account-id) need_arg "$1" "${2-}"; ACCOUNT_ID="$2"; shift 2 ;;
|
|
22
|
+
--name) need_arg "$1" "${2-}"; NAME="$2"; shift 2 ;;
|
|
23
|
+
--domains) need_arg "$1" "${2-}"; DOMAINS="$2"; shift 2 ;;
|
|
24
|
+
--mode) need_arg "$1" "${2-}"; MODE="$2"; shift 2 ;;
|
|
25
|
+
*) echo "widget-create: unknown arg $1" >&2; exit 2 ;;
|
|
26
|
+
esac
|
|
27
|
+
done
|
|
28
|
+
|
|
29
|
+
: "${CLOUDFLARE_API_TOKEN:?CLOUDFLARE_API_TOKEN must be set}"
|
|
30
|
+
API_TOKEN="$CLOUDFLARE_API_TOKEN"
|
|
31
|
+
unset CLOUDFLARE_API_TOKEN
|
|
32
|
+
[[ -n "$ACCOUNT_ID" ]] || { echo "widget-create: --account-id required" >&2; exit 2; }
|
|
33
|
+
[[ -n "$NAME" ]] || { echo "widget-create: --name required" >&2; exit 2; }
|
|
34
|
+
[[ -n "$DOMAINS" ]] || { echo "widget-create: --domains required" >&2; exit 2; }
|
|
35
|
+
[[ "$API_TOKEN" =~ ^[A-Za-z0-9_-]+$ ]] || {
|
|
36
|
+
echo "widget-create: CLOUDFLARE_API_TOKEN has an invalid format" >&2
|
|
37
|
+
exit 1
|
|
38
|
+
}
|
|
39
|
+
case "$MODE" in
|
|
40
|
+
managed|invisible|non-interactive) ;;
|
|
41
|
+
*) echo "widget-create: unsupported mode" >&2; exit 2 ;;
|
|
42
|
+
esac
|
|
43
|
+
|
|
44
|
+
for command_name in curl python3; do
|
|
45
|
+
command -v "$command_name" >/dev/null 2>&1 || {
|
|
46
|
+
echo "widget-create: $command_name is required" >&2
|
|
47
|
+
exit 1
|
|
48
|
+
}
|
|
49
|
+
done
|
|
50
|
+
|
|
51
|
+
BODY_JSON="$(python3 -I -c '
|
|
52
|
+
import json, sys
|
|
53
|
+
name, domains_csv, mode = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
54
|
+
domains = [domain.strip() for domain in domains_csv.split(",") if domain.strip()]
|
|
55
|
+
if not domains:
|
|
56
|
+
raise SystemExit(2)
|
|
57
|
+
print(json.dumps({"name": name, "domains": domains, "mode": mode}))
|
|
58
|
+
' "$NAME" "$DOMAINS" "$MODE")" || {
|
|
59
|
+
echo "widget-create: --domains must include at least one domain" >&2
|
|
60
|
+
exit 2
|
|
61
|
+
}
|
|
62
|
+
ACCOUNT_ENCODED="$(python3 -I -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$ACCOUNT_ID")"
|
|
63
|
+
|
|
64
|
+
if ! API_RESPONSE="$(
|
|
65
|
+
printf 'header = "Authorization: Bearer %s"\n' "$API_TOKEN" |
|
|
66
|
+
curl --disable --config - --silent --show-error --write-out $'\n%{http_code}' -X POST \
|
|
67
|
+
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ENCODED/challenges/widgets" \
|
|
68
|
+
-H "Content-Type: application/json" \
|
|
69
|
+
--data "$BODY_JSON"
|
|
70
|
+
)"; then
|
|
71
|
+
echo "widget-create: Cloudflare API request failed" >&2
|
|
72
|
+
echo '{"status":"error","code":0,"message":"Cloudflare API request failed"}'
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
unset BODY_JSON
|
|
76
|
+
unset API_TOKEN
|
|
77
|
+
|
|
78
|
+
HTTP_CODE="${API_RESPONSE##*$'\n'}"
|
|
79
|
+
RESPONSE_BODY="${API_RESPONSE%$'\n'*}"
|
|
80
|
+
unset API_RESPONSE
|
|
81
|
+
|
|
82
|
+
if ! printf '%s' "$RESPONSE_BODY" | python3 -I -c '
|
|
83
|
+
import json
|
|
84
|
+
import re
|
|
85
|
+
import sys
|
|
86
|
+
|
|
87
|
+
http_code = sys.argv[1]
|
|
88
|
+
try:
|
|
89
|
+
data = json.load(sys.stdin)
|
|
90
|
+
except Exception:
|
|
91
|
+
print(f"widget-create: non-JSON response (HTTP {http_code})", file=sys.stderr)
|
|
92
|
+
print(json.dumps({"status":"error","code":0,"message":"Cloudflare API returned an invalid response"}))
|
|
93
|
+
raise SystemExit(1)
|
|
94
|
+
|
|
95
|
+
errors = data.get("errors") if isinstance(data, dict) else []
|
|
96
|
+
first = errors[0] if isinstance(errors, list) and errors and isinstance(errors[0], dict) else {}
|
|
97
|
+
code = first.get("code", 0)
|
|
98
|
+
if not isinstance(data, dict) or data.get("success") is not True:
|
|
99
|
+
print(f"widget-create: request failed (HTTP {http_code}, code={code})", file=sys.stderr)
|
|
100
|
+
print(json.dumps({"status":"error","code":code,"message":"Cloudflare API request failed"}))
|
|
101
|
+
raise SystemExit(1)
|
|
102
|
+
|
|
103
|
+
result = data.get("result")
|
|
104
|
+
sitekey = result.get("sitekey") if isinstance(result, dict) else None
|
|
105
|
+
secret = result.get("secret") if isinstance(result, dict) else None
|
|
106
|
+
if not (
|
|
107
|
+
isinstance(sitekey, str)
|
|
108
|
+
and re.fullmatch(r"\S{1,256}", sitekey)
|
|
109
|
+
and isinstance(secret, str)
|
|
110
|
+
and re.fullmatch(r"\S{1,1024}", secret)
|
|
111
|
+
):
|
|
112
|
+
print("widget-create: API returned invalid widget credentials", file=sys.stderr)
|
|
113
|
+
print(json.dumps({"status":"error","code":0,"message":"Cloudflare API returned invalid widget credentials"}))
|
|
114
|
+
raise SystemExit(1)
|
|
115
|
+
|
|
116
|
+
print(json.dumps({"status":"ok","sitekey":sitekey,"secret":secret}))
|
|
117
|
+
' "$HTTP_CODE"; then
|
|
118
|
+
unset RESPONSE_BODY
|
|
119
|
+
exit 1
|
|
120
|
+
fi
|
|
121
|
+
unset RESPONSE_BODY
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Skill validation cases
|
|
2
|
+
|
|
3
|
+
These cases match the assertions in the Turnstile Spin PRD. Run them after editing this skill to confirm an agent loading it can still execute the wizard end-to-end.
|
|
4
|
+
|
|
5
|
+
## Test 1: Dummy Siteverify returns a structured error
|
|
6
|
+
|
|
7
|
+
Step 10's `validate.sh` sends a deliberately-invalid token directly to `challenges.cloudflare.com/turnstile/v0/siteverify` using the captured secret. The expected response is `success: false` with `error-codes: ["invalid-input-response"]`. Anything else means the secret is wrong or the widget is misconfigured.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
printf '%s' "$WIDGET_SECRET" |
|
|
11
|
+
python3 -I -c 'import sys,urllib.parse; print(urllib.parse.urlencode({"secret":sys.stdin.read(),"response":"XXXX.DUMMY.TOKEN.XXXX"}),end="")' |
|
|
12
|
+
curl --disable --fail --silent --show-error \
|
|
13
|
+
"https://challenges.cloudflare.com/turnstile/v0/siteverify" \
|
|
14
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
15
|
+
--data-binary @- |
|
|
16
|
+
jq -e '.success == false and (.["error-codes"] | index("invalid-input-response"))'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Expected exit code: 0.
|
|
20
|
+
|
|
21
|
+
## Test 2: Metadata matches the sitekey and secret
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
printf '%s' "$WIDGET_SECRET" |
|
|
25
|
+
scripts/validate.sh \
|
|
26
|
+
--sitekey "$SITEKEY" \
|
|
27
|
+
--account-id "$ACCOUNT_ID" \
|
|
28
|
+
--expected-domains '["example.com","localhost","127.0.0.1"]'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Expected exit code: 0 for all valid clearance levels: `no_clearance`, `interactive`, `managed`, and `jschallenge`. A secret from another sitekey must fail.
|
|
32
|
+
|
|
33
|
+
## Test 3: Runtime checks match the protected surface
|
|
34
|
+
|
|
35
|
+
Inspect every generated frontend and backend pair:
|
|
36
|
+
|
|
37
|
+
- The widget has a meaningful action such as `signup`, `login`, or `contact`.
|
|
38
|
+
- The backend requires the same `result.action` value.
|
|
39
|
+
- The backend requires `result.hostname` to match its deployment-specific frontend hostname allowlist.
|
|
40
|
+
- A production hostname allowlist does not contain `localhost` or `127.0.0.1`.
|
|
41
|
+
|
|
42
|
+
## Test 4: Same-page retries reset the correct widget
|
|
43
|
+
|
|
44
|
+
Native forms that navigate do not need reset logic. For each same-page flow, verify that the code retains the widget ID returned by `turnstile.render()` and calls `turnstile.reset(widgetId)` after the request completes. Multiple protected surfaces must not share a widget ID or reset without an ID.
|
|
45
|
+
|
|
46
|
+
## Test 5: Skill persists to a bundle location
|
|
47
|
+
|
|
48
|
+
After Step 11:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
test -f .claude/skills/turnstile-spin/SKILL.md \
|
|
52
|
+
|| test -f .codex/skills/turnstile-spin/SKILL.md \
|
|
53
|
+
|| test -f .opencode/skills/turnstile-spin/SKILL.md
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Expected exit code: 0. File-oriented rules targets install the hosted `prompt.md` directly instead of using `persist-skill.sh`.
|
|
57
|
+
|
|
58
|
+
## Running all cases
|
|
59
|
+
|
|
60
|
+
The consuming test harness must pass the widget secret through standard input. It must not export it or place it in a command argument.
|
|
61
|
+
|
|
62
|
+
(`run-all.sh` is not bundled with this skill; the cases above are intended to be wired into the consuming agent's own test harness, or run by hand after a deploy.)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: workers-best-practices
|
|
3
|
+
description: Reviews and authors Cloudflare Workers code against production best practices. Load when writing new Workers, reviewing Worker code, configuring wrangler.jsonc, or checking for common Workers anti-patterns (streaming, floating promises, global state, secrets, bindings, observability). Biases towards retrieval from Cloudflare docs over pre-trained knowledge.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Your knowledge of Cloudflare Workers APIs, types, and configuration may be outdated. **Prefer retrieval over pre-training** for any Workers code task — writing or reviewing.
|
|
7
|
+
|
|
8
|
+
## Retrieval Sources
|
|
9
|
+
|
|
10
|
+
Fetch the **latest** versions before writing or reviewing Workers code. Do not rely on baked-in knowledge for API signatures, config fields, or binding shapes.
|
|
11
|
+
|
|
12
|
+
| Source | How to retrieve | Use for |
|
|
13
|
+
|--------|----------------|---------|
|
|
14
|
+
| Workers best practices | Fetch `https://developers.cloudflare.com/workers/best-practices/workers-best-practices/` | Canonical rules, patterns, anti-patterns |
|
|
15
|
+
| Workers types | See `references/review.md` for retrieval steps | API signatures, handler types, binding types |
|
|
16
|
+
| Wrangler config schema | `node_modules/wrangler/config-schema.json` | Config fields, binding shapes, allowed values |
|
|
17
|
+
| Cloudflare docs | Search tool or `https://developers.cloudflare.com/workers/` | API reference, compatibility dates/flags |
|
|
18
|
+
|
|
19
|
+
## FIRST: Fetch Latest References
|
|
20
|
+
|
|
21
|
+
Before reviewing or writing Workers code, retrieve the current best practices page and relevant type definitions. If the project's `node_modules` has an older version, **prefer the latest published version**.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Fetch latest workers types
|
|
25
|
+
mkdir -p /tmp/workers-types-latest && \
|
|
26
|
+
npm pack @cloudflare/workers-types --pack-destination /tmp/workers-types-latest && \
|
|
27
|
+
tar -xzf /tmp/workers-types-latest/cloudflare-workers-types-*.tgz -C /tmp/workers-types-latest
|
|
28
|
+
# Types at /tmp/workers-types-latest/package/index.d.ts
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Reference Documentation
|
|
32
|
+
|
|
33
|
+
- `references/rules.md` — all best practice rules with code examples and anti-patterns
|
|
34
|
+
- `references/review.md` — type validation, config validation, binding access patterns, review process
|
|
35
|
+
|
|
36
|
+
## Rules Quick Reference
|
|
37
|
+
|
|
38
|
+
### Configuration
|
|
39
|
+
|
|
40
|
+
| Rule | Summary |
|
|
41
|
+
|------|---------|
|
|
42
|
+
| Compatibility date | Set `compatibility_date` to today on new projects; update periodically on existing ones |
|
|
43
|
+
| nodejs_compat | Enable the `nodejs_compat` flag — many libraries depend on Node.js built-ins |
|
|
44
|
+
| wrangler types | Run `wrangler types` to generate `Env` — never hand-write binding interfaces |
|
|
45
|
+
| Secrets | Use `wrangler secret put`, never hardcode secrets in config or source |
|
|
46
|
+
| wrangler.jsonc | Use JSONC config for non-secret settings — newer features are JSON-only |
|
|
47
|
+
|
|
48
|
+
### Request & Response Handling
|
|
49
|
+
|
|
50
|
+
| Rule | Summary |
|
|
51
|
+
|------|---------|
|
|
52
|
+
| Streaming | Stream large/unknown payloads — never `await response.text()` on unbounded data |
|
|
53
|
+
| waitUntil | Use `ctx.waitUntil()` for post-response work; do not destructure `ctx` |
|
|
54
|
+
|
|
55
|
+
### Architecture
|
|
56
|
+
|
|
57
|
+
| Rule | Summary |
|
|
58
|
+
|------|---------|
|
|
59
|
+
| Bindings over REST | Use in-process bindings (KV, R2, D1, Queues) — not the Cloudflare REST API |
|
|
60
|
+
| Queues & Workflows | Move async/background work off the critical path |
|
|
61
|
+
| Service bindings | Use service bindings for Worker-to-Worker calls — not public HTTP |
|
|
62
|
+
| Hyperdrive | Always use Hyperdrive for external PostgreSQL/MySQL connections |
|
|
63
|
+
|
|
64
|
+
### Observability
|
|
65
|
+
|
|
66
|
+
| Rule | Summary |
|
|
67
|
+
|------|---------|
|
|
68
|
+
| Logs & Traces | Enable `observability` in config with `head_sampling_rate`; use structured JSON logging |
|
|
69
|
+
|
|
70
|
+
### Code Patterns
|
|
71
|
+
|
|
72
|
+
| Rule | Summary |
|
|
73
|
+
|------|---------|
|
|
74
|
+
| No global request state | Never store request-scoped data in module-level variables |
|
|
75
|
+
| Floating promises | Every Promise must be `await`ed, `return`ed, `void`ed, or passed to `ctx.waitUntil()` |
|
|
76
|
+
|
|
77
|
+
### Security
|
|
78
|
+
|
|
79
|
+
| Rule | Summary |
|
|
80
|
+
|------|---------|
|
|
81
|
+
| Web Crypto | Use `crypto.randomUUID()` / `crypto.getRandomValues()` — never `Math.random()` for security |
|
|
82
|
+
| No passThroughOnException | Use explicit try/catch with structured error responses |
|
|
83
|
+
|
|
84
|
+
## Anti-Patterns to Flag
|
|
85
|
+
|
|
86
|
+
| Anti-pattern | Why it matters |
|
|
87
|
+
|-------------|----------------|
|
|
88
|
+
| `await response.text()` on unbounded data | Memory exhaustion — 128 MB limit |
|
|
89
|
+
| Hardcoded secrets in source or config | Credential leak via version control |
|
|
90
|
+
| `Math.random()` for tokens/IDs | Predictable, not cryptographically secure |
|
|
91
|
+
| Bare `fetch()` without `await` or `waitUntil` | Floating promise — dropped result, swallowed error |
|
|
92
|
+
| Module-level mutable variables for request state | Cross-request data leaks, stale state, I/O errors |
|
|
93
|
+
| Cloudflare REST API from inside a Worker | Unnecessary network hop, auth overhead, added latency |
|
|
94
|
+
| `ctx.passThroughOnException()` as error handling | Hides bugs, makes debugging impossible |
|
|
95
|
+
| Hand-written `Env` interface | Drifts from actual wrangler config bindings |
|
|
96
|
+
| Direct string comparison for secret values | Timing side-channel — use `crypto.subtle.timingSafeEqual` |
|
|
97
|
+
| Destructuring `ctx` (`const { waitUntil } = ctx`) | Loses `this` binding — throws "Illegal invocation" at runtime |
|
|
98
|
+
| `any` on `Env` or handler params | Defeats type safety for all binding access |
|
|
99
|
+
| `as unknown as T` double-cast | Hides real type incompatibilities — fix the design |
|
|
100
|
+
| `implements` on platform base classes (instead of `extends`) | Legacy — loses `this.ctx`, `this.env`. Applies to DurableObject, WorkerEntrypoint, Workflow |
|
|
101
|
+
| `env.X` inside platform base class | Should be `this.env.X` in classes extending DurableObject, WorkerEntrypoint, etc. |
|
|
102
|
+
|
|
103
|
+
## Review Workflow
|
|
104
|
+
|
|
105
|
+
1. **Retrieve** — fetch latest best practices page, workers types, and wrangler schema
|
|
106
|
+
2. **Read full files** — not just diffs; context matters for binding access patterns
|
|
107
|
+
3. **Check types** — binding access, handler signatures, no `any`, no unsafe casts (see `references/review.md`)
|
|
108
|
+
4. **Check config** — compatibility_date, nodejs_compat, observability, secrets, binding-code consistency
|
|
109
|
+
5. **Check patterns** — streaming, floating promises, global state, serialization boundaries
|
|
110
|
+
6. **Check security** — crypto usage, secret handling, timing-safe comparisons, error handling
|
|
111
|
+
7. **Validate with tools** — `npx tsc --noEmit`, lint for `no-floating-promises`
|
|
112
|
+
8. **Reference rules** — see `references/rules.md` for each rule's correct pattern
|
|
113
|
+
|
|
114
|
+
## Scope
|
|
115
|
+
|
|
116
|
+
This skill covers Workers-specific best practices and code review. For related topics:
|
|
117
|
+
|
|
118
|
+
- **Durable Objects**: load the `durable-objects` skill
|
|
119
|
+
- **Workflows**: see [Rules of Workflows](https://developers.cloudflare.com/workflows/build/rules-of-workflows/)
|
|
120
|
+
- **Wrangler CLI commands**: load the `wrangler` skill
|
|
121
|
+
|
|
122
|
+
## Principles
|
|
123
|
+
|
|
124
|
+
- **Be certain.** Retrieve before flagging. If unsure about an API, config field, or pattern, fetch the docs first.
|
|
125
|
+
- **Provide evidence.** Reference line numbers, tool output, or docs links.
|
|
126
|
+
- **Focus on what developers will copy.** Workers code in examples and docs gets pasted into production.
|
|
127
|
+
- **Correctness over completeness.** A concise example that works beats a comprehensive one with errors.
|