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
package/blueprints/platform-cloudflare-durable-objects/guide/platform-cloudflare-durable-objects.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# platform-cloudflare-durable-objects guide
|
|
2
|
+
|
|
3
|
+
## When to reach for this blueprint
|
|
4
|
+
|
|
5
|
+
You reach for `platform-cloudflare-durable-objects` when your
|
|
6
|
+
Worker needs strongly consistent authoritative state, coordinated
|
|
7
|
+
multiplayer websocket connections, or both on the same DO namespace
|
|
8
|
+
mechanic. Two shapes ship in one blueprint: the SINGLE-CELL shape
|
|
9
|
+
(counter, session store, lock, coordinator) and the WEBSOCKET-HUB
|
|
10
|
+
shape (rooms, presence, live cursors).
|
|
11
|
+
|
|
12
|
+
If you need eventually-consistent low-latency reads on a read-hot
|
|
13
|
+
path (feature flags, session cache, config cache), reach for
|
|
14
|
+
`platform-cloudflare-kv` (round 6 T-1) instead. If you need
|
|
15
|
+
durable multi-step workflows with retries and state across steps,
|
|
16
|
+
reach for the follow-up Workflows adapter on `jobs-background`
|
|
17
|
+
v1.1.0 (round-6 minor bump per spec section 5.7).
|
|
18
|
+
|
|
19
|
+
## Decision tree
|
|
20
|
+
|
|
21
|
+
- Strongly consistent authoritative cell (counter, session store,
|
|
22
|
+
lock, coordinator) -> SINGLE-CELL shape (this blueprint,
|
|
23
|
+
`platform-cloudflare-durable-objects` v1.0.0).
|
|
24
|
+
- Coordinated multiplayer websocket connections in one authoritative
|
|
25
|
+
hub (rooms, live cursors, presence) -> WEBSOCKET-HUB shape (this
|
|
26
|
+
blueprint, same v1.0.0).
|
|
27
|
+
- Cache-shaped eventually-consistent reads -> `platform-cloudflare-kv`
|
|
28
|
+
v1.0.0.
|
|
29
|
+
- Durable multi-step workflow -> follow-up Workflows adapter on
|
|
30
|
+
`jobs-background` v1.1.0.
|
|
31
|
+
- Not on Cloudflare Workers -> reach for a platform-native
|
|
32
|
+
strongly-consistent adapter when one ships; the shelf has no
|
|
33
|
+
non-Cloudflare strong-consistency cell blueprint today.
|
|
34
|
+
|
|
35
|
+
## The apply-time answers
|
|
36
|
+
|
|
37
|
+
Answer seven elicits at `rcf define blueprint add` time:
|
|
38
|
+
|
|
39
|
+
- `do-cell-binding` (default `CELL`): the DO namespace binding name
|
|
40
|
+
under `[[durable_objects.bindings]]` in wrangler.toml for the
|
|
41
|
+
single-cell shape.
|
|
42
|
+
- `do-hub-binding` (default `HUB`): the DO namespace binding name
|
|
43
|
+
for the hub shape.
|
|
44
|
+
- `do-cell-class-name` (default `SingleCellObject`): the stable class
|
|
45
|
+
name string committed under the mint `[[migrations]]` tag. A
|
|
46
|
+
future rename lands as a subsequent migrations tag, not a silent
|
|
47
|
+
edit.
|
|
48
|
+
- `do-hub-class-name` (default `HubObject`): the stable class name
|
|
49
|
+
string for the hub class.
|
|
50
|
+
- `do-storage-backend` (default `sql` per ADR-3403): SQL (typed
|
|
51
|
+
columns, query) or KV (simple `put`/`get`/`delete`/`list`).
|
|
52
|
+
- `do-hub-broadcast-window-ms` (default `500`): the elicited window
|
|
53
|
+
for broadcast fan-out from A to all connected sockets.
|
|
54
|
+
- `do-hub-hibernate-after-idle-ms` (default `30000` per ADR-3405):
|
|
55
|
+
the hibernate-after-idle window on the hub shape. The wake
|
|
56
|
+
handler is idempotent-by-contract per the same ADR.
|
|
57
|
+
|
|
58
|
+
## The two shapes: single-cell first
|
|
59
|
+
|
|
60
|
+
The single-cell shape is one named object exposing typed domain
|
|
61
|
+
verbs. Cloudflare's DO runtime serialises invocations against the
|
|
62
|
+
same instance; the shipped SingleCellObject class realises that
|
|
63
|
+
contract via a per-instance FIFO promise queue so two concurrent
|
|
64
|
+
callers cannot silently overwrite each other. Each increment
|
|
65
|
+
resolves with a `{counter, witness}` pair: the FIFO-first caller
|
|
66
|
+
sees `witness=0`, the second sees `witness=1`, and a subsequent
|
|
67
|
+
read returns the sum.
|
|
68
|
+
|
|
69
|
+
Storage is elicited (`sql` or `kv` per ADR-3403). The shipped
|
|
70
|
+
driver factory is backend-agnostic and threads through the elicited
|
|
71
|
+
answer as `driver.backend`. SQL supports typed columns and query;
|
|
72
|
+
KV is simpler and single-key. Pick SQL when your object has a
|
|
73
|
+
non-trivial data shape; pick KV when a single key is all you need.
|
|
74
|
+
|
|
75
|
+
Alarm is a first-class surface. `setAlarm(offsetMs)` persists a
|
|
76
|
+
schedule; the `alarm()` handler runs at that time, drains the
|
|
77
|
+
persisted alarm from storage, and emits `doAlarmFired` on the
|
|
78
|
+
injected sink with `{objectName, scheduledTime}`. Cloudflare's
|
|
79
|
+
runtime guarantees exactly-once delivery per scheduled time; a
|
|
80
|
+
second call to `alarm()` on the drained storage records
|
|
81
|
+
`scheduledTime: null` rather than re-firing for the same schedule.
|
|
82
|
+
|
|
83
|
+
## The two shapes: websocket hub
|
|
84
|
+
|
|
85
|
+
The hub shape is one named object accepting websocket clients via
|
|
86
|
+
`state.acceptWebSocket`. Messages route by JSON `type` field:
|
|
87
|
+
`broadcast` fans out to all connected sockets (echo included, per
|
|
88
|
+
the hub shape trade-off), `set-state` and `get-state` wrap the
|
|
89
|
+
underlying storage.
|
|
90
|
+
|
|
91
|
+
Every broadcast persists `lastBroadcast` to storage so a re-emerging
|
|
92
|
+
client can catch up on the missed message. When the object goes
|
|
93
|
+
idle past the elicited `hibernate-after-idle` window, Cloudflare's
|
|
94
|
+
runtime hibernates the object; on the next message the wake handler
|
|
95
|
+
runs from a cold start and reads the same storage. The shipped
|
|
96
|
+
HubObject class emits `doWakeUp` exactly once on the first wake
|
|
97
|
+
(idempotent-by-contract per ADR-3405) and returns the persisted
|
|
98
|
+
`lastBroadcast` from storage so a downstream client can rebuild
|
|
99
|
+
state.
|
|
100
|
+
|
|
101
|
+
The elicited `do-hub-broadcast-window-ms` (default `500`) is the
|
|
102
|
+
window in which A's broadcast reaches every connected socket on
|
|
103
|
+
the shipped path. A tighter window is fine on a small hub; a
|
|
104
|
+
looser window trades latency for fan-out cost on a busy hub.
|
|
105
|
+
|
|
106
|
+
## The migration-safe class-export contract
|
|
107
|
+
|
|
108
|
+
The DO class names are stable strings committed to `wrangler.toml`.
|
|
109
|
+
Both binding blocks name the class explicitly; the `[[migrations]]`
|
|
110
|
+
block records the mint under `tag = "v1"` with `new_classes` naming
|
|
111
|
+
both classes. A copy-paste block for a fresh Worker project:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
[[durable_objects.bindings]]
|
|
115
|
+
name = "CELL"
|
|
116
|
+
class_name = "SingleCellObject"
|
|
117
|
+
|
|
118
|
+
[[durable_objects.bindings]]
|
|
119
|
+
name = "HUB"
|
|
120
|
+
class_name = "HubObject"
|
|
121
|
+
|
|
122
|
+
[[migrations]]
|
|
123
|
+
tag = "v1"
|
|
124
|
+
new_classes = ["SingleCellObject", "HubObject"]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
A rename in a later release ships as a NEW `[[migrations]]` tag on
|
|
128
|
+
the same list (`tag = "v2"`, `renamed_classes = [...]`), never a
|
|
129
|
+
silent edit of the class name. A rename without a migration is a
|
|
130
|
+
runtime error the shipped anatomy assertion catches at self-review.
|
|
131
|
+
|
|
132
|
+
## The sole-reader guarantee
|
|
133
|
+
|
|
134
|
+
The DO facade module (`src/do-facade.mjs`) is the ONLY module in
|
|
135
|
+
the applied source tree that dereferences `env.CELL` and `env.HUB`.
|
|
136
|
+
Every consumer of DO calls the facade's typed handles; a call site
|
|
137
|
+
outside the facade is a leak the sole-reader-scan probe surfaces
|
|
138
|
+
at self-review.
|
|
139
|
+
|
|
140
|
+
The probe walks every `.mjs`, `.js` and `.ts` file under the
|
|
141
|
+
applied source root, strips block and line comments (so a
|
|
142
|
+
documentation mention of `env.CELL` does not flag), and matches
|
|
143
|
+
literal accesses against the file path. A clean scan surfaces zero
|
|
144
|
+
non-facade leaks; a leak returns `aggregateVerdict: fail` and the
|
|
145
|
+
review does not ship until the leak is closed.
|
|
146
|
+
|
|
147
|
+
## Metadata-only lifecycle events
|
|
148
|
+
|
|
149
|
+
Every lifecycle event on the sink is a metadata-only record. The
|
|
150
|
+
allowed key set is `{event, key, size, ttl, timestamp, objectName,
|
|
151
|
+
scheduledTime}`; no message payloads, request bodies, headers,
|
|
152
|
+
cookies or PII cross the sink boundary. A logging companion
|
|
153
|
+
renders records directly without a per-blueprint scrub pass.
|
|
154
|
+
|
|
155
|
+
The event-secrecy assertion rides on the websocket-hub-broadcast
|
|
156
|
+
probe (the shipped path emits `doAccept`, `doHibernate`, `doWakeUp`
|
|
157
|
+
and the `namespaceReady` on the paired facade). Under
|
|
158
|
+
`SIMULATE_PII_LEAK=true` a wrapped sink forwards synthetic
|
|
159
|
+
body-bearing records; the probe surfaces the forbidden keys and
|
|
160
|
+
returns fail on the AC-33106-1 result.
|
|
161
|
+
|
|
162
|
+
## Composition
|
|
163
|
+
|
|
164
|
+
- Consumes `deploy-cloudflare-workers` v1.2.0 (T-0). The DO bindings
|
|
165
|
+
and migrations tag land in the same `wrangler.toml`.
|
|
166
|
+
- Companions `logging` and `errorHandling` supply the sink factory
|
|
167
|
+
and the internal-error record factory.
|
|
168
|
+
- Complements `platform-cloudflare-kv` (round 6 T-1): DO owns the
|
|
169
|
+
strong-consistency slot; KV owns the cache-shaped eventually-
|
|
170
|
+
consistent slot. Both compose on the same Worker.
|
|
171
|
+
- A future non-Cloudflare adapter on `strongConsistencyCellContract`
|
|
172
|
+
or `websocketHubContract` mints on demand; each contributes the
|
|
173
|
+
same topic string with a different answer, forcing a DELIBERATE
|
|
174
|
+
conflict the operator resolves via a project-level ADR.
|
|
175
|
+
|
|
176
|
+
## Real-account smoke
|
|
177
|
+
|
|
178
|
+
The `real-account-storage-smoke` probe opens the DO facade against
|
|
179
|
+
a real Cloudflare account with a real DO namespace when
|
|
180
|
+
`CI_HAS_CLOUDFLARE_ACCOUNT=true` (paired with `CF_ACCOUNT_ID`,
|
|
181
|
+
`CF_DO_NAMESPACE_ID` and `CF_API_TOKEN`); without the env var it
|
|
182
|
+
records `accountBoundSkipped: true`, aggregates to `pass`, and
|
|
183
|
+
exits 0 per spec section 3.5 (Clerk pattern).
|
|
184
|
+
|
|
185
|
+
## Wrangler-seam probe
|
|
186
|
+
|
|
187
|
+
The eighth probe, `wrangler-seam.mjs`, spawns `wrangler dev
|
|
188
|
+
--local` on the cf-platform fixture and drives the shipped DO
|
|
189
|
+
facade + SingleCellObject + HubObject code path against a real
|
|
190
|
+
workerd runtime:
|
|
191
|
+
|
|
192
|
+
- Two concurrent `POST /cell/<id>/increment` requests route
|
|
193
|
+
through `src/index.mjs` -> `createDoFacade({env,
|
|
194
|
+
eventSink}).cellFetch(<id>, request)` -> the shipped
|
|
195
|
+
SingleCellObject class. The probe asserts per-instance
|
|
196
|
+
serialisation (sorted counters equal `[1, 2]`, sorted
|
|
197
|
+
witnesses equal `[0, 1]`; each request observed the other's
|
|
198
|
+
write).
|
|
199
|
+
- One WebSocket upgrade against `/hub/<id>/connect` routes
|
|
200
|
+
through the same facade to `env.HUB` and receives one
|
|
201
|
+
broadcast frame from the HubObject fetch handler on connect
|
|
202
|
+
(payload `hello-from-hub`).
|
|
203
|
+
- An additional `AC-33108-1` result on the same run greps the
|
|
204
|
+
fixture `wrangler.toml` for both `[[durable_objects.bindings]]`
|
|
205
|
+
binding pairs and the `[[migrations]]` `tag = "v1"` with
|
|
206
|
+
`new_classes`; the grep is deterministic and does not require
|
|
207
|
+
wrangler.
|
|
208
|
+
|
|
209
|
+
Warn semantics per section 3.1 pass-with-skip: if the wrangler
|
|
210
|
+
devDependency is missing under the fixture's `node_modules`, or
|
|
211
|
+
if the CLI does not bind within the cap, the probe returns
|
|
212
|
+
`aggregateVerdict: warn` (never fail). A handler thrown at the
|
|
213
|
+
workerd boundary is a genuine `fail`.
|
|
214
|
+
|
|
215
|
+
The routing layer in `src/index.mjs` never dereferences
|
|
216
|
+
`env.CELL` or `env.HUB` directly; every DO call routes through
|
|
217
|
+
`createDoFacade({env, eventSink}).cellFetch` /
|
|
218
|
+
`.hubFetch` so the sole-reader guarantee still holds. The
|
|
219
|
+
sole-reader-scan probe covers the boundary.
|
|
220
|
+
|
|
221
|
+
## The v1.0.0 boundary: what defers to v1.1.0
|
|
222
|
+
|
|
223
|
+
Per spec section 5.3, the following items are OUT of v1.0.0 and
|
|
224
|
+
land as an additive v1.1.0 minor when at least one project needs
|
|
225
|
+
them:
|
|
226
|
+
|
|
227
|
+
- RPC-style class methods (per the DO RPC surface).
|
|
228
|
+
- Storage backups.
|
|
229
|
+
- Multi-object transactions across namespaces.
|
|
230
|
+
|
|
231
|
+
Do not extend the shipped code path to open any of these seams in
|
|
232
|
+
v1.0.0. A minor bump post-round lands the deferred items as an
|
|
233
|
+
additive contribution set without a fresh blueprint.
|
|
234
|
+
|
|
235
|
+
## References
|
|
236
|
+
|
|
237
|
+
- Cloudflare Durable Objects overview: https://developers.cloudflare.com/durable-objects/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `platform-cloudflare-kv` are recorded here. The shape follows Keep a Changelog and Semantic Versioning per the blueprint authoring standard.
|
|
4
|
+
|
|
5
|
+
## 1.0.0 (2026-09-07)
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- v1.0.0 mint of the `platform-cloudflare-kv` blueprint, category `platform`, capabilities `["keyValueStore"]`. Ships a facade over Cloudflare Workers KV with typed put/get/delete/list verbs, a cache-aside helper, four metadata-only lifecycle events (`facadeReady`, `kvHit`, `kvMiss`, `kvWrite`), and an eventual-consistency note in the guide that sets the elicited cache-aside TTL as the staleness ceiling readers observe.
|
|
10
|
+
- 5 REQs (`platform-cloudflare-kv-REQ-001..005`), 8 USs (`platform-cloudflare-kv-US-31101..31108`), 3 TACs (`TAC-3201` facade, `TAC-3202` cache-aside, `TAC-3203` event sink), 3 ADRs (`ADR-3201` scope-global on new topic `keyValueStoreContract` with `standardsTraceClause: Cloudflare Workers KV documented consistency model`; `ADR-3202` default cache-aside TTL 60 seconds floor 1 second `elicited: true`; `ADR-3203` key naming convention `recommendedDefault: prefixed` `elicited: true`).
|
|
11
|
+
- 5 Node-only probes under `contributions/probes/`: `facade-round-trip`, `cache-aside-hit-then-miss`, `event-secrecy`, `list-with-prefix` (four local probes driving the in-memory KV driver on the `cf-platform` fixture) and `real-account-eventual-consistency-smoke` (`accountBound: true`; skipped in CI without `CI_HAS_CLOUDFLARE_ACCOUNT`).
|
|
12
|
+
- Elicited parameters on `blueprint.json`: `kv-binding-name` (default `CACHE`), `kv-default-cache-ttl-seconds` (default `60`, floor `1`), `kv-metadata-field-pattern` (default `{v:1}`), `kv-key-naming-convention` (default `prefixed`).
|
|
13
|
+
- `suggestedCompanions`: `logging` (for the event-sink boundary) and `errorHandling` (for the error record shape).
|
|
14
|
+
- Extends the shared `cf-platform` sample-app fixture with the `[[kv_namespaces]]` binding block (name `CACHE`), the sole-reader KV facade module (`src/kv-facade.mjs`), the cache-aside helper (`src/cache-aside.mjs`), and the in-memory KV driver (`src/kv-driver.mjs`) that realises the Workers KV binding shape so the local probes drive without a live-KV dependency.
|
|
15
|
+
- Anatomy test at `packages/rcf-lite/test/blueprint/platform-cloudflare-kv-anatomy.test.js` covers `TS-080..087` on the T-1 chain slice (blueprint shape, contributions cross-check, probe module contracts, fixture files, ADR bodies and clauses, guide sections and URLs, three-state probed verdicts).
|
|
16
|
+
|
|
17
|
+
### Known limitations
|
|
18
|
+
|
|
19
|
+
- The `real-account-eventual-consistency-smoke` probe records `accountBoundSkipped: true` and aggregates to `pass` when `CI_HAS_CLOUDFLARE_ACCOUNT` is unset (spec section 3.5 pass-with-skip). Full mechanism reach requires a CI environment with the paired `CF_ACCOUNT_ID`, `CF_KV_NAMESPACE_ID` and `CF_API_TOKEN` env vars.
|
|
20
|
+
- The four local probes drive an in-memory KV driver whose shape matches the Workers KV binding at the facade boundary. Vendor surface changes beyond that boundary (a new list cursor format, a header-only limit) are not caught by the local probes; the real-account smoke is the mechanism-reach closure for that gap.
|
|
21
|
+
- The loader's supported `when` block on `elicits[]` only accepts `requiresCapability` arrays, so the elicited `kv-metadata-field-pattern` cannot yet gate on an `elicitedNonEmpty` predicate for `kv-binding-name`. A future loader minor extending `validateElicits` would close that gap; the elicit fires unconditionally today and the guide teaches the pattern.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# platform-cloudflare-kv
|
|
2
|
+
|
|
3
|
+
A rcf-lite blueprint that ships a small, opinionated facade over
|
|
4
|
+
Cloudflare Workers KV plus a cache-aside helper. One module holds the
|
|
5
|
+
KV binding; every other module reads through typed domain verbs; every
|
|
6
|
+
KV operation emits a metadata-only lifecycle event a logging companion
|
|
7
|
+
can render without ever writing a body byte.
|
|
8
|
+
|
|
9
|
+
- Version: `1.0.0`
|
|
10
|
+
- Category: `platform`
|
|
11
|
+
- Capabilities: `["keyValueStore"]`
|
|
12
|
+
- Suggested companions: `logging`, `errorHandling`
|
|
13
|
+
|
|
14
|
+
## What it gives you
|
|
15
|
+
|
|
16
|
+
- One place that reads `env.<binding>` (the KV binding) and exports
|
|
17
|
+
typed verbs (`get`, `getWithMetadata`, `put`, `delete`, `list`).
|
|
18
|
+
- A cache-aside helper (`getOr(key, originFn, {ttl?})`) that reads
|
|
19
|
+
local first, invokes origin on miss, writes back with the elicited
|
|
20
|
+
TTL, and returns the fresh value.
|
|
21
|
+
- Four metadata-only lifecycle events (`facadeReady`, `kvHit`,
|
|
22
|
+
`kvMiss`, `kvWrite`) with payload `{event, key, size, ttl,
|
|
23
|
+
timestamp}` and nothing else. Two-layer secrecy assertion in the
|
|
24
|
+
event-secrecy probe.
|
|
25
|
+
- A decision-tree cross-reference in the guide to
|
|
26
|
+
`platform-cloudflare-durable-objects` (round-6 T-3) for cases that
|
|
27
|
+
need strong-consistency semantics.
|
|
28
|
+
|
|
29
|
+
## The five REQs
|
|
30
|
+
|
|
31
|
+
| REQ | What |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `platform-cloudflare-kv-REQ-001` | The facade module is the sole reader of the KV binding and opens on boot with `facadeReady`. |
|
|
34
|
+
| `platform-cloudflare-kv-REQ-002` | Typed `put get delete list` verbs with the metadata field pattern realise the Workers KV binding shape behind the facade. |
|
|
35
|
+
| `platform-cloudflare-kv-REQ-003` | The cache-aside helper reads local first, falls back to origin, writes back with elicited TTL (floor 1 second). |
|
|
36
|
+
| `platform-cloudflare-kv-REQ-004` | Lifecycle events carry only `{event, key, size, ttl, timestamp}`; the event-secrecy probe drives this at mechanism reach. |
|
|
37
|
+
| `platform-cloudflare-kv-REQ-005` | Eventual-consistency note in the guide: a write may not appear on a global read within the same request; the elicited TTL sets the staleness ceiling. |
|
|
38
|
+
|
|
39
|
+
## The two-path facade shape
|
|
40
|
+
|
|
41
|
+
The facade is the ONE place the KV binding lives. Every other module
|
|
42
|
+
imports the facade and calls its typed verbs. The public surface is:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
createKvFacade({ binding, eventSink, keyPrefix?, defaultCacheTtl? })
|
|
46
|
+
-> { ready, get, getWithMetadata, put, delete, list }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The cache-aside helper wraps the facade:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
createCacheAside({ facade, defaultTtl })
|
|
53
|
+
-> { getOr(key, originFn, {ttl?}) }
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Elicited parameters
|
|
57
|
+
|
|
58
|
+
- `kv-binding-name` (default `CACHE`): the KV namespace binding name
|
|
59
|
+
written into `wrangler.toml` under `[[kv_namespaces]]`.
|
|
60
|
+
- `kv-default-cache-ttl-seconds` (default `60`, floor `1`): the
|
|
61
|
+
cache-aside default TTL. The cache-aside helper enforces the floor
|
|
62
|
+
at its own seam per `ADR-3202`.
|
|
63
|
+
- `kv-metadata-field-pattern` (default `{"v":1}`): the recommended
|
|
64
|
+
per-key metadata shape for a schema version marker.
|
|
65
|
+
- `kv-key-naming-convention` (default `prefixed`): whether the applied
|
|
66
|
+
project uses a domain prefix on keys (`users/`, `flags/`) or a flat
|
|
67
|
+
keyspace. See `ADR-3203`.
|
|
68
|
+
|
|
69
|
+
## The five probes
|
|
70
|
+
|
|
71
|
+
The five probes live under `contributions/probes/`. Each has a
|
|
72
|
+
matching `run-<probe-name>.mjs` shim that writes a per-blueprint
|
|
73
|
+
report to
|
|
74
|
+
`.rcf/reports/blueprints/platform-cloudflare-kv/<probe-name>.json`
|
|
75
|
+
under the fixture root.
|
|
76
|
+
|
|
77
|
+
| Probe | Anchor AC | Account-bound | What it drives |
|
|
78
|
+
| --- | --- | --- | --- |
|
|
79
|
+
| `facade-round-trip.mjs` | `AC-31103-1` | no | Opens the facade against the in-memory KV driver, puts a fixture key, reads it back, deletes it, asserts the paired lifecycle events. Also covers `AC-31103-2` and `AC-31104-1`. |
|
|
80
|
+
| `cache-aside-hit-then-miss.mjs` | `AC-31105-1` | no | Wraps a spy origin function with the cache-aside helper, drives one call within TTL (hit, no origin call), advances the fake clock past TTL, drives another call (miss, second origin call). |
|
|
81
|
+
| `event-secrecy.mjs` | `AC-31108-1` | no | Two-layer assertion: whitelist check on every event record and PII-substring scan on the JSON serialisation. A mutation-run under `SIMULATE_PII_LEAK` flips the probe to fail. |
|
|
82
|
+
| `list-with-prefix.mjs` | `AC-31104-1` | no | Puts 10 keys under `flags/` plus one decoy outside the prefix, calls `list({prefix: flags/})`, asserts all 10 return with correct metadata shape and the decoy is absent. |
|
|
83
|
+
| `real-account-eventual-consistency-smoke.mjs` | `AC-31108-1` | yes | Opens the facade against a real Cloudflare KV namespace via the Workers KV REST API, writes a fixture key, polls up to 60 seconds bounded, asserts the write eventually appears; without `CI_HAS_CLOUDFLARE_ACCOUNT` records `accountBoundSkipped: true` and aggregates `pass` per spec section 3.5. |
|
|
84
|
+
|
|
85
|
+
## How to run the probes
|
|
86
|
+
|
|
87
|
+
Two-line boot from the `cf-platform` sample-app fixture:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
cd packages/rcf-lite/test/fixtures/cf-platform
|
|
91
|
+
node ../../../../../blueprints/platform-cloudflare-kv/contributions/probes/run-facade-round-trip.mjs
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The other three local probes follow the same pattern. Reports land
|
|
95
|
+
in `.rcf/reports/blueprints/platform-cloudflare-kv/`.
|
|
96
|
+
|
|
97
|
+
Induced-failure switches:
|
|
98
|
+
|
|
99
|
+
- `SIMULATE_PII_LEAK=true` on the `event-secrecy` shim: forwards a
|
|
100
|
+
body-bearing event record; the probe surfaces `forbiddenKeys` and
|
|
101
|
+
`piiHits` and returns `aggregateVerdict: fail`.
|
|
102
|
+
- `SIMULATE_CACHE_MISS=true` on the `cache-aside-hit-then-miss`
|
|
103
|
+
shim: disables the writeback path; the probe surfaces two origin
|
|
104
|
+
calls where one was expected and returns `aggregateVerdict: fail`.
|
|
105
|
+
|
|
106
|
+
The real-account smoke needs `CI_HAS_CLOUDFLARE_ACCOUNT=true` plus
|
|
107
|
+
the paired `CF_ACCOUNT_ID`, `CF_KV_NAMESPACE_ID`, `CF_API_TOKEN`
|
|
108
|
+
env vars.
|
|
109
|
+
|
|
110
|
+
## Known mechanism-reach gaps
|
|
111
|
+
|
|
112
|
+
- The four local probes drive an in-memory KV driver whose binding
|
|
113
|
+
shape matches Workers KV at the facade boundary. Vendor surface
|
|
114
|
+
changes beyond that boundary (a new list cursor format, a
|
|
115
|
+
header-only per-request limit) are not caught by the local probes.
|
|
116
|
+
The `real-account-eventual-consistency-smoke` probe is the
|
|
117
|
+
mechanism-reach closure for that gap; in CI without the account,
|
|
118
|
+
the aggregate flips to `pass` with `accountBoundSkipped: true` per
|
|
119
|
+
spec section 3.5. Full mechanism reach requires a CI environment
|
|
120
|
+
with the paired env vars set.
|
|
121
|
+
- The elicited `kv-metadata-field-pattern` cannot yet gate on an
|
|
122
|
+
`elicitedNonEmpty` predicate for `kv-binding-name`; the loader's
|
|
123
|
+
`validateElicits` accepts only `requiresCapability` on the `when`
|
|
124
|
+
block. The elicit fires unconditionally and the guide teaches the
|
|
125
|
+
pattern.
|
|
126
|
+
|
|
127
|
+
## Companion suggestions
|
|
128
|
+
|
|
129
|
+
- `logging` supplies the event-sink factory the facade uses to emit
|
|
130
|
+
`facadeReady`, `kvHit`, `kvMiss`, `kvWrite`. Without a logging
|
|
131
|
+
companion, the sink is a no-op and the lifecycle events do not
|
|
132
|
+
render anywhere.
|
|
133
|
+
- `errorHandling` supplies the internal error record factory for a
|
|
134
|
+
KV read or write failure boundary; a project without an
|
|
135
|
+
error-handling companion sees a raw `Error` propagate to the
|
|
136
|
+
Worker fetch handler.
|
|
137
|
+
|
|
138
|
+
## Standards trace
|
|
139
|
+
|
|
140
|
+
- ADR-3201 (scope-global on `keyValueStoreContract`) carries
|
|
141
|
+
`standardsTraceClause: Cloudflare Workers KV documented
|
|
142
|
+
consistency model` and cites
|
|
143
|
+
<https://developers.cloudflare.com/kv/concepts/how-kv-works/>.
|
|
144
|
+
- ADR-3202 (default cache-aside TTL) carries
|
|
145
|
+
`standardsTraceClause: generic enterprise practice` and cites the
|
|
146
|
+
Cloudflare-documented 60-second cache TTL at
|
|
147
|
+
<https://developers.cloudflare.com/kv/concepts/how-kv-works/>.
|
|
148
|
+
- ADR-3203 (key naming convention) carries
|
|
149
|
+
`standardsTraceClause: generic enterprise practice`.
|
|
150
|
+
|
|
151
|
+
## Chain-slice pointers
|
|
152
|
+
|
|
153
|
+
The anatomy test at
|
|
154
|
+
`packages/rcf-lite/test/blueprint/platform-cloudflare-kv-anatomy.test.js`
|
|
155
|
+
binds every AC on `US-5001..5401` (`AC-5001-1..AC-5401-1`) to a test
|
|
156
|
+
case in that file with a resolvable `testPointer`. Repo-chain slice
|
|
157
|
+
under `packages/rcf-lite/rcf/`: `REQ-050..054` (5), `US-5001..5401`
|
|
158
|
+
(8), `TS-080..087` (8), `FBS-070` (1), `CN-230..234` (5) per the
|
|
159
|
+
HQ round-6 T-1 reserved-block ruling 2026-09-07T10:12Z.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"slug": "platform-cloudflare-kv",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"category": "platform",
|
|
5
|
+
"capabilities": ["keyValueStore"],
|
|
6
|
+
"suggestedCompanions": [
|
|
7
|
+
{
|
|
8
|
+
"role": "logging",
|
|
9
|
+
"reason": "Every KV facade operation emits a metadata-only lifecycle event through the applied logger; a logging companion supplies the sink factory."
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"role": "errorHandling",
|
|
13
|
+
"reason": "A KV read or write failure constructs an internal error record; an error-handling companion supplies the record factory and the boundary."
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"elicits": [
|
|
17
|
+
{
|
|
18
|
+
"id": "kv-binding-name",
|
|
19
|
+
"prompt": "What is the KV namespace binding name to use in wrangler.toml? (default: CACHE)",
|
|
20
|
+
"kind": "string",
|
|
21
|
+
"default": "CACHE"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "kv-default-cache-ttl-seconds",
|
|
25
|
+
"prompt": "Default cache-aside TTL in seconds (floor 1, per ADR-3202; the shipped default aligns with the Cloudflare KV documented 60-second cache TTL)",
|
|
26
|
+
"kind": "string",
|
|
27
|
+
"default": "60"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "kv-metadata-field-pattern",
|
|
31
|
+
"prompt": "Default metadata field pattern on put and getWithMetadata (JSON serialisable object; recommended default {v: number} for a per-key schema version)",
|
|
32
|
+
"kind": "string",
|
|
33
|
+
"default": "{\"v\":1}"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "kv-key-naming-convention",
|
|
37
|
+
"prompt": "Key naming convention: prefixed (domain prefix like users/, flags/) or flat (per ADR-3203; recommended default prefixed)",
|
|
38
|
+
"kind": "enum",
|
|
39
|
+
"options": ["prefixed", "flat"],
|
|
40
|
+
"default": "prefixed"
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"contributions": [
|
|
44
|
+
{ "id": "platform-cloudflare-kv-REQ-001", "kind": "req", "path": "requirements/platform-cloudflare-kv-req-001.json" },
|
|
45
|
+
{ "id": "platform-cloudflare-kv-REQ-002", "kind": "req", "path": "requirements/platform-cloudflare-kv-req-002.json" },
|
|
46
|
+
{ "id": "platform-cloudflare-kv-REQ-003", "kind": "req", "path": "requirements/platform-cloudflare-kv-req-003.json" },
|
|
47
|
+
{ "id": "platform-cloudflare-kv-REQ-004", "kind": "req", "path": "requirements/platform-cloudflare-kv-req-004.json" },
|
|
48
|
+
{ "id": "platform-cloudflare-kv-REQ-005", "kind": "req", "path": "requirements/platform-cloudflare-kv-req-005.json" },
|
|
49
|
+
{ "id": "platform-cloudflare-kv-US-31101", "kind": "us", "path": "user-stories/platform-cloudflare-kv-us-31101.json" },
|
|
50
|
+
{ "id": "platform-cloudflare-kv-US-31102", "kind": "us", "path": "user-stories/platform-cloudflare-kv-us-31102.json" },
|
|
51
|
+
{ "id": "platform-cloudflare-kv-US-31103", "kind": "us", "path": "user-stories/platform-cloudflare-kv-us-31103.json" },
|
|
52
|
+
{ "id": "platform-cloudflare-kv-US-31104", "kind": "us", "path": "user-stories/platform-cloudflare-kv-us-31104.json" },
|
|
53
|
+
{ "id": "platform-cloudflare-kv-US-31105", "kind": "us", "path": "user-stories/platform-cloudflare-kv-us-31105.json" },
|
|
54
|
+
{ "id": "platform-cloudflare-kv-US-31106", "kind": "us", "path": "user-stories/platform-cloudflare-kv-us-31106.json" },
|
|
55
|
+
{ "id": "platform-cloudflare-kv-US-31107", "kind": "us", "path": "user-stories/platform-cloudflare-kv-us-31107.json" },
|
|
56
|
+
{ "id": "platform-cloudflare-kv-US-31108", "kind": "us", "path": "user-stories/platform-cloudflare-kv-us-31108.json" },
|
|
57
|
+
{ "id": "TAC-3201-platform-cloudflare-kv-facade", "kind": "tac", "path": "tacs/tac-3201-platform-cloudflare-kv-facade.json" },
|
|
58
|
+
{ "id": "TAC-3202-platform-cloudflare-kv-cache-aside", "kind": "tac", "path": "tacs/tac-3202-platform-cloudflare-kv-cache-aside.json" },
|
|
59
|
+
{ "id": "TAC-3203-platform-cloudflare-kv-event-sink", "kind": "tac", "path": "tacs/tac-3203-platform-cloudflare-kv-event-sink.json" },
|
|
60
|
+
{
|
|
61
|
+
"id": "ADR-3201-platform-cloudflare-kv-key-value-store-contract",
|
|
62
|
+
"kind": "adr",
|
|
63
|
+
"path": "adrs/adr-3201-platform-cloudflare-kv-key-value-store-contract.json",
|
|
64
|
+
"scope": "global",
|
|
65
|
+
"topic": "keyValueStoreContract",
|
|
66
|
+
"recommendedDefault": true,
|
|
67
|
+
"elicited": false,
|
|
68
|
+
"standardsTraceClause": "Cloudflare Workers KV documented consistency model"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": "ADR-3202-platform-cloudflare-kv-default-cache-ttl",
|
|
72
|
+
"kind": "adr",
|
|
73
|
+
"path": "adrs/adr-3202-platform-cloudflare-kv-default-cache-ttl.json",
|
|
74
|
+
"recommendedDefault": true,
|
|
75
|
+
"elicited": true,
|
|
76
|
+
"standardsTraceClause": "generic enterprise practice"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": "ADR-3203-platform-cloudflare-kv-key-naming-convention",
|
|
80
|
+
"kind": "adr",
|
|
81
|
+
"path": "adrs/adr-3203-platform-cloudflare-kv-key-naming-convention.json",
|
|
82
|
+
"recommendedDefault": true,
|
|
83
|
+
"elicited": true,
|
|
84
|
+
"standardsTraceClause": "generic enterprise practice"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-3201-platform-cloudflare-kv-key-value-store-contract",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Key-value store contract: Cloudflare Workers KV as the shipped shape (scope global, new topic keyValueStoreContract)",
|
|
8
|
+
"context": "An applying Workers project has one native key-value store answer today: Cloudflare Workers KV. The binding is declared through wrangler configuration ([[kv_namespaces]] with binding, id and preview_id) and the shipped runtime binds env.<binding> to an object with get, getWithMetadata, put, delete and list per https://developers.cloudflare.com/kv/api/. KV is eventually consistent: a write may not appear on a global read within the same request, and changes may take up to 60 seconds or more to be visible in other network locations as their cached versions time out (https://developers.cloudflare.com/kv/concepts/how-kv-works/). The v1.0.0 facade must hold the adapter reference opaque at the facade boundary so a future non-Cloudflare adapter or an in-memory adapter for tests slots in without a facade re-shape, and so the round-6 Durable Objects sibling (T-3) is the shipped answer for strong-consistency needs.",
|
|
9
|
+
"decision": "The shipped v1.0.0 default is Cloudflare Workers KV, wired through wrangler config ([[kv_namespaces]] with binding, id and preview_id) per https://developers.cloudflare.com/kv/. The facade module (TAC-3201) is the sole holder of the KV binding reference per REQ-001. The keyValueStoreContract topic scope is global on this blueprint; the topic string is keyValueStoreContract (lower camelCase, one concept per topic, no version suffix, per the round-2 rules-for-new-topics clause on the shelf registry). A future non-KV adapter (a Redis-shape store, a strong-consistency DO cell for a single-owner use case) would contribute the same topic string with a different answer, forcing a DELIBERATE conflict the operator resolves with a project-level ADR per the round-2 conflict pattern.",
|
|
10
|
+
"consequences": "The applying project inherits Workers KV wire-format, the platform-assigned per-namespace limits (https://developers.cloudflare.com/kv/platform/limits/) and the documented eventual-consistency semantics. Standards trace clause: Cloudflare Workers KV documented consistency model (per https://developers.cloudflare.com/kv/concepts/how-kv-works/). Consumer code needing strong-consistency semantics reaches for the round-6 T-3 platform-cloudflare-durable-objects sibling instead; the guide carries the decision-tree cross-reference.",
|
|
11
|
+
"alternativesConsidered": [],
|
|
12
|
+
"createdAt": "2026-09-07T10:28:32.000Z",
|
|
13
|
+
"updatedAt": "2026-09-07T10:28:32.000Z"
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-3202-platform-cloudflare-kv-default-cache-ttl",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Default cache-aside TTL: 60 seconds shipped, floor 1 second, no ceiling",
|
|
8
|
+
"context": "The cache-aside helper writes back to KV with an expirationTtl on every miss; the applied project elicits the default TTL. Cloudflare documents a default cache TTL of 60 seconds on the read path (https://developers.cloudflare.com/kv/concepts/how-kv-works/); aligning the cache-aside default with the vendor default keeps two staleness ceilings synchronised.",
|
|
9
|
+
"decision": "Ship 60 seconds as the elicited default TTL for cache-aside. The helper enforces a 1-second floor on every per-call TTL (a misconfigured project cannot ship a sub-second TTL through the cache-aside seam). No upper ceiling is imposed by the helper; the Cloudflare KV documented per-namespace limits at https://developers.cloudflare.com/kv/platform/limits/ are the vendor ceiling. The elicited answer is written into the applied project as the defaultCacheTtl argument on the facade factory; per-call overrides use cache.getOr(key, originFn, {ttl}).",
|
|
10
|
+
"consequences": "The applied project observes a bounded staleness ceiling that matches the elicited TTL. A project needing shorter staleness re-elicits with a smaller value at apply time; a project needing longer staleness re-elicits with a larger value. The 1-second floor prevents an accidental cache-thrash pattern where the writeback expires before the next read arrives.",
|
|
11
|
+
"alternativesConsidered": [],
|
|
12
|
+
"createdAt": "2026-09-07T10:28:32.000Z",
|
|
13
|
+
"updatedAt": "2026-09-07T10:28:32.000Z"
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-3203-platform-cloudflare-kv-key-naming-convention",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Key naming convention: prefix-per-domain shipped, flat allowed",
|
|
8
|
+
"context": "KV keys are string-typed and globally addressed within a namespace. Two shipped shapes exist for a small-to-medium application: flat (keys are their own domain identifier, no prefix) and prefixed (keys carry a domain prefix such as users/, flags/, sessions/). The shipped shape must be one; the elicited answer supports the other for projects that already carry a naming discipline.",
|
|
9
|
+
"decision": "Ship prefixed as the default (recommendedDefault: prefixed). The facade accepts an elicited keyPrefix; when set, every operation transparently rewrites the key with the prefix on the storage boundary and the domain code sees prefix-free keys. When the elicited answer is flat, the facade passes the key through verbatim. The prefix disambiguation is what makes list({prefix}) predictable across multiple domain concepts sharing one namespace.",
|
|
10
|
+
"consequences": "The applying project chooses the shape at apply time. The default prefixed shape is the shape the round-6 spec section 5.1 example ACs assume (users/1234/profile, flags/feature-0). A project already keyed flat re-elicits and the facade passes keys through.",
|
|
11
|
+
"alternativesConsidered": [],
|
|
12
|
+
"createdAt": "2026-09-07T10:28:32.000Z",
|
|
13
|
+
"updatedAt": "2026-09-07T10:28:32.000Z"
|
|
14
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Cache-aside hit-then-miss probe for platform-cloudflare-kv v1.0.0.
|
|
2
|
+
//
|
|
3
|
+
// Drives the cache-aside helper against the fixture facade under a
|
|
4
|
+
// fake clock:
|
|
5
|
+
//
|
|
6
|
+
// 1) First getOr(key, origin): miss, origin invoked, writeback,
|
|
7
|
+
// counter=1.
|
|
8
|
+
// 2) Second getOr within TTL: hit, origin NOT invoked, counter
|
|
9
|
+
// still 1.
|
|
10
|
+
// 3) Advance clock past TTL, third getOr: miss, origin invoked
|
|
11
|
+
// again, counter=2.
|
|
12
|
+
//
|
|
13
|
+
// Induced-failure switch SIMULATE_CACHE_MISS=true disables the
|
|
14
|
+
// writeback path (wraps the facade so put is a no-op); the probe
|
|
15
|
+
// observes two origin calls where one was expected and returns
|
|
16
|
+
// aggregateVerdict: fail with the missing writeback named.
|
|
17
|
+
//
|
|
18
|
+
// anchorAcId: AC-5201-1 (AC-5201-2 covered as an additional result).
|
|
19
|
+
// accountBound: false.
|
|
20
|
+
|
|
21
|
+
export const anchorAcId = 'AC-5201-1';
|
|
22
|
+
export const accountBound = false;
|
|
23
|
+
|
|
24
|
+
const SIMULATE_CACHE_MISS = process.env.SIMULATE_CACHE_MISS === 'true';
|
|
25
|
+
|
|
26
|
+
export default async function runProbe() {
|
|
27
|
+
const { createInMemoryKv } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/src/kv-driver.mjs');
|
|
28
|
+
const { createKvFacade } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/src/kv-facade.mjs');
|
|
29
|
+
const { createCacheAside } = await import('../../../../packages/rcf-lite/test/fixtures/cf-platform/src/cache-aside.mjs');
|
|
30
|
+
|
|
31
|
+
let now = 1_000_000_000_000;
|
|
32
|
+
const clock = () => now;
|
|
33
|
+
|
|
34
|
+
const binding = createInMemoryKv({ clock });
|
|
35
|
+
const rawFacade = createKvFacade({ binding, eventSink: () => {} });
|
|
36
|
+
const facade = SIMULATE_CACHE_MISS
|
|
37
|
+
? { ...rawFacade, put: async () => {} }
|
|
38
|
+
: rawFacade;
|
|
39
|
+
|
|
40
|
+
const cache = createCacheAside({ facade, defaultTtl: 5 });
|
|
41
|
+
|
|
42
|
+
let originCalls = 0;
|
|
43
|
+
const origin = async () => {
|
|
44
|
+
originCalls += 1;
|
|
45
|
+
return `origin-value-${originCalls}`;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const key = 'cache-aside/hit-then-miss';
|
|
49
|
+
|
|
50
|
+
const first = await cache.getOr(key, origin);
|
|
51
|
+
const second = await cache.getOr(key, origin);
|
|
52
|
+
now += 6 * 1000; // advance past 5-second TTL
|
|
53
|
+
const third = await cache.getOr(key, origin);
|
|
54
|
+
|
|
55
|
+
const results = [];
|
|
56
|
+
|
|
57
|
+
const withinTtlPass = originCalls >= 1 && second.source === 'cache' && first.value === second.value;
|
|
58
|
+
results.push({
|
|
59
|
+
anchorAcId: 'AC-5201-1',
|
|
60
|
+
verdict: SIMULATE_CACHE_MISS
|
|
61
|
+
? (originCalls > 1 && second.source === 'origin' ? 'fail' : 'fail')
|
|
62
|
+
: (withinTtlPass ? 'pass' : 'fail'),
|
|
63
|
+
detail: SIMULATE_CACHE_MISS
|
|
64
|
+
? `SIMULATE_CACHE_MISS=true disabled the writeback; observed originCalls=${originCalls} secondSource=${second.source} (expected 1 and cache under the shipped code path)`
|
|
65
|
+
: (withinTtlPass
|
|
66
|
+
? `first miss then cached: originCalls=${originCalls} secondSource=${second.source}`
|
|
67
|
+
: `within-TTL branch fault: originCalls=${originCalls} secondSource=${second.source}`),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const pastTtlPass = originCalls === 2 && third.source === 'origin';
|
|
71
|
+
results.push({
|
|
72
|
+
anchorAcId: 'AC-5201-2',
|
|
73
|
+
verdict: SIMULATE_CACHE_MISS ? 'fail' : (pastTtlPass ? 'pass' : 'fail'),
|
|
74
|
+
detail: SIMULATE_CACHE_MISS
|
|
75
|
+
? `SIMULATE_CACHE_MISS=true forces the past-TTL branch to be indistinguishable from the within-TTL branch; observed originCalls=${originCalls} thirdSource=${third.source}`
|
|
76
|
+
: (pastTtlPass
|
|
77
|
+
? `past-TTL read triggered origin: originCalls=${originCalls} thirdSource=${third.source}`
|
|
78
|
+
: `past-TTL branch fault: originCalls=${originCalls} thirdSource=${third.source}`),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return { results };
|
|
82
|
+
}
|