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,161 @@
1
+ {
2
+ "slug": "edge-cloudflare-turnstile",
3
+ "version": "1.0.0",
4
+ "category": "edge",
5
+ "capabilities": [
6
+ "humanCheck"
7
+ ],
8
+ "suggestedCompanions": [
9
+ {
10
+ "role": "logging",
11
+ "reason": "Every siteverify call and every refuse-if-token-missing rejection writes through the applied logger; a logging companion supplies the sink factory."
12
+ },
13
+ {
14
+ "role": "errorHandling",
15
+ "reason": "A siteverify network failure, a malformed token or a missing sitekey and secret constructs an internal error record; an error-handling companion supplies the record factory and the boundary."
16
+ },
17
+ {
18
+ "role": "secretsManagement",
19
+ "reason": "The paired TURNSTILE_SITEKEY and TURNSTILE_SECRET are stored in the operator applied secretsManagement companion; the applied vault seam receives the elicited values at apply time and injects them at deploy."
20
+ }
21
+ ],
22
+ "elicits": [
23
+ {
24
+ "id": "turnstile-sitekey",
25
+ "prompt": "Cloudflare Turnstile sitekey the widget renders with. See https://developers.cloudflare.com/turnstile/ for issuing. Test sitekeys are pinned in the shipped fixture per https://developers.cloudflare.com/turnstile/troubleshooting/testing/.",
26
+ "kind": "string",
27
+ "default": ""
28
+ },
29
+ {
30
+ "id": "turnstile-secret",
31
+ "prompt": "Cloudflare Turnstile secret the server-side verifier posts to siteverify with. Never inline; stored via the applied secretsManagement companion or your environment.",
32
+ "kind": "string",
33
+ "default": ""
34
+ },
35
+ {
36
+ "id": "turnstile-widget-mode",
37
+ "prompt": "Cloudflare Turnstile widget mode per ADR-3602 and https://developers.cloudflare.com/turnstile/. managed (recommendedDefault; Cloudflare decides when to show the challenge); non-interactive (always shows a non-interactive challenge); invisible (mounts an invisible widget).",
38
+ "kind": "enum",
39
+ "options": [
40
+ "managed",
41
+ "non-interactive",
42
+ "invisible"
43
+ ],
44
+ "default": "managed"
45
+ },
46
+ {
47
+ "id": "turnstile-guarded-surfaces",
48
+ "prompt": "List of applied route ids the token-required guard registers on. Every guarded surface refuses missing-token submits with 400 before any downstream handler runs.",
49
+ "kind": "string",
50
+ "default": ""
51
+ }
52
+ ],
53
+ "contributions": [
54
+ {
55
+ "id": "edge-cloudflare-turnstile-REQ-001",
56
+ "kind": "req",
57
+ "path": "requirements/edge-cloudflare-turnstile-req-001.json"
58
+ },
59
+ {
60
+ "id": "edge-cloudflare-turnstile-REQ-002",
61
+ "kind": "req",
62
+ "path": "requirements/edge-cloudflare-turnstile-req-002.json"
63
+ },
64
+ {
65
+ "id": "edge-cloudflare-turnstile-REQ-003",
66
+ "kind": "req",
67
+ "path": "requirements/edge-cloudflare-turnstile-req-003.json"
68
+ },
69
+ {
70
+ "id": "edge-cloudflare-turnstile-REQ-004",
71
+ "kind": "req",
72
+ "path": "requirements/edge-cloudflare-turnstile-req-004.json"
73
+ },
74
+ {
75
+ "id": "edge-cloudflare-turnstile-REQ-005",
76
+ "kind": "req",
77
+ "path": "requirements/edge-cloudflare-turnstile-req-005.json"
78
+ },
79
+ {
80
+ "id": "edge-cloudflare-turnstile-US-35101",
81
+ "kind": "us",
82
+ "path": "user-stories/edge-cloudflare-turnstile-us-35101.json"
83
+ },
84
+ {
85
+ "id": "edge-cloudflare-turnstile-US-35102",
86
+ "kind": "us",
87
+ "path": "user-stories/edge-cloudflare-turnstile-us-35102.json"
88
+ },
89
+ {
90
+ "id": "edge-cloudflare-turnstile-US-35103",
91
+ "kind": "us",
92
+ "path": "user-stories/edge-cloudflare-turnstile-us-35103.json"
93
+ },
94
+ {
95
+ "id": "edge-cloudflare-turnstile-US-35104",
96
+ "kind": "us",
97
+ "path": "user-stories/edge-cloudflare-turnstile-us-35104.json"
98
+ },
99
+ {
100
+ "id": "edge-cloudflare-turnstile-US-35105",
101
+ "kind": "us",
102
+ "path": "user-stories/edge-cloudflare-turnstile-us-35105.json"
103
+ },
104
+ {
105
+ "id": "edge-cloudflare-turnstile-US-35106",
106
+ "kind": "us",
107
+ "path": "user-stories/edge-cloudflare-turnstile-us-35106.json"
108
+ },
109
+ {
110
+ "id": "edge-cloudflare-turnstile-US-35107",
111
+ "kind": "us",
112
+ "path": "user-stories/edge-cloudflare-turnstile-us-35107.json"
113
+ },
114
+ {
115
+ "id": "edge-cloudflare-turnstile-US-35108",
116
+ "kind": "us",
117
+ "path": "user-stories/edge-cloudflare-turnstile-us-35108.json"
118
+ },
119
+ {
120
+ "id": "TAC-3601-edge-cloudflare-turnstile-widget-mount",
121
+ "kind": "tac",
122
+ "path": "tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json"
123
+ },
124
+ {
125
+ "id": "TAC-3602-edge-cloudflare-turnstile-server-verifier",
126
+ "kind": "tac",
127
+ "path": "tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json"
128
+ },
129
+ {
130
+ "id": "TAC-3603-edge-cloudflare-turnstile-magic-link-hook",
131
+ "kind": "tac",
132
+ "path": "tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json"
133
+ },
134
+ {
135
+ "id": "ADR-3601-edge-cloudflare-turnstile-verifier-contract",
136
+ "kind": "adr",
137
+ "path": "adrs/adr-3601-edge-cloudflare-turnstile-verifier-contract.json",
138
+ "scope": "global",
139
+ "topic": "humanVerificationGate",
140
+ "recommendedDefault": true,
141
+ "elicited": false,
142
+ "standardsTraceClause": "Cloudflare Turnstile siteverify endpoint documented shape"
143
+ },
144
+ {
145
+ "id": "ADR-3602-edge-cloudflare-turnstile-widget-mode",
146
+ "kind": "adr",
147
+ "path": "adrs/adr-3602-edge-cloudflare-turnstile-widget-mode.json",
148
+ "recommendedDefault": true,
149
+ "elicited": true,
150
+ "standardsTraceClause": "Cloudflare Turnstile documented widget modes"
151
+ },
152
+ {
153
+ "id": "ADR-3603-edge-cloudflare-turnstile-refuse-shape",
154
+ "kind": "adr",
155
+ "path": "adrs/adr-3603-edge-cloudflare-turnstile-refuse-shape.json",
156
+ "recommendedDefault": true,
157
+ "elicited": false,
158
+ "standardsTraceClause": "Cloudflare Turnstile documented error codes"
159
+ }
160
+ ]
161
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "adrId": "ADR-3601-edge-cloudflare-turnstile-verifier-contract",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "accepted",
7
+ "title": "Human verification gate: Cloudflare Turnstile with server-side siteverify (scope global, new topic humanVerificationGate)",
8
+ "context": "An applying project that mounts a public-facing form (contact, subscribe, magic-link mint, low-cost-per-request public API) needs a human verification gate that keeps unattended bots off the form. Cloudflare Turnstile is the CF-native answer: a client widget that emits a response token and a server-side siteverify endpoint (https://challenges.cloudflare.com/turnstile/v0/siteverify) that returns success:true or success:false with error-codes per https://developers.cloudflare.com/turnstile/. Every applied Worker needs one project-wide answer to the humanVerificationGate topic; a future non-Cloudflare sibling (hCaptcha, reCAPTCHA) would conflict on the same topic by design.",
9
+ "decision": "The shipped v1.0.0 default is Cloudflare Turnstile with server-side siteverify. The verifier POSTs {secret, response} to https://challenges.cloudflare.com/turnstile/v0/siteverify per the Cloudflare Turnstile documented endpoint shape. On success:true the handler proceeds; on success:false the handler rejects 400 with the error-codes value in the refusal body. The humanVerificationGate topic scope is global on this blueprint; the topic string is humanVerificationGate (lower camel case, one concept per topic, no version suffix). Standards trace clause: Cloudflare Turnstile siteverify endpoint documented shape.",
10
+ "consequences": "The applying project inherits Cloudflare Turnstile documented widget-and-siteverify contract per https://developers.cloudflare.com/turnstile/. A future hCaptcha or reCAPTCHA sibling contributes the same humanVerificationGate topic with a different answer, forcing a DELIBERATE operator-resolved conflict at the project ADR level. The pack fixture pins Cloudflare public test keys per https://developers.cloudflare.com/turnstile/troubleshooting/testing/ so the pack does not need real Turnstile credentials to run.",
11
+ "alternativesConsidered": [],
12
+ "createdAt": "2026-09-07T20:00:00.000Z",
13
+ "updatedAt": "2026-09-07T20:00:00.000Z"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "adrId": "ADR-3602-edge-cloudflare-turnstile-widget-mode",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "accepted",
7
+ "title": "Widget mode is elicited as an enum (managed, non-interactive, invisible); recommendedDefault managed",
8
+ "context": "Cloudflare Turnstile documents three widget modes per https://developers.cloudflare.com/turnstile/: managed (Cloudflare decides when to show a challenge, minimising user friction), non-interactive (always renders a non-interactive challenge for uniform behaviour) and invisible (mounts an invisible widget). Each mode is a per-surface operational profile; the elicit forces the operator to name the intent.",
9
+ "decision": "Widget mode is elicited (elicited: true). Values: managed, non-interactive, invisible per Cloudflare Turnstile documented modes. recommendedDefault: managed. The applied-sidecar records the operator answer per applying surface. Standards trace clause: Cloudflare Turnstile documented widget modes.",
10
+ "consequences": "The elicitation forces an explicit answer on every apply. The pack fixture accepts ?mode=<managed|non-interactive|invisible> and pins the invisible-widget test sitekeys (1x00000000000000000000BB and 2x00000000000000000000BB per https://developers.cloudflare.com/turnstile/troubleshooting/testing/) alongside the managed pass/fail sitekeys so every mode is exercised on the gate.",
11
+ "alternativesConsidered": [],
12
+ "createdAt": "2026-09-07T20:00:00.000Z",
13
+ "updatedAt": "2026-09-07T20:00:00.000Z"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "adrId": "ADR-3603-edge-cloudflare-turnstile-refuse-shape",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "accepted",
7
+ "title": "Refuse-if-token-missing status is 400 with an error-code body (no sitekey leak); siteverify failure carries the documented error-codes value",
8
+ "context": "Cloudflare Turnstile siteverify returns {success: false, error-codes: [...]} on failure per https://developers.cloudflare.com/turnstile/. The applying project needs a stable refusal shape that never leaks the sitekey, the secret or the response token into an error body or event record.",
9
+ "decision": "Refuse-if-token-missing status is 400. Refusal body carries a stable error-code: turnstile.token-missing for the guard branch, or the Cloudflare error-codes[0] for the siteverify-failure branch. Refusal body never carries the sitekey, the secret or the response token value. Standards trace clause: Cloudflare Turnstile documented error codes.",
10
+ "consequences": "The 400 status is machine-observable at every applied surface; downstream observability records the outcome by error-code, not by sitekey. Event records ship {sitekeyHash, outcome, timestamp} only; the event-secrecy probe asserts this shape (AC-35108-1).",
11
+ "alternativesConsidered": [],
12
+ "createdAt": "2026-09-07T20:00:00.000Z",
13
+ "updatedAt": "2026-09-07T20:00:00.000Z"
14
+ }
@@ -0,0 +1,51 @@
1
+ // Probe: every event record carries sitekeyHash, outcome and timestamp only; never the token, never the secret.
2
+ // anchorAcId: AC-35108-1. accountBound: false. Drives one pass and one fail through the live siteverify endpoint.
3
+
4
+ export const anchorAcId = 'AC-35108-1';
5
+ export const accountBound = false;
6
+
7
+ export default async function runProbe() {
8
+ const { TEST_SECRETS, TEST_SITEKEYS, bootFixture } = await import('./probe-utils.mjs');
9
+ const results = [];
10
+
11
+ const fixture = await bootFixture({ TURNSTILE_SECRET: TEST_SECRETS.alwaysPass, TURNSTILE_SITEKEY: TEST_SITEKEYS.alwaysPass, TURNSTILE_FAIL_SECRET: TEST_SECRETS.alwaysFail });
12
+ try {
13
+ await fetch(`${fixture.url}/api/events/clear`, { method: 'POST' });
14
+ // Pass branch: submit with any token.
15
+ const passBody = new URLSearchParams();
16
+ passBody.set('email', 'reviewer@example.com');
17
+ passBody.set('turnstile-sitekey', TEST_SITEKEYS.alwaysPass);
18
+ passBody.set('cf-turnstile-response', 'PASS-TOKEN-LITERAL-XYZ');
19
+ const passResp = await fetch(`${fixture.url}/api/submit`, {
20
+ method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, body: passBody,
21
+ });
22
+
23
+ // Fail branch: submit with fail-secret=1 forcing the always-fail secret path.
24
+ const failBody = new URLSearchParams();
25
+ failBody.set('email', 'reviewer@example.com');
26
+ failBody.set('turnstile-sitekey', TEST_SITEKEYS.alwaysBlock);
27
+ failBody.set('cf-turnstile-response', 'FAIL-TOKEN-LITERAL-ABC');
28
+ const failResp = await fetch(`${fixture.url}/api/submit?fail-secret=1`, {
29
+ method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, body: failBody,
30
+ });
31
+
32
+ const events = await (await fetch(`${fixture.url}/api/events`)).json();
33
+ const allowed = new Set(['sitekeyHash', 'outcome', 'timestamp']);
34
+ const extraKeyRecords = events.filter((r) => Object.keys(r).some((k) => !allowed.has(k)));
35
+ const forbiddenSubstrings = ['PASS-TOKEN-LITERAL-XYZ', 'FAIL-TOKEN-LITERAL-ABC', TEST_SECRETS.alwaysPass, TEST_SECRETS.alwaysFail];
36
+ const serialized = JSON.stringify(events);
37
+ const leaks = forbiddenSubstrings.filter((s) => serialized.includes(s));
38
+ const outcomes = events.map((e) => e.outcome).sort();
39
+ const shapeOk = events.length === 2 && extraKeyRecords.length === 0 && leaks.length === 0
40
+ && outcomes[0] === 'refused' && outcomes[1] === 'verified';
41
+ results.push({
42
+ anchorAcId: 'AC-35108-1',
43
+ verdict: shapeOk ? 'pass' : 'fail',
44
+ detail: shapeOk
45
+ ? `event-secrecy: 2 events captured, keys=[sitekeyHash,outcome,timestamp] only; no token or secret leak; outcomes=${JSON.stringify(outcomes)}; passResp=${passResp.status} failResp=${failResp.status}`
46
+ : `event-secrecy failure: events=${events.length} extraKeyRecords=${JSON.stringify(extraKeyRecords)} leaks=${JSON.stringify(leaks)} outcomes=${JSON.stringify(outcomes)} passResp=${passResp.status} failResp=${failResp.status}`,
47
+ });
48
+ } finally { await fixture.stop(); }
49
+
50
+ return { results };
51
+ }
@@ -0,0 +1,48 @@
1
+ // Probe: every elicited surface in the pack fixture source registers under the token-required guard;
2
+ // a live missing-token submit is refused with 400 before any downstream handler runs.
3
+ // anchorAcId: AC-35104-1. accountBound: false.
4
+
5
+ export const anchorAcId = 'AC-35104-1';
6
+ export const accountBound = false;
7
+
8
+ export default async function runProbe() {
9
+ const { FIXTURE_DIR, bootFixture, fixturePost, readFileText } = await import('./probe-utils.mjs');
10
+ const { resolve } = await import('node:path');
11
+ const results = [];
12
+
13
+ // 1. Source scan: server.js must register the guard on every guarded surface.
14
+ const serverSrc = await readFileText(resolve(FIXTURE_DIR, 'server.js'));
15
+ // The guard is the tokenRequiredGuard function; every POST route on a guarded surface must call it.
16
+ const guardedSurfacesPattern = /GUARDED_SURFACES/;
17
+ const guardCallPattern = /tokenRequiredGuard\(req, res, params\)/;
18
+ const surfaceCheckPattern = /if \(!GUARDED_SURFACES\.includes/;
19
+ const hasGuardedSurfaces = guardedSurfacesPattern.test(serverSrc);
20
+ const hasGuardCall = guardCallPattern.test(serverSrc);
21
+ const hasSurfaceCheck = surfaceCheckPattern.test(serverSrc);
22
+ const scanOk = hasGuardedSurfaces && hasGuardCall && hasSurfaceCheck;
23
+ results.push({
24
+ anchorAcId: 'AC-35104-1',
25
+ verdict: scanOk ? 'pass' : 'fail',
26
+ detail: scanOk
27
+ ? 'guard-shape scan: GUARDED_SURFACES declared, tokenRequiredGuard called on POST handlers, surface-check gate present before guard call'
28
+ : `guard-shape scan miss: GUARDED_SURFACES=${hasGuardedSurfaces}, guardCall=${hasGuardCall}, surfaceCheck=${hasSurfaceCheck}`,
29
+ });
30
+
31
+ // 2. Live refuse: missing-token POST to every guarded surface returns 400 with turnstile.token-missing.
32
+ const fixture = await bootFixture();
33
+ try {
34
+ for (const path of ['/api/submit', '/api/magic-link']) {
35
+ const resp = await fixturePost(fixture.url, path, { email: 'reviewer@example.com', 'turnstile-sitekey': '1x00000000000000000000AA' });
36
+ const ok = resp.status === 400 && resp.json && resp.json.errorCode === 'turnstile.token-missing';
37
+ results.push({
38
+ anchorAcId: 'AC-35104-1',
39
+ verdict: ok ? 'pass' : 'fail',
40
+ detail: ok
41
+ ? `guard rejected missing-token submit on ${path} with status=400 errorCode=turnstile.token-missing`
42
+ : `guard unexpected shape on ${path} status=${resp.status} body=${resp.text}`,
43
+ });
44
+ }
45
+ } finally { await fixture.stop(); }
46
+
47
+ return { results };
48
+ }
@@ -0,0 +1,139 @@
1
+ // Shared helpers for edge-cloudflare-turnstile probes.
2
+ //
3
+ // Runtime-dependency posture: probes drive the shipped pack fixture at
4
+ // packages/rcf-lite/test/fixtures/probe-pack-edge-cloudflare-turnstile so
5
+ // rcf-lite gains no new runtime dependency (Node's built-in http, url and
6
+ // crypto modules cover the fixture). Two probes are pure source-tree AST
7
+ // scans (secret-shape-scan, guard-shape-scan); two probes drive the live
8
+ // https://challenges.cloudflare.com/turnstile/v0/siteverify endpoint with
9
+ // the pinned Cloudflare public test keys documented at
10
+ // https://developers.cloudflare.com/turnstile/troubleshooting/testing/
11
+ // (siteverify-fixture, event-secrecy).
12
+
13
+ import { mkdir, writeFile, readFile, readdir, stat } from 'node:fs/promises';
14
+ import { spawn } from 'node:child_process';
15
+ import { dirname, resolve, join } from 'node:path';
16
+ import { fileURLToPath } from 'node:url';
17
+
18
+ const HERE = dirname(fileURLToPath(import.meta.url));
19
+
20
+ export const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
21
+ export const FIXTURE_DIR = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/probe-pack-edge-cloudflare-turnstile');
22
+ export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/edge-cloudflare-turnstile');
23
+
24
+ // Pinned Cloudflare Turnstile public test keys per
25
+ // https://developers.cloudflare.com/turnstile/troubleshooting/testing/.
26
+ export const TEST_SITEKEYS = Object.freeze({
27
+ alwaysPass: '1x00000000000000000000AA',
28
+ alwaysBlock: '2x00000000000000000000AB',
29
+ forcedInteractive: '3x00000000000000000000FF',
30
+ invisiblePass: '1x00000000000000000000BB',
31
+ invisibleBlock: '2x00000000000000000000BB',
32
+ });
33
+ export const TEST_SECRETS = Object.freeze({
34
+ alwaysPass: '1x0000000000000000000000000000000AA',
35
+ alwaysFail: '2x0000000000000000000000000000000AA',
36
+ tokenSpent: '3x0000000000000000000000000000000AA',
37
+ });
38
+ export const SITEVERIFY_URL = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
39
+
40
+ export function aggregate(results) {
41
+ if (results.some((r) => r.verdict === 'fail')) return 'fail';
42
+ if (results.some((r) => r.verdict === 'warn')) return 'warn';
43
+ return 'pass';
44
+ }
45
+
46
+ export async function writeReport({ probeName, engine, results, extra }) {
47
+ await mkdir(REPORT_DIR, { recursive: true });
48
+ const report = {
49
+ slug: 'edge-cloudflare-turnstile',
50
+ probeName,
51
+ runAt: new Date().toISOString(),
52
+ engine,
53
+ results,
54
+ aggregateVerdict: aggregate(results),
55
+ ...(extra ?? {}),
56
+ };
57
+ const path = resolve(REPORT_DIR, `${probeName}.json`);
58
+ await writeFile(path, JSON.stringify(report, null, 2) + '\n', 'utf8');
59
+ return { report, path };
60
+ }
61
+
62
+ export async function runShim(probeName, engine, mainFn) {
63
+ try {
64
+ const { results, extra } = await mainFn();
65
+ const { report, path } = await writeReport({ probeName, engine, results, extra });
66
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
67
+ process.stdout.write(`report written to ${path}\n`);
68
+ if (report.aggregateVerdict === 'fail') process.exitCode = 1;
69
+ } catch (err) {
70
+ const results = [{
71
+ anchorAcId: 'unknown',
72
+ verdict: 'fail',
73
+ detail: `probe threw: ${err && err.message ? err.message : String(err)}`,
74
+ }];
75
+ const { report, path } = await writeReport({ probeName, engine, results });
76
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
77
+ process.stderr.write(`probe error: ${err && err.stack ? err.stack : String(err)}\n`);
78
+ process.stderr.write(`report written to ${path}\n`);
79
+ process.exitCode = 1;
80
+ }
81
+ }
82
+
83
+ // Boot the pack fixture on a free port. Returns {url, stop}.
84
+ export async function bootFixture(env = {}) {
85
+ const child = spawn(process.execPath, ['server.js'], {
86
+ cwd: FIXTURE_DIR,
87
+ env: { ...process.env, PORT: '0', ...env },
88
+ stdio: ['ignore', 'pipe', 'pipe'],
89
+ });
90
+ const port = await new Promise((resolveP, rejectP) => {
91
+ const timer = setTimeout(() => rejectP(new Error('fixture boot timeout')), 8000);
92
+ let buf = '';
93
+ child.stdout.on('data', (d) => {
94
+ buf += String(d);
95
+ const m = buf.match(/LISTENING (\d+)/);
96
+ if (m) { clearTimeout(timer); resolveP(Number(m[1])); }
97
+ });
98
+ child.stderr.on('data', (d) => { buf += String(d); });
99
+ child.on('exit', (code) => { clearTimeout(timer); rejectP(new Error(`fixture exited early code=${code}: ${buf}`)); });
100
+ });
101
+ return {
102
+ url: `http://127.0.0.1:${port}`,
103
+ stop: () => new Promise((resolveP) => { child.once('exit', () => resolveP()); child.kill('SIGTERM'); }),
104
+ child,
105
+ };
106
+ }
107
+
108
+ export async function fixturePost(url, path, body) {
109
+ const params = new URLSearchParams();
110
+ for (const [k, v] of Object.entries(body)) params.set(k, String(v));
111
+ const resp = await fetch(`${url}${path}`, {
112
+ method: 'POST',
113
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
114
+ body: params,
115
+ });
116
+ const text = await resp.text();
117
+ let json = null;
118
+ try { json = JSON.parse(text); } catch { /* leave null */ }
119
+ return { status: resp.status, json, text };
120
+ }
121
+
122
+ // Recursively walk a directory and return every file path with one of the given extensions.
123
+ export async function collectFiles(root, exts = ['.js', '.mjs', '.cjs', '.ts']) {
124
+ const out = [];
125
+ async function walk(dir) {
126
+ let entries;
127
+ try { entries = await readdir(dir, { withFileTypes: true }); } catch { return; }
128
+ for (const e of entries) {
129
+ if (e.name === 'node_modules' || e.name === 'proof' || e.name === '.git') continue;
130
+ const p = join(dir, e.name);
131
+ if (e.isDirectory()) await walk(p);
132
+ else if (exts.some((x) => e.name.endsWith(x))) out.push(p);
133
+ }
134
+ }
135
+ await walk(root);
136
+ return out;
137
+ }
138
+
139
+ export async function readFileText(p) { return readFile(p, 'utf8'); }
@@ -0,0 +1,5 @@
1
+ import runProbe from './event-secrecy.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'live-endpoint', image: 'Cloudflare siteverify endpoint via probe-pack-edge-cloudflare-turnstile fixture; event sink asserted for secrecy', healthy: true };
5
+ runShim('event-secrecy', engine, runProbe);
@@ -0,0 +1,5 @@
1
+ import runProbe from './guard-shape-scan.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'source-tree-plus-live', image: 'source AST scan plus live POST against probe-pack-edge-cloudflare-turnstile fixture', healthy: true };
5
+ runShim('guard-shape-scan', engine, runProbe);
@@ -0,0 +1,5 @@
1
+ import runProbe from './secret-shape-scan.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'source-tree', image: 'AST-shaped source scan over probe-pack-edge-cloudflare-turnstile fixture', healthy: true };
5
+ runShim('secret-shape-scan', engine, runProbe);
@@ -0,0 +1,5 @@
1
+ import runProbe from './siteverify-fixture.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'live-endpoint', image: 'Cloudflare siteverify endpoint challenges.cloudflare.com/turnstile/v0/siteverify via probe-pack-edge-cloudflare-turnstile fixture', healthy: true };
5
+ runShim('siteverify-fixture', engine, runProbe);
@@ -0,0 +1,77 @@
1
+ // Probe: TURNSTILE_SECRET is read only via env-shaped identifiers; no non-test-key secret literal in the pack fixture source.
2
+ // anchorAcId: AC-35107-1. accountBound: false.
3
+ //
4
+ // The pack fixture pins the Cloudflare public test keys as environment defaults so the pack does not need real Turnstile credentials
5
+ // to run (spec section 3.2). The test keys are documented at https://developers.cloudflare.com/turnstile/troubleshooting/testing/
6
+ // and are public per Cloudflare; the scan allows those literals only and refuses any other secret-shaped literal.
7
+
8
+ export const anchorAcId = 'AC-35107-1';
9
+ export const accountBound = false;
10
+
11
+ export default async function runProbe() {
12
+ const { FIXTURE_DIR, TEST_SECRETS, collectFiles, readFileText } = await import('./probe-utils.mjs');
13
+ const results = [];
14
+
15
+ const files = await collectFiles(FIXTURE_DIR, ['.js', '.mjs', '.cjs']);
16
+ // 1. Every TURNSTILE_SECRET reference must be an env-shaped read (process.env.TURNSTILE_SECRET).
17
+ const envReadPattern = /process\.env\.TURNSTILE_(?:SECRET|FAIL_SECRET|SITEKEY|INVISIBLE_SITEKEY|INVISIBLE_BLOCK_SITEKEY|BLOCK_SITEKEY|FORCED_SITEKEY|WIDGET_MODE|GUARDED_SURFACES)\b/;
18
+ const bareRefPattern = /\bTURNSTILE_SECRET\b/g;
19
+
20
+ let envReadCount = 0;
21
+ let bareRefCount = 0;
22
+ const bareRefLocations = [];
23
+
24
+ for (const file of files) {
25
+ const src = await readFileText(file);
26
+ const bare = [...src.matchAll(bareRefPattern)];
27
+ for (const m of bare) {
28
+ const window = src.slice(Math.max(0, m.index - 40), m.index + m[0].length);
29
+ if (window.match(envReadPattern)) envReadCount++;
30
+ else {
31
+ const lineStart = src.lastIndexOf('\n', m.index) + 1;
32
+ const lineEnd = src.indexOf('\n', m.index);
33
+ const line = src.slice(lineStart, lineEnd === -1 ? src.length : lineEnd);
34
+ const beforeCommented = line.slice(0, m.index - lineStart).includes('//');
35
+ if (beforeCommented || line.trim().startsWith('//') || line.trim().startsWith('*')) continue;
36
+ bareRefCount++;
37
+ bareRefLocations.push({ file: file.replace(FIXTURE_DIR + '/', ''), line: src.slice(0, m.index).split('\n').length });
38
+ }
39
+ }
40
+ }
41
+
42
+ results.push({
43
+ anchorAcId: 'AC-35107-1',
44
+ verdict: (envReadCount >= 1 && bareRefCount === 0) ? 'pass' : 'fail',
45
+ detail: (envReadCount >= 1 && bareRefCount === 0)
46
+ ? `TURNSTILE_SECRET is read only via env-shaped identifiers; envReads=${envReadCount}, bareOutsideEnvFacade=0, filesScanned=${files.length}`
47
+ : `TURNSTILE_SECRET bare references outside process.env facade: ${JSON.stringify(bareRefLocations)}`,
48
+ });
49
+
50
+ // 2. No non-pinned-test secret literal appears in source. Cloudflare public test keys (documented on
51
+ // https://developers.cloudflare.com/turnstile/troubleshooting/testing/) are the ONLY secret-shaped
52
+ // literals allowed as env defaults per spec section 3.2.
53
+ const allowedTestSecrets = new Set(Object.values(TEST_SECRETS));
54
+ // A secret-shaped literal is a 30-char-or-longer alphanumeric string sitting inside single or double quotes.
55
+ const secretLiteralPattern = /["']([A-Za-z0-9_-]{30,})["']/g;
56
+ const leaks = [];
57
+ for (const file of files) {
58
+ const src = await readFileText(file);
59
+ let m;
60
+ while ((m = secretLiteralPattern.exec(src)) !== null) {
61
+ const lit = m[1];
62
+ if (allowedTestSecrets.has(lit)) continue;
63
+ // Ignore obvious non-secrets: URLs (contain slashes), function names.
64
+ if (lit.startsWith('http') || lit.includes('/')) continue;
65
+ leaks.push({ file: file.replace(FIXTURE_DIR + '/', ''), fragment: lit.slice(0, 8) + '...' });
66
+ }
67
+ }
68
+ results.push({
69
+ anchorAcId: 'AC-35107-1',
70
+ verdict: leaks.length === 0 ? 'pass' : 'fail',
71
+ detail: leaks.length === 0
72
+ ? `only Cloudflare public test secrets appear as env defaults (allowed per Cloudflare testing docs); no other secret-shaped literal found in ${files.length} files`
73
+ : `unexpected secret-shaped literal in fixture source: ${JSON.stringify(leaks)}`,
74
+ });
75
+
76
+ return { results, extra: { filesScanned: files.length, allowedTestSecretCount: allowedTestSecrets.size } };
77
+ }
@@ -0,0 +1,53 @@
1
+ // Probe: server-side siteverify with pinned always-pass secret returns success:true;
2
+ // with pinned always-fail secret returns success:false. anchorAcId: AC-35102-1. accountBound: false.
3
+ // Drives the LIVE Cloudflare siteverify endpoint per spec section 3.1 (real-engine rule)
4
+ // with the public test keys documented at
5
+ // https://developers.cloudflare.com/turnstile/troubleshooting/testing/.
6
+
7
+ export const anchorAcId = 'AC-35102-1';
8
+ export const accountBound = false;
9
+
10
+ export default async function runProbe() {
11
+ const { TEST_SECRETS, SITEVERIFY_URL, bootFixture, fixturePost, TEST_SITEKEYS } = await import('./probe-utils.mjs');
12
+ const results = [];
13
+
14
+ // Pass branch: drive siteverify with always-pass secret via the shipped verifier
15
+ const passFixture = await bootFixture({ TURNSTILE_SECRET: TEST_SECRETS.alwaysPass, TURNSTILE_SITEKEY: TEST_SITEKEYS.alwaysPass });
16
+ try {
17
+ const passResp = await fixturePost(passFixture.url, '/api/submit', {
18
+ email: 'reviewer@example.com',
19
+ 'turnstile-sitekey': TEST_SITEKEYS.alwaysPass,
20
+ 'cf-turnstile-response': 'XXXX.DUMMY.TOKEN.XXXX',
21
+ });
22
+ const okPass = passResp.status === 200 && passResp.json && passResp.json.received === 'ok';
23
+ results.push({
24
+ anchorAcId: 'AC-35102-1',
25
+ verdict: okPass ? 'pass' : 'fail',
26
+ detail: okPass
27
+ ? `siteverify pass via ${SITEVERIFY_URL} with always-pass secret returned success:true; fixture /api/submit responded status=200 body=${JSON.stringify(passResp.json)}`
28
+ : `siteverify pass unexpected shape status=${passResp.status} body=${passResp.text}`,
29
+ });
30
+ } finally { await passFixture.stop(); }
31
+
32
+ // Fail branch: drive siteverify with always-fail secret; handler must reject with 400 and errorCodes
33
+ const failFixture = await bootFixture({ TURNSTILE_SECRET: TEST_SECRETS.alwaysFail, TURNSTILE_SITEKEY: TEST_SITEKEYS.alwaysBlock });
34
+ try {
35
+ const failResp = await fixturePost(failFixture.url, '/api/submit', {
36
+ email: 'reviewer@example.com',
37
+ 'turnstile-sitekey': TEST_SITEKEYS.alwaysBlock,
38
+ 'cf-turnstile-response': 'XXXX.DUMMY.TOKEN.XXXX',
39
+ });
40
+ const errorCodes = failResp.json && failResp.json.errorCodes;
41
+ const codesOk = Array.isArray(errorCodes) && errorCodes.length > 0;
42
+ const okFail = failResp.status === 400 && failResp.json && failResp.json.errorCode === 'turnstile.siteverify-failed' && codesOk;
43
+ results.push({
44
+ anchorAcId: 'AC-35102-1',
45
+ verdict: okFail ? 'pass' : 'fail',
46
+ detail: okFail
47
+ ? `siteverify fail via ${SITEVERIFY_URL} with always-fail secret returned success:false; fixture /api/submit responded status=400 errorCode=turnstile.siteverify-failed errorCodes=${JSON.stringify(errorCodes)}`
48
+ : `siteverify fail unexpected shape status=${failResp.status} body=${failResp.text}`,
49
+ });
50
+ } finally { await failFixture.stop(); }
51
+
52
+ return { results };
53
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "reqId": "edge-cloudflare-turnstile-REQ-001",
3
+ "prdId": "PRD-001",
4
+ "title": "Client widget mount: an elicited sitekey renders the Turnstile widget and the mount injects no third-party script beyond Cloudflare Turnstile JS host",
5
+ "description": "The applying project reaches Cloudflare Turnstile through a client widget mount that renders on elicited surfaces using the elicited TURNSTILE_SITEKEY. The mount injects only Cloudflare Turnstile JS from the Cloudflare Turnstile host (https://challenges.cloudflare.com/turnstile/v0/api.js per https://developers.cloudflare.com/turnstile/) and no other third-party script. On submit the widget populates a hidden Cf-Turnstile-Response token field the form payload carries.",
6
+ "category": "functional",
7
+ "domain": "edge",
8
+ "priority": "must",
9
+ "rationale": "Ratified in the Cloudflare round 6 spec (2026-09-06 section 5.5). Ships as v1.0.0 of edge-cloudflare-turnstile.",
10
+ "tags": [
11
+ "blueprint:edge-cloudflare-turnstile"
12
+ ],
13
+ "version": "1.0.0",
14
+ "status": "approved",
15
+ "createdAt": "2026-09-07T20:00:00.000Z",
16
+ "updatedAt": "2026-09-07T20:00:00.000Z"
17
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "reqId": "edge-cloudflare-turnstile-REQ-002",
3
+ "prdId": "PRD-001",
4
+ "title": "Server-side siteverify: POST to https://challenges.cloudflare.com/turnstile/v0/siteverify with the elicited secret; success:true proceeds, failure rejects 400",
5
+ "description": "The applying project verifies every Turnstile response token server-side by POSTing {secret: TURNSTILE_SECRET, response: token} to https://challenges.cloudflare.com/turnstile/v0/siteverify. On success:true the handler proceeds; on success:false the handler rejects with 400 and the refusal body carries the documented error-codes value, not the sitekey or the secret.",
6
+ "category": "functional",
7
+ "domain": "edge",
8
+ "priority": "must",
9
+ "rationale": "Ratified in the Cloudflare round 6 spec (2026-09-06 section 5.5). Ships as v1.0.0 of edge-cloudflare-turnstile.",
10
+ "tags": [
11
+ "blueprint:edge-cloudflare-turnstile"
12
+ ],
13
+ "version": "1.0.0",
14
+ "status": "approved",
15
+ "createdAt": "2026-09-07T20:00:00.000Z",
16
+ "updatedAt": "2026-09-07T20:00:00.000Z"
17
+ }