rcf-lite 0.22.0 → 0.24.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/CHANGELOG.md +38 -0
- package/bin/rcf.js +13 -2
- package/blueprints/application-account-settings/docs/topics.md +9 -1
- package/blueprints/application-admin-console/CHANGELOG.md +12 -0
- package/blueprints/application-admin-console/blueprint.json +34 -1
- package/blueprints/application-admin-console/contributions/adrs/adr-2214-application-admin-console-consume-zero-trust-gate.json +25 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-014.json +17 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2214-application-admin-console-access-gated-signin-surface.json +32 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21815.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21816.json +27 -0
- package/blueprints/application-admin-console/docs/topics.md +9 -1
- package/blueprints/application-admin-console/guide/application-admin-console.md +24 -0
- package/blueprints/application-admin-console/probe-packs/application-admin-console.pack.mjs +26 -1
- package/blueprints/application-api-rest/docs/topics.md +9 -1
- package/blueprints/application-charts/docs/topics.md +9 -1
- package/blueprints/application-dashboard/docs/topics.md +9 -1
- package/blueprints/application-datatable/docs/topics.md +9 -1
- package/blueprints/application-empty-error-states/docs/topics.md +9 -1
- package/blueprints/application-error-handling/docs/topics.md +9 -1
- package/blueprints/application-file-upload/docs/topics.md +9 -1
- package/blueprints/application-forms-wizard/docs/topics.md +9 -1
- package/blueprints/application-notifications-in-app/docs/topics.md +9 -1
- package/blueprints/application-onboarding-tour/docs/topics.md +9 -1
- package/blueprints/application-spa/docs/topics.md +10 -2
- package/blueprints/delivery-ci-workflows/docs/topics.md +9 -1
- package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +69 -0
- package/blueprints/deploy-cloudflare-workers/README.md +12 -0
- package/blueprints/deploy-cloudflare-workers/blueprint.json +234 -36
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +30 -0
- package/blueprints/deploy-cloudflare-workers/contributions/probes/assets-manifest-scan.mjs +207 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-013.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-014.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12113.json +36 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12114.json +27 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12115.json +27 -0
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +10 -2
- package/blueprints/deploy-cloudflare-workers/guide/deploy-cloudflare-workers.md +25 -0
- package/blueprints/edge-cloudflare-access/CHANGELOG.md +23 -0
- package/blueprints/edge-cloudflare-access/README.md +141 -0
- package/blueprints/edge-cloudflare-access/blueprint.json +197 -0
- package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3501-edge-cloudflare-access-jwt-gate.json +14 -0
- package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3502-edge-cloudflare-access-identity-provider.json +25 -0
- package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3503-edge-cloudflare-access-policy-scope.json +12 -0
- package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3504-edge-cloudflare-access-audit-retention.json +12 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +100 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/audit-event-secrecy.mjs +70 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/jwt-validator-fixture.mjs +63 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/jwt-validator-reject.mjs +95 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/probe-utils.mjs +90 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/real-account-gated-url.mjs +65 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/run-admin-console-gate-surface.mjs +5 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/run-audit-event-secrecy.mjs +5 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/run-jwt-validator-fixture.mjs +5 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/run-jwt-validator-reject.mjs +5 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/run-real-account-gated-url.mjs +5 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/run-wrangler-seam.mjs +5 -0
- package/blueprints/edge-cloudflare-access/contributions/probes/wrangler-seam.mjs +203 -0
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-001.json +17 -0
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-002.json +17 -0
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-003.json +17 -0
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-004.json +17 -0
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-005.json +17 -0
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-006.json +18 -0
- package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3501-edge-cloudflare-access-jwt-validator.json +31 -0
- package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3502-edge-cloudflare-access-application-declaration.json +33 -0
- package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3503-edge-cloudflare-access-policy-shape.json +25 -0
- package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3504-edge-cloudflare-access-audit-sink.json +25 -0
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34101.json +27 -0
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34102.json +28 -0
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34103.json +27 -0
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34104.json +27 -0
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34105.json +27 -0
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34106.json +27 -0
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34107.json +27 -0
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34108.json +27 -0
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34109.json +27 -0
- package/blueprints/edge-cloudflare-access/docs/topics.md +68 -0
- package/blueprints/edge-cloudflare-access/guide/edge-cloudflare-access.md +180 -0
- package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +10 -0
- package/blueprints/edge-cloudflare-rate-limiting/README.md +73 -0
- package/blueprints/edge-cloudflare-rate-limiting/blueprint.json +174 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3701-edge-cloudflare-rate-limiting-throttle-contract.json +14 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3702-edge-cloudflare-rate-limiting-layering.json +14 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3703-edge-cloudflare-rate-limiting-manifest-shape.json +14 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3704-edge-cloudflare-rate-limiting-drift-audit-cadence.json +14 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/event-secrecy.mjs +104 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/manifest-presence.mjs +95 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/manifest-schema-validate.mjs +130 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/probe-utils.mjs +111 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/real-account-burst-and-429.mjs +104 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-event-secrecy.mjs +5 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-manifest-presence.mjs +5 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-manifest-schema-validate.mjs +5 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-real-account-burst-and-429.mjs +5 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-001.json +17 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-002.json +17 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-003.json +17 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-004.json +17 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-005.json +17 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/schemas/rate-limit-rule.schema.json +67 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json +31 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json +25 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json +26 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36101.json +27 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36102.json +27 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36103.json +27 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36104.json +27 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36105.json +27 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36106.json +27 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36107.json +27 -0
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36108.json +27 -0
- package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +68 -0
- package/blueprints/edge-cloudflare-rate-limiting/guide/edge-cloudflare-rate-limiting.md +88 -0
- package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +20 -0
- package/blueprints/edge-cloudflare-turnstile/README.md +95 -0
- package/blueprints/edge-cloudflare-turnstile/blueprint.json +161 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3601-edge-cloudflare-turnstile-verifier-contract.json +14 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3602-edge-cloudflare-turnstile-widget-mode.json +14 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3603-edge-cloudflare-turnstile-refuse-shape.json +14 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/probes/event-secrecy.mjs +51 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/probes/guard-shape-scan.mjs +48 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/probes/probe-utils.mjs +139 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-event-secrecy.mjs +5 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-guard-shape-scan.mjs +5 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-secret-shape-scan.mjs +5 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-siteverify-fixture.mjs +5 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/probes/secret-shape-scan.mjs +77 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/probes/siteverify-fixture.mjs +53 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-001.json +17 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-002.json +17 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-003.json +17 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-004.json +17 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-005.json +17 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json +26 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json +36 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json +25 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35101.json +27 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35102.json +27 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35103.json +27 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35104.json +27 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35105.json +36 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35106.json +27 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35107.json +27 -0
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35108.json +27 -0
- package/blueprints/edge-cloudflare-turnstile/docs/topics.md +68 -0
- package/blueprints/edge-cloudflare-turnstile/guide/edge-cloudflare-turnstile.md +104 -0
- package/blueprints/edge-cloudflare-turnstile/probe-packs/edge-cloudflare-turnstile.pack.mjs +146 -0
- package/blueprints/email-smtp-resend/docs/topics.md +9 -1
- package/blueprints/jobs-background/CHANGELOG.md +16 -0
- package/blueprints/jobs-background/README.md +105 -0
- package/blueprints/jobs-background/blueprint.json +149 -0
- package/blueprints/jobs-background/contributions/adrs/adr-3101-jobs-background-model.json +27 -0
- package/blueprints/jobs-background/contributions/adrs/adr-3102-jobs-background-scheduler-mode.json +25 -0
- package/blueprints/jobs-background/contributions/adrs/adr-3103-jobs-background-requires-applied-capabilities.json +25 -0
- package/blueprints/jobs-background/contributions/adrs/adr-3104-jobs-background-timeout-floor.json +25 -0
- package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +95 -0
- package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +82 -0
- package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +69 -0
- package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +65 -0
- package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +91 -0
- package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +65 -0
- package/blueprints/jobs-background/contributions/probes/run-apply-time-override.mjs +10 -0
- package/blueprints/jobs-background/contributions/probes/run-apply-time-refusal.mjs +11 -0
- package/blueprints/jobs-background/contributions/probes/run-event-secrecy.mjs +11 -0
- package/blueprints/jobs-background/contributions/probes/run-fake-clock-cron.mjs +11 -0
- package/blueprints/jobs-background/contributions/probes/run-retry-and-fail.mjs +11 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-001.json +18 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-002.json +18 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-003.json +18 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-004.json +18 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-005.json +18 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-006.json +18 -0
- package/blueprints/jobs-background/contributions/tacs/tac-3101-jobs-background-job-definition.json +50 -0
- package/blueprints/jobs-background/contributions/tacs/tac-3102-jobs-background-scheduler.json +50 -0
- package/blueprints/jobs-background/contributions/tacs/tac-3103-jobs-background-run-log.json +49 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30101.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30102.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30103.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30104.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30105.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30106.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30107.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30108.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30109.json +25 -0
- package/blueprints/jobs-background/docs/topics.md +68 -0
- package/blueprints/jobs-background/guide/jobs-background.md +147 -0
- package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +15 -0
- package/blueprints/messaging-queue-cloudflare/README.md +125 -0
- package/blueprints/messaging-queue-cloudflare/blueprint.json +67 -0
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +30 -0
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3003-messaging-queue-cloudflare-max-attempts-floor.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3004-messaging-queue-cloudflare-batch-defaults.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/event-secrecy.mjs +137 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/probe-utils.mjs +82 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/producer-facade-ready.mjs +35 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/publish-to-delivery.mjs +94 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +54 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/retry-and-dlq.mjs +87 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/run-event-secrecy.mjs +5 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/run-producer-facade-ready.mjs +11 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/run-publish-to-delivery.mjs +5 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/run-real-account-concurrency-smoke.mjs +5 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/run-retry-and-dlq.mjs +5 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-001.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-002.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-003.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-004.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-005.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3001-messaging-queue-cloudflare-producer-facade.json +56 -0
- package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3002-messaging-queue-cloudflare-consumer-registration.json +40 -0
- package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3003-messaging-queue-cloudflare-event-sink.json +39 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29101.json +34 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29102.json +34 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29103.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29104.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29105.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29106.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29107.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29108.json +25 -0
- package/blueprints/messaging-queue-cloudflare/docs/topics.md +68 -0
- package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +110 -0
- package/blueprints/object-storage-s3/docs/topics.md +9 -1
- package/blueprints/observability-essentials/docs/topics.md +9 -1
- package/blueprints/observability-logging/docs/topics.md +9 -1
- package/blueprints/observability-probe-endpoints/docs/topics.md +9 -1
- package/blueprints/persistence-data-d1/docs/topics.md +9 -1
- package/blueprints/persistence-data-postgres/docs/topics.md +9 -1
- package/blueprints/persistence-data-sqlite/docs/topics.md +9 -1
- package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +22 -0
- package/blueprints/platform-cloudflare-cron-triggers/README.md +117 -0
- package/blueprints/platform-cloudflare-cron-triggers/blueprint.json +85 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3301-platform-cloudflare-cron-triggers-scheduled-trigger-contract.json +14 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3302-platform-cloudflare-cron-triggers-dispatcher-mode.json +14 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3303-platform-cloudflare-cron-triggers-skew-tolerance-default.json +14 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/dispatcher-routing.mjs +64 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/event-secrecy.mjs +100 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/probe-utils.mjs +70 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/real-account-scheduled-smoke.mjs +100 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-dispatcher-routing.mjs +5 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-event-secrecy.mjs +5 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-real-account-scheduled-smoke.mjs +5 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-skew-tolerance.mjs +5 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-wrangler-test-scheduled.mjs +5 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/skew-tolerance.mjs +130 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/wrangler-test-scheduled.mjs +129 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-001.json +17 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-002.json +17 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-003.json +17 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-004.json +17 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3301-platform-cloudflare-cron-triggers-scheduled-handler.json +22 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3302-platform-cloudflare-cron-triggers-expression-router.json +22 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3303-platform-cloudflare-cron-triggers-event-sink.json +21 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32101.json +25 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32102.json +34 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32103.json +34 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32104.json +34 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32105.json +25 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32106.json +25 -0
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32107.json +25 -0
- package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +71 -0
- package/blueprints/platform-cloudflare-cron-triggers/guide/platform-cloudflare-cron-triggers.md +119 -0
- package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +23 -0
- package/blueprints/platform-cloudflare-durable-objects/README.md +200 -0
- package/blueprints/platform-cloudflare-durable-objects/blueprint.json +243 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3401-platform-cloudflare-durable-objects-single-cell-contract.json +14 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3402-platform-cloudflare-durable-objects-websocket-hub-contract.json +14 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3403-platform-cloudflare-durable-objects-storage-backend.json +14 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3404-platform-cloudflare-durable-objects-migrations-shape.json +14 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3405-platform-cloudflare-durable-objects-hibernation-posture.json +14 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/alarm-fires-once.mjs +63 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/namespace-facade-ready.mjs +60 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/probe-utils.mjs +105 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/real-account-storage-smoke.mjs +58 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-alarm-fires-once.mjs +5 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-namespace-facade-ready.mjs +5 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-real-account-storage-smoke.mjs +5 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-single-cell-concurrent-increment.mjs +5 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-sole-reader-scan.mjs +5 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-storage-round-trip.mjs +5 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-websocket-hub-broadcast.mjs +5 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-wrangler-seam.mjs +5 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/single-cell-concurrent-increment.mjs +56 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/sole-reader-scan.mjs +117 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/storage-round-trip.mjs +87 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/websocket-hub-broadcast.mjs +112 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/probes/wrangler-seam.mjs +257 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-001.json +17 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-002.json +17 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-003.json +17 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-004.json +17 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-005.json +17 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-006.json +17 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-007.json +17 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-008.json +17 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3401-platform-cloudflare-durable-objects-namespace-facade.json +31 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3402-platform-cloudflare-durable-objects-single-cell-shape.json +30 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3403-platform-cloudflare-durable-objects-alarm-handler.json +29 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3404-platform-cloudflare-durable-objects-websocket-hub.json +31 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3405-platform-cloudflare-durable-objects-event-sink.json +24 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33101.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33102.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33103.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33104.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33105.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33106.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33107.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33108.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33109.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33110.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33111.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33112.json +27 -0
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33113.json +25 -0
- package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +73 -0
- package/blueprints/platform-cloudflare-durable-objects/guide/platform-cloudflare-durable-objects.md +237 -0
- package/blueprints/platform-cloudflare-kv/CHANGELOG.md +21 -0
- package/blueprints/platform-cloudflare-kv/README.md +159 -0
- package/blueprints/platform-cloudflare-kv/blueprint.json +87 -0
- package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3201-platform-cloudflare-kv-key-value-store-contract.json +14 -0
- package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3202-platform-cloudflare-kv-default-cache-ttl.json +14 -0
- package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3203-platform-cloudflare-kv-key-naming-convention.json +14 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/cache-aside-hit-then-miss.mjs +82 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/event-secrecy.mjs +102 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/facade-round-trip.mjs +92 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/list-with-prefix.mjs +52 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/probe-utils.mjs +73 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/real-account-eventual-consistency-smoke.mjs +102 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/run-cache-aside-hit-then-miss.mjs +5 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/run-event-secrecy.mjs +5 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/run-facade-round-trip.mjs +5 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/run-list-with-prefix.mjs +5 -0
- package/blueprints/platform-cloudflare-kv/contributions/probes/run-real-account-eventual-consistency-smoke.mjs +5 -0
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-001.json +18 -0
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-002.json +18 -0
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-003.json +18 -0
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-004.json +18 -0
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-005.json +18 -0
- package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3201-platform-cloudflare-kv-facade.json +27 -0
- package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3202-platform-cloudflare-kv-cache-aside.json +26 -0
- package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3203-platform-cloudflare-kv-event-sink.json +25 -0
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31101.json +27 -0
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31102.json +27 -0
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31103.json +36 -0
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31104.json +27 -0
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31105.json +27 -0
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31106.json +27 -0
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31107.json +27 -0
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31108.json +27 -0
- package/blueprints/platform-cloudflare-kv/docs/topics.md +71 -0
- package/blueprints/platform-cloudflare-kv/guide/platform-cloudflare-kv.md +138 -0
- package/blueprints/security-auth-clerk/docs/topics.md +9 -1
- package/blueprints/security-auth-keycloak/docs/topics.md +9 -1
- package/blueprints/security-auth-magic-link/docs/topics.md +9 -1
- package/blueprints/security-auth-oauth2/docs/topics.md +9 -1
- package/blueprints/security-secrets-management/docs/topics.md +9 -1
- package/fixtures/canary-manifest.json +6 -6
- package/package.json +1 -1
- package/rcf/adrs/adr-2214-application-admin-console-consume-zero-trust-gate.json +13 -0
- package/rcf/adrs/adr-3501-edge-cloudflare-access-jwt-gate.json +13 -0
- package/rcf/adrs/adr-3502-edge-cloudflare-access-identity-provider.json +13 -0
- package/rcf/adrs/adr-3503-edge-cloudflare-access-policy-scope.json +13 -0
- package/rcf/adrs/adr-3504-edge-cloudflare-access-audit-retention.json +13 -0
- package/rcf/adrs/adr-3601-edge-cloudflare-turnstile-verifier-contract.json +13 -0
- package/rcf/adrs/adr-3602-edge-cloudflare-turnstile-widget-mode.json +13 -0
- package/rcf/adrs/adr-3603-edge-cloudflare-turnstile-refuse-shape.json +13 -0
- package/rcf/adrs/adr-3701-edge-cloudflare-rate-limiting-throttle-contract.json +13 -0
- package/rcf/adrs/adr-3702-edge-cloudflare-rate-limiting-layering.json +13 -0
- package/rcf/adrs/adr-3703-edge-cloudflare-rate-limiting-manifest-shape.json +13 -0
- package/rcf/adrs/adr-3704-edge-cloudflare-rate-limiting-drift-audit-cadence.json +13 -0
- package/rcf/code-nodes/cn-206.json +14 -0
- package/rcf/code-nodes/cn-207.json +13 -0
- package/rcf/code-nodes/cn-208.json +14 -0
- package/rcf/code-nodes/cn-209.json +14 -0
- package/rcf/code-nodes/cn-210.json +13 -0
- package/rcf/code-nodes/cn-211.json +12 -0
- package/rcf/code-nodes/cn-212.json +12 -0
- package/rcf/code-nodes/cn-213.json +12 -0
- package/rcf/code-nodes/cn-214.json +15 -0
- package/rcf/code-nodes/cn-215.json +13 -0
- package/rcf/code-nodes/cn-216.json +14 -0
- package/rcf/code-nodes/cn-217.json +13 -0
- package/rcf/code-nodes/cn-230.json +13 -0
- package/rcf/code-nodes/cn-231.json +14 -0
- package/rcf/code-nodes/cn-232.json +13 -0
- package/rcf/code-nodes/cn-233.json +14 -0
- package/rcf/code-nodes/cn-234.json +13 -0
- package/rcf/code-nodes/cn-260.json +21 -0
- package/rcf/code-nodes/cn-261.json +14 -0
- package/rcf/code-nodes/cn-262.json +18 -0
- package/rcf/code-nodes/cn-263.json +12 -0
- package/rcf/code-nodes/cn-264.json +13 -0
- package/rcf/code-nodes/cn-265.json +15 -0
- package/rcf/code-nodes/cn-266.json +12 -0
- package/rcf/code-nodes/cn-267.json +12 -0
- package/rcf/code-nodes/cn-290.json +21 -0
- package/rcf/code-nodes/cn-291.json +12 -0
- package/rcf/code-nodes/cn-292.json +13 -0
- package/rcf/code-nodes/cn-293.json +13 -0
- package/rcf/code-nodes/cn-294.json +13 -0
- package/rcf/code-nodes/cn-295.json +12 -0
- package/rcf/code-nodes/cn-296.json +12 -0
- package/rcf/code-nodes/cn-297.json +12 -0
- package/rcf/code-nodes/cn-298.json +12 -0
- package/rcf/code-nodes/cn-299.json +12 -0
- package/rcf/code-nodes/cn-300.json +12 -0
- package/rcf/code-nodes/cn-301.json +14 -0
- package/rcf/code-nodes/cn-302.json +12 -0
- package/rcf/code-nodes/cn-303.json +12 -0
- package/rcf/code-nodes/cn-304.json +21 -0
- package/rcf/code-nodes/cn-320.json +20 -0
- package/rcf/code-nodes/cn-321.json +14 -0
- package/rcf/code-nodes/cn-350.json +19 -0
- package/rcf/code-nodes/cn-380.json +19 -0
- package/rcf/fbs/fbs-062.json +20 -0
- package/rcf/fbs/fbs-063.json +22 -0
- package/rcf/fbs/fbs-064.json +23 -0
- package/rcf/fbs/fbs-070.json +24 -0
- package/rcf/fbs/fbs-080.json +24 -0
- package/rcf/fbs/fbs-090.json +24 -0
- package/rcf/fbs/fbs-100.json +23 -0
- package/rcf/fbs/fbs-101.json +16 -0
- package/rcf/fbs/fbs-110.json +23 -0
- package/rcf/fbs/fbs-120.json +22 -0
- package/rcf/requirements/req-029.json +57 -0
- package/rcf/requirements/req-030.json +67 -0
- package/rcf/requirements/req-042.json +59 -0
- package/rcf/requirements/req-043.json +39 -0
- package/rcf/requirements/req-050.json +18 -0
- package/rcf/requirements/req-051.json +18 -0
- package/rcf/requirements/req-052.json +18 -0
- package/rcf/requirements/req-053.json +18 -0
- package/rcf/requirements/req-054.json +18 -0
- package/rcf/requirements/req-060.json +20 -0
- package/rcf/requirements/req-061.json +18 -0
- package/rcf/requirements/req-062.json +20 -0
- package/rcf/requirements/req-063.json +20 -0
- package/rcf/requirements/req-070.json +18 -0
- package/rcf/requirements/req-071.json +18 -0
- package/rcf/requirements/req-072.json +18 -0
- package/rcf/requirements/req-073.json +18 -0
- package/rcf/requirements/req-074.json +18 -0
- package/rcf/requirements/req-075.json +18 -0
- package/rcf/requirements/req-076.json +18 -0
- package/rcf/requirements/req-077.json +18 -0
- package/rcf/requirements/req-080.json +18 -0
- package/rcf/requirements/req-081.json +18 -0
- package/rcf/requirements/req-082.json +18 -0
- package/rcf/requirements/req-083.json +18 -0
- package/rcf/requirements/req-084.json +18 -0
- package/rcf/requirements/req-085.json +18 -0
- package/rcf/requirements/req-086.json +18 -0
- package/rcf/requirements/req-090.json +44 -0
- package/rcf/requirements/req-091.json +53 -0
- package/rcf/requirements/req-092.json +32 -0
- package/rcf/requirements/req-093.json +52 -0
- package/rcf/requirements/req-094.json +32 -0
- package/rcf/requirements/req-100.json +13 -0
- package/rcf/requirements/req-101.json +13 -0
- package/rcf/requirements/req-102.json +13 -0
- package/rcf/requirements/req-103.json +13 -0
- package/rcf/requirements/req-104.json +13 -0
- package/rcf/tacs/tac-2214-application-admin-console-access-gated-signin-surface.json +15 -0
- package/rcf/tacs/tac-3501-edge-cloudflare-access-jwt-validator.json +15 -0
- package/rcf/tacs/tac-3502-edge-cloudflare-access-application-declaration.json +15 -0
- package/rcf/tacs/tac-3503-edge-cloudflare-access-policy-shape.json +15 -0
- package/rcf/tacs/tac-3504-edge-cloudflare-access-audit-sink.json +15 -0
- package/rcf/tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json +15 -0
- package/rcf/tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json +15 -0
- package/rcf/tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json +15 -0
- package/rcf/tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json +16 -0
- package/rcf/tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json +15 -0
- package/rcf/tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json +16 -0
- package/rcf/test-suites/ts-052.json +58 -8
- package/rcf/test-suites/ts-072.json +62 -0
- package/rcf/test-suites/ts-073.json +38 -0
- package/rcf/test-suites/ts-074.json +30 -0
- package/rcf/test-suites/ts-075.json +38 -0
- package/rcf/test-suites/ts-076.json +70 -0
- package/rcf/test-suites/ts-080.json +22 -0
- package/rcf/test-suites/ts-081.json +22 -0
- package/rcf/test-suites/ts-082.json +30 -0
- package/rcf/test-suites/ts-083.json +22 -0
- package/rcf/test-suites/ts-084.json +30 -0
- package/rcf/test-suites/ts-085.json +22 -0
- package/rcf/test-suites/ts-086.json +22 -0
- package/rcf/test-suites/ts-087.json +22 -0
- package/rcf/test-suites/ts-090.json +22 -0
- package/rcf/test-suites/ts-091.json +22 -0
- package/rcf/test-suites/ts-092.json +22 -0
- package/rcf/test-suites/ts-093.json +30 -0
- package/rcf/test-suites/ts-094.json +30 -0
- package/rcf/test-suites/ts-095.json +30 -0
- package/rcf/test-suites/ts-096.json +22 -0
- package/rcf/test-suites/ts-100.json +22 -0
- package/rcf/test-suites/ts-101.json +22 -0
- package/rcf/test-suites/ts-102.json +22 -0
- package/rcf/test-suites/ts-103.json +22 -0
- package/rcf/test-suites/ts-104.json +22 -0
- package/rcf/test-suites/ts-105.json +22 -0
- package/rcf/test-suites/ts-106.json +22 -0
- package/rcf/test-suites/ts-107.json +22 -0
- package/rcf/test-suites/ts-108.json +22 -0
- package/rcf/test-suites/ts-109.json +22 -0
- package/rcf/test-suites/ts-110.json +22 -0
- package/rcf/test-suites/ts-111.json +22 -0
- package/rcf/test-suites/ts-112.json +22 -0
- package/rcf/test-suites/ts-113.json +22 -0
- package/rcf/test-suites/ts-114.json +22 -0
- package/rcf/test-suites/ts-115.json +22 -0
- package/rcf/test-suites/ts-116.json +22 -0
- package/rcf/test-suites/ts-117.json +22 -0
- package/rcf/test-suites/ts-118.json +22 -0
- package/rcf/test-suites/ts-119.json +30 -0
- package/rcf/test-suites/ts-120.json +22 -0
- package/rcf/test-suites/ts-121.json +22 -0
- package/rcf/test-suites/ts-122.json +22 -0
- package/rcf/test-suites/ts-123.json +22 -0
- package/rcf/test-suites/ts-124.json +22 -0
- package/rcf/test-suites/ts-125.json +22 -0
- package/rcf/test-suites/ts-126.json +22 -0
- package/rcf/test-suites/ts-127.json +22 -0
- package/rcf/test-suites/ts-130.json +22 -0
- package/rcf/test-suites/ts-131.json +22 -0
- package/rcf/test-suites/ts-132.json +22 -0
- package/rcf/test-suites/ts-133.json +22 -0
- package/rcf/test-suites/ts-134.json +22 -0
- package/rcf/test-suites/ts-135.json +22 -0
- package/rcf/test-suites/ts-136.json +22 -0
- package/rcf/test-suites/ts-137.json +22 -0
- package/rcf/user-stories/us-10001.json +23 -0
- package/rcf/user-stories/us-10101.json +23 -0
- package/rcf/user-stories/us-10201.json +23 -0
- package/rcf/user-stories/us-10301.json +23 -0
- package/rcf/user-stories/us-10401.json +23 -0
- package/rcf/user-stories/us-10601.json +23 -0
- package/rcf/user-stories/us-10701.json +23 -0
- package/rcf/user-stories/us-10801.json +23 -0
- package/rcf/user-stories/us-2901.json +45 -0
- package/rcf/user-stories/us-2902.json +36 -0
- package/rcf/user-stories/us-3001.json +45 -0
- package/rcf/user-stories/us-4201.json +69 -0
- package/rcf/user-stories/us-4301.json +78 -0
- package/rcf/user-stories/us-5001.json +27 -0
- package/rcf/user-stories/us-5002.json +27 -0
- package/rcf/user-stories/us-5101.json +36 -0
- package/rcf/user-stories/us-5102.json +27 -0
- package/rcf/user-stories/us-5201.json +36 -0
- package/rcf/user-stories/us-5301.json +27 -0
- package/rcf/user-stories/us-5302.json +27 -0
- package/rcf/user-stories/us-5401.json +27 -0
- package/rcf/user-stories/us-6001.json +27 -0
- package/rcf/user-stories/us-6002.json +27 -0
- package/rcf/user-stories/us-6003.json +27 -0
- package/rcf/user-stories/us-6101.json +36 -0
- package/rcf/user-stories/us-6201.json +36 -0
- package/rcf/user-stories/us-6301.json +36 -0
- package/rcf/user-stories/us-6302.json +27 -0
- package/rcf/user-stories/us-7001.json +27 -0
- package/rcf/user-stories/us-7002.json +27 -0
- package/rcf/user-stories/us-7101.json +27 -0
- package/rcf/user-stories/us-7201.json +27 -0
- package/rcf/user-stories/us-7301.json +27 -0
- package/rcf/user-stories/us-7401.json +27 -0
- package/rcf/user-stories/us-7402.json +27 -0
- package/rcf/user-stories/us-7501.json +27 -0
- package/rcf/user-stories/us-7601.json +27 -0
- package/rcf/user-stories/us-7701.json +27 -0
- package/rcf/user-stories/us-8001.json +24 -0
- package/rcf/user-stories/us-8002.json +24 -0
- package/rcf/user-stories/us-8003.json +24 -0
- package/rcf/user-stories/us-8101.json +24 -0
- package/rcf/user-stories/us-8201.json +24 -0
- package/rcf/user-stories/us-8301.json +24 -0
- package/rcf/user-stories/us-8401.json +24 -0
- package/rcf/user-stories/us-8501.json +24 -0
- package/rcf/user-stories/us-8502.json +24 -0
- package/rcf/user-stories/us-8601.json +24 -0
- package/rcf/user-stories/us-8602.json +24 -0
- package/rcf/user-stories/us-9001.json +27 -0
- package/rcf/user-stories/us-9002.json +27 -0
- package/rcf/user-stories/us-9101.json +27 -0
- package/rcf/user-stories/us-9102.json +27 -0
- package/rcf/user-stories/us-9201.json +27 -0
- package/rcf/user-stories/us-9301.json +27 -0
- package/rcf/user-stories/us-9302.json +27 -0
- package/rcf/user-stories/us-9401.json +27 -0
- package/releases/releases.yaml +21 -1
- package/src/blueprint/apply.js +7 -4
- package/src/blueprint/capabilities.js +25 -0
- package/src/cli/blueprint.js +8 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Shared helpers for edge-cloudflare-rate-limiting probes.
|
|
2
|
+
//
|
|
3
|
+
// Runtime-dependency posture: three probes read the cf-edge fixture
|
|
4
|
+
// manifest directory in-process (no network); one probe fires an
|
|
5
|
+
// undici burst against a scheduled real-account URL when
|
|
6
|
+
// CI_HAS_CLOUDFLARE_ACCOUNT and CF_RATE_LIMIT_URL are set, and
|
|
7
|
+
// records accountBoundSkipped: true otherwise per spec section 3.5
|
|
8
|
+
// and ruling 6. The drift-audit runner realisation lives in the
|
|
9
|
+
// fixture at src/drift-audit-runner.mjs.
|
|
10
|
+
|
|
11
|
+
import { mkdir, writeFile, readFile, readdir, rename, stat } from 'node:fs/promises';
|
|
12
|
+
import { dirname, resolve, join, basename } from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
|
|
15
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
|
|
17
|
+
export const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
|
|
18
|
+
export const FIXTURE_DIR = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/cf-edge');
|
|
19
|
+
export const MANIFEST_DIR = resolve(FIXTURE_DIR, 'cloudflare/rate-limits');
|
|
20
|
+
export const SCHEMA_PATH = resolve(HERE, '..', 'schemas', 'rate-limit-rule.schema.json');
|
|
21
|
+
export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/edge-cloudflare-rate-limiting');
|
|
22
|
+
|
|
23
|
+
export const REQUIRED_FIELDS = Object.freeze([
|
|
24
|
+
'id',
|
|
25
|
+
'expression',
|
|
26
|
+
'threshold',
|
|
27
|
+
'period',
|
|
28
|
+
'characteristics',
|
|
29
|
+
'action',
|
|
30
|
+
'duration',
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
export const ACTION_ENUM = Object.freeze(['block', 'challenge', 'log', 'managed_challenge']);
|
|
34
|
+
|
|
35
|
+
export function aggregate(results) {
|
|
36
|
+
if (results.some((r) => r.verdict === 'fail')) return 'fail';
|
|
37
|
+
if (results.some((r) => r.verdict === 'warn')) return 'warn';
|
|
38
|
+
return 'pass';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function writeReport({ probeName, engine, results, extra }) {
|
|
42
|
+
await mkdir(REPORT_DIR, { recursive: true });
|
|
43
|
+
const report = {
|
|
44
|
+
slug: 'edge-cloudflare-rate-limiting',
|
|
45
|
+
probeName,
|
|
46
|
+
runAt: new Date().toISOString(),
|
|
47
|
+
engine,
|
|
48
|
+
results,
|
|
49
|
+
aggregateVerdict: aggregate(results),
|
|
50
|
+
...(extra ?? {}),
|
|
51
|
+
};
|
|
52
|
+
const path = resolve(REPORT_DIR, `${probeName}.json`);
|
|
53
|
+
await writeFile(path, JSON.stringify(report, null, 2) + '\n', 'utf8');
|
|
54
|
+
return { report, path };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function runShim(probeName, engine, mainFn) {
|
|
58
|
+
try {
|
|
59
|
+
const { results, extra } = await mainFn();
|
|
60
|
+
const { report, path } = await writeReport({ probeName, engine, results, extra });
|
|
61
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
62
|
+
process.stdout.write(`report written to ${path}\n`);
|
|
63
|
+
if (report.aggregateVerdict === 'fail') process.exitCode = 1;
|
|
64
|
+
} catch (err) {
|
|
65
|
+
const results = [{
|
|
66
|
+
anchorAcId: 'unknown',
|
|
67
|
+
verdict: 'fail',
|
|
68
|
+
detail: `probe threw: ${err && err.message ? err.message : String(err)}`,
|
|
69
|
+
}];
|
|
70
|
+
const { report, path } = await writeReport({ probeName, engine, results });
|
|
71
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
72
|
+
process.stderr.write(`probe error: ${err && err.stack ? err.stack : String(err)}\n`);
|
|
73
|
+
process.stderr.write(`report written to ${path}\n`);
|
|
74
|
+
process.exitCode = 1;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function readManifestFiles(dir = MANIFEST_DIR) {
|
|
79
|
+
const missing = process.env.SIMULATE_MANIFEST_MISSING === 'true';
|
|
80
|
+
let entries;
|
|
81
|
+
try {
|
|
82
|
+
entries = (await readdir(dir)).filter((f) => f.endsWith('.json')).sort();
|
|
83
|
+
} catch (err) {
|
|
84
|
+
return { present: false, missing: [], entries: [], error: err.message };
|
|
85
|
+
}
|
|
86
|
+
const hidden = new Set();
|
|
87
|
+
if (missing && entries.length > 0) {
|
|
88
|
+
hidden.add(entries[0]);
|
|
89
|
+
}
|
|
90
|
+
const files = [];
|
|
91
|
+
for (const name of entries) {
|
|
92
|
+
if (hidden.has(name)) continue;
|
|
93
|
+
const p = join(dir, name);
|
|
94
|
+
const text = await readFile(p, 'utf8');
|
|
95
|
+
files.push({ name, path: p, text });
|
|
96
|
+
}
|
|
97
|
+
return { present: entries.length > 0, entries, files, hiddenBySimulate: [...hidden] };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function scanForPlaintextSecrets(text) {
|
|
101
|
+
const hits = [];
|
|
102
|
+
if (/[Bb]earer\s+[A-Za-z0-9._-]{20,}/.test(text)) hits.push('bearer-token-like');
|
|
103
|
+
if (/-----BEGIN [A-Z ]*PRIVATE KEY-----/.test(text)) hits.push('pem-private-key');
|
|
104
|
+
if (/"?CF_API_TOKEN"?\s*:\s*"[^"]{5,}"/.test(text)) hits.push('inline-cf-api-token');
|
|
105
|
+
return hits;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function loadSchema() {
|
|
109
|
+
const raw = await readFile(SCHEMA_PATH, 'utf8');
|
|
110
|
+
return JSON.parse(raw);
|
|
111
|
+
}
|
package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/real-account-burst-and-429.mjs
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Probe: real-account burst-and-429 against a scheduled URL.
|
|
2
|
+
//
|
|
3
|
+
// anchorAcId: AC-36103-1. accountBound: true.
|
|
4
|
+
//
|
|
5
|
+
// When CI_HAS_CLOUDFLARE_ACCOUNT=true AND CF_RATE_LIMIT_URL is set,
|
|
6
|
+
// the probe fires an in-process burst against the scheduled URL and
|
|
7
|
+
// asserts:
|
|
8
|
+
// - the (N+1)th and subsequent requests within the elicited
|
|
9
|
+
// duration return HTTP 429.
|
|
10
|
+
// - the 429 responses carry a Retry-After header consistent with
|
|
11
|
+
// the elicited duration.
|
|
12
|
+
// - the 429 responses carry a Cf-Ray header naming the CF edge.
|
|
13
|
+
//
|
|
14
|
+
// Without either env var the probe records accountBoundSkipped: true
|
|
15
|
+
// and aggregates to pass per spec section 3.5 and ruling 6.
|
|
16
|
+
// N (the elicited threshold) is read from CF_RATE_LIMIT_THRESHOLD
|
|
17
|
+
// (default 60); the burst count is N+3.
|
|
18
|
+
|
|
19
|
+
export const anchorAcId = 'AC-36103-1';
|
|
20
|
+
export const accountBound = true;
|
|
21
|
+
|
|
22
|
+
const BURST_TIMEOUT_MS = 10000;
|
|
23
|
+
|
|
24
|
+
async function fireOne(url) {
|
|
25
|
+
const ctrl = new AbortController();
|
|
26
|
+
const to = setTimeout(() => ctrl.abort(), BURST_TIMEOUT_MS);
|
|
27
|
+
try {
|
|
28
|
+
const res = await fetch(url, { method: 'GET', redirect: 'manual', signal: ctrl.signal });
|
|
29
|
+
return { status: res.status, retryAfter: res.headers.get('retry-after'), cfRay: res.headers.get('cf-ray') };
|
|
30
|
+
} finally {
|
|
31
|
+
clearTimeout(to);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default async function runProbe() {
|
|
36
|
+
const has = process.env.CI_HAS_CLOUDFLARE_ACCOUNT === 'true';
|
|
37
|
+
const url = process.env.CF_RATE_LIMIT_URL || '';
|
|
38
|
+
if (!has || !url) {
|
|
39
|
+
return {
|
|
40
|
+
results: [{
|
|
41
|
+
anchorAcId: 'AC-36103-1',
|
|
42
|
+
verdict: 'pass',
|
|
43
|
+
accountBoundSkipped: true,
|
|
44
|
+
detail: `accountBoundSkipped: CI_HAS_CLOUDFLARE_ACCOUNT=${has} CF_RATE_LIMIT_URL=${url ? 'set' : 'unset'}; per spec section 3.5 and ruling 6 pass-with-skip.`,
|
|
45
|
+
}],
|
|
46
|
+
extra: { accountBoundSkipped: true },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const threshold = Number.parseInt(process.env.CF_RATE_LIMIT_THRESHOLD || '60', 10);
|
|
50
|
+
const burstCount = threshold + 3;
|
|
51
|
+
const results429 = [];
|
|
52
|
+
const responses = [];
|
|
53
|
+
try {
|
|
54
|
+
for (let i = 0; i < burstCount; i += 1) {
|
|
55
|
+
const r = await fireOne(url);
|
|
56
|
+
responses.push(r);
|
|
57
|
+
if (r.status === 429) results429.push(r);
|
|
58
|
+
}
|
|
59
|
+
} catch (err) {
|
|
60
|
+
return {
|
|
61
|
+
results: [{
|
|
62
|
+
anchorAcId: 'AC-36103-1',
|
|
63
|
+
verdict: 'fail',
|
|
64
|
+
detail: `real-account burst threw before completion: ${err && err.message ? err.message : String(err)}`,
|
|
65
|
+
}],
|
|
66
|
+
extra: { accountBound: true, responsesFired: responses.length },
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const results = [];
|
|
70
|
+
if (results429.length < 2) {
|
|
71
|
+
results.push({
|
|
72
|
+
anchorAcId: 'AC-36103-1',
|
|
73
|
+
verdict: 'fail',
|
|
74
|
+
detail: `burst of ${burstCount} produced ${results429.length} 429 response(s); expected at least the ${burstCount - threshold} requests above the elicited threshold to return 429.`,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const missingRetryAfter = results429.filter((r) => !r.retryAfter);
|
|
78
|
+
if (missingRetryAfter.length > 0) {
|
|
79
|
+
results.push({
|
|
80
|
+
anchorAcId: 'AC-36103-1',
|
|
81
|
+
verdict: 'fail',
|
|
82
|
+
detail: `${missingRetryAfter.length} of the 429 response(s) missing a Retry-After header; the Cloudflare WAF rate-limiting rules documented shape names Retry-After as the value the client honours.`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const missingCfRay = results429.filter((r) => !r.cfRay);
|
|
86
|
+
if (missingCfRay.length > 0) {
|
|
87
|
+
results.push({
|
|
88
|
+
anchorAcId: 'AC-36103-1',
|
|
89
|
+
verdict: 'fail',
|
|
90
|
+
detail: `${missingCfRay.length} of the 429 response(s) missing a Cf-Ray header; the header identifies the CF edge that served the refusal.`,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (results.length === 0) {
|
|
94
|
+
results.push({
|
|
95
|
+
anchorAcId: 'AC-36103-1',
|
|
96
|
+
verdict: 'pass',
|
|
97
|
+
detail: `burst of ${burstCount} produced ${results429.length} 429 response(s), every 429 carries Retry-After and Cf-Ray; over-threshold behaviour confirmed against the scheduled URL.`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
results,
|
|
102
|
+
extra: { accountBound: true, responsesFired: responses.length, count429: results429.length, threshold },
|
|
103
|
+
};
|
|
104
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import runProbe from './event-secrecy.mjs';
|
|
2
|
+
import { runShim } from './probe-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const engine = { kind: 'event-sink-accumulation', image: 'cf-edge fixture drift-audit runner driven with synthetic manifest and fake fetch (in-process)', healthy: true };
|
|
5
|
+
runShim('event-secrecy', engine, runProbe);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import runProbe from './manifest-schema-validate.mjs';
|
|
2
|
+
import { runShim } from './probe-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const engine = { kind: 'source-scan', image: 'cf-edge fixture manifest directory validated against draft-07 JSON Schema (in-process)', healthy: true };
|
|
5
|
+
runShim('manifest-schema-validate', engine, runProbe);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import runProbe from './real-account-burst-and-429.mjs';
|
|
2
|
+
import { runShim } from './probe-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const engine = { kind: 'real-account', image: 'undici burst against scheduled Cloudflare-fronted URL', healthy: true };
|
|
5
|
+
runShim('real-account-burst-and-429', engine, runProbe);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "edge-cloudflare-rate-limiting-REQ-001",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "The rate-limit rule set is committed to the applying project as a local manifest under cloudflare/rate-limits/, one JSON file per rule",
|
|
5
|
+
"description": "The applying project holds its rate-limit rule set as a set of JSON documents under the elicited rate-limit-rules-dir (default cloudflare/rate-limits/), one file per rule per ADR-3703. Every manifest file declares the seven documented fields the Cloudflare WAF rate-limiting rules contract names per https://developers.cloudflare.com/waf/rate-limiting-rules/: id (a stable operator-facing string), expression (the WAF rules-language expression string), threshold (positive integer), period (seconds), characteristics (non-empty array of stable characteristic strings), action (block or challenge or log or managed_challenge), duration (seconds, the length of the block window). No rule references a secret in plaintext; the zone id is elicited and stored via the applied secretsManagement companion. The manifest is the source of truth an operator applies via the wrangler or dashboard flow named in the guide; no committed script writes the rules to the live zone.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "edge",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "Ratified in the Cloudflare round 6 spec (cloudflare-round-6-spec-2026-09-06.md section 5.6). Ships as v1.0.0 of edge-cloudflare-rate-limiting.",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:edge-cloudflare-rate-limiting"
|
|
12
|
+
],
|
|
13
|
+
"version": "1.0.0",
|
|
14
|
+
"status": "approved",
|
|
15
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
16
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "edge-cloudflare-rate-limiting-REQ-002",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "The operator-facing management surface is a documented wrangler or Cloudflare-dashboard flow that applies the local manifest to the live zone",
|
|
5
|
+
"description": "The blueprint ships no committed script that writes rules to the live Cloudflare zone. The applying project's operator applies the manifest to the elicited zone through one of two documented flows per TAC-3702 and the guide: a wrangler-based flow (the guide names the exact wrangler subcommands the operator runs; commits an audit trail through the wrangler history) or a Cloudflare-dashboard flow (the guide walks the dashboard screens the operator clicks per https://developers.cloudflare.com/waf/rate-limiting-rules/). The elicited rate-limit-management-surface value records the flow the operator chose; the guide's copy-paste walkthrough covers both. The intent is a management surface an operator can hand-run at a known cadence and reproduce from the manifest without inventing a bespoke deploy tool.",
|
|
6
|
+
"category": "operational",
|
|
7
|
+
"domain": "edge",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "Ratified in the Cloudflare round 6 spec (cloudflare-round-6-spec-2026-09-06.md section 5.6). Ships as v1.0.0 of edge-cloudflare-rate-limiting.",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:edge-cloudflare-rate-limiting"
|
|
12
|
+
],
|
|
13
|
+
"version": "1.0.0",
|
|
14
|
+
"status": "approved",
|
|
15
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
16
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "edge-cloudflare-rate-limiting-REQ-003",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Over-threshold behaviour: the (N+1)th and subsequent requests within the elicited duration return 429 with Retry-After and Cf-Ray, and the origin never sees them",
|
|
5
|
+
"description": "Given a rule that permits N requests per period on a characteristic set, when a client sends the (N+1)th request within that period, Cloudflare's zone-level rate limiter refuses the request at the edge for the elicited duration. The refusal response is HTTP 429 with a Retry-After header naming a value consistent with the elicited duration and a Cf-Ray header identifying the CF edge that served the refusal per the Cloudflare WAF rate-limiting rules documented shape at https://developers.cloudflare.com/waf/rate-limiting-rules/. The origin Worker never sees the refused requests. This is the runtime observable AC-rateLimiting-overThresholdBlocks binds; the runtime verification is the real-account burst probe per REQ-004's account-bound category, and per ruling 6 the local CI records accountBound: skipped without CI_HAS_CLOUDFLARE_ACCOUNT.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "edge",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "Ratified in the Cloudflare round 6 spec (cloudflare-round-6-spec-2026-09-06.md section 5.6). Ships as v1.0.0 of edge-cloudflare-rate-limiting.",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:edge-cloudflare-rate-limiting"
|
|
12
|
+
],
|
|
13
|
+
"version": "1.0.0",
|
|
14
|
+
"status": "approved",
|
|
15
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
16
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "edge-cloudflare-rate-limiting-REQ-004",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Drift audit: an opt-in scheduled runner reads live zone rules via the Cloudflare API and diffs against the local manifest, reporting mismatches metadata-only",
|
|
5
|
+
"description": "The blueprint ships a scheduled drift-audit runner (TAC-3703) the applying project can wire behind the elicited rate-limit-drift-audit-cadence per ADR-3704. When enabled (daily or hourly), the runner fetches the live rate-limiting rules on the elicited zone via the Cloudflare API, diffs the returned rule set against the local manifest field-by-field, and constructs one drift-audit record per mismatched rule. Each record is written through the applied logger's audit sink with the metadata-only shape {ruleId, clientIpHash, outcome, timestamp} plus the diff fields; a record never carries a full client IP, a request body or a user agent per REQ-005's event-secrecy discipline. The runner's report artefact writes to the standard blueprint-report location under .rcf/reports/blueprints/edge-cloudflare-rate-limiting/. When the elicited cadence is off, the runner is not wired.",
|
|
6
|
+
"category": "operational",
|
|
7
|
+
"domain": "edge",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "Ratified in the Cloudflare round 6 spec (cloudflare-round-6-spec-2026-09-06.md section 5.6). Ships as v1.0.0 of edge-cloudflare-rate-limiting.",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:edge-cloudflare-rate-limiting"
|
|
12
|
+
],
|
|
13
|
+
"version": "1.0.0",
|
|
14
|
+
"status": "approved",
|
|
15
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
16
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "edge-cloudflare-rate-limiting-REQ-005",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Composition with security-auth-magic-link: the zone-level rate rule layers over the per-email application rule",
|
|
5
|
+
"description": "When both edge-cloudflare-rate-limiting and security-auth-magic-link are applied on the same project, the composition follows ADR-3702: the zone-level rate rule sits at the CF edge and refuses the (N+1)th request for the elicited duration before it reaches the origin Worker; the per-email application rate limiter that security-auth-magic-link ships continues to run on requests that pass the edge gate, applying per-email per-minute limits at the mint-surface. Zone rule layers OVER the application rule; the two operate on different characteristic sets (IP-per-URL at the zone, email at the application) and never overlap on the same characteristic. The guide names the composition explicitly with a copy-paste example. Applying both blueprints without the ADR-3702 layering understanding would leave two rate rules operating on the same characteristic and shadowing each other; ADR-3702 states the layering explicitly and the applied recorder records both blueprints so the operator sees the two-rule shape at apply time.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "edge",
|
|
8
|
+
"priority": "should",
|
|
9
|
+
"rationale": "Ratified in the Cloudflare round 6 spec (cloudflare-round-6-spec-2026-09-06.md section 5.6). Ships as v1.0.0 of edge-cloudflare-rate-limiting.",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:edge-cloudflare-rate-limiting"
|
|
12
|
+
],
|
|
13
|
+
"version": "1.0.0",
|
|
14
|
+
"status": "approved",
|
|
15
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
16
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
17
|
+
}
|
package/blueprints/edge-cloudflare-rate-limiting/contributions/schemas/rate-limit-rule.schema.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://stravica.ai/rcf-lite/schemas/rate-limit-rule.schema.json",
|
|
4
|
+
"title": "Cloudflare rate-limit rule manifest file",
|
|
5
|
+
"description": "One rule per file under the elicited rate-limit-rules-dir. Fields track the Cloudflare WAF rate-limiting rules documented shape at https://developers.cloudflare.com/waf/rate-limiting-rules/.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"id",
|
|
10
|
+
"expression",
|
|
11
|
+
"threshold",
|
|
12
|
+
"period",
|
|
13
|
+
"characteristics",
|
|
14
|
+
"action",
|
|
15
|
+
"duration"
|
|
16
|
+
],
|
|
17
|
+
"properties": {
|
|
18
|
+
"id": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"minLength": 1,
|
|
21
|
+
"description": "Operator-facing stable rule id (kebab-case; used in drift-audit records as ruleId)."
|
|
22
|
+
},
|
|
23
|
+
"expression": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"minLength": 1,
|
|
26
|
+
"description": "Cloudflare WAF rules-language expression string; scopes the rule to a request set."
|
|
27
|
+
},
|
|
28
|
+
"threshold": {
|
|
29
|
+
"type": "integer",
|
|
30
|
+
"minimum": 1,
|
|
31
|
+
"description": "Requests permitted per period on the characteristic set."
|
|
32
|
+
},
|
|
33
|
+
"period": {
|
|
34
|
+
"type": "integer",
|
|
35
|
+
"minimum": 1,
|
|
36
|
+
"description": "Window in seconds the threshold applies over."
|
|
37
|
+
},
|
|
38
|
+
"characteristics": {
|
|
39
|
+
"type": "array",
|
|
40
|
+
"minItems": 1,
|
|
41
|
+
"items": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"minLength": 1
|
|
44
|
+
},
|
|
45
|
+
"description": "Non-empty list of characteristic strings the rule keys on (e.g. cf.colo.id, ip.src, http.host + http.request.uri.path)."
|
|
46
|
+
},
|
|
47
|
+
"action": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"enum": [
|
|
50
|
+
"block",
|
|
51
|
+
"challenge",
|
|
52
|
+
"log",
|
|
53
|
+
"managed_challenge"
|
|
54
|
+
],
|
|
55
|
+
"description": "Cloudflare-documented action verb the rule applies over-threshold."
|
|
56
|
+
},
|
|
57
|
+
"duration": {
|
|
58
|
+
"type": "integer",
|
|
59
|
+
"minimum": 1,
|
|
60
|
+
"description": "Block window in seconds the (N+1)th and subsequent requests are refused for."
|
|
61
|
+
},
|
|
62
|
+
"description": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"description": "Optional operator-facing description of the rule intent."
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tacId": "TAC-3701-edge-cloudflare-rate-limiting-manifest-schema",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"name": "Rate-limit rule manifest schema and manifest layout",
|
|
8
|
+
"purpose": "The shipped JSON Schema (draft-07) at blueprints/edge-cloudflare-rate-limiting/contributions/schemas/rate-limit-rule.schema.json is the single source of truth for the shape of one manifest file under the elicited rate-limit-rules-dir. The schema names the seven Cloudflare WAF rate-limiting rules fields per https://developers.cloudflare.com/waf/rate-limiting-rules/ (id, expression, threshold, period, characteristics, action, duration), their types (string, string, positive integer, positive integer, non-empty string array, enum of block/challenge/log/managed_challenge, positive integer), and the additionalProperties: false stance. The manifest-schema-validate probe reads every file in the fixture manifest directory and validates against this schema; the manifest-presence probe asserts the seven required fields are all present. This TAC anchors AC-36101-1, AC-36106-1 and AC-36108-1.",
|
|
9
|
+
"responsibilities": [
|
|
10
|
+
"Ship a JSON Schema (draft-07) at contributions/schemas/rate-limit-rule.schema.json naming the seven required fields, their types and additionalProperties: false (AC-36101-1, AC-36106-1).",
|
|
11
|
+
"Ship the shape used by the manifest-presence probe to assert every manifest file carries the seven required fields (AC-36101-1).",
|
|
12
|
+
"Ship the shape used by the manifest-schema-validate probe to refuse a manifest file with a missing threshold under SIMULATE_SCHEMA_INVALID=true (AC-36106-1).",
|
|
13
|
+
"Ship the layout used by the manifest-presence probe under SIMULATE_MANIFEST_MISSING=true to name the missing file's basename in the detail (AC-36108-1)."
|
|
14
|
+
],
|
|
15
|
+
"internalStructure": "One JSON Schema file (contributions/schemas/rate-limit-rule.schema.json). One shipped example manifest directory in the cf-edge fixture with two files (cloudflare/rate-limits/example.json, cloudflare/rate-limits/api-writes.json). Two induced-failure switches in the fixture: SIMULATE_MANIFEST_MISSING=true moves one manifest file to a scratch location so manifest-presence fails; SIMULATE_SCHEMA_INVALID=true writes a manifest file with a missing threshold so manifest-schema-validate fails. Both switches restore before commit; the anatomy test verifies the negative path.",
|
|
16
|
+
"interfaces": [
|
|
17
|
+
{
|
|
18
|
+
"name": "rate-limit-rule.schema.json",
|
|
19
|
+
"kind": "schema",
|
|
20
|
+
"summary": "JSON Schema (draft-07) for one rate-limit rule manifest file."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "cloudflare/rate-limits/",
|
|
24
|
+
"kind": "layout",
|
|
25
|
+
"summary": "Elicited manifest directory, one JSON file per rule."
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"dependencies": [],
|
|
29
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
30
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
31
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tacId": "TAC-3702-edge-cloudflare-rate-limiting-management-surface-doc",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"name": "Operator-facing management surface documentation (wrangler and Cloudflare dashboard flows)",
|
|
8
|
+
"purpose": "The shipped guide at blueprints/edge-cloudflare-rate-limiting/guide/edge-cloudflare-rate-limiting.md documents both a wrangler command flow and a Cloudflare dashboard flow for applying one rule from a manifest file to the elicited zone. The guide is the sole management-surface artefact the blueprint ships; no committed script writes rules to the live zone. The elicited rate-limit-management-surface value records the flow the operator chose. The guide also names the composition with security-auth-magic-link per ADR-3702 and shows a copy-paste example. This TAC anchors AC-36102-1 and AC-36105-1.",
|
|
9
|
+
"responsibilities": [
|
|
10
|
+
"Ship a guide with a wrangler command flow and a Cloudflare dashboard flow, both walking through the apply of one rule from a manifest file (AC-36102-1).",
|
|
11
|
+
"Reference https://developers.cloudflare.com/waf/rate-limiting-rules/ as the vendor doc for the rule shape (AC-36102-1).",
|
|
12
|
+
"Ship a Composition with security-auth-magic-link section naming ADR-3702 explicitly, stating the zone rule characteristic (IP-per-URL) and the application rule characteristic (per-email per-minute) with a copy-paste example (AC-36105-1)."
|
|
13
|
+
],
|
|
14
|
+
"internalStructure": "One guide file (guide/edge-cloudflare-rate-limiting.md) with three named sections: Manifest, Management surface (wrangler and dashboard subsections) and Composition with security-auth-magic-link. Every section links back to the corresponding REQ and ADR.",
|
|
15
|
+
"interfaces": [
|
|
16
|
+
{
|
|
17
|
+
"name": "guide/edge-cloudflare-rate-limiting.md",
|
|
18
|
+
"kind": "documentation",
|
|
19
|
+
"summary": "Operator-facing management surface guide with both wrangler and dashboard flows plus the composition example."
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"dependencies": [],
|
|
23
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
24
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tacId": "TAC-3703-edge-cloudflare-rate-limiting-drift-audit-runner",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"name": "Drift-audit runner: read live zone rules via the Cloudflare API and diff against the local manifest",
|
|
8
|
+
"purpose": "The single project-side module realising the scheduled drift-audit runner. It fetches the live rate-limiting rules on the elicited zone via the Cloudflare API (GET /client/v4/zones/{zone_id}/rulesets), diffs the returned rule set against the local manifest file-by-file, and constructs one drift-audit record per mismatched rule. Records write through the applied logger's audit sink with the metadata-only shape {ruleId, clientIpHash, outcome, timestamp, diff}; no record carries a full IP, a request body or a user agent (event-secrecy discipline per REQ-004 and AC-36107-1). The runner is factory-driven for testability: probes and the anatomy test inject a fake fetch that returns a synthetic live-zone response. This TAC anchors AC-36104-1 and AC-36107-1.",
|
|
9
|
+
"responsibilities": [
|
|
10
|
+
"Export createDriftAuditRunner({env, eventSink, fetch, clock, cadence}) returning {runOnce, schedule, stop} matching the drift-audit shape (AC-36104-1).",
|
|
11
|
+
"Diff every manifest rule against every live rule and construct one drift record per mismatched rule, with the metadata-only shape {ruleId, outcome, timestamp, diff} (AC-36104-1, AC-36107-1).",
|
|
12
|
+
"Emit exactly one audit event per drift record on the injected sink, Object.frozen at the boundary (AC-36107-1).",
|
|
13
|
+
"Refuse to run when the elicited cadence is off (AC-36104-1)."
|
|
14
|
+
],
|
|
15
|
+
"internalStructure": "One shipped runner module the blueprint contributes at guide-installation time (the runner code is copy-paste from the guide into the applying project; the shipped fixture at packages/rcf-lite/test/fixtures/cf-edge/src/drift-audit-runner.mjs realises the shape the guide names). The runner constructs one drift record per mismatched rule; the record is Object.frozen at the boundary so a downstream handler cannot enrich it with a leaked field.",
|
|
16
|
+
"interfaces": [
|
|
17
|
+
{
|
|
18
|
+
"name": "createDriftAuditRunner",
|
|
19
|
+
"kind": "factory",
|
|
20
|
+
"summary": "Drift-audit runner factory over env, eventSink, fetch, clock and the elicited cadence."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"dependencies": [],
|
|
24
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
25
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
26
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "edge-cloudflare-rate-limiting-US-36101",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "edge-cloudflare-rate-limiting-REQ-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "Rules manifest present in the applying project as one JSON file per rule under the elicited manifest directory",
|
|
8
|
+
"asA": "shelf consumer applying the edge-cloudflare-rate-limiting v1.0.0 blueprint on a Workers project using the cf-edge fixture",
|
|
9
|
+
"iWant": "the elicited rate-limit-rules-dir to contain at least one committed JSON file per rate-limit rule the applying project intends to run, each file matching the elicited rule shape and none referencing a secret in plaintext",
|
|
10
|
+
"soThat": "the applying project's rate-limit rules are source-controlled and reviewable, and the operator has a stable source of truth to apply to the live zone through the wrangler or dashboard flow",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-36101-1",
|
|
14
|
+
"description": "The rate-limit manifest directory (default cloudflare/rate-limits/) exists in the applied project and holds at least one JSON file per rule; every file parses as JSON and carries the seven documented Cloudflare WAF rate-limiting rules fields (id, expression, threshold, period, characteristics, action, duration); no file body contains a plaintext Cloudflare API token or the elicited zone id (the zone id is elicited and stored via the applied secretsManagement companion).",
|
|
15
|
+
"given": "the cf-edge fixture with the two committed manifest files under cloudflare/rate-limits/",
|
|
16
|
+
"when": "the manifest-presence probe scans the fixture directory",
|
|
17
|
+
"then": "every manifest file parses, every file carries the seven required fields, and no file references a secret in plaintext",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"tacIds": [
|
|
23
|
+
"TAC-3701-edge-cloudflare-rate-limiting-manifest-schema"
|
|
24
|
+
],
|
|
25
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
26
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "edge-cloudflare-rate-limiting-US-36102",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "edge-cloudflare-rate-limiting-REQ-002",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "Guide documents the operator-facing management surface with both wrangler and dashboard flows",
|
|
8
|
+
"asA": "operator on the applying project preparing to push rate-limit rules from the local manifest to the live Cloudflare zone",
|
|
9
|
+
"iWant": "a documented step-by-step flow that walks me through both a wrangler command sequence and a Cloudflare dashboard sequence for applying each manifest rule",
|
|
10
|
+
"soThat": "I can pick the flow that suits the project's operating discipline and reproduce the apply from the manifest at any cadence without inventing a bespoke tool",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-36102-1",
|
|
14
|
+
"description": "The blueprint guide at blueprints/edge-cloudflare-rate-limiting/guide/edge-cloudflare-rate-limiting.md documents an operator-facing management surface with both a wrangler command flow and a Cloudflare dashboard flow; each flow names the exact steps to apply one rule from a manifest file to the elicited zone; the guide references https://developers.cloudflare.com/waf/rate-limiting-rules/ as the vendor doc for the rule shape.",
|
|
15
|
+
"given": "the shipped guide file in the blueprint tree",
|
|
16
|
+
"when": "the anatomy test scans the guide for the wrangler headings, the dashboard headings and the vendor URL",
|
|
17
|
+
"then": "both flow headings are present and the vendor URL appears",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "documentation"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"tacIds": [
|
|
23
|
+
"TAC-3702-edge-cloudflare-rate-limiting-management-surface-doc"
|
|
24
|
+
],
|
|
25
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
26
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "edge-cloudflare-rate-limiting-US-36103",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "edge-cloudflare-rate-limiting-REQ-003",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "Over-threshold burst returns 429 with Retry-After and Cf-Ray on the (N+1)th request within the elicited duration",
|
|
8
|
+
"asA": "operator running the real-account burst probe against a scheduled HQ-owned URL configured with the manifest rule",
|
|
9
|
+
"iWant": "the probe to fire an undici burst above the rule threshold and observe the (N+1)th and subsequent requests return HTTP 429 with a Retry-After header consistent with the elicited duration and a Cf-Ray header for the CF edge that served the refusal",
|
|
10
|
+
"soThat": "the shipped over-threshold behaviour is verified against a real Cloudflare account and, in CI without CI_HAS_CLOUDFLARE_ACCOUNT, the probe records accountBound: skipped per ruling 6",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-36103-1",
|
|
14
|
+
"description": "When CI_HAS_CLOUDFLARE_ACCOUNT is true and CF_RATE_LIMIT_URL is set to a scheduled HQ-owned URL configured with the manifest rule, the real-account-burst-and-429 probe fires the elicited threshold plus one requests within the rule period and observes the (N+1)th and subsequent requests within the elicited duration return HTTP 429 with a Retry-After header value consistent with the elicited duration and a Cf-Ray header naming the CF edge; when either env var is absent the probe records accountBoundSkipped: true and the aggregate verdict is pass per spec section 3.5 and ruling 6.",
|
|
15
|
+
"given": "a scheduled HQ-owned URL configured with the manifest rule (or the accountBound: skipped fallback in CI)",
|
|
16
|
+
"when": "the real-account-burst-and-429 probe fires the burst (or records the skip)",
|
|
17
|
+
"then": "the probe returns 429 with the two required headers on the over-threshold requests, or records accountBoundSkipped: true and aggregates to pass",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"tacIds": [
|
|
23
|
+
"TAC-3701-edge-cloudflare-rate-limiting-manifest-schema"
|
|
24
|
+
],
|
|
25
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
26
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "edge-cloudflare-rate-limiting-US-36104",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "edge-cloudflare-rate-limiting-REQ-004",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "Drift-audit runner reads live zone rules via the Cloudflare API and diffs against the local manifest, constructing metadata-only records",
|
|
8
|
+
"asA": "operator on the applying project running the scheduled drift-audit runner behind the elicited cadence (daily or hourly)",
|
|
9
|
+
"iWant": "the runner to fetch the live rule set from the Cloudflare API for the elicited zone and diff every rule against the local manifest, constructing one drift-audit record per mismatched rule with the metadata-only shape and writing a report to .rcf/reports/blueprints/edge-cloudflare-rate-limiting/",
|
|
10
|
+
"soThat": "manifest drift (a rule changed on the dashboard without a manifest update, or vice versa) is surfaced through the logging companion at the elicited cadence rather than lingering unnoticed",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-36104-1",
|
|
14
|
+
"description": "Given a synthetic drift scenario (a fixture manifest file that names threshold 10 and a fake live-zone response that reports threshold 20 on the same rule id), the drift-audit runner's diff step constructs one drift record per mismatched rule; the record carries {ruleId, outcome: driftDetected, timestamp, diff: [field: threshold, manifestValue: 10, liveValue: 20]} and NO full IP, NO request body, NO user agent; when the cadence elicit is off the runner is not wired and no report is written.",
|
|
15
|
+
"given": "the cf-edge fixture with the committed manifest and a synthetic Cloudflare API response with one mismatched rule",
|
|
16
|
+
"when": "the drift-audit runner's diff step runs against the pair",
|
|
17
|
+
"then": "one drift record is constructed per mismatched rule with the metadata-only shape and the report writes to .rcf/reports/blueprints/edge-cloudflare-rate-limiting/",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"tacIds": [
|
|
23
|
+
"TAC-3703-edge-cloudflare-rate-limiting-drift-audit-runner"
|
|
24
|
+
],
|
|
25
|
+
"createdAt": "2026-09-07T22:00:00.000Z",
|
|
26
|
+
"updatedAt": "2026-09-07T22:00:00.000Z"
|
|
27
|
+
}
|