opencodekit 0.15.4 → 0.15.5
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/dist/index.js +1 -1
- package/dist/template/.opencode/command/cloudflare.md +70 -0
- package/dist/template/.opencode/package.json +1 -1
- package/dist/template/.opencode/skill/cloudflare/SKILL.md +233 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/README.md +35 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/api.md +100 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/configuration.md +99 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/gotchas.md +59 -0
- package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/patterns.md +89 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-gateway/README.md +695 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/api.md +38 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/configuration.md +52 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/gotchas.md +41 -0
- package/dist/template/.opencode/skill/cloudflare/references/ai-search/patterns.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/api.md +27 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/configuration.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/gotchas.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/patterns.md +36 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/README.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/api.md +31 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/configuration.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/gotchas.md +28 -0
- package/dist/template/.opencode/skill/cloudflare/references/api/patterns.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/README.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/api.md +78 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/configuration.md +128 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/gotchas.md +51 -0
- package/dist/template/.opencode/skill/cloudflare/references/api-shield/patterns.md +145 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/api.md +50 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/configuration.md +53 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/gotchas.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/patterns.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/configuration.md +58 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/gotchas.md +35 -0
- package/dist/template/.opencode/skill/cloudflare/references/bindings/patterns.md +37 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/README.md +71 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/api.md +168 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/configuration.md +114 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/gotchas.md +99 -0
- package/dist/template/.opencode/skill/cloudflare/references/bot-management/patterns.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/api.md +54 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/configuration.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/gotchas.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/patterns.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/c3/README.md +264 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/README.md +93 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/api.md +176 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/configuration.md +164 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/gotchas.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/patterns.md +180 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/api.md +43 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/configuration.md +56 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/gotchas.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/containers/patterns.md +40 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/README.md +85 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/api.md +198 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/configuration.md +151 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/gotchas.md +129 -0
- package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/patterns.md +122 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/README.md +92 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/api.md +141 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/configuration.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/gotchas.md +70 -0
- package/dist/template/.opencode/skill/cloudflare/references/d1/patterns.md +144 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/README.md +34 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/api.md +136 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/configuration.md +67 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/gotchas.md +114 -0
- package/dist/template/.opencode/skill/cloudflare/references/ddos/patterns.md +158 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/README.md +62 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/api.md +89 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/configuration.md +116 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/gotchas.md +93 -0
- package/dist/template/.opencode/skill/cloudflare/references/do-storage/patterns.md +112 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/README.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/api.md +152 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/configuration.md +148 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/gotchas.md +158 -0
- package/dist/template/.opencode/skill/cloudflare/references/durable-objects/patterns.md +255 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/README.md +18 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/api.md +46 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/configuration.md +63 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/gotchas.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-routing/patterns.md +46 -0
- package/dist/template/.opencode/skill/cloudflare/references/email-workers/README.md +598 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/README.md +62 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/api.md +137 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/configuration.md +133 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/gotchas.md +184 -0
- package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/patterns.md +176 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/configuration.md +45 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/gotchas.md +23 -0
- package/dist/template/.opencode/skill/cloudflare/references/images/patterns.md +31 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/README.md +60 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/api.md +114 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/configuration.md +92 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/gotchas.md +117 -0
- package/dist/template/.opencode/skill/cloudflare/references/kv/patterns.md +139 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/README.md +64 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/api.md +144 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/configuration.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/gotchas.md +187 -0
- package/dist/template/.opencode/skill/cloudflare/references/miniflare/patterns.md +211 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/README.md +60 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/api.md +240 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/configuration.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/gotchas.md +171 -0
- package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/patterns.md +171 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/README.md +18 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/api.md +51 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/configuration.md +60 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/gotchas.md +36 -0
- package/dist/template/.opencode/skill/cloudflare/references/observability/patterns.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/README.md +76 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/api.md +200 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/configuration.md +228 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/gotchas.md +161 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages/patterns.md +145 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/README.md +57 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/api.md +201 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/configuration.md +159 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/gotchas.md +151 -0
- package/dist/template/.opencode/skill/cloudflare/references/pages-functions/patterns.md +190 -0
- package/dist/template/.opencode/skill/cloudflare/references/pipelines/README.md +664 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/README.md +107 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/api.md +194 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/configuration.md +216 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/gotchas.md +223 -0
- package/dist/template/.opencode/skill/cloudflare/references/pulumi/patterns.md +139 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/README.md +69 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/api.md +138 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/configuration.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/gotchas.md +112 -0
- package/dist/template/.opencode/skill/cloudflare/references/queues/patterns.md +155 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/README.md +61 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/api.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/configuration.md +76 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/gotchas.md +94 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2/patterns.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/README.md +18 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/api.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/configuration.md +39 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/gotchas.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/patterns.md +46 -0
- package/dist/template/.opencode/skill/cloudflare/references/r2-sql/README.md +512 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/README.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/api.md +135 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/configuration.md +63 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/gotchas.md +75 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/patterns.md +102 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/README.md +81 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/api.md +164 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/configuration.md +147 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/gotchas.md +172 -0
- package/dist/template/.opencode/skill/cloudflare/references/realtimekit/patterns.md +155 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/README.md +90 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/api.md +178 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/configuration.md +131 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/gotchas.md +156 -0
- package/dist/template/.opencode/skill/cloudflare/references/sandbox/patterns.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/README.md +58 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/api.md +182 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/configuration.md +140 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/gotchas.md +129 -0
- package/dist/template/.opencode/skill/cloudflare/references/secrets-store/patterns.md +218 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/README.md +91 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/api.md +139 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/configuration.md +129 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/gotchas.md +87 -0
- package/dist/template/.opencode/skill/cloudflare/references/smart-placement/patterns.md +135 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/README.md +15 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/api.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/configuration.md +33 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/gotchas.md +21 -0
- package/dist/template/.opencode/skill/cloudflare/references/snippets/patterns.md +34 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/api.md +24 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/configuration.md +43 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/gotchas.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/spectrum/patterns.md +40 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/configuration.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/gotchas.md +44 -0
- package/dist/template/.opencode/skill/cloudflare/references/static-assets/patterns.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/README.md +103 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/api.md +204 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/configuration.md +127 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/gotchas.md +131 -0
- package/dist/template/.opencode/skill/cloudflare/references/stream/patterns.md +152 -0
- package/dist/template/.opencode/skill/cloudflare/references/tail-workers/README.md +640 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/README.md +76 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/api.md +159 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/configuration.md +156 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/gotchas.md +207 -0
- package/dist/template/.opencode/skill/cloudflare/references/terraform/patterns.md +135 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/README.md +82 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/api.md +105 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/configuration.md +113 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/gotchas.md +115 -0
- package/dist/template/.opencode/skill/cloudflare/references/tunnel/patterns.md +157 -0
- package/dist/template/.opencode/skill/cloudflare/references/turn/README.md +699 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/configuration.md +19 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/gotchas.md +27 -0
- package/dist/template/.opencode/skill/cloudflare/references/turnstile/patterns.md +41 -0
- package/dist/template/.opencode/skill/cloudflare/references/vectorize/README.md +682 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/README.md +14 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/api.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/configuration.md +44 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/gotchas.md +24 -0
- package/dist/template/.opencode/skill/cloudflare/references/waf/patterns.md +29 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/README.md +19 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/api.md +52 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/configuration.md +31 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/gotchas.md +28 -0
- package/dist/template/.opencode/skill/cloudflare/references/web-analytics/patterns.md +52 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/README.md +47 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/api.md +199 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/configuration.md +185 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/gotchas.md +203 -0
- package/dist/template/.opencode/skill/cloudflare/references/workerd/patterns.md +216 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/README.md +96 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/api.md +137 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/configuration.md +147 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/gotchas.md +99 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers/patterns.md +149 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-ai/README.md +116 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/README.md +48 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/api.md +169 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/configuration.md +136 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/gotchas.md +130 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/patterns.md +170 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/README.md +16 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/api.md +20 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/configuration.md +3 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/gotchas.md +35 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-playground/patterns.md +42 -0
- package/dist/template/.opencode/skill/cloudflare/references/workers-vpc/README.md +579 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/README.md +62 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/api.md +125 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/configuration.md +177 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/gotchas.md +136 -0
- package/dist/template/.opencode/skill/cloudflare/references/workflows/patterns.md +132 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/README.md +90 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/api.md +140 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/configuration.md +128 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/gotchas.md +93 -0
- package/dist/template/.opencode/skill/cloudflare/references/wrangler/patterns.md +150 -0
- package/dist/template/.opencode/skill/cloudflare/references/zaraz/README.md +360 -0
- package/dist/template/.opencode/skill/react-best-practices/AGENTS.md +2410 -0
- package/dist/template/.opencode/skill/react-best-practices/README.md +123 -0
- package/dist/template/.opencode/skill/react-best-practices/SKILL.md +125 -0
- package/dist/template/.opencode/skill/react-best-practices/metadata.json +15 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/_sections.md +46 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/_template.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-api-routes.md +38 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-defer-await.md +80 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-dependencies.md +36 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-parallel.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-conditional.md +31 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/bundle-preload.md +50 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-event-listeners.md +74 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-storage.md +70 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-early-exit.md +50 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-index-maps.md +37 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-length-check-first.md +49 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-activity.md +26 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-memo.md +44 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/rerender-transitions.md +40 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-cache-lru.md +41 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-cache-react.md +76 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/dist/template/.opencode/skill/react-best-practices/rules/server-serialization.md +38 -0
- package/dist/template/.opencode/skill/supabase/SKILL.md +120 -0
- package/dist/template/.opencode/skill/supabase/mcp.json +27 -0
- package/dist/template/.opencode/skill/vercel-deploy-claimable/SKILL.md +112 -0
- package/dist/template/.opencode/skill/vercel-deploy-claimable/scripts/deploy.sh +249 -0
- package/dist/template/.opencode/skill/web-design-guidelines/SKILL.md +39 -0
- package/package.json +1 -1
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
## Binding API
|
|
4
|
+
|
|
5
|
+
### Basic Access
|
|
6
|
+
|
|
7
|
+
**CRITICAL**: Async `.get()` required - secrets NOT directly available.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
interface Env {
|
|
11
|
+
API_KEY: { get(): Promise<string> };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
16
|
+
const apiKey = await env.API_KEY.get();
|
|
17
|
+
return fetch("https://api.example.com", {
|
|
18
|
+
headers: { "Authorization": `Bearer ${apiKey}` }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Multiple Secrets
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
const [stripeKey, sendgridKey] = await Promise.all([
|
|
28
|
+
env.STRIPE_KEY.get(),
|
|
29
|
+
env.SENDGRID_KEY.get()
|
|
30
|
+
]);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Anti-Patterns
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// ❌ Missing .get()
|
|
37
|
+
const key = env.API_KEY;
|
|
38
|
+
|
|
39
|
+
// ❌ Module-level cache
|
|
40
|
+
const CACHED_KEY = await env.API_KEY.get(); // Fails
|
|
41
|
+
|
|
42
|
+
// ✅ Request-scope cache
|
|
43
|
+
export default {
|
|
44
|
+
async fetch(request: Request, env: Env) {
|
|
45
|
+
const key = await env.API_KEY.get(); // OK - reuse in request
|
|
46
|
+
const r1 = await fetchWithAuth(key, "/ep1");
|
|
47
|
+
const r2 = await fetchWithAuth(key, "/ep2");
|
|
48
|
+
return Response.json({ r1, r2 });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## REST API
|
|
54
|
+
|
|
55
|
+
Base: `https://api.cloudflare.com/client/v4`
|
|
56
|
+
|
|
57
|
+
### Auth
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
curl -H "Authorization: Bearer $CF_TOKEN" \
|
|
61
|
+
https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Store Operations
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# List
|
|
68
|
+
GET /accounts/{account_id}/secrets_store/stores
|
|
69
|
+
|
|
70
|
+
# Create
|
|
71
|
+
POST /accounts/{account_id}/secrets_store/stores
|
|
72
|
+
{"name": "my-store"}
|
|
73
|
+
|
|
74
|
+
# Delete
|
|
75
|
+
DELETE /accounts/{account_id}/secrets_store/stores/{store_id}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Secret Operations
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# List
|
|
82
|
+
GET /accounts/{account_id}/secrets_store/stores/{store_id}/secrets
|
|
83
|
+
|
|
84
|
+
# Create (single)
|
|
85
|
+
POST /accounts/{account_id}/secrets_store/stores/{store_id}/secrets
|
|
86
|
+
{
|
|
87
|
+
"name": "my_secret",
|
|
88
|
+
"value": "secret_value",
|
|
89
|
+
"scopes": ["workers"],
|
|
90
|
+
"comment": "Optional"
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# Create (batch)
|
|
94
|
+
POST /accounts/{account_id}/secrets_store/stores/{store_id}/secrets
|
|
95
|
+
[
|
|
96
|
+
{"name": "secret_one", "value": "val1", "scopes": ["workers"]},
|
|
97
|
+
{"name": "secret_two", "value": "val2", "scopes": ["workers", "ai-gateway"]}
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
# Get metadata
|
|
101
|
+
GET /accounts/{account_id}/secrets_store/stores/{store_id}/secrets/{secret_id}
|
|
102
|
+
|
|
103
|
+
# Update
|
|
104
|
+
PATCH /accounts/{account_id}/secrets_store/stores/{store_id}/secrets/{secret_id}
|
|
105
|
+
{"value": "new_value", "comment": "Updated"}
|
|
106
|
+
|
|
107
|
+
# Delete (single)
|
|
108
|
+
DELETE /accounts/{account_id}/secrets_store/stores/{store_id}/secrets/{secret_id}
|
|
109
|
+
|
|
110
|
+
# Delete (batch)
|
|
111
|
+
DELETE /accounts/{account_id}/secrets_store/stores/{store_id}/secrets
|
|
112
|
+
{"secret_ids": ["id-1", "id-2"]}
|
|
113
|
+
|
|
114
|
+
# Duplicate
|
|
115
|
+
POST /accounts/{account_id}/secrets_store/stores/{store_id}/secrets/{secret_id}/duplicate
|
|
116
|
+
{"name": "new_name"}
|
|
117
|
+
|
|
118
|
+
# Quota
|
|
119
|
+
GET /accounts/{account_id}/secrets_store/quota
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Responses
|
|
123
|
+
|
|
124
|
+
Success:
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"success": true,
|
|
128
|
+
"result": {
|
|
129
|
+
"id": "secret-id-123",
|
|
130
|
+
"name": "my_secret",
|
|
131
|
+
"created": "2025-01-11T12:00:00Z",
|
|
132
|
+
"scopes": ["workers"]
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Error:
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"success": false,
|
|
141
|
+
"errors": [{"code": 10000, "message": "Name exists"}]
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## TypeScript Helpers
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
interface SecretsStoreBinding {
|
|
149
|
+
get(): Promise<string>;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
interface Env {
|
|
153
|
+
STRIPE_API_KEY: SecretsStoreBinding;
|
|
154
|
+
DATABASE_URL: SecretsStoreBinding;
|
|
155
|
+
WORKER_SECRET: string; // Regular Worker secret (direct access)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Fallback helper
|
|
159
|
+
async function getSecretWithFallback(
|
|
160
|
+
primary: SecretsStoreBinding,
|
|
161
|
+
fallback?: SecretsStoreBinding
|
|
162
|
+
): Promise<string> {
|
|
163
|
+
try {
|
|
164
|
+
return await primary.get();
|
|
165
|
+
} catch (error) {
|
|
166
|
+
if (fallback) return await fallback.get();
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Batch helper
|
|
172
|
+
async function getAllSecrets(
|
|
173
|
+
secrets: Record<string, SecretsStoreBinding>
|
|
174
|
+
): Promise<Record<string, string>> {
|
|
175
|
+
const entries = await Promise.all(
|
|
176
|
+
Object.entries(secrets).map(async ([k, v]) => [k, await v.get()])
|
|
177
|
+
);
|
|
178
|
+
return Object.fromEntries(entries);
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
See: [configuration.md](./configuration.md), [patterns.md](./patterns.md), [gotchas.md](./gotchas.md)
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
## Wrangler Config
|
|
4
|
+
|
|
5
|
+
### Basic Binding
|
|
6
|
+
|
|
7
|
+
```toml
|
|
8
|
+
# wrangler.toml
|
|
9
|
+
secrets_store_secrets = [
|
|
10
|
+
{ binding = "API_KEY", store_id = "abc123", secret_name = "stripe_api_key" }
|
|
11
|
+
]
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```jsonc
|
|
15
|
+
// wrangler.jsonc
|
|
16
|
+
"secrets_store_secrets": [
|
|
17
|
+
{ "binding": "API_KEY", "store_id": "abc123", "secret_name": "stripe_api_key" }
|
|
18
|
+
]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Fields:
|
|
22
|
+
- `binding`: Variable name for `env` access
|
|
23
|
+
- `store_id`: From `wrangler secrets-store store list`
|
|
24
|
+
- `secret_name`: Identifier (no spaces)
|
|
25
|
+
|
|
26
|
+
### Environment-Specific
|
|
27
|
+
|
|
28
|
+
```toml
|
|
29
|
+
[env.production]
|
|
30
|
+
secrets_store_secrets = [
|
|
31
|
+
{ binding = "API_KEY", store_id = "prod-store", secret_name = "prod_api_key" }
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[env.staging]
|
|
35
|
+
secrets_store_secrets = [
|
|
36
|
+
{ binding = "API_KEY", store_id = "staging-store", secret_name = "staging_api_key" }
|
|
37
|
+
]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Wrangler Commands
|
|
41
|
+
|
|
42
|
+
### Store Management
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
wrangler secrets-store store list
|
|
46
|
+
wrangler secrets-store store create my-store --remote
|
|
47
|
+
wrangler secrets-store store delete <store-id> --remote
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Secret Management (Production)
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Create (interactive)
|
|
54
|
+
wrangler secrets-store secret create <store-id> \
|
|
55
|
+
--name MY_SECRET --scopes workers --remote
|
|
56
|
+
|
|
57
|
+
# Create (piped)
|
|
58
|
+
cat secret.txt | wrangler secrets-store secret create <store-id> \
|
|
59
|
+
--name MY_SECRET --scopes workers --remote
|
|
60
|
+
|
|
61
|
+
# List/get/update/delete
|
|
62
|
+
wrangler secrets-store secret list <store-id> --remote
|
|
63
|
+
wrangler secrets-store secret get <store-id> --name MY_SECRET --remote
|
|
64
|
+
wrangler secrets-store secret update <store-id> --name MY_SECRET --new-value "val" --remote
|
|
65
|
+
wrangler secrets-store secret delete <store-id> --name MY_SECRET --remote
|
|
66
|
+
|
|
67
|
+
# Duplicate
|
|
68
|
+
wrangler secrets-store secret duplicate <store-id> \
|
|
69
|
+
--name ORIG --new-name COPY --remote
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Local Development
|
|
73
|
+
|
|
74
|
+
**CRITICAL**: Production secrets (`--remote`) NOT accessible in local dev.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Create local-only (no --remote)
|
|
78
|
+
wrangler secrets-store secret create <store-id> --name DEV_KEY --scopes workers
|
|
79
|
+
|
|
80
|
+
wrangler dev # Uses local secrets
|
|
81
|
+
wrangler deploy # Uses production secrets
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Best practice: Separate names for local/prod:
|
|
85
|
+
|
|
86
|
+
```toml
|
|
87
|
+
[env.development]
|
|
88
|
+
secrets_store_secrets = [
|
|
89
|
+
{ binding = "API_KEY", store_id = "store", secret_name = "dev_api_key" }
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
[env.production]
|
|
93
|
+
secrets_store_secrets = [
|
|
94
|
+
{ binding = "API_KEY", store_id = "store", secret_name = "prod_api_key" }
|
|
95
|
+
]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Dashboard
|
|
99
|
+
|
|
100
|
+
### Creating Secrets
|
|
101
|
+
|
|
102
|
+
1. **Secrets Store** → **Create secret**
|
|
103
|
+
2. Fill: Name (no spaces), Value, Scope (`Workers`), Comment
|
|
104
|
+
3. **Save** (value hidden after)
|
|
105
|
+
|
|
106
|
+
### Adding Bindings
|
|
107
|
+
|
|
108
|
+
**Method 1**: Worker → Settings → Bindings → Add → Secrets Store
|
|
109
|
+
**Method 2**: Create secret directly from Worker settings dropdown
|
|
110
|
+
|
|
111
|
+
Deploy options:
|
|
112
|
+
- **Deploy**: Immediate 100%
|
|
113
|
+
- **Save version**: Gradual rollout
|
|
114
|
+
|
|
115
|
+
## CI/CD
|
|
116
|
+
|
|
117
|
+
### GitHub Actions
|
|
118
|
+
|
|
119
|
+
```yaml
|
|
120
|
+
- name: Create secret
|
|
121
|
+
env:
|
|
122
|
+
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_TOKEN }}
|
|
123
|
+
run: |
|
|
124
|
+
echo "${{ secrets.API_KEY }}" | \
|
|
125
|
+
npx wrangler secrets-store secret create $STORE_ID \
|
|
126
|
+
--name API_KEY --scopes workers --remote
|
|
127
|
+
|
|
128
|
+
- name: Deploy
|
|
129
|
+
run: npx wrangler deploy
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### GitLab CI
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
script:
|
|
136
|
+
- echo "$API_KEY_VALUE" | npx wrangler secrets-store secret create $STORE_ID --name API_KEY --scopes workers --remote
|
|
137
|
+
- npx wrangler deploy
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
See: [api.md](./api.md), [patterns.md](./patterns.md)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Gotchas
|
|
2
|
+
|
|
3
|
+
## Security
|
|
4
|
+
|
|
5
|
+
### Never Log Secret Values
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// ❌ Logs secret
|
|
9
|
+
const secret = await env.API_KEY.get();
|
|
10
|
+
console.log(`Using secret: ${secret}`);
|
|
11
|
+
|
|
12
|
+
// ✅ Log metadata only
|
|
13
|
+
console.log("Retrieved API_KEY from Secrets Store");
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### No Module-Level Caching
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
// ❌ Fails - secrets unavailable during module init
|
|
20
|
+
import { env } from "cloudflare:workers";
|
|
21
|
+
const CACHED = await env.API_KEY.get();
|
|
22
|
+
|
|
23
|
+
// ✅ Cache in request scope
|
|
24
|
+
export default {
|
|
25
|
+
async fetch(request: Request, env: Env) {
|
|
26
|
+
const key = await env.API_KEY.get(); // Reuse in request
|
|
27
|
+
// ...
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Troubleshooting
|
|
33
|
+
|
|
34
|
+
### "Secret not found"
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
Error: Secret 'my_secret' not found in store
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Fix:
|
|
41
|
+
1. `wrangler secrets-store secret list <store-id> --remote`
|
|
42
|
+
2. Check `secret_name` matches exactly (case-sensitive)
|
|
43
|
+
3. Ensure secret has `workers` scope
|
|
44
|
+
4. Verify `store_id` correct
|
|
45
|
+
|
|
46
|
+
### Local Dev: Production Secrets Inaccessible
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Error: Cannot access secret 'API_KEY' in local dev
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Fix:
|
|
53
|
+
```bash
|
|
54
|
+
# Create local-only (no --remote)
|
|
55
|
+
wrangler secrets-store secret create <store-id> --name API_KEY --scopes workers
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Keep prod/local secrets separate.
|
|
59
|
+
|
|
60
|
+
### Type Errors
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// Error: Property 'get' does not exist
|
|
64
|
+
const key = await env.API_KEY.get();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Fix:
|
|
68
|
+
```typescript
|
|
69
|
+
interface Env {
|
|
70
|
+
API_KEY: { get(): Promise<string> };
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### "Binding already exists"
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
Error: Binding 'API_KEY' already exists
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Fix:
|
|
81
|
+
1. Remove duplicate from dashboard Settings → Bindings
|
|
82
|
+
2. Check `wrangler.toml` vs dashboard conflicts
|
|
83
|
+
3. Delete old Worker secret: `wrangler secret delete API_KEY`
|
|
84
|
+
|
|
85
|
+
### Quota Exceeded
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
Error: Account secret quota exceeded (100/100)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Fix:
|
|
92
|
+
1. `wrangler secrets-store quota --remote`
|
|
93
|
+
2. Delete unused secrets
|
|
94
|
+
3. Consolidate duplicates
|
|
95
|
+
4. Contact Cloudflare for increase
|
|
96
|
+
|
|
97
|
+
## Limits
|
|
98
|
+
|
|
99
|
+
- 100 secrets/account (beta)
|
|
100
|
+
- 1 store/account (beta)
|
|
101
|
+
- 1024 bytes max/secret
|
|
102
|
+
- Production secrets count toward limit (local don't)
|
|
103
|
+
|
|
104
|
+
## Comparison Table
|
|
105
|
+
|
|
106
|
+
| Feature | Secrets Store | Worker Secrets |
|
|
107
|
+
|---------|---------------|----------------|
|
|
108
|
+
| Scope | Account-level | Per-Worker |
|
|
109
|
+
| Reusability | Multi-Worker | Single Worker |
|
|
110
|
+
| Access | `await env.BINDING.get()` | `env.SECRET_NAME` |
|
|
111
|
+
| Management | Centralized | Per-Worker |
|
|
112
|
+
| Commands | `secrets-store` | `secret` |
|
|
113
|
+
| Local dev | Separate local secrets | `.dev.vars`/`.env` |
|
|
114
|
+
| Limits | 100/account | Per-Worker |
|
|
115
|
+
|
|
116
|
+
## Best Practices
|
|
117
|
+
|
|
118
|
+
1. **Always async**: `await env.BINDING.get()`
|
|
119
|
+
2. **Local vs prod**: Separate secrets (no `--remote` for local)
|
|
120
|
+
3. **Type safety**: Define `{ get(): Promise<string> }`
|
|
121
|
+
4. **Never log values**: Metadata only
|
|
122
|
+
5. **Design for rotation**: Use fallback bindings
|
|
123
|
+
6. **Scopes**: Set `workers` scope
|
|
124
|
+
7. **Request-scope caching**: OK to cache within request, not module-level
|
|
125
|
+
8. **Separate names**: Different names for dev/staging/prod
|
|
126
|
+
9. **Quota awareness**: Monitor 100-secret limit
|
|
127
|
+
10. **No direct access**: Values never returned after creation
|
|
128
|
+
|
|
129
|
+
See: [configuration.md](./configuration.md), [api.md](./api.md), [patterns.md](./patterns.md)
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Patterns
|
|
2
|
+
|
|
3
|
+
## Secret Rotation
|
|
4
|
+
|
|
5
|
+
Design for rotation with fallback:
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
interface Env {
|
|
9
|
+
PRIMARY_KEY: { get(): Promise<string> };
|
|
10
|
+
FALLBACK_KEY?: { get(): Promise<string> };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
15
|
+
let key = await env.PRIMARY_KEY.get();
|
|
16
|
+
let resp = await fetch("https://api.example.com", {
|
|
17
|
+
headers: { "Authorization": `Bearer ${key}` }
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Fallback during rotation
|
|
21
|
+
if (!resp.ok && env.FALLBACK_KEY) {
|
|
22
|
+
key = await env.FALLBACK_KEY.get();
|
|
23
|
+
resp = await fetch("https://api.example.com", {
|
|
24
|
+
headers: { "Authorization": `Bearer ${key}` }
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return resp;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Rotation workflow:
|
|
34
|
+
1. Create new secret (`api_key_v2`)
|
|
35
|
+
2. Add fallback binding
|
|
36
|
+
3. Deploy & verify
|
|
37
|
+
4. Update primary binding
|
|
38
|
+
5. Deploy
|
|
39
|
+
6. Remove old secret
|
|
40
|
+
|
|
41
|
+
## Encryption with KV
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
interface Env {
|
|
45
|
+
CACHE: KVNamespace;
|
|
46
|
+
ENCRYPTION_KEY: { get(): Promise<string> };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function encryptValue(value: string, key: string): Promise<string> {
|
|
50
|
+
const enc = new TextEncoder();
|
|
51
|
+
const keyMaterial = await crypto.subtle.importKey(
|
|
52
|
+
"raw", enc.encode(key), { name: "AES-GCM" }, false, ["encrypt"]
|
|
53
|
+
);
|
|
54
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
55
|
+
const encrypted = await crypto.subtle.encrypt(
|
|
56
|
+
{ name: "AES-GCM", iv }, keyMaterial, enc.encode(value)
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const combined = new Uint8Array(iv.length + encrypted.byteLength);
|
|
60
|
+
combined.set(iv);
|
|
61
|
+
combined.set(new Uint8Array(encrypted), iv.length);
|
|
62
|
+
return btoa(String.fromCharCode(...combined));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default {
|
|
66
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
67
|
+
const key = await env.ENCRYPTION_KEY.get();
|
|
68
|
+
const encrypted = await encryptValue("sensitive-data", key);
|
|
69
|
+
await env.CACHE.put("user:123:data", encrypted);
|
|
70
|
+
return Response.json({ ok: true });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## HMAC Signing
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
interface Env {
|
|
79
|
+
HMAC_SECRET: { get(): Promise<string> };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function signRequest(data: string, secret: string): Promise<string> {
|
|
83
|
+
const enc = new TextEncoder();
|
|
84
|
+
const key = await crypto.subtle.importKey(
|
|
85
|
+
"raw", enc.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]
|
|
86
|
+
);
|
|
87
|
+
const sig = await crypto.subtle.sign("HMAC", key, enc.encode(data));
|
|
88
|
+
return btoa(String.fromCharCode(...new Uint8Array(sig)));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default {
|
|
92
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
93
|
+
const secret = await env.HMAC_SECRET.get();
|
|
94
|
+
const payload = await request.text();
|
|
95
|
+
const signature = await signRequest(payload, secret);
|
|
96
|
+
return Response.json({ signature });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Audit & Monitoring
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
export default {
|
|
105
|
+
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
|
|
106
|
+
const startTime = Date.now();
|
|
107
|
+
try {
|
|
108
|
+
const apiKey = await env.API_KEY.get();
|
|
109
|
+
const resp = await fetch("https://api.example.com", {
|
|
110
|
+
headers: { "Authorization": `Bearer ${apiKey}` }
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
ctx.waitUntil(
|
|
114
|
+
fetch("https://log.example.com/log", {
|
|
115
|
+
method: "POST",
|
|
116
|
+
body: JSON.stringify({
|
|
117
|
+
event: "secret_used",
|
|
118
|
+
secret_name: "API_KEY",
|
|
119
|
+
timestamp: new Date().toISOString(),
|
|
120
|
+
duration_ms: Date.now() - startTime,
|
|
121
|
+
success: resp.ok
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
);
|
|
125
|
+
return resp;
|
|
126
|
+
} catch (error) {
|
|
127
|
+
ctx.waitUntil(
|
|
128
|
+
fetch("https://log.example.com/log", {
|
|
129
|
+
method: "POST",
|
|
130
|
+
body: JSON.stringify({
|
|
131
|
+
event: "secret_access_failed",
|
|
132
|
+
secret_name: "API_KEY",
|
|
133
|
+
error: error instanceof Error ? error.message : "Unknown"
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
);
|
|
137
|
+
return new Response("Error", { status: 500 });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Migration
|
|
144
|
+
|
|
145
|
+
### From Worker Secrets
|
|
146
|
+
|
|
147
|
+
Before:
|
|
148
|
+
```typescript
|
|
149
|
+
// wrangler secret put API_KEY
|
|
150
|
+
const key = env.API_KEY; // Direct access
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
After:
|
|
154
|
+
```toml
|
|
155
|
+
secrets_store_secrets = [
|
|
156
|
+
{ binding = "API_KEY", store_id = "abc123", secret_name = "shared_key" }
|
|
157
|
+
]
|
|
158
|
+
```
|
|
159
|
+
```typescript
|
|
160
|
+
const key = await env.API_KEY.get(); // Async access
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Steps:
|
|
164
|
+
1. Create secret in Secrets Store
|
|
165
|
+
2. Add `secrets_store_secrets` binding
|
|
166
|
+
3. Update code to `await env.BINDING.get()`
|
|
167
|
+
4. Test staging
|
|
168
|
+
5. Deploy
|
|
169
|
+
6. Delete old: `wrangler secret delete API_KEY`
|
|
170
|
+
|
|
171
|
+
### Sharing Across Workers
|
|
172
|
+
|
|
173
|
+
```toml
|
|
174
|
+
# worker-1/wrangler.toml
|
|
175
|
+
secrets_store_secrets = [
|
|
176
|
+
{ binding = "SHARED_DB", store_id = "abc123", secret_name = "postgres_url" }
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
# worker-2/wrangler.toml
|
|
180
|
+
secrets_store_secrets = [
|
|
181
|
+
{ binding = "DB_CONN", store_id = "abc123", secret_name = "postgres_url" }
|
|
182
|
+
]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Both access same secret, different binding names.
|
|
186
|
+
|
|
187
|
+
## Integration
|
|
188
|
+
|
|
189
|
+
### D1 Database
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
interface Env {
|
|
193
|
+
DB: D1Database;
|
|
194
|
+
DB_CREDENTIALS: { get(): Promise<string> };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export default {
|
|
198
|
+
async fetch(request: Request, env: Env) {
|
|
199
|
+
const creds = await env.DB_CREDENTIALS.get();
|
|
200
|
+
const { username, password } = JSON.parse(creds);
|
|
201
|
+
// Use with D1
|
|
202
|
+
return Response.json({ ok: true });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Service Bindings
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
// auth-worker: Signs JWT with Secrets Store
|
|
211
|
+
interface Env { JWT_SECRET: { get(): Promise<string> }; }
|
|
212
|
+
|
|
213
|
+
// api-worker: Calls auth service
|
|
214
|
+
interface Env { AUTH: Fetcher; }
|
|
215
|
+
const authResp = await env.AUTH.fetch(new Request("https://auth/verify"));
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
See: [api.md](./api.md), [gotchas.md](./gotchas.md)
|