rcf-lite 0.23.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 (474) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/blueprints/application-account-settings/docs/topics.md +7 -1
  3. package/blueprints/application-admin-console/CHANGELOG.md +12 -0
  4. package/blueprints/application-admin-console/blueprint.json +34 -1
  5. package/blueprints/application-admin-console/contributions/adrs/adr-2214-application-admin-console-consume-zero-trust-gate.json +25 -0
  6. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-014.json +17 -0
  7. package/blueprints/application-admin-console/contributions/tacs/tac-2214-application-admin-console-access-gated-signin-surface.json +32 -0
  8. package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21815.json +27 -0
  9. package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21816.json +27 -0
  10. package/blueprints/application-admin-console/docs/topics.md +7 -1
  11. package/blueprints/application-admin-console/guide/application-admin-console.md +24 -0
  12. package/blueprints/application-admin-console/probe-packs/application-admin-console.pack.mjs +26 -1
  13. package/blueprints/application-api-rest/docs/topics.md +7 -1
  14. package/blueprints/application-charts/docs/topics.md +7 -1
  15. package/blueprints/application-dashboard/docs/topics.md +7 -1
  16. package/blueprints/application-datatable/docs/topics.md +7 -1
  17. package/blueprints/application-empty-error-states/docs/topics.md +7 -1
  18. package/blueprints/application-error-handling/docs/topics.md +7 -1
  19. package/blueprints/application-file-upload/docs/topics.md +7 -1
  20. package/blueprints/application-forms-wizard/docs/topics.md +7 -1
  21. package/blueprints/application-notifications-in-app/docs/topics.md +7 -1
  22. package/blueprints/application-onboarding-tour/docs/topics.md +7 -1
  23. package/blueprints/application-spa/docs/topics.md +7 -1
  24. package/blueprints/delivery-ci-workflows/docs/topics.md +7 -1
  25. package/blueprints/deploy-cloudflare-workers/docs/topics.md +7 -1
  26. package/blueprints/edge-cloudflare-access/CHANGELOG.md +23 -0
  27. package/blueprints/edge-cloudflare-access/README.md +141 -0
  28. package/blueprints/edge-cloudflare-access/blueprint.json +197 -0
  29. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3501-edge-cloudflare-access-jwt-gate.json +14 -0
  30. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3502-edge-cloudflare-access-identity-provider.json +25 -0
  31. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3503-edge-cloudflare-access-policy-scope.json +12 -0
  32. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3504-edge-cloudflare-access-audit-retention.json +12 -0
  33. package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +100 -0
  34. package/blueprints/edge-cloudflare-access/contributions/probes/audit-event-secrecy.mjs +70 -0
  35. package/blueprints/edge-cloudflare-access/contributions/probes/jwt-validator-fixture.mjs +63 -0
  36. package/blueprints/edge-cloudflare-access/contributions/probes/jwt-validator-reject.mjs +95 -0
  37. package/blueprints/edge-cloudflare-access/contributions/probes/probe-utils.mjs +90 -0
  38. package/blueprints/edge-cloudflare-access/contributions/probes/real-account-gated-url.mjs +65 -0
  39. package/blueprints/edge-cloudflare-access/contributions/probes/run-admin-console-gate-surface.mjs +5 -0
  40. package/blueprints/edge-cloudflare-access/contributions/probes/run-audit-event-secrecy.mjs +5 -0
  41. package/blueprints/edge-cloudflare-access/contributions/probes/run-jwt-validator-fixture.mjs +5 -0
  42. package/blueprints/edge-cloudflare-access/contributions/probes/run-jwt-validator-reject.mjs +5 -0
  43. package/blueprints/edge-cloudflare-access/contributions/probes/run-real-account-gated-url.mjs +5 -0
  44. package/blueprints/edge-cloudflare-access/contributions/probes/run-wrangler-seam.mjs +5 -0
  45. package/blueprints/edge-cloudflare-access/contributions/probes/wrangler-seam.mjs +203 -0
  46. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-001.json +17 -0
  47. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-002.json +17 -0
  48. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-003.json +17 -0
  49. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-004.json +17 -0
  50. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-005.json +17 -0
  51. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-006.json +18 -0
  52. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3501-edge-cloudflare-access-jwt-validator.json +31 -0
  53. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3502-edge-cloudflare-access-application-declaration.json +33 -0
  54. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3503-edge-cloudflare-access-policy-shape.json +25 -0
  55. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3504-edge-cloudflare-access-audit-sink.json +25 -0
  56. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34101.json +27 -0
  57. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34102.json +28 -0
  58. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34103.json +27 -0
  59. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34104.json +27 -0
  60. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34105.json +27 -0
  61. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34106.json +27 -0
  62. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34107.json +27 -0
  63. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34108.json +27 -0
  64. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34109.json +27 -0
  65. package/blueprints/edge-cloudflare-access/docs/topics.md +68 -0
  66. package/blueprints/edge-cloudflare-access/guide/edge-cloudflare-access.md +180 -0
  67. package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +10 -0
  68. package/blueprints/edge-cloudflare-rate-limiting/README.md +73 -0
  69. package/blueprints/edge-cloudflare-rate-limiting/blueprint.json +174 -0
  70. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3701-edge-cloudflare-rate-limiting-throttle-contract.json +14 -0
  71. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3702-edge-cloudflare-rate-limiting-layering.json +14 -0
  72. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3703-edge-cloudflare-rate-limiting-manifest-shape.json +14 -0
  73. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3704-edge-cloudflare-rate-limiting-drift-audit-cadence.json +14 -0
  74. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/event-secrecy.mjs +104 -0
  75. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/manifest-presence.mjs +95 -0
  76. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/manifest-schema-validate.mjs +130 -0
  77. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/probe-utils.mjs +111 -0
  78. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/real-account-burst-and-429.mjs +104 -0
  79. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-event-secrecy.mjs +5 -0
  80. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-manifest-presence.mjs +5 -0
  81. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-manifest-schema-validate.mjs +5 -0
  82. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-real-account-burst-and-429.mjs +5 -0
  83. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-001.json +17 -0
  84. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-002.json +17 -0
  85. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-003.json +17 -0
  86. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-004.json +17 -0
  87. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-005.json +17 -0
  88. package/blueprints/edge-cloudflare-rate-limiting/contributions/schemas/rate-limit-rule.schema.json +67 -0
  89. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json +31 -0
  90. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json +25 -0
  91. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json +26 -0
  92. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36101.json +27 -0
  93. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36102.json +27 -0
  94. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36103.json +27 -0
  95. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36104.json +27 -0
  96. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36105.json +27 -0
  97. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36106.json +27 -0
  98. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36107.json +27 -0
  99. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36108.json +27 -0
  100. package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +68 -0
  101. package/blueprints/edge-cloudflare-rate-limiting/guide/edge-cloudflare-rate-limiting.md +88 -0
  102. package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +20 -0
  103. package/blueprints/edge-cloudflare-turnstile/README.md +95 -0
  104. package/blueprints/edge-cloudflare-turnstile/blueprint.json +161 -0
  105. package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3601-edge-cloudflare-turnstile-verifier-contract.json +14 -0
  106. package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3602-edge-cloudflare-turnstile-widget-mode.json +14 -0
  107. package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3603-edge-cloudflare-turnstile-refuse-shape.json +14 -0
  108. package/blueprints/edge-cloudflare-turnstile/contributions/probes/event-secrecy.mjs +51 -0
  109. package/blueprints/edge-cloudflare-turnstile/contributions/probes/guard-shape-scan.mjs +48 -0
  110. package/blueprints/edge-cloudflare-turnstile/contributions/probes/probe-utils.mjs +139 -0
  111. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-event-secrecy.mjs +5 -0
  112. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-guard-shape-scan.mjs +5 -0
  113. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-secret-shape-scan.mjs +5 -0
  114. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-siteverify-fixture.mjs +5 -0
  115. package/blueprints/edge-cloudflare-turnstile/contributions/probes/secret-shape-scan.mjs +77 -0
  116. package/blueprints/edge-cloudflare-turnstile/contributions/probes/siteverify-fixture.mjs +53 -0
  117. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-001.json +17 -0
  118. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-002.json +17 -0
  119. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-003.json +17 -0
  120. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-004.json +17 -0
  121. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-005.json +17 -0
  122. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json +26 -0
  123. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json +36 -0
  124. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json +25 -0
  125. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35101.json +27 -0
  126. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35102.json +27 -0
  127. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35103.json +27 -0
  128. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35104.json +27 -0
  129. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35105.json +36 -0
  130. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35106.json +27 -0
  131. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35107.json +27 -0
  132. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35108.json +27 -0
  133. package/blueprints/edge-cloudflare-turnstile/docs/topics.md +68 -0
  134. package/blueprints/edge-cloudflare-turnstile/guide/edge-cloudflare-turnstile.md +104 -0
  135. package/blueprints/edge-cloudflare-turnstile/probe-packs/edge-cloudflare-turnstile.pack.mjs +146 -0
  136. package/blueprints/email-smtp-resend/docs/topics.md +7 -1
  137. package/blueprints/jobs-background/docs/topics.md +7 -1
  138. package/blueprints/messaging-queue-cloudflare/docs/topics.md +7 -1
  139. package/blueprints/object-storage-s3/docs/topics.md +7 -1
  140. package/blueprints/observability-essentials/docs/topics.md +7 -1
  141. package/blueprints/observability-logging/docs/topics.md +7 -1
  142. package/blueprints/observability-probe-endpoints/docs/topics.md +7 -1
  143. package/blueprints/persistence-data-d1/docs/topics.md +7 -1
  144. package/blueprints/persistence-data-postgres/docs/topics.md +7 -1
  145. package/blueprints/persistence-data-sqlite/docs/topics.md +7 -1
  146. package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +22 -0
  147. package/blueprints/platform-cloudflare-cron-triggers/README.md +117 -0
  148. package/blueprints/platform-cloudflare-cron-triggers/blueprint.json +85 -0
  149. package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3301-platform-cloudflare-cron-triggers-scheduled-trigger-contract.json +14 -0
  150. package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3302-platform-cloudflare-cron-triggers-dispatcher-mode.json +14 -0
  151. package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3303-platform-cloudflare-cron-triggers-skew-tolerance-default.json +14 -0
  152. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/dispatcher-routing.mjs +64 -0
  153. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/event-secrecy.mjs +100 -0
  154. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/probe-utils.mjs +70 -0
  155. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/real-account-scheduled-smoke.mjs +100 -0
  156. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-dispatcher-routing.mjs +5 -0
  157. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-event-secrecy.mjs +5 -0
  158. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-real-account-scheduled-smoke.mjs +5 -0
  159. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-skew-tolerance.mjs +5 -0
  160. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-wrangler-test-scheduled.mjs +5 -0
  161. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/skew-tolerance.mjs +130 -0
  162. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/wrangler-test-scheduled.mjs +129 -0
  163. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-001.json +17 -0
  164. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-002.json +17 -0
  165. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-003.json +17 -0
  166. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-004.json +17 -0
  167. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3301-platform-cloudflare-cron-triggers-scheduled-handler.json +22 -0
  168. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3302-platform-cloudflare-cron-triggers-expression-router.json +22 -0
  169. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3303-platform-cloudflare-cron-triggers-event-sink.json +21 -0
  170. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32101.json +25 -0
  171. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32102.json +34 -0
  172. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32103.json +34 -0
  173. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32104.json +34 -0
  174. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32105.json +25 -0
  175. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32106.json +25 -0
  176. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32107.json +25 -0
  177. package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +71 -0
  178. package/blueprints/platform-cloudflare-cron-triggers/guide/platform-cloudflare-cron-triggers.md +119 -0
  179. package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +23 -0
  180. package/blueprints/platform-cloudflare-durable-objects/README.md +200 -0
  181. package/blueprints/platform-cloudflare-durable-objects/blueprint.json +243 -0
  182. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3401-platform-cloudflare-durable-objects-single-cell-contract.json +14 -0
  183. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3402-platform-cloudflare-durable-objects-websocket-hub-contract.json +14 -0
  184. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3403-platform-cloudflare-durable-objects-storage-backend.json +14 -0
  185. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3404-platform-cloudflare-durable-objects-migrations-shape.json +14 -0
  186. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3405-platform-cloudflare-durable-objects-hibernation-posture.json +14 -0
  187. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/alarm-fires-once.mjs +63 -0
  188. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/namespace-facade-ready.mjs +60 -0
  189. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/probe-utils.mjs +105 -0
  190. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/real-account-storage-smoke.mjs +58 -0
  191. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-alarm-fires-once.mjs +5 -0
  192. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-namespace-facade-ready.mjs +5 -0
  193. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-real-account-storage-smoke.mjs +5 -0
  194. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-single-cell-concurrent-increment.mjs +5 -0
  195. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-sole-reader-scan.mjs +5 -0
  196. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-storage-round-trip.mjs +5 -0
  197. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-websocket-hub-broadcast.mjs +5 -0
  198. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-wrangler-seam.mjs +5 -0
  199. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/single-cell-concurrent-increment.mjs +56 -0
  200. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/sole-reader-scan.mjs +117 -0
  201. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/storage-round-trip.mjs +87 -0
  202. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/websocket-hub-broadcast.mjs +112 -0
  203. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/wrangler-seam.mjs +257 -0
  204. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-001.json +17 -0
  205. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-002.json +17 -0
  206. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-003.json +17 -0
  207. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-004.json +17 -0
  208. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-005.json +17 -0
  209. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-006.json +17 -0
  210. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-007.json +17 -0
  211. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-008.json +17 -0
  212. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3401-platform-cloudflare-durable-objects-namespace-facade.json +31 -0
  213. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3402-platform-cloudflare-durable-objects-single-cell-shape.json +30 -0
  214. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3403-platform-cloudflare-durable-objects-alarm-handler.json +29 -0
  215. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3404-platform-cloudflare-durable-objects-websocket-hub.json +31 -0
  216. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3405-platform-cloudflare-durable-objects-event-sink.json +24 -0
  217. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33101.json +27 -0
  218. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33102.json +27 -0
  219. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33103.json +27 -0
  220. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33104.json +27 -0
  221. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33105.json +27 -0
  222. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33106.json +27 -0
  223. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33107.json +27 -0
  224. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33108.json +27 -0
  225. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33109.json +27 -0
  226. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33110.json +27 -0
  227. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33111.json +27 -0
  228. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33112.json +27 -0
  229. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33113.json +25 -0
  230. package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +73 -0
  231. package/blueprints/platform-cloudflare-durable-objects/guide/platform-cloudflare-durable-objects.md +237 -0
  232. package/blueprints/platform-cloudflare-kv/CHANGELOG.md +21 -0
  233. package/blueprints/platform-cloudflare-kv/README.md +159 -0
  234. package/blueprints/platform-cloudflare-kv/blueprint.json +87 -0
  235. package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3201-platform-cloudflare-kv-key-value-store-contract.json +14 -0
  236. package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3202-platform-cloudflare-kv-default-cache-ttl.json +14 -0
  237. package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3203-platform-cloudflare-kv-key-naming-convention.json +14 -0
  238. package/blueprints/platform-cloudflare-kv/contributions/probes/cache-aside-hit-then-miss.mjs +82 -0
  239. package/blueprints/platform-cloudflare-kv/contributions/probes/event-secrecy.mjs +102 -0
  240. package/blueprints/platform-cloudflare-kv/contributions/probes/facade-round-trip.mjs +92 -0
  241. package/blueprints/platform-cloudflare-kv/contributions/probes/list-with-prefix.mjs +52 -0
  242. package/blueprints/platform-cloudflare-kv/contributions/probes/probe-utils.mjs +73 -0
  243. package/blueprints/platform-cloudflare-kv/contributions/probes/real-account-eventual-consistency-smoke.mjs +102 -0
  244. package/blueprints/platform-cloudflare-kv/contributions/probes/run-cache-aside-hit-then-miss.mjs +5 -0
  245. package/blueprints/platform-cloudflare-kv/contributions/probes/run-event-secrecy.mjs +5 -0
  246. package/blueprints/platform-cloudflare-kv/contributions/probes/run-facade-round-trip.mjs +5 -0
  247. package/blueprints/platform-cloudflare-kv/contributions/probes/run-list-with-prefix.mjs +5 -0
  248. package/blueprints/platform-cloudflare-kv/contributions/probes/run-real-account-eventual-consistency-smoke.mjs +5 -0
  249. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-001.json +18 -0
  250. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-002.json +18 -0
  251. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-003.json +18 -0
  252. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-004.json +18 -0
  253. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-005.json +18 -0
  254. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3201-platform-cloudflare-kv-facade.json +27 -0
  255. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3202-platform-cloudflare-kv-cache-aside.json +26 -0
  256. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3203-platform-cloudflare-kv-event-sink.json +25 -0
  257. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31101.json +27 -0
  258. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31102.json +27 -0
  259. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31103.json +36 -0
  260. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31104.json +27 -0
  261. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31105.json +27 -0
  262. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31106.json +27 -0
  263. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31107.json +27 -0
  264. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31108.json +27 -0
  265. package/blueprints/platform-cloudflare-kv/docs/topics.md +71 -0
  266. package/blueprints/platform-cloudflare-kv/guide/platform-cloudflare-kv.md +138 -0
  267. package/blueprints/security-auth-clerk/docs/topics.md +7 -1
  268. package/blueprints/security-auth-keycloak/docs/topics.md +7 -1
  269. package/blueprints/security-auth-magic-link/docs/topics.md +7 -1
  270. package/blueprints/security-auth-oauth2/docs/topics.md +7 -1
  271. package/blueprints/security-secrets-management/docs/topics.md +7 -1
  272. package/fixtures/canary-manifest.json +6 -6
  273. package/package.json +1 -1
  274. package/rcf/adrs/adr-2214-application-admin-console-consume-zero-trust-gate.json +13 -0
  275. package/rcf/adrs/adr-3501-edge-cloudflare-access-jwt-gate.json +13 -0
  276. package/rcf/adrs/adr-3502-edge-cloudflare-access-identity-provider.json +13 -0
  277. package/rcf/adrs/adr-3503-edge-cloudflare-access-policy-scope.json +13 -0
  278. package/rcf/adrs/adr-3504-edge-cloudflare-access-audit-retention.json +13 -0
  279. package/rcf/adrs/adr-3601-edge-cloudflare-turnstile-verifier-contract.json +13 -0
  280. package/rcf/adrs/adr-3602-edge-cloudflare-turnstile-widget-mode.json +13 -0
  281. package/rcf/adrs/adr-3603-edge-cloudflare-turnstile-refuse-shape.json +13 -0
  282. package/rcf/adrs/adr-3701-edge-cloudflare-rate-limiting-throttle-contract.json +13 -0
  283. package/rcf/adrs/adr-3702-edge-cloudflare-rate-limiting-layering.json +13 -0
  284. package/rcf/adrs/adr-3703-edge-cloudflare-rate-limiting-manifest-shape.json +13 -0
  285. package/rcf/adrs/adr-3704-edge-cloudflare-rate-limiting-drift-audit-cadence.json +13 -0
  286. package/rcf/code-nodes/cn-230.json +13 -0
  287. package/rcf/code-nodes/cn-231.json +14 -0
  288. package/rcf/code-nodes/cn-232.json +13 -0
  289. package/rcf/code-nodes/cn-233.json +14 -0
  290. package/rcf/code-nodes/cn-234.json +13 -0
  291. package/rcf/code-nodes/cn-260.json +21 -0
  292. package/rcf/code-nodes/cn-261.json +14 -0
  293. package/rcf/code-nodes/cn-262.json +18 -0
  294. package/rcf/code-nodes/cn-263.json +12 -0
  295. package/rcf/code-nodes/cn-264.json +13 -0
  296. package/rcf/code-nodes/cn-265.json +15 -0
  297. package/rcf/code-nodes/cn-266.json +12 -0
  298. package/rcf/code-nodes/cn-267.json +12 -0
  299. package/rcf/code-nodes/cn-290.json +21 -0
  300. package/rcf/code-nodes/cn-291.json +12 -0
  301. package/rcf/code-nodes/cn-292.json +13 -0
  302. package/rcf/code-nodes/cn-293.json +13 -0
  303. package/rcf/code-nodes/cn-294.json +13 -0
  304. package/rcf/code-nodes/cn-295.json +12 -0
  305. package/rcf/code-nodes/cn-296.json +12 -0
  306. package/rcf/code-nodes/cn-297.json +12 -0
  307. package/rcf/code-nodes/cn-298.json +12 -0
  308. package/rcf/code-nodes/cn-299.json +12 -0
  309. package/rcf/code-nodes/cn-300.json +12 -0
  310. package/rcf/code-nodes/cn-301.json +14 -0
  311. package/rcf/code-nodes/cn-302.json +12 -0
  312. package/rcf/code-nodes/cn-303.json +12 -0
  313. package/rcf/code-nodes/cn-304.json +21 -0
  314. package/rcf/code-nodes/cn-320.json +20 -0
  315. package/rcf/code-nodes/cn-321.json +14 -0
  316. package/rcf/code-nodes/cn-350.json +19 -0
  317. package/rcf/code-nodes/cn-380.json +19 -0
  318. package/rcf/fbs/fbs-070.json +24 -0
  319. package/rcf/fbs/fbs-080.json +24 -0
  320. package/rcf/fbs/fbs-090.json +24 -0
  321. package/rcf/fbs/fbs-100.json +23 -0
  322. package/rcf/fbs/fbs-101.json +16 -0
  323. package/rcf/fbs/fbs-110.json +23 -0
  324. package/rcf/fbs/fbs-120.json +22 -0
  325. package/rcf/requirements/req-050.json +18 -0
  326. package/rcf/requirements/req-051.json +18 -0
  327. package/rcf/requirements/req-052.json +18 -0
  328. package/rcf/requirements/req-053.json +18 -0
  329. package/rcf/requirements/req-054.json +18 -0
  330. package/rcf/requirements/req-060.json +20 -0
  331. package/rcf/requirements/req-061.json +18 -0
  332. package/rcf/requirements/req-062.json +20 -0
  333. package/rcf/requirements/req-063.json +20 -0
  334. package/rcf/requirements/req-070.json +18 -0
  335. package/rcf/requirements/req-071.json +18 -0
  336. package/rcf/requirements/req-072.json +18 -0
  337. package/rcf/requirements/req-073.json +18 -0
  338. package/rcf/requirements/req-074.json +18 -0
  339. package/rcf/requirements/req-075.json +18 -0
  340. package/rcf/requirements/req-076.json +18 -0
  341. package/rcf/requirements/req-077.json +18 -0
  342. package/rcf/requirements/req-080.json +18 -0
  343. package/rcf/requirements/req-081.json +18 -0
  344. package/rcf/requirements/req-082.json +18 -0
  345. package/rcf/requirements/req-083.json +18 -0
  346. package/rcf/requirements/req-084.json +18 -0
  347. package/rcf/requirements/req-085.json +18 -0
  348. package/rcf/requirements/req-086.json +18 -0
  349. package/rcf/requirements/req-090.json +44 -0
  350. package/rcf/requirements/req-091.json +53 -0
  351. package/rcf/requirements/req-092.json +32 -0
  352. package/rcf/requirements/req-093.json +52 -0
  353. package/rcf/requirements/req-094.json +32 -0
  354. package/rcf/requirements/req-100.json +13 -0
  355. package/rcf/requirements/req-101.json +13 -0
  356. package/rcf/requirements/req-102.json +13 -0
  357. package/rcf/requirements/req-103.json +13 -0
  358. package/rcf/requirements/req-104.json +13 -0
  359. package/rcf/tacs/tac-2214-application-admin-console-access-gated-signin-surface.json +15 -0
  360. package/rcf/tacs/tac-3501-edge-cloudflare-access-jwt-validator.json +15 -0
  361. package/rcf/tacs/tac-3502-edge-cloudflare-access-application-declaration.json +15 -0
  362. package/rcf/tacs/tac-3503-edge-cloudflare-access-policy-shape.json +15 -0
  363. package/rcf/tacs/tac-3504-edge-cloudflare-access-audit-sink.json +15 -0
  364. package/rcf/tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json +15 -0
  365. package/rcf/tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json +15 -0
  366. package/rcf/tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json +15 -0
  367. package/rcf/tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json +16 -0
  368. package/rcf/tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json +15 -0
  369. package/rcf/tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json +16 -0
  370. package/rcf/test-suites/ts-052.json +58 -8
  371. package/rcf/test-suites/ts-080.json +22 -0
  372. package/rcf/test-suites/ts-081.json +22 -0
  373. package/rcf/test-suites/ts-082.json +30 -0
  374. package/rcf/test-suites/ts-083.json +22 -0
  375. package/rcf/test-suites/ts-084.json +30 -0
  376. package/rcf/test-suites/ts-085.json +22 -0
  377. package/rcf/test-suites/ts-086.json +22 -0
  378. package/rcf/test-suites/ts-087.json +22 -0
  379. package/rcf/test-suites/ts-090.json +22 -0
  380. package/rcf/test-suites/ts-091.json +22 -0
  381. package/rcf/test-suites/ts-092.json +22 -0
  382. package/rcf/test-suites/ts-093.json +30 -0
  383. package/rcf/test-suites/ts-094.json +30 -0
  384. package/rcf/test-suites/ts-095.json +30 -0
  385. package/rcf/test-suites/ts-096.json +22 -0
  386. package/rcf/test-suites/ts-100.json +22 -0
  387. package/rcf/test-suites/ts-101.json +22 -0
  388. package/rcf/test-suites/ts-102.json +22 -0
  389. package/rcf/test-suites/ts-103.json +22 -0
  390. package/rcf/test-suites/ts-104.json +22 -0
  391. package/rcf/test-suites/ts-105.json +22 -0
  392. package/rcf/test-suites/ts-106.json +22 -0
  393. package/rcf/test-suites/ts-107.json +22 -0
  394. package/rcf/test-suites/ts-108.json +22 -0
  395. package/rcf/test-suites/ts-109.json +22 -0
  396. package/rcf/test-suites/ts-110.json +22 -0
  397. package/rcf/test-suites/ts-111.json +22 -0
  398. package/rcf/test-suites/ts-112.json +22 -0
  399. package/rcf/test-suites/ts-113.json +22 -0
  400. package/rcf/test-suites/ts-114.json +22 -0
  401. package/rcf/test-suites/ts-115.json +22 -0
  402. package/rcf/test-suites/ts-116.json +22 -0
  403. package/rcf/test-suites/ts-117.json +22 -0
  404. package/rcf/test-suites/ts-118.json +22 -0
  405. package/rcf/test-suites/ts-119.json +30 -0
  406. package/rcf/test-suites/ts-120.json +22 -0
  407. package/rcf/test-suites/ts-121.json +22 -0
  408. package/rcf/test-suites/ts-122.json +22 -0
  409. package/rcf/test-suites/ts-123.json +22 -0
  410. package/rcf/test-suites/ts-124.json +22 -0
  411. package/rcf/test-suites/ts-125.json +22 -0
  412. package/rcf/test-suites/ts-126.json +22 -0
  413. package/rcf/test-suites/ts-127.json +22 -0
  414. package/rcf/test-suites/ts-130.json +22 -0
  415. package/rcf/test-suites/ts-131.json +22 -0
  416. package/rcf/test-suites/ts-132.json +22 -0
  417. package/rcf/test-suites/ts-133.json +22 -0
  418. package/rcf/test-suites/ts-134.json +22 -0
  419. package/rcf/test-suites/ts-135.json +22 -0
  420. package/rcf/test-suites/ts-136.json +22 -0
  421. package/rcf/test-suites/ts-137.json +22 -0
  422. package/rcf/user-stories/us-10001.json +23 -0
  423. package/rcf/user-stories/us-10101.json +23 -0
  424. package/rcf/user-stories/us-10201.json +23 -0
  425. package/rcf/user-stories/us-10301.json +23 -0
  426. package/rcf/user-stories/us-10401.json +23 -0
  427. package/rcf/user-stories/us-10601.json +23 -0
  428. package/rcf/user-stories/us-10701.json +23 -0
  429. package/rcf/user-stories/us-10801.json +23 -0
  430. package/rcf/user-stories/us-5001.json +27 -0
  431. package/rcf/user-stories/us-5002.json +27 -0
  432. package/rcf/user-stories/us-5101.json +36 -0
  433. package/rcf/user-stories/us-5102.json +27 -0
  434. package/rcf/user-stories/us-5201.json +36 -0
  435. package/rcf/user-stories/us-5301.json +27 -0
  436. package/rcf/user-stories/us-5302.json +27 -0
  437. package/rcf/user-stories/us-5401.json +27 -0
  438. package/rcf/user-stories/us-6001.json +27 -0
  439. package/rcf/user-stories/us-6002.json +27 -0
  440. package/rcf/user-stories/us-6003.json +27 -0
  441. package/rcf/user-stories/us-6101.json +36 -0
  442. package/rcf/user-stories/us-6201.json +36 -0
  443. package/rcf/user-stories/us-6301.json +36 -0
  444. package/rcf/user-stories/us-6302.json +27 -0
  445. package/rcf/user-stories/us-7001.json +27 -0
  446. package/rcf/user-stories/us-7002.json +27 -0
  447. package/rcf/user-stories/us-7101.json +27 -0
  448. package/rcf/user-stories/us-7201.json +27 -0
  449. package/rcf/user-stories/us-7301.json +27 -0
  450. package/rcf/user-stories/us-7401.json +27 -0
  451. package/rcf/user-stories/us-7402.json +27 -0
  452. package/rcf/user-stories/us-7501.json +27 -0
  453. package/rcf/user-stories/us-7601.json +27 -0
  454. package/rcf/user-stories/us-7701.json +27 -0
  455. package/rcf/user-stories/us-8001.json +24 -0
  456. package/rcf/user-stories/us-8002.json +24 -0
  457. package/rcf/user-stories/us-8003.json +24 -0
  458. package/rcf/user-stories/us-8101.json +24 -0
  459. package/rcf/user-stories/us-8201.json +24 -0
  460. package/rcf/user-stories/us-8301.json +24 -0
  461. package/rcf/user-stories/us-8401.json +24 -0
  462. package/rcf/user-stories/us-8501.json +24 -0
  463. package/rcf/user-stories/us-8502.json +24 -0
  464. package/rcf/user-stories/us-8601.json +24 -0
  465. package/rcf/user-stories/us-8602.json +24 -0
  466. package/rcf/user-stories/us-9001.json +27 -0
  467. package/rcf/user-stories/us-9002.json +27 -0
  468. package/rcf/user-stories/us-9101.json +27 -0
  469. package/rcf/user-stories/us-9102.json +27 -0
  470. package/rcf/user-stories/us-9201.json +27 -0
  471. package/rcf/user-stories/us-9301.json +27 -0
  472. package/rcf/user-stories/us-9302.json +27 -0
  473. package/rcf/user-stories/us-9401.json +27 -0
  474. package/releases/releases.yaml +11 -1
