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.
Files changed (591) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/bin/rcf.js +13 -2
  3. package/blueprints/application-account-settings/docs/topics.md +9 -1
  4. package/blueprints/application-admin-console/CHANGELOG.md +12 -0
  5. package/blueprints/application-admin-console/blueprint.json +34 -1
  6. package/blueprints/application-admin-console/contributions/adrs/adr-2214-application-admin-console-consume-zero-trust-gate.json +25 -0
  7. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-014.json +17 -0
  8. package/blueprints/application-admin-console/contributions/tacs/tac-2214-application-admin-console-access-gated-signin-surface.json +32 -0
  9. package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21815.json +27 -0
  10. package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21816.json +27 -0
  11. package/blueprints/application-admin-console/docs/topics.md +9 -1
  12. package/blueprints/application-admin-console/guide/application-admin-console.md +24 -0
  13. package/blueprints/application-admin-console/probe-packs/application-admin-console.pack.mjs +26 -1
  14. package/blueprints/application-api-rest/docs/topics.md +9 -1
  15. package/blueprints/application-charts/docs/topics.md +9 -1
  16. package/blueprints/application-dashboard/docs/topics.md +9 -1
  17. package/blueprints/application-datatable/docs/topics.md +9 -1
  18. package/blueprints/application-empty-error-states/docs/topics.md +9 -1
  19. package/blueprints/application-error-handling/docs/topics.md +9 -1
  20. package/blueprints/application-file-upload/docs/topics.md +9 -1
  21. package/blueprints/application-forms-wizard/docs/topics.md +9 -1
  22. package/blueprints/application-notifications-in-app/docs/topics.md +9 -1
  23. package/blueprints/application-onboarding-tour/docs/topics.md +9 -1
  24. package/blueprints/application-spa/docs/topics.md +10 -2
  25. package/blueprints/delivery-ci-workflows/docs/topics.md +9 -1
  26. package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +69 -0
  27. package/blueprints/deploy-cloudflare-workers/README.md +12 -0
  28. package/blueprints/deploy-cloudflare-workers/blueprint.json +234 -36
  29. package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +30 -0
  30. package/blueprints/deploy-cloudflare-workers/contributions/probes/assets-manifest-scan.mjs +207 -0
  31. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-013.json +18 -0
  32. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-014.json +18 -0
  33. package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12113.json +36 -0
  34. package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12114.json +27 -0
  35. package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12115.json +27 -0
  36. package/blueprints/deploy-cloudflare-workers/docs/topics.md +10 -2
  37. package/blueprints/deploy-cloudflare-workers/guide/deploy-cloudflare-workers.md +25 -0
  38. package/blueprints/edge-cloudflare-access/CHANGELOG.md +23 -0
  39. package/blueprints/edge-cloudflare-access/README.md +141 -0
  40. package/blueprints/edge-cloudflare-access/blueprint.json +197 -0
  41. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3501-edge-cloudflare-access-jwt-gate.json +14 -0
  42. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3502-edge-cloudflare-access-identity-provider.json +25 -0
  43. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3503-edge-cloudflare-access-policy-scope.json +12 -0
  44. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3504-edge-cloudflare-access-audit-retention.json +12 -0
  45. package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +100 -0
  46. package/blueprints/edge-cloudflare-access/contributions/probes/audit-event-secrecy.mjs +70 -0
  47. package/blueprints/edge-cloudflare-access/contributions/probes/jwt-validator-fixture.mjs +63 -0
  48. package/blueprints/edge-cloudflare-access/contributions/probes/jwt-validator-reject.mjs +95 -0
  49. package/blueprints/edge-cloudflare-access/contributions/probes/probe-utils.mjs +90 -0
  50. package/blueprints/edge-cloudflare-access/contributions/probes/real-account-gated-url.mjs +65 -0
  51. package/blueprints/edge-cloudflare-access/contributions/probes/run-admin-console-gate-surface.mjs +5 -0
  52. package/blueprints/edge-cloudflare-access/contributions/probes/run-audit-event-secrecy.mjs +5 -0
  53. package/blueprints/edge-cloudflare-access/contributions/probes/run-jwt-validator-fixture.mjs +5 -0
  54. package/blueprints/edge-cloudflare-access/contributions/probes/run-jwt-validator-reject.mjs +5 -0
  55. package/blueprints/edge-cloudflare-access/contributions/probes/run-real-account-gated-url.mjs +5 -0
  56. package/blueprints/edge-cloudflare-access/contributions/probes/run-wrangler-seam.mjs +5 -0
  57. package/blueprints/edge-cloudflare-access/contributions/probes/wrangler-seam.mjs +203 -0
  58. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-001.json +17 -0
  59. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-002.json +17 -0
  60. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-003.json +17 -0
  61. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-004.json +17 -0
  62. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-005.json +17 -0
  63. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-006.json +18 -0
  64. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3501-edge-cloudflare-access-jwt-validator.json +31 -0
  65. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3502-edge-cloudflare-access-application-declaration.json +33 -0
  66. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3503-edge-cloudflare-access-policy-shape.json +25 -0
  67. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3504-edge-cloudflare-access-audit-sink.json +25 -0
  68. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34101.json +27 -0
  69. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34102.json +28 -0
  70. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34103.json +27 -0
  71. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34104.json +27 -0
  72. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34105.json +27 -0
  73. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34106.json +27 -0
  74. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34107.json +27 -0
  75. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34108.json +27 -0
  76. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34109.json +27 -0
  77. package/blueprints/edge-cloudflare-access/docs/topics.md +68 -0
  78. package/blueprints/edge-cloudflare-access/guide/edge-cloudflare-access.md +180 -0
  79. package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +10 -0
  80. package/blueprints/edge-cloudflare-rate-limiting/README.md +73 -0
  81. package/blueprints/edge-cloudflare-rate-limiting/blueprint.json +174 -0
  82. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3701-edge-cloudflare-rate-limiting-throttle-contract.json +14 -0
  83. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3702-edge-cloudflare-rate-limiting-layering.json +14 -0
  84. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3703-edge-cloudflare-rate-limiting-manifest-shape.json +14 -0
  85. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3704-edge-cloudflare-rate-limiting-drift-audit-cadence.json +14 -0
  86. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/event-secrecy.mjs +104 -0
  87. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/manifest-presence.mjs +95 -0
  88. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/manifest-schema-validate.mjs +130 -0
  89. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/probe-utils.mjs +111 -0
  90. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/real-account-burst-and-429.mjs +104 -0
  91. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-event-secrecy.mjs +5 -0
  92. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-manifest-presence.mjs +5 -0
  93. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-manifest-schema-validate.mjs +5 -0
  94. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-real-account-burst-and-429.mjs +5 -0
  95. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-001.json +17 -0
  96. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-002.json +17 -0
  97. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-003.json +17 -0
  98. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-004.json +17 -0
  99. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-005.json +17 -0
  100. package/blueprints/edge-cloudflare-rate-limiting/contributions/schemas/rate-limit-rule.schema.json +67 -0
  101. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json +31 -0
  102. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json +25 -0
  103. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json +26 -0
  104. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36101.json +27 -0
  105. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36102.json +27 -0
  106. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36103.json +27 -0
  107. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36104.json +27 -0
  108. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36105.json +27 -0
  109. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36106.json +27 -0
  110. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36107.json +27 -0
  111. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36108.json +27 -0
  112. package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +68 -0
  113. package/blueprints/edge-cloudflare-rate-limiting/guide/edge-cloudflare-rate-limiting.md +88 -0
  114. package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +20 -0
  115. package/blueprints/edge-cloudflare-turnstile/README.md +95 -0
  116. package/blueprints/edge-cloudflare-turnstile/blueprint.json +161 -0
  117. package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3601-edge-cloudflare-turnstile-verifier-contract.json +14 -0
  118. package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3602-edge-cloudflare-turnstile-widget-mode.json +14 -0
  119. package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3603-edge-cloudflare-turnstile-refuse-shape.json +14 -0
  120. package/blueprints/edge-cloudflare-turnstile/contributions/probes/event-secrecy.mjs +51 -0
  121. package/blueprints/edge-cloudflare-turnstile/contributions/probes/guard-shape-scan.mjs +48 -0
  122. package/blueprints/edge-cloudflare-turnstile/contributions/probes/probe-utils.mjs +139 -0
  123. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-event-secrecy.mjs +5 -0
  124. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-guard-shape-scan.mjs +5 -0
  125. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-secret-shape-scan.mjs +5 -0
  126. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-siteverify-fixture.mjs +5 -0
  127. package/blueprints/edge-cloudflare-turnstile/contributions/probes/secret-shape-scan.mjs +77 -0
  128. package/blueprints/edge-cloudflare-turnstile/contributions/probes/siteverify-fixture.mjs +53 -0
  129. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-001.json +17 -0
  130. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-002.json +17 -0
  131. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-003.json +17 -0
  132. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-004.json +17 -0
  133. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-005.json +17 -0
  134. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json +26 -0
  135. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json +36 -0
  136. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json +25 -0
  137. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35101.json +27 -0
  138. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35102.json +27 -0
  139. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35103.json +27 -0
  140. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35104.json +27 -0
  141. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35105.json +36 -0
  142. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35106.json +27 -0
  143. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35107.json +27 -0
  144. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35108.json +27 -0
  145. package/blueprints/edge-cloudflare-turnstile/docs/topics.md +68 -0
  146. package/blueprints/edge-cloudflare-turnstile/guide/edge-cloudflare-turnstile.md +104 -0
  147. package/blueprints/edge-cloudflare-turnstile/probe-packs/edge-cloudflare-turnstile.pack.mjs +146 -0
  148. package/blueprints/email-smtp-resend/docs/topics.md +9 -1
  149. package/blueprints/jobs-background/CHANGELOG.md +16 -0
  150. package/blueprints/jobs-background/README.md +105 -0
  151. package/blueprints/jobs-background/blueprint.json +149 -0
  152. package/blueprints/jobs-background/contributions/adrs/adr-3101-jobs-background-model.json +27 -0
  153. package/blueprints/jobs-background/contributions/adrs/adr-3102-jobs-background-scheduler-mode.json +25 -0
  154. package/blueprints/jobs-background/contributions/adrs/adr-3103-jobs-background-requires-applied-capabilities.json +25 -0
  155. package/blueprints/jobs-background/contributions/adrs/adr-3104-jobs-background-timeout-floor.json +25 -0
  156. package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +95 -0
  157. package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +82 -0
  158. package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +69 -0
  159. package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +65 -0
  160. package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +91 -0
  161. package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +65 -0
  162. package/blueprints/jobs-background/contributions/probes/run-apply-time-override.mjs +10 -0
  163. package/blueprints/jobs-background/contributions/probes/run-apply-time-refusal.mjs +11 -0
  164. package/blueprints/jobs-background/contributions/probes/run-event-secrecy.mjs +11 -0
  165. package/blueprints/jobs-background/contributions/probes/run-fake-clock-cron.mjs +11 -0
  166. package/blueprints/jobs-background/contributions/probes/run-retry-and-fail.mjs +11 -0
  167. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-001.json +18 -0
  168. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-002.json +18 -0
  169. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-003.json +18 -0
  170. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-004.json +18 -0
  171. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-005.json +18 -0
  172. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-006.json +18 -0
  173. package/blueprints/jobs-background/contributions/tacs/tac-3101-jobs-background-job-definition.json +50 -0
  174. package/blueprints/jobs-background/contributions/tacs/tac-3102-jobs-background-scheduler.json +50 -0
  175. package/blueprints/jobs-background/contributions/tacs/tac-3103-jobs-background-run-log.json +49 -0
  176. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30101.json +25 -0
  177. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30102.json +25 -0
  178. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30103.json +25 -0
  179. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30104.json +25 -0
  180. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30105.json +25 -0
  181. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30106.json +25 -0
  182. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30107.json +25 -0
  183. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30108.json +25 -0
  184. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30109.json +25 -0
  185. package/blueprints/jobs-background/docs/topics.md +68 -0
  186. package/blueprints/jobs-background/guide/jobs-background.md +147 -0
  187. package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +15 -0
  188. package/blueprints/messaging-queue-cloudflare/README.md +125 -0
  189. package/blueprints/messaging-queue-cloudflare/blueprint.json +67 -0
  190. package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +30 -0
  191. package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +25 -0
  192. package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3003-messaging-queue-cloudflare-max-attempts-floor.json +25 -0
  193. package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3004-messaging-queue-cloudflare-batch-defaults.json +25 -0
  194. package/blueprints/messaging-queue-cloudflare/contributions/probes/event-secrecy.mjs +137 -0
  195. package/blueprints/messaging-queue-cloudflare/contributions/probes/probe-utils.mjs +82 -0
  196. package/blueprints/messaging-queue-cloudflare/contributions/probes/producer-facade-ready.mjs +35 -0
  197. package/blueprints/messaging-queue-cloudflare/contributions/probes/publish-to-delivery.mjs +94 -0
  198. package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +54 -0
  199. package/blueprints/messaging-queue-cloudflare/contributions/probes/retry-and-dlq.mjs +87 -0
  200. package/blueprints/messaging-queue-cloudflare/contributions/probes/run-event-secrecy.mjs +5 -0
  201. package/blueprints/messaging-queue-cloudflare/contributions/probes/run-producer-facade-ready.mjs +11 -0
  202. package/blueprints/messaging-queue-cloudflare/contributions/probes/run-publish-to-delivery.mjs +5 -0
  203. package/blueprints/messaging-queue-cloudflare/contributions/probes/run-real-account-concurrency-smoke.mjs +5 -0
  204. package/blueprints/messaging-queue-cloudflare/contributions/probes/run-retry-and-dlq.mjs +5 -0
  205. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-001.json +18 -0
  206. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-002.json +18 -0
  207. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-003.json +18 -0
  208. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-004.json +18 -0
  209. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-005.json +18 -0
  210. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +18 -0
  211. package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3001-messaging-queue-cloudflare-producer-facade.json +56 -0
  212. package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3002-messaging-queue-cloudflare-consumer-registration.json +40 -0
  213. package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3003-messaging-queue-cloudflare-event-sink.json +39 -0
  214. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29101.json +34 -0
  215. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29102.json +34 -0
  216. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29103.json +25 -0
  217. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29104.json +25 -0
  218. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29105.json +25 -0
  219. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29106.json +25 -0
  220. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29107.json +25 -0
  221. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29108.json +25 -0
  222. package/blueprints/messaging-queue-cloudflare/docs/topics.md +68 -0
  223. package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +110 -0
  224. package/blueprints/object-storage-s3/docs/topics.md +9 -1
  225. package/blueprints/observability-essentials/docs/topics.md +9 -1
  226. package/blueprints/observability-logging/docs/topics.md +9 -1
  227. package/blueprints/observability-probe-endpoints/docs/topics.md +9 -1
  228. package/blueprints/persistence-data-d1/docs/topics.md +9 -1
  229. package/blueprints/persistence-data-postgres/docs/topics.md +9 -1
  230. package/blueprints/persistence-data-sqlite/docs/topics.md +9 -1
  231. package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +22 -0
  232. package/blueprints/platform-cloudflare-cron-triggers/README.md +117 -0
  233. package/blueprints/platform-cloudflare-cron-triggers/blueprint.json +85 -0
  234. package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3301-platform-cloudflare-cron-triggers-scheduled-trigger-contract.json +14 -0
  235. package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3302-platform-cloudflare-cron-triggers-dispatcher-mode.json +14 -0
  236. package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3303-platform-cloudflare-cron-triggers-skew-tolerance-default.json +14 -0
  237. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/dispatcher-routing.mjs +64 -0
  238. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/event-secrecy.mjs +100 -0
  239. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/probe-utils.mjs +70 -0
  240. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/real-account-scheduled-smoke.mjs +100 -0
  241. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-dispatcher-routing.mjs +5 -0
  242. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-event-secrecy.mjs +5 -0
  243. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-real-account-scheduled-smoke.mjs +5 -0
  244. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-skew-tolerance.mjs +5 -0
  245. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-wrangler-test-scheduled.mjs +5 -0
  246. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/skew-tolerance.mjs +130 -0
  247. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/wrangler-test-scheduled.mjs +129 -0
  248. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-001.json +17 -0
  249. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-002.json +17 -0
  250. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-003.json +17 -0
  251. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-004.json +17 -0
  252. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3301-platform-cloudflare-cron-triggers-scheduled-handler.json +22 -0
  253. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3302-platform-cloudflare-cron-triggers-expression-router.json +22 -0
  254. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3303-platform-cloudflare-cron-triggers-event-sink.json +21 -0
  255. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32101.json +25 -0
  256. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32102.json +34 -0
  257. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32103.json +34 -0
  258. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32104.json +34 -0
  259. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32105.json +25 -0
  260. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32106.json +25 -0
  261. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32107.json +25 -0
  262. package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +71 -0
  263. package/blueprints/platform-cloudflare-cron-triggers/guide/platform-cloudflare-cron-triggers.md +119 -0
  264. package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +23 -0
  265. package/blueprints/platform-cloudflare-durable-objects/README.md +200 -0
  266. package/blueprints/platform-cloudflare-durable-objects/blueprint.json +243 -0
  267. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3401-platform-cloudflare-durable-objects-single-cell-contract.json +14 -0
  268. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3402-platform-cloudflare-durable-objects-websocket-hub-contract.json +14 -0
  269. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3403-platform-cloudflare-durable-objects-storage-backend.json +14 -0
  270. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3404-platform-cloudflare-durable-objects-migrations-shape.json +14 -0
  271. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3405-platform-cloudflare-durable-objects-hibernation-posture.json +14 -0
  272. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/alarm-fires-once.mjs +63 -0
  273. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/namespace-facade-ready.mjs +60 -0
  274. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/probe-utils.mjs +105 -0
  275. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/real-account-storage-smoke.mjs +58 -0
  276. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-alarm-fires-once.mjs +5 -0
  277. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-namespace-facade-ready.mjs +5 -0
  278. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-real-account-storage-smoke.mjs +5 -0
  279. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-single-cell-concurrent-increment.mjs +5 -0
  280. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-sole-reader-scan.mjs +5 -0
  281. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-storage-round-trip.mjs +5 -0
  282. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-websocket-hub-broadcast.mjs +5 -0
  283. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-wrangler-seam.mjs +5 -0
  284. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/single-cell-concurrent-increment.mjs +56 -0
  285. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/sole-reader-scan.mjs +117 -0
  286. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/storage-round-trip.mjs +87 -0
  287. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/websocket-hub-broadcast.mjs +112 -0
  288. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/wrangler-seam.mjs +257 -0
  289. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-001.json +17 -0
  290. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-002.json +17 -0
  291. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-003.json +17 -0
  292. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-004.json +17 -0
  293. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-005.json +17 -0
  294. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-006.json +17 -0
  295. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-007.json +17 -0
  296. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-008.json +17 -0
  297. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3401-platform-cloudflare-durable-objects-namespace-facade.json +31 -0
  298. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3402-platform-cloudflare-durable-objects-single-cell-shape.json +30 -0
  299. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3403-platform-cloudflare-durable-objects-alarm-handler.json +29 -0
  300. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3404-platform-cloudflare-durable-objects-websocket-hub.json +31 -0
  301. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3405-platform-cloudflare-durable-objects-event-sink.json +24 -0
  302. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33101.json +27 -0
  303. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33102.json +27 -0
  304. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33103.json +27 -0
  305. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33104.json +27 -0
  306. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33105.json +27 -0
  307. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33106.json +27 -0
  308. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33107.json +27 -0
  309. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33108.json +27 -0
  310. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33109.json +27 -0
  311. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33110.json +27 -0
  312. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33111.json +27 -0
  313. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33112.json +27 -0
  314. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33113.json +25 -0
  315. package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +73 -0
  316. package/blueprints/platform-cloudflare-durable-objects/guide/platform-cloudflare-durable-objects.md +237 -0
  317. package/blueprints/platform-cloudflare-kv/CHANGELOG.md +21 -0
  318. package/blueprints/platform-cloudflare-kv/README.md +159 -0
  319. package/blueprints/platform-cloudflare-kv/blueprint.json +87 -0
  320. package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3201-platform-cloudflare-kv-key-value-store-contract.json +14 -0
  321. package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3202-platform-cloudflare-kv-default-cache-ttl.json +14 -0
  322. package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3203-platform-cloudflare-kv-key-naming-convention.json +14 -0
  323. package/blueprints/platform-cloudflare-kv/contributions/probes/cache-aside-hit-then-miss.mjs +82 -0
  324. package/blueprints/platform-cloudflare-kv/contributions/probes/event-secrecy.mjs +102 -0
  325. package/blueprints/platform-cloudflare-kv/contributions/probes/facade-round-trip.mjs +92 -0
  326. package/blueprints/platform-cloudflare-kv/contributions/probes/list-with-prefix.mjs +52 -0
  327. package/blueprints/platform-cloudflare-kv/contributions/probes/probe-utils.mjs +73 -0
  328. package/blueprints/platform-cloudflare-kv/contributions/probes/real-account-eventual-consistency-smoke.mjs +102 -0
  329. package/blueprints/platform-cloudflare-kv/contributions/probes/run-cache-aside-hit-then-miss.mjs +5 -0
  330. package/blueprints/platform-cloudflare-kv/contributions/probes/run-event-secrecy.mjs +5 -0
  331. package/blueprints/platform-cloudflare-kv/contributions/probes/run-facade-round-trip.mjs +5 -0
  332. package/blueprints/platform-cloudflare-kv/contributions/probes/run-list-with-prefix.mjs +5 -0
  333. package/blueprints/platform-cloudflare-kv/contributions/probes/run-real-account-eventual-consistency-smoke.mjs +5 -0
  334. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-001.json +18 -0
  335. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-002.json +18 -0
  336. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-003.json +18 -0
  337. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-004.json +18 -0
  338. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-005.json +18 -0
  339. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3201-platform-cloudflare-kv-facade.json +27 -0
  340. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3202-platform-cloudflare-kv-cache-aside.json +26 -0
  341. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3203-platform-cloudflare-kv-event-sink.json +25 -0
  342. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31101.json +27 -0
  343. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31102.json +27 -0
  344. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31103.json +36 -0
  345. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31104.json +27 -0
  346. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31105.json +27 -0
  347. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31106.json +27 -0
  348. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31107.json +27 -0
  349. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31108.json +27 -0
  350. package/blueprints/platform-cloudflare-kv/docs/topics.md +71 -0
  351. package/blueprints/platform-cloudflare-kv/guide/platform-cloudflare-kv.md +138 -0
  352. package/blueprints/security-auth-clerk/docs/topics.md +9 -1
  353. package/blueprints/security-auth-keycloak/docs/topics.md +9 -1
  354. package/blueprints/security-auth-magic-link/docs/topics.md +9 -1
  355. package/blueprints/security-auth-oauth2/docs/topics.md +9 -1
  356. package/blueprints/security-secrets-management/docs/topics.md +9 -1
  357. package/fixtures/canary-manifest.json +6 -6
  358. package/package.json +1 -1
  359. package/rcf/adrs/adr-2214-application-admin-console-consume-zero-trust-gate.json +13 -0
  360. package/rcf/adrs/adr-3501-edge-cloudflare-access-jwt-gate.json +13 -0
  361. package/rcf/adrs/adr-3502-edge-cloudflare-access-identity-provider.json +13 -0
  362. package/rcf/adrs/adr-3503-edge-cloudflare-access-policy-scope.json +13 -0
  363. package/rcf/adrs/adr-3504-edge-cloudflare-access-audit-retention.json +13 -0
  364. package/rcf/adrs/adr-3601-edge-cloudflare-turnstile-verifier-contract.json +13 -0
  365. package/rcf/adrs/adr-3602-edge-cloudflare-turnstile-widget-mode.json +13 -0
  366. package/rcf/adrs/adr-3603-edge-cloudflare-turnstile-refuse-shape.json +13 -0
  367. package/rcf/adrs/adr-3701-edge-cloudflare-rate-limiting-throttle-contract.json +13 -0
  368. package/rcf/adrs/adr-3702-edge-cloudflare-rate-limiting-layering.json +13 -0
  369. package/rcf/adrs/adr-3703-edge-cloudflare-rate-limiting-manifest-shape.json +13 -0
  370. package/rcf/adrs/adr-3704-edge-cloudflare-rate-limiting-drift-audit-cadence.json +13 -0
  371. package/rcf/code-nodes/cn-206.json +14 -0
  372. package/rcf/code-nodes/cn-207.json +13 -0
  373. package/rcf/code-nodes/cn-208.json +14 -0
  374. package/rcf/code-nodes/cn-209.json +14 -0
  375. package/rcf/code-nodes/cn-210.json +13 -0
  376. package/rcf/code-nodes/cn-211.json +12 -0
  377. package/rcf/code-nodes/cn-212.json +12 -0
  378. package/rcf/code-nodes/cn-213.json +12 -0
  379. package/rcf/code-nodes/cn-214.json +15 -0
  380. package/rcf/code-nodes/cn-215.json +13 -0
  381. package/rcf/code-nodes/cn-216.json +14 -0
  382. package/rcf/code-nodes/cn-217.json +13 -0
  383. package/rcf/code-nodes/cn-230.json +13 -0
  384. package/rcf/code-nodes/cn-231.json +14 -0
  385. package/rcf/code-nodes/cn-232.json +13 -0
  386. package/rcf/code-nodes/cn-233.json +14 -0
  387. package/rcf/code-nodes/cn-234.json +13 -0
  388. package/rcf/code-nodes/cn-260.json +21 -0
  389. package/rcf/code-nodes/cn-261.json +14 -0
  390. package/rcf/code-nodes/cn-262.json +18 -0
  391. package/rcf/code-nodes/cn-263.json +12 -0
  392. package/rcf/code-nodes/cn-264.json +13 -0
  393. package/rcf/code-nodes/cn-265.json +15 -0
  394. package/rcf/code-nodes/cn-266.json +12 -0
  395. package/rcf/code-nodes/cn-267.json +12 -0
  396. package/rcf/code-nodes/cn-290.json +21 -0
  397. package/rcf/code-nodes/cn-291.json +12 -0
  398. package/rcf/code-nodes/cn-292.json +13 -0
  399. package/rcf/code-nodes/cn-293.json +13 -0
  400. package/rcf/code-nodes/cn-294.json +13 -0
  401. package/rcf/code-nodes/cn-295.json +12 -0
  402. package/rcf/code-nodes/cn-296.json +12 -0
  403. package/rcf/code-nodes/cn-297.json +12 -0
  404. package/rcf/code-nodes/cn-298.json +12 -0
  405. package/rcf/code-nodes/cn-299.json +12 -0
  406. package/rcf/code-nodes/cn-300.json +12 -0
  407. package/rcf/code-nodes/cn-301.json +14 -0
  408. package/rcf/code-nodes/cn-302.json +12 -0
  409. package/rcf/code-nodes/cn-303.json +12 -0
  410. package/rcf/code-nodes/cn-304.json +21 -0
  411. package/rcf/code-nodes/cn-320.json +20 -0
  412. package/rcf/code-nodes/cn-321.json +14 -0
  413. package/rcf/code-nodes/cn-350.json +19 -0
  414. package/rcf/code-nodes/cn-380.json +19 -0
  415. package/rcf/fbs/fbs-062.json +20 -0
  416. package/rcf/fbs/fbs-063.json +22 -0
  417. package/rcf/fbs/fbs-064.json +23 -0
  418. package/rcf/fbs/fbs-070.json +24 -0
  419. package/rcf/fbs/fbs-080.json +24 -0
  420. package/rcf/fbs/fbs-090.json +24 -0
  421. package/rcf/fbs/fbs-100.json +23 -0
  422. package/rcf/fbs/fbs-101.json +16 -0
  423. package/rcf/fbs/fbs-110.json +23 -0
  424. package/rcf/fbs/fbs-120.json +22 -0
  425. package/rcf/requirements/req-029.json +57 -0
  426. package/rcf/requirements/req-030.json +67 -0
  427. package/rcf/requirements/req-042.json +59 -0
  428. package/rcf/requirements/req-043.json +39 -0
  429. package/rcf/requirements/req-050.json +18 -0
  430. package/rcf/requirements/req-051.json +18 -0
  431. package/rcf/requirements/req-052.json +18 -0
  432. package/rcf/requirements/req-053.json +18 -0
  433. package/rcf/requirements/req-054.json +18 -0
  434. package/rcf/requirements/req-060.json +20 -0
  435. package/rcf/requirements/req-061.json +18 -0
  436. package/rcf/requirements/req-062.json +20 -0
  437. package/rcf/requirements/req-063.json +20 -0
  438. package/rcf/requirements/req-070.json +18 -0
  439. package/rcf/requirements/req-071.json +18 -0
  440. package/rcf/requirements/req-072.json +18 -0
  441. package/rcf/requirements/req-073.json +18 -0
  442. package/rcf/requirements/req-074.json +18 -0
  443. package/rcf/requirements/req-075.json +18 -0
  444. package/rcf/requirements/req-076.json +18 -0
  445. package/rcf/requirements/req-077.json +18 -0
  446. package/rcf/requirements/req-080.json +18 -0
  447. package/rcf/requirements/req-081.json +18 -0
  448. package/rcf/requirements/req-082.json +18 -0
  449. package/rcf/requirements/req-083.json +18 -0
  450. package/rcf/requirements/req-084.json +18 -0
  451. package/rcf/requirements/req-085.json +18 -0
  452. package/rcf/requirements/req-086.json +18 -0
  453. package/rcf/requirements/req-090.json +44 -0
  454. package/rcf/requirements/req-091.json +53 -0
  455. package/rcf/requirements/req-092.json +32 -0
  456. package/rcf/requirements/req-093.json +52 -0
  457. package/rcf/requirements/req-094.json +32 -0
  458. package/rcf/requirements/req-100.json +13 -0
  459. package/rcf/requirements/req-101.json +13 -0
  460. package/rcf/requirements/req-102.json +13 -0
  461. package/rcf/requirements/req-103.json +13 -0
  462. package/rcf/requirements/req-104.json +13 -0
  463. package/rcf/tacs/tac-2214-application-admin-console-access-gated-signin-surface.json +15 -0
  464. package/rcf/tacs/tac-3501-edge-cloudflare-access-jwt-validator.json +15 -0
  465. package/rcf/tacs/tac-3502-edge-cloudflare-access-application-declaration.json +15 -0
  466. package/rcf/tacs/tac-3503-edge-cloudflare-access-policy-shape.json +15 -0
  467. package/rcf/tacs/tac-3504-edge-cloudflare-access-audit-sink.json +15 -0
  468. package/rcf/tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json +15 -0
  469. package/rcf/tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json +15 -0
  470. package/rcf/tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json +15 -0
  471. package/rcf/tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json +16 -0
  472. package/rcf/tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json +15 -0
  473. package/rcf/tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json +16 -0
  474. package/rcf/test-suites/ts-052.json +58 -8
  475. package/rcf/test-suites/ts-072.json +62 -0
  476. package/rcf/test-suites/ts-073.json +38 -0
  477. package/rcf/test-suites/ts-074.json +30 -0
  478. package/rcf/test-suites/ts-075.json +38 -0
  479. package/rcf/test-suites/ts-076.json +70 -0
  480. package/rcf/test-suites/ts-080.json +22 -0
  481. package/rcf/test-suites/ts-081.json +22 -0
  482. package/rcf/test-suites/ts-082.json +30 -0
  483. package/rcf/test-suites/ts-083.json +22 -0
  484. package/rcf/test-suites/ts-084.json +30 -0
  485. package/rcf/test-suites/ts-085.json +22 -0
  486. package/rcf/test-suites/ts-086.json +22 -0
  487. package/rcf/test-suites/ts-087.json +22 -0
  488. package/rcf/test-suites/ts-090.json +22 -0
  489. package/rcf/test-suites/ts-091.json +22 -0
  490. package/rcf/test-suites/ts-092.json +22 -0
  491. package/rcf/test-suites/ts-093.json +30 -0
  492. package/rcf/test-suites/ts-094.json +30 -0
  493. package/rcf/test-suites/ts-095.json +30 -0
  494. package/rcf/test-suites/ts-096.json +22 -0
  495. package/rcf/test-suites/ts-100.json +22 -0
  496. package/rcf/test-suites/ts-101.json +22 -0
  497. package/rcf/test-suites/ts-102.json +22 -0
  498. package/rcf/test-suites/ts-103.json +22 -0
  499. package/rcf/test-suites/ts-104.json +22 -0
  500. package/rcf/test-suites/ts-105.json +22 -0
  501. package/rcf/test-suites/ts-106.json +22 -0
  502. package/rcf/test-suites/ts-107.json +22 -0
  503. package/rcf/test-suites/ts-108.json +22 -0
  504. package/rcf/test-suites/ts-109.json +22 -0
  505. package/rcf/test-suites/ts-110.json +22 -0
  506. package/rcf/test-suites/ts-111.json +22 -0
  507. package/rcf/test-suites/ts-112.json +22 -0
  508. package/rcf/test-suites/ts-113.json +22 -0
  509. package/rcf/test-suites/ts-114.json +22 -0
  510. package/rcf/test-suites/ts-115.json +22 -0
  511. package/rcf/test-suites/ts-116.json +22 -0
  512. package/rcf/test-suites/ts-117.json +22 -0
  513. package/rcf/test-suites/ts-118.json +22 -0
  514. package/rcf/test-suites/ts-119.json +30 -0
  515. package/rcf/test-suites/ts-120.json +22 -0
  516. package/rcf/test-suites/ts-121.json +22 -0
  517. package/rcf/test-suites/ts-122.json +22 -0
  518. package/rcf/test-suites/ts-123.json +22 -0
  519. package/rcf/test-suites/ts-124.json +22 -0
  520. package/rcf/test-suites/ts-125.json +22 -0
  521. package/rcf/test-suites/ts-126.json +22 -0
  522. package/rcf/test-suites/ts-127.json +22 -0
  523. package/rcf/test-suites/ts-130.json +22 -0
  524. package/rcf/test-suites/ts-131.json +22 -0
  525. package/rcf/test-suites/ts-132.json +22 -0
  526. package/rcf/test-suites/ts-133.json +22 -0
  527. package/rcf/test-suites/ts-134.json +22 -0
  528. package/rcf/test-suites/ts-135.json +22 -0
  529. package/rcf/test-suites/ts-136.json +22 -0
  530. package/rcf/test-suites/ts-137.json +22 -0
  531. package/rcf/user-stories/us-10001.json +23 -0
  532. package/rcf/user-stories/us-10101.json +23 -0
  533. package/rcf/user-stories/us-10201.json +23 -0
  534. package/rcf/user-stories/us-10301.json +23 -0
  535. package/rcf/user-stories/us-10401.json +23 -0
  536. package/rcf/user-stories/us-10601.json +23 -0
  537. package/rcf/user-stories/us-10701.json +23 -0
  538. package/rcf/user-stories/us-10801.json +23 -0
  539. package/rcf/user-stories/us-2901.json +45 -0
  540. package/rcf/user-stories/us-2902.json +36 -0
  541. package/rcf/user-stories/us-3001.json +45 -0
  542. package/rcf/user-stories/us-4201.json +69 -0
  543. package/rcf/user-stories/us-4301.json +78 -0
  544. package/rcf/user-stories/us-5001.json +27 -0
  545. package/rcf/user-stories/us-5002.json +27 -0
  546. package/rcf/user-stories/us-5101.json +36 -0
  547. package/rcf/user-stories/us-5102.json +27 -0
  548. package/rcf/user-stories/us-5201.json +36 -0
  549. package/rcf/user-stories/us-5301.json +27 -0
  550. package/rcf/user-stories/us-5302.json +27 -0
  551. package/rcf/user-stories/us-5401.json +27 -0
  552. package/rcf/user-stories/us-6001.json +27 -0
  553. package/rcf/user-stories/us-6002.json +27 -0
  554. package/rcf/user-stories/us-6003.json +27 -0
  555. package/rcf/user-stories/us-6101.json +36 -0
  556. package/rcf/user-stories/us-6201.json +36 -0
  557. package/rcf/user-stories/us-6301.json +36 -0
  558. package/rcf/user-stories/us-6302.json +27 -0
  559. package/rcf/user-stories/us-7001.json +27 -0
  560. package/rcf/user-stories/us-7002.json +27 -0
  561. package/rcf/user-stories/us-7101.json +27 -0
  562. package/rcf/user-stories/us-7201.json +27 -0
  563. package/rcf/user-stories/us-7301.json +27 -0
  564. package/rcf/user-stories/us-7401.json +27 -0
  565. package/rcf/user-stories/us-7402.json +27 -0
  566. package/rcf/user-stories/us-7501.json +27 -0
  567. package/rcf/user-stories/us-7601.json +27 -0
  568. package/rcf/user-stories/us-7701.json +27 -0
  569. package/rcf/user-stories/us-8001.json +24 -0
  570. package/rcf/user-stories/us-8002.json +24 -0
  571. package/rcf/user-stories/us-8003.json +24 -0
  572. package/rcf/user-stories/us-8101.json +24 -0
  573. package/rcf/user-stories/us-8201.json +24 -0
  574. package/rcf/user-stories/us-8301.json +24 -0
  575. package/rcf/user-stories/us-8401.json +24 -0
  576. package/rcf/user-stories/us-8501.json +24 -0
  577. package/rcf/user-stories/us-8502.json +24 -0
  578. package/rcf/user-stories/us-8601.json +24 -0
  579. package/rcf/user-stories/us-8602.json +24 -0
  580. package/rcf/user-stories/us-9001.json +27 -0
  581. package/rcf/user-stories/us-9002.json +27 -0
  582. package/rcf/user-stories/us-9101.json +27 -0
  583. package/rcf/user-stories/us-9102.json +27 -0
  584. package/rcf/user-stories/us-9201.json +27 -0
  585. package/rcf/user-stories/us-9301.json +27 -0
  586. package/rcf/user-stories/us-9302.json +27 -0
  587. package/rcf/user-stories/us-9401.json +27 -0
  588. package/releases/releases.yaml +21 -1
  589. package/src/blueprint/apply.js +7 -4
  590. package/src/blueprint/capabilities.js +25 -0
  591. package/src/cli/blueprint.js +8 -1
@@ -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
+ }