@@ -0,0 +1,180 @@
1
+ # edge-cloudflare-access guide
2
+
3
+ ## When to reach for this blueprint
4
+
5
+ You reach for `edge-cloudflare-access` when your Workers project
6
+ needs an authenticated edge (only authenticated principals reach
7
+ the origin Worker), when you have adopted the Zero Trust posture,
8
+ and when you want a vendor-neutral seam (`request.auth`) between
9
+ Cloudflare's Access edge and your downstream handlers.
10
+
11
+ If you are shipping a fully-public Worker (no authentication at all),
12
+ this blueprint is not for you. If you are running a security-auth-*
13
+ blueprint inside the Worker (in-app authentication), you probably
14
+ also want Cloudflare Access as a second layer to keep unauthenticated
15
+ traffic off the origin; the composition is straightforward.
16
+
17
+ ## Composition with application-admin-console
18
+
19
+ Applying `application-admin-console` v1.1.0 alongside this blueprint
20
+ flips the admin-console sign-in surface (`/admin/sign-in`):
21
+
22
+ - With `zeroTrustGate` in the applied capability set (this
23
+ blueprint declares it): the sign-in page renders
24
+ `[data-surface=access-gated]` with no local form.
25
+ - Without `zeroTrustGate` (this blueprint not applied): the
26
+ sign-in page renders `[data-surface=local-login]` with the local
27
+ `security-auth-*` form unchanged from v1.0.0.
28
+
29
+ The Q4 default (spec section 5.4.1) is: consumption is OPTIONAL.
30
+ The v1.1.0 admin-console remains backward-compatible with every
31
+ v1.0.0 deployment.
32
+
33
+ ## Elicited parameters at apply
34
+
35
+ - `access-application-host` OR `access-selfhosted-app-id`: pick
36
+ exactly one. The dashboard walk-through follows the hostname
37
+ path when the first is set and the self-hosted-app id path
38
+ when the second is set.
39
+ - `access-audience`: the JWT audience tag the Access policy issues.
40
+ Every JWT the validator accepts must carry this string as its
41
+ `aud` claim.
42
+ - `access-jwks-url`: the JWKS endpoint URL the validator fetches.
43
+ Cloudflare Access publishes this at
44
+ `https://<team>.cloudflareaccess.com/cdn-cgi/access/certs`.
45
+ - `access-policy-shape` (default `email-domain`): one of the four
46
+ values in the enum below.
47
+ - `access-bypass-service-auth-id`: leave blank to disable
48
+ break-glass. When set, the paired secret is delegated to the
49
+ applied `secretsManagement` companion.
50
+
51
+ ## Policy shape enum
52
+
53
+ | Shape | What it allows | Suited to |
54
+ | --- | --- | --- |
55
+ | `email-domain` | Any principal whose email ends `@<domain>` on the Access-managed identity provider. | Solo, small team, workspace-wide access on a company domain. |
56
+ | `service-token-only` | Only the elicited bypass-service-auth pair; no browser principals. | CI-only endpoints (webhooks, ingest APIs). |
57
+ | `service-token-plus-email-domain` | Either the paired service-auth or an on-domain email principal. | Endpoints reached by CI AND humans. |
58
+ | `group-membership` | Only principals whose identity-provider group claim contains an elicited group name (Okta, Entra ID, Google Groups). | Enterprise SSO with role-based access. |
59
+
60
+ The Cloudflare edge enforces the shape before a request reaches
61
+ the origin Worker; the shipped validator receives the JWT the
62
+ Access edge signs and verifies the audience, the expiry and the
63
+ signature.
64
+
65
+ ## Zero Trust dashboard walk-through
66
+
67
+ Screen-by-screen path for a fresh Cloudflare account. Vendor URL:
68
+ `https://developers.cloudflare.com/cloudflare-one/policies/access/`.
69
+
70
+ 1. Sign in to `dash.cloudflare.com` and select your account.
71
+ 2. In the left nav, open `Zero Trust`. If the dashboard prompts
72
+ you to create a team, do so with the elicited team name (the
73
+ `<team>` in `https://<team>.cloudflareaccess.com/`).
74
+ 3. In the Zero Trust dashboard, open `Access` -> `Applications`,
75
+ then `Add an application`.
76
+ 4. Pick `Self-hosted` (both for hostname-scoped applications and
77
+ for self-hosted-app id-based applications).
78
+ 5. Enter the application name (`admin.example.com` for the
79
+ hostname path or the app id string for the self-hosted-app id
80
+ path), the session duration (default 24h is fine for an
81
+ internal console) and the application domain (the hostname
82
+ the Worker binds to).
83
+ 6. On the `Add policies` screen, `Add a policy`.
84
+ 7. On the policy screen, pick the `Action` (`Allow` for the
85
+ principal set the shape names above), then add one `Include`
86
+ selector matching the shape:
87
+ - `email-domain`: `Include -> Email ending in` -> your domain.
88
+ - `service-token-only`: `Include -> Service Auth Token` -> the
89
+ token generated in `Zero Trust` -> `Access` -> `Service Auth`.
90
+ - `service-token-plus-email-domain`: add both selectors.
91
+ - `group-membership`: `Include -> IdP Group name` -> the group
92
+ the elicited identity-provider claims.
93
+ 8. Save the policy, save the application. The dashboard prints
94
+ the `Application audience tag` at the top of the application
95
+ card; copy it verbatim into the `access-audience` elicit
96
+ answer on apply.
97
+ 9. Confirm the JWKS endpoint at
98
+ `https://<team>.cloudflareaccess.com/cdn-cgi/access/certs`
99
+ returns a valid JWKS document; copy the URL into the
100
+ `access-jwks-url` elicit answer.
101
+
102
+ The blueprint is now ready to apply on the Worker project.
103
+
104
+ ## API alternative
105
+
106
+ If you prefer to script the policy issuance rather than click
107
+ through the dashboard, use the Cloudflare API. Vendor URL:
108
+ `https://developers.cloudflare.com/cloudflare-one/policies/access/`.
109
+
110
+ ```
111
+ curl -X POST \
112
+ https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_id}/policies \
113
+ -H "Authorization: Bearer $CF_API_TOKEN" \
114
+ -H "Content-Type: application/json" \
115
+ -d '{
116
+ "name": "Access policy for admin.example.com",
117
+ "decision": "allow",
118
+ "include": [
119
+ { "email_domain": { "domain": "example.com" } }
120
+ ],
121
+ "session_duration": "24h"
122
+ }'
123
+ ```
124
+
125
+ Replace the `include` block with the shape you picked from the
126
+ enum. The `app_id` is the value the dashboard printed when the
127
+ application was created; the `account_id` is the standard
128
+ Cloudflare account id from your account settings. The endpoint is
129
+ idempotent when the policy name matches an existing policy per
130
+ Cloudflare's documented semantics.
131
+
132
+ ## Break-glass posture
133
+
134
+ Set `access-bypass-service-auth-id` at apply to enable break-glass.
135
+ The paired secret is delegated to the applied `secretsManagement`
136
+ companion via `security-secrets-management`; the CI runner then
137
+ supplies both values as `CF-Access-Client-Id` and
138
+ `CF-Access-Client-Secret` headers on every request that would
139
+ otherwise fail Access at the browser boundary. The validator
140
+ observes the pair, records `outcome: bypass` on the audit sink
141
+ with the metadata-only shape, and delegates to the handler with
142
+ `request.auth.email = 'service:'+id`.
143
+
144
+ The break-glass code path is disabled unless an elicited pair is
145
+ applied; a request presenting the paired headers when no pair is
146
+ elicited is rejected as `missing` (fall through to the JWT path).
147
+
148
+ ## Composed apply-line
149
+
150
+ One project, admin-console v1.1.0 plus edge-cloudflare-access
151
+ v1.0.0, `email-domain` policy shape:
152
+
153
+ ```
154
+ rcf define blueprint add application-admin-console --version 1.1.0
155
+ rcf define blueprint add edge-cloudflare-access --version 1.0.0 \
156
+ --answer access-application-host=admin.example.com \
157
+ --answer access-audience=<audience-copied-from-dashboard> \
158
+ --answer access-jwks-url=https://<team>.cloudflareaccess.com/cdn-cgi/access/certs \
159
+ --answer access-policy-shape=email-domain
160
+ ```
161
+
162
+ The admin-console applies first (its `principalDirectory`
163
+ requirement is met by whatever `security-auth-*` you have
164
+ applied). The Access blueprint applies second, records
165
+ `zeroTrustGate` on `rcf/blueprints/edge-cloudflare-access.applied.json`,
166
+ and the admin-console's next surface render picks the Access-gated
167
+ branch on `/admin/sign-in`.
168
+
169
+ ## Standards trace
170
+
171
+ - `ADR-3501-edge-cloudflare-access-jwt-gate` carries
172
+ `standardsTraceClause: Cloudflare Access policy actions and rule
173
+ selectors` per
174
+ https://developers.cloudflare.com/cloudflare-one/policies/access/.
175
+ - `ADR-3503-edge-cloudflare-access-policy-scope` carries the same
176
+ clause.
177
+ - `ADR-3502-edge-cloudflare-access-identity-provider` and
178
+ `ADR-3504-edge-cloudflare-access-audit-retention` carry the
179
+ sentinel `generic enterprise practice` (no vendor documentation
180
+ constrains identity provider or audit retention).
@@ -0,0 +1,10 @@
1
+ # edge-cloudflare-rate-limiting changelog
2
+
3
+ ## 1.0.0 (round 6 T-6, 2026-09-07)
4
+
5
+ - First shipped version. Zone-level rate limiting as an edge gate in front of Worker handlers per the ratified `cloudflare-round-6-spec-2026-09-06.md` section 5.6.
6
+ - Five REQs, eight USs, three TACs, four ADRs. Twenty contributions total.
7
+ - Ships the local rate-limit rules manifest schema (draft-07), the operator-facing management surface guide with both wrangler and dashboard flows, the drift-audit runner realisation on the `cf-edge` fixture and the composition ADR with `security-auth-magic-link`.
8
+ - Mints capability `edgeRateLimit` and global topic `edgeThrottleContract` (ADR-3701, scope global).
9
+ - Four Node-only probes: `manifest-presence`, `manifest-schema-validate`, `event-secrecy`, `real-account-burst-and-429`. The last carries `accountBound: true` and records `accountBoundSkipped: true` in CI without `CI_HAS_CLOUDFLARE_ACCOUNT` per spec section 3.5 and ruling 6.
10
+ - `cf-edge` fixture extended additively: `cloudflare/rate-limits/example.json`, `cloudflare/rate-limits/api-writes.json`, `src/drift-audit-runner.mjs`, three induced-failure switches (`SIMULATE_MANIFEST_MISSING`, `SIMULATE_SCHEMA_INVALID`, `SIMULATE_EVENT_LEAK_IP`).
@@ -0,0 +1,73 @@
1
+ # edge-cloudflare-rate-limiting
2
+
3
+ Zone-level rate limiting as an edge gate in front of Worker handlers, configured through a local manifest the applying project commits and applies to the live Cloudflare zone via a documented wrangler or dashboard flow. Ships v1.0.0 of the round-6 T-6 track per `projects/blueprint-library/specs/cloudflare-round-6-spec-2026-09-06.md` section 5.6.
4
+
5
+ - **Category:** `edge`.
6
+ - **Capability provided:** `edgeRateLimit`.
7
+ - **Global topic minted:** `edgeThrottleContract` (ADR-3701, scope global).
8
+ - **Suggested companions:** `logging`, `errorHandling`, `secretsManagement`.
9
+
10
+ ## The five REQs
11
+
12
+ | Id | What it commits |
13
+ | --- | --- |
14
+ | REQ-001 | Local rules manifest: one JSON file per rule under the elicited `rate-limit-rules-dir` (default `cloudflare/rate-limits/`) carries the seven documented fields. |
15
+ | REQ-002 | Operator-facing management surface: a documented wrangler or Cloudflare-dashboard flow the operator runs to apply the manifest to the live zone. No committed script. |
16
+ | REQ-003 | Over-threshold behaviour: over the rule limit within the period, the (N+1)th and subsequent requests within the elicited duration return 429 with `Retry-After` and `Cf-Ray`; the origin never sees them. |
17
+ | REQ-004 | Drift audit: an opt-in scheduled runner reads live zone rules via the Cloudflare API and diffs against the local manifest, constructing metadata-only records per REQ-005 event-secrecy. |
18
+ | REQ-005 | Composition with `security-auth-magic-link`: the zone rule sits OVER the per-email application rule per ADR-3702 layering. |
19
+
20
+ ## Elicited parameters
21
+
22
+ - `rate-limit-rules-dir` (default `cloudflare/rate-limits`): where the applying project commits manifest files.
23
+ - `rate-limit-zone-id` (default empty): the Cloudflare zone id the rules apply to. Never inlined in a manifest file; stored via the applied `secretsManagement` companion.
24
+ - `rate-limit-management-surface` (default `both`): `wrangler`, `dashboard`, or `both`. Records the operator's flow choice; the guide walks both.
25
+ - `rate-limit-drift-audit-cadence` (default `daily`): `off`, `daily`, `hourly`. Per ADR-3704.
26
+
27
+ ## Manifest shape (TAC-3701)
28
+
29
+ The shipped JSON Schema at `contributions/schemas/rate-limit-rule.schema.json` (draft-07) names the seven required fields per `https://developers.cloudflare.com/waf/rate-limiting-rules/`:
30
+
31
+ | Field | Type | Meaning |
32
+ | --- | --- | --- |
33
+ | `id` | string | Stable operator-facing rule id (kebab-case). Used as `ruleId` in drift-audit records. |
34
+ | `expression` | string | Cloudflare WAF rules-language expression scoping the rule. |
35
+ | `threshold` | integer >=1 | Requests permitted per period on the characteristic set. |
36
+ | `period` | integer >=1 | Window in seconds the threshold applies over. |
37
+ | `characteristics` | string[] (non-empty) | Characteristic strings the rule keys on (e.g. `ip.src`, `cf.colo.id`). |
38
+ | `action` | enum | `block`, `challenge`, `log`, `managed_challenge`. |
39
+ | `duration` | integer >=1 | Block window in seconds the (N+1)th and subsequent requests are refused for. |
40
+
41
+ `additionalProperties: false`; a `description` field is optional.
42
+
43
+ ## Probes
44
+
45
+ Four Node-only probes under `contributions/probes/`; three run in CI, one is account-bound and skips per ruling 6.
46
+
47
+ | Probe | Anchor AC | `accountBound` | What it drives |
48
+ | --- | --- | --- | --- |
49
+ | `manifest-presence.mjs` | AC-36101-1 (also AC-36108-1 under `SIMULATE_MANIFEST_MISSING=true`) | false | Reads `cf-edge/cloudflare/rate-limits/`, asserts every file parses, carries the seven required fields and holds no plaintext secret. |
50
+ | `manifest-schema-validate.mjs` | AC-36106-1 | false | Validates every manifest file against the shipped JSON Schema. Under `SIMULATE_SCHEMA_INVALID=true` writes a scratch file missing `threshold` and fails. |
51
+ | `event-secrecy.mjs` | AC-36107-1 | false | Drives the shipped drift-audit runner realisation with a synthetic manifest and a fake fetch; asserts every drift record carries only `{ruleId, clientIpHash, outcome, timestamp, diff}`. Under `SIMULATE_EVENT_LEAK_IP=true` the runner injects a full IP and the probe fails. |
52
+ | `real-account-burst-and-429.mjs` | AC-36103-1 | true | Fires an in-process burst against `CF_RATE_LIMIT_URL` under `CI_HAS_CLOUDFLARE_ACCOUNT=true` and asserts the (N+1)th and subsequent responses return 429 with `Retry-After` and `Cf-Ray`. Without either env var records `accountBoundSkipped: true` and aggregates to `pass` per spec section 3.5 and ruling 6. |
53
+
54
+ ### Ruling 6 restated
55
+
56
+ Spec section 1, verbatim: "If the rate-limiting real-account burst probe is not CI-feasible, ship with the local manifest AC and mark the burst check account-bound skipped." Without `CI_HAS_CLOUDFLARE_ACCOUNT` the CI verdict for `real-account-burst-and-429` is `accountBoundSkipped: true` and this IS the accepted verdict; the aggregate flips to `pass`. The local manifest ACs (AC-36101-1, AC-36106-1, AC-36107-1) always run and always gate the ship.
57
+
58
+ ## Composition with `security-auth-magic-link` (ADR-3702)
59
+
60
+ When both blueprints apply, the zone-level rate rule (characteristic set: IP-per-URL) sits at the CF edge and refuses the (N+1)th request for the elicited duration before it reaches the origin; the `security-auth-magic-link` per-email application rate limiter (characteristic set: per-email per-minute) continues to run on requests that pass the edge gate at the mint-surface. The two rules operate on different characteristic sets and are additive, not overlapping. See the guide for a copy-paste example.
61
+
62
+ ## Standards trace
63
+
64
+ - ADR-3701: `Cloudflare WAF rate-limiting rules documented shape` (`https://developers.cloudflare.com/waf/rate-limiting-rules/`).
65
+ - ADR-3702, ADR-3703, ADR-3704: `generic enterprise practice`.
66
+
67
+ ## Vendor citations
68
+
69
+ - Cloudflare WAF rate-limiting rules: `https://developers.cloudflare.com/waf/rate-limiting-rules/` (documents `expression`, `threshold`, `period`, `characteristics`, `action`, `duration`; fetched 200 on 2026-09-07 for the round-6 T-6 ship).
70
+
71
+ ## Known mechanism-reach gaps
72
+
73
+ - The over-threshold observable (AC-36103-1) is only proven at the runtime seam with a real Cloudflare account. In CI without `CI_HAS_CLOUDFLARE_ACCOUNT` the probe records `accountBoundSkipped: true` per ruling 6; the local manifest and event-secrecy ACs cover source-observable correctness.
@@ -0,0 +1,174 @@
1
+ {
2
+ "slug": "edge-cloudflare-rate-limiting",
3
+ "version": "1.0.0",
4
+ "category": "edge",
5
+ "capabilities": [
6
+ "edgeRateLimit"
7
+ ],
8
+ "suggestedCompanions": [
9
+ {
10
+ "role": "logging",
11
+ "reason": "Every drift-audit report and every rate-limit event writes through the applied logger; a logging companion supplies the sink factory."
12
+ },
13
+ {
14
+ "role": "errorHandling",
15
+ "reason": "A drift-audit failure, a Cloudflare API error, a manifest schema violation constructs an internal error record; an error-handling companion supplies the record factory and the boundary."
16
+ },
17
+ {
18
+ "role": "secretsManagement",
19
+ "reason": "The Cloudflare API token that the drift-audit runner and any wrangler-based apply flow use is stored via the applied secretsManagement companion; the elicited zone id may also be projected through the vault when the operator wants a single source of truth."
20
+ }
21
+ ],
22
+ "elicits": [
23
+ {
24
+ "id": "rate-limit-rules-dir",
25
+ "prompt": "Directory the applying project commits its rate-limit rule manifest files into. One file per rule per ADR-3703. The manifest is source-of-truth; the operator applies it via wrangler or the Cloudflare dashboard per REQ-002.",
26
+ "kind": "string",
27
+ "default": "cloudflare/rate-limits"
28
+ },
29
+ {
30
+ "id": "rate-limit-zone-id",
31
+ "prompt": "Cloudflare zone id the rules apply to. Never inline in a rule manifest; store via the applied secretsManagement companion and reference at apply time. Empty string leaves the zone id unresolved (the drift audit and any wrangler flow surface the omission).",
32
+ "kind": "string",
33
+ "default": ""
34
+ },
35
+ {
36
+ "id": "rate-limit-management-surface",
37
+ "prompt": "Operator-facing management surface per REQ-002 and TAC-3702. wrangler names the command flow the guide walks through; dashboard names the Cloudflare dashboard flow; both records both flows and lets the operator pick per rule.",
38
+ "kind": "enum",
39
+ "options": [
40
+ "wrangler",
41
+ "dashboard",
42
+ "both"
43
+ ],
44
+ "default": "both"
45
+ },
46
+ {
47
+ "id": "rate-limit-drift-audit-cadence",
48
+ "prompt": "Drift-audit cadence per ADR-3704. off disables the runner; daily runs it every 24 hours; hourly runs it every hour. daily is the recommended default.",
49
+ "kind": "enum",
50
+ "options": [
51
+ "off",
52
+ "daily",
53
+ "hourly"
54
+ ],
55
+ "default": "daily"
56
+ }
57
+ ],
58
+ "contributions": [
59
+ {
60
+ "id": "edge-cloudflare-rate-limiting-REQ-001",
61
+ "kind": "req",
62
+ "path": "requirements/edge-cloudflare-rate-limiting-req-001.json"
63
+ },
64
+ {
65
+ "id": "edge-cloudflare-rate-limiting-REQ-002",
66
+ "kind": "req",
67
+ "path": "requirements/edge-cloudflare-rate-limiting-req-002.json"
68
+ },
69
+ {
70
+ "id": "edge-cloudflare-rate-limiting-REQ-003",
71
+ "kind": "req",
72
+ "path": "requirements/edge-cloudflare-rate-limiting-req-003.json"
73
+ },
74
+ {
75
+ "id": "edge-cloudflare-rate-limiting-REQ-004",
76
+ "kind": "req",
77
+ "path": "requirements/edge-cloudflare-rate-limiting-req-004.json"
78
+ },
79
+ {
80
+ "id": "edge-cloudflare-rate-limiting-REQ-005",
81
+ "kind": "req",
82
+ "path": "requirements/edge-cloudflare-rate-limiting-req-005.json"
83
+ },
84
+ {
85
+ "id": "edge-cloudflare-rate-limiting-US-36101",
86
+ "kind": "us",
87
+ "path": "user-stories/edge-cloudflare-rate-limiting-us-36101.json"
88
+ },
89
+ {
90
+ "id": "edge-cloudflare-rate-limiting-US-36102",
91
+ "kind": "us",
92
+ "path": "user-stories/edge-cloudflare-rate-limiting-us-36102.json"
93
+ },
94
+ {
95
+ "id": "edge-cloudflare-rate-limiting-US-36103",
96
+ "kind": "us",
97
+ "path": "user-stories/edge-cloudflare-rate-limiting-us-36103.json"
98
+ },
99
+ {
100
+ "id": "edge-cloudflare-rate-limiting-US-36104",
101
+ "kind": "us",
102
+ "path": "user-stories/edge-cloudflare-rate-limiting-us-36104.json"
103
+ },
104
+ {
105
+ "id": "edge-cloudflare-rate-limiting-US-36105",
106
+ "kind": "us",
107
+ "path": "user-stories/edge-cloudflare-rate-limiting-us-36105.json"
108
+ },
109
+ {
110
+ "id": "edge-cloudflare-rate-limiting-US-36106",
111
+ "kind": "us",
112
+ "path": "user-stories/edge-cloudflare-rate-limiting-us-36106.json"
113
+ },
114
+ {
115
+ "id": "edge-cloudflare-rate-limiting-US-36107",
116
+ "kind": "us",
117
+ "path": "user-stories/edge-cloudflare-rate-limiting-us-36107.json"
118
+ },
119
+ {
120
+ "id": "edge-cloudflare-rate-limiting-US-36108",
121
+ "kind": "us",
122
+ "path": "user-stories/edge-cloudflare-rate-limiting-us-36108.json"
123
+ },
124
+ {
125
+ "id": "TAC-3701-edge-cloudflare-rate-limiting-manifest-schema",
126
+ "kind": "tac",
127
+ "path": "tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json"
128
+ },
129
+ {
130
+ "id": "TAC-3702-edge-cloudflare-rate-limiting-management-surface-doc",
131
+ "kind": "tac",
132
+ "path": "tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json"
133
+ },
134
+ {
135
+ "id": "TAC-3703-edge-cloudflare-rate-limiting-drift-audit-runner",
136
+ "kind": "tac",
137
+ "path": "tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json"
138
+ },
139
+ {
140
+ "id": "ADR-3701-edge-cloudflare-rate-limiting-throttle-contract",
141
+ "kind": "adr",
142
+ "path": "adrs/adr-3701-edge-cloudflare-rate-limiting-throttle-contract.json",
143
+ "scope": "global",
144
+ "topic": "edgeThrottleContract",
145
+ "recommendedDefault": true,
146
+ "elicited": false,
147
+ "standardsTraceClause": "Cloudflare WAF rate-limiting rules documented shape"
148
+ },
149
+ {
150
+ "id": "ADR-3702-edge-cloudflare-rate-limiting-layering",
151
+ "kind": "adr",
152
+ "path": "adrs/adr-3702-edge-cloudflare-rate-limiting-layering.json",
153
+ "recommendedDefault": true,
154
+ "elicited": false,
155
+ "standardsTraceClause": "generic enterprise practice"
156
+ },
157
+ {
158
+ "id": "ADR-3703-edge-cloudflare-rate-limiting-manifest-shape",
159
+ "kind": "adr",
160
+ "path": "adrs/adr-3703-edge-cloudflare-rate-limiting-manifest-shape.json",
161
+ "recommendedDefault": true,
162
+ "elicited": false,
163
+ "standardsTraceClause": "generic enterprise practice"
164
+ },
165
+ {
166
+ "id": "ADR-3704-edge-cloudflare-rate-limiting-drift-audit-cadence",
167
+ "kind": "adr",
168
+ "path": "adrs/adr-3704-edge-cloudflare-rate-limiting-drift-audit-cadence.json",
169
+ "recommendedDefault": true,
170
+ "elicited": true,
171
+ "standardsTraceClause": "generic enterprise practice"
172
+ }
173
+ ]
174
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "adrId": "ADR-3701-edge-cloudflare-rate-limiting-throttle-contract",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "accepted",
7
+ "title": "Edge throttle contract: Cloudflare WAF rate-limiting rules as the shipped shape (scope global, new topic edgeThrottleContract)",
8
+ "context": "An applying Workers project that fronts a public surface needs a zone-level guard that refuses over-threshold bursts at the CF edge before they reach the origin Worker. Cloudflare's WAF rate-limiting rules provide the native answer: a set of rules on the zone, each with expression, threshold, period, characteristics, action and duration per https://developers.cloudflare.com/waf/rate-limiting-rules/. Every applied Worker needs one project-wide answer to the edgeThrottleContract topic; a future non-Cloudflare edge-throttle sibling (Fastly rate-limits, Vercel edge config throttles) would conflict on the same topic by design.",
9
+ "decision": "The shipped v1.0.0 default is Cloudflare WAF rate-limiting rules as the zone-level edge throttle. The rule shape (id, expression, threshold, period, characteristics, action, duration) matches the Cloudflare-documented shape per https://developers.cloudflare.com/waf/rate-limiting-rules/. The edgeThrottleContract topic scope is global on this blueprint; the topic string is edgeThrottleContract (lower camel case, one concept per topic, no version suffix). A future non-Cloudflare adapter contributes the same topic string with a different answer, forcing a DELIBERATE conflict the operator resolves with a project-level ADR. Standards trace clause: Cloudflare WAF rate-limiting rules documented shape.",
10
+ "consequences": "The applying project inherits Cloudflare's documented rule shape and the platform-imposed limits on rules per zone. The rule state lives on the Cloudflare account, not in the project git tree; the local manifest under cloudflare/rate-limits/ is the source of truth an operator applies via the wrangler or dashboard flow per REQ-002. Drift risk is addressed via ADR-3704 (drift-audit cadence) and TAC-3703 (drift-audit runner). Consumers deploying to a non-Cloudflare edge reach for a sibling adapter blueprint that would land as a v1.x minor on this shelf.",
11
+ "alternativesConsidered": [],
12
+ "createdAt": "2026-09-07T22:00:00.000Z",
13
+ "updatedAt": "2026-09-07T22:00:00.000Z"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "adrId": "ADR-3702-edge-cloudflare-rate-limiting-layering",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "accepted",
7
+ "title": "Layering with security-auth-magic-link: zone rate rule sits OVER the per-email application rule",
8
+ "context": "The security-auth-magic-link blueprint ships a per-email per-minute application-level rate limiter on the mint surface. The edge-cloudflare-rate-limiting blueprint ships a zone-level rate rule characterised by IP-per-URL at the CF edge. Applying both blueprints without an explicit layering ADR would leave two rate rules whose characteristic sets an operator could easily mistake for overlapping.",
9
+ "decision": "When both blueprints are applied, the zone-level rate rule sits at the CF edge and refuses the (N+1)th request for the elicited duration before it reaches the origin Worker; the security-auth-magic-link per-email application limiter continues to run on requests that pass the edge gate, applying per-email per-minute limits at the mint-surface. The two rules operate on different characteristic sets (IP-per-URL at the zone, email at the application) and are additive, not overlapping. recommendedDefault: true. Standards trace clause: generic enterprise practice.",
10
+ "consequences": "The composition is documented in the blueprint guide with a copy-paste example (AC-36105-1). The applied recorder records both blueprints so the operator sees the two-rule shape at apply time; a subsequent change to either rule's characteristic that would drift the composition into overlap is caught in the drift-audit runner (TAC-3703).",
11
+ "alternativesConsidered": [],
12
+ "createdAt": "2026-09-07T22:00:00.000Z",
13
+ "updatedAt": "2026-09-07T22:00:00.000Z"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "adrId": "ADR-3703-edge-cloudflare-rate-limiting-manifest-shape",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "accepted",
7
+ "title": "Manifest lives at cloudflare/rate-limits/, one JSON file per rule; the operator applies via wrangler or dashboard, not via a committed script",
8
+ "context": "The rule set could be committed as a wrangler-shape script, a bespoke apply tool, a single manifest file, or one file per rule. The single-file shape hides diff signal when one rule changes; the committed script couples the source of truth to a specific tool. The one-file-per-rule shape keeps a rule change to one file diff, makes review straightforward, and leaves the apply flow to the operator's choice of wrangler or dashboard.",
9
+ "decision": "The manifest lives at the elicited rate-limit-rules-dir (default cloudflare/rate-limits/), with one JSON file per rule. The blueprint ships no committed script that writes rules to the live zone; the operator applies through the documented wrangler or dashboard flow per REQ-002 and TAC-3702. recommendedDefault: true. Standards trace clause: generic enterprise practice.",
10
+ "consequences": "One-file-per-rule keeps each rule diff scoped; the operator can review a rule change in isolation. No committed apply script means the shipped blueprint does not couple to a specific tool version and does not require a Cloudflare API token at build time. Operator applies the manifest at a cadence they set; drift risk is addressed via ADR-3704 and TAC-3703.",
11
+ "alternativesConsidered": [],
12
+ "createdAt": "2026-09-07T22:00:00.000Z",
13
+ "updatedAt": "2026-09-07T22:00:00.000Z"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "adrId": "ADR-3704-edge-cloudflare-rate-limiting-drift-audit-cadence",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "accepted",
7
+ "title": "Drift-audit cadence: off, daily or hourly (elicited; recommendedDefault daily)",
8
+ "context": "Rate-limit rules live on the Cloudflare account, not in the project git tree. An operator that changes a rule on the dashboard without a matching manifest update leaves the source of truth behind; a manifest edit that is not applied to the live zone leaves the live behaviour behind. Both directions of drift are runtime-observable but only if the applying project runs the drift-audit runner at a cadence.",
9
+ "decision": "The drift-audit cadence is elicited (rate-limit-drift-audit-cadence) with three options: off (disables the runner), daily (24-hour cadence), hourly (60-minute cadence). recommendedDefault: daily. elicited: true. Standards trace clause: generic enterprise practice.",
10
+ "consequences": "daily is the safe default for the typical operator (a manifest change that misses the live zone is surfaced within 24 hours through the applied logging companion's audit sink). hourly is the safe default for a high-cadence operation (the applying project makes rule changes multiple times a week and wants a same-day signal). off is safe only when the operator has an alternative drift-check discipline (a manual review after every change); the elicit prompts for the operator's choice at apply time.",
11
+ "alternativesConsidered": [],
12
+ "createdAt": "2026-09-07T22:00:00.000Z",
13
+ "updatedAt": "2026-09-07T22:00:00.000Z"
14
+ }
@@ -0,0 +1,104 @@
1
+ // Probe: drift-audit event secrecy.
2
+ //
3
+ // anchorAcId: AC-36107-1. accountBound: false.
4
+ //
5
+ // Drives the shipped drift-audit runner realisation
6
+ // (packages/rcf-lite/test/fixtures/cf-edge/src/drift-audit-runner.mjs)
7
+ // with a synthetic manifest loader and a fake fetch that returns a
8
+ // live-zone response with one mismatched rule. Asserts every record
9
+ // on the sink carries only {ruleId, clientIpHash, outcome, timestamp,
10
+ // diff} keys and NO full IPv4 or IPv6 address, NO body key, NO user
11
+ // agent key. Under SIMULATE_EVENT_LEAK_IP=true the runner injects a
12
+ // full client IP into the outcome so the probe surfaces the leak.
13
+
14
+ import { FIXTURE_DIR } from './probe-utils.mjs';
15
+
16
+ export const anchorAcId = 'AC-36107-1';
17
+ export const accountBound = false;
18
+
19
+ const IPV4 = /\b(?:25[0-5]|2[0-4]\d|[01]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)){3}\b/;
20
+ const IPV6 = /\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/;
21
+ const ALLOWED_KEYS = new Set(['ruleId', 'clientIpHash', 'outcome', 'timestamp', 'diff']);
22
+ const FORBIDDEN_KEYS = new Set(['body', 'userAgent', 'user-agent', 'clientIp', 'ip', 'sourceIp']);
23
+
24
+ function containsIp(text) {
25
+ if (typeof text !== 'string') return null;
26
+ const v4 = text.match(IPV4);
27
+ if (v4) return v4[0];
28
+ const v6 = text.match(IPV6);
29
+ if (v6) return v6[0];
30
+ return null;
31
+ }
32
+
33
+ export default async function runProbe() {
34
+ const runnerMod = await import(`${FIXTURE_DIR}/src/drift-audit-runner.mjs`);
35
+ const manifestRule = {
36
+ id: 'public-api-per-ip',
37
+ expression: '(http.request.uri.path matches "^/api/")',
38
+ threshold: 60,
39
+ period: 60,
40
+ characteristics: ['ip.src', 'cf.colo.id'],
41
+ action: 'block',
42
+ duration: 60,
43
+ };
44
+ const liveRule = { ...manifestRule, threshold: 90 };
45
+ const captured = [];
46
+ const eventSink = (record) => captured.push(record);
47
+ const fakeFetch = async () => ({
48
+ ok: true,
49
+ status: 200,
50
+ async json() { return { result: [liveRule] }; },
51
+ });
52
+ const runner = runnerMod.createDriftAuditRunner({
53
+ env: {
54
+ CF_ZONE_ID: 'fixture-zone-id',
55
+ SIMULATE_EVENT_LEAK_IP: process.env.SIMULATE_EVENT_LEAK_IP,
56
+ },
57
+ eventSink,
58
+ fetch: fakeFetch,
59
+ clock: () => '2026-09-07T22:00:00.000Z',
60
+ cadence: 'daily',
61
+ manifestLoader: async () => [manifestRule],
62
+ });
63
+ const report = await runner.runOnce();
64
+ const results = [];
65
+ if (captured.length === 0) {
66
+ results.push({ anchorAcId: 'AC-36107-1', verdict: 'fail', detail: 'drift-audit runner produced zero records; expected one for the threshold drift.' });
67
+ return { results };
68
+ }
69
+ let ipLeak = null;
70
+ let keyLeak = null;
71
+ for (const rec of captured) {
72
+ for (const k of Object.keys(rec)) {
73
+ if (FORBIDDEN_KEYS.has(k)) keyLeak = k;
74
+ if (!ALLOWED_KEYS.has(k)) keyLeak = keyLeak || `unexpected-key:${k}`;
75
+ }
76
+ for (const v of Object.values(rec)) {
77
+ if (typeof v === 'string') {
78
+ const hit = containsIp(v);
79
+ if (hit) ipLeak = hit;
80
+ }
81
+ }
82
+ }
83
+ if (keyLeak) {
84
+ results.push({ anchorAcId: 'AC-36107-1', verdict: 'fail', detail: `drift-audit record carries a forbidden or unexpected key: ${keyLeak}` });
85
+ }
86
+ if (ipLeak) {
87
+ results.push({ anchorAcId: 'AC-36107-1', verdict: 'fail', detail: `drift-audit record leaked a full IP address in a string field: ${ipLeak}` });
88
+ }
89
+ if (results.length === 0) {
90
+ results.push({
91
+ anchorAcId: 'AC-36107-1',
92
+ verdict: 'pass',
93
+ detail: `drift-audit runner produced ${captured.length} record(s); every record carries only ${[...ALLOWED_KEYS].join(', ')} and no full IP, body or user-agent field appears.`,
94
+ });
95
+ }
96
+ return {
97
+ results,
98
+ extra: {
99
+ recordCount: captured.length,
100
+ driftCount: report.driftCount,
101
+ allowedKeys: [...ALLOWED_KEYS],
102
+ },
103
+ };
104
+ }