rcf-lite 0.23.0 → 0.25.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 (666) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/blueprints/application-account-settings/docs/topics.md +10 -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 +10 -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 +10 -1
  14. package/blueprints/application-charts/docs/topics.md +10 -1
  15. package/blueprints/application-dashboard/docs/topics.md +10 -1
  16. package/blueprints/application-datatable/docs/topics.md +10 -1
  17. package/blueprints/application-empty-error-states/docs/topics.md +10 -1
  18. package/blueprints/application-error-handling/docs/topics.md +10 -1
  19. package/blueprints/application-file-upload/docs/topics.md +10 -1
  20. package/blueprints/application-forms-wizard/docs/topics.md +10 -1
  21. package/blueprints/application-notifications-in-app/docs/topics.md +10 -1
  22. package/blueprints/application-onboarding-tour/docs/topics.md +10 -1
  23. package/blueprints/application-spa/docs/topics.md +10 -1
  24. package/blueprints/delivery-ci-workflows/docs/topics.md +10 -1
  25. package/blueprints/deploy-cloudflare-workers/docs/topics.md +10 -1
  26. package/blueprints/deploy-hetzner-server/CHANGELOG.md +34 -0
  27. package/blueprints/deploy-hetzner-server/README.md +202 -0
  28. package/blueprints/deploy-hetzner-server/blueprint.json +233 -0
  29. package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3801-deploy-hetzner-server-cloud-host-contract.json +14 -0
  30. package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3802-deploy-hetzner-server-snapshot-cadence.json +14 -0
  31. package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3803-deploy-hetzner-server-provisioning-tool.json +20 -0
  32. package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3804-deploy-hetzner-server-hardening-baseline.json +14 -0
  33. package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +64 -0
  34. package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +116 -0
  35. package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +180 -0
  36. package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +106 -0
  37. package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +63 -0
  38. package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +60 -0
  39. package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +58 -0
  40. package/blueprints/deploy-hetzner-server/contributions/probes/run-cloud-init-render-lint.mjs +9 -0
  41. package/blueprints/deploy-hetzner-server/contributions/probes/run-hcloud-dry-run-mock.mjs +9 -0
  42. package/blueprints/deploy-hetzner-server/contributions/probes/run-manifest-schema-validate.mjs +9 -0
  43. package/blueprints/deploy-hetzner-server/contributions/probes/run-real-account-cloud-init-hardened.mjs +9 -0
  44. package/blueprints/deploy-hetzner-server/contributions/probes/run-real-account-snapshot-on-demand.mjs +9 -0
  45. package/blueprints/deploy-hetzner-server/contributions/probes/run-real-account-throwaway-server-provision.mjs +9 -0
  46. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-001.json +18 -0
  47. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-002.json +18 -0
  48. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-003.json +18 -0
  49. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-004.json +18 -0
  50. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-005.json +18 -0
  51. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-006.json +18 -0
  52. package/blueprints/deploy-hetzner-server/contributions/schemas/hetzner-server.schema.json +108 -0
  53. package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3801-deploy-hetzner-server-provisioner.json +27 -0
  54. package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3802-deploy-hetzner-server-manifest-schema.json +26 -0
  55. package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3803-deploy-hetzner-server-cloud-init-template.json +26 -0
  56. package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3804-deploy-hetzner-server-firewall-shape.json +25 -0
  57. package/blueprints/deploy-hetzner-server/contributions/templates/cloud-init.yaml.tmpl +93 -0
  58. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37101.json +24 -0
  59. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37102.json +24 -0
  60. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37103.json +25 -0
  61. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37104.json +24 -0
  62. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37105.json +24 -0
  63. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37106.json +25 -0
  64. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37107.json +24 -0
  65. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37108.json +24 -0
  66. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37109.json +24 -0
  67. package/blueprints/deploy-hetzner-server/docs/topics.md +48 -0
  68. package/blueprints/deploy-hetzner-server/guide/deploy-hetzner-server.md +180 -0
  69. package/blueprints/edge-cloudflare-access/CHANGELOG.md +23 -0
  70. package/blueprints/edge-cloudflare-access/README.md +141 -0
  71. package/blueprints/edge-cloudflare-access/blueprint.json +197 -0
  72. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3501-edge-cloudflare-access-jwt-gate.json +14 -0
  73. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3502-edge-cloudflare-access-identity-provider.json +25 -0
  74. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3503-edge-cloudflare-access-policy-scope.json +12 -0
  75. package/blueprints/edge-cloudflare-access/contributions/adrs/adr-3504-edge-cloudflare-access-audit-retention.json +12 -0
  76. package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +100 -0
  77. package/blueprints/edge-cloudflare-access/contributions/probes/audit-event-secrecy.mjs +70 -0
  78. package/blueprints/edge-cloudflare-access/contributions/probes/jwt-validator-fixture.mjs +63 -0
  79. package/blueprints/edge-cloudflare-access/contributions/probes/jwt-validator-reject.mjs +95 -0
  80. package/blueprints/edge-cloudflare-access/contributions/probes/probe-utils.mjs +90 -0
  81. package/blueprints/edge-cloudflare-access/contributions/probes/real-account-gated-url.mjs +65 -0
  82. package/blueprints/edge-cloudflare-access/contributions/probes/run-admin-console-gate-surface.mjs +5 -0
  83. package/blueprints/edge-cloudflare-access/contributions/probes/run-audit-event-secrecy.mjs +5 -0
  84. package/blueprints/edge-cloudflare-access/contributions/probes/run-jwt-validator-fixture.mjs +5 -0
  85. package/blueprints/edge-cloudflare-access/contributions/probes/run-jwt-validator-reject.mjs +5 -0
  86. package/blueprints/edge-cloudflare-access/contributions/probes/run-real-account-gated-url.mjs +5 -0
  87. package/blueprints/edge-cloudflare-access/contributions/probes/run-wrangler-seam.mjs +5 -0
  88. package/blueprints/edge-cloudflare-access/contributions/probes/wrangler-seam.mjs +203 -0
  89. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-001.json +17 -0
  90. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-002.json +17 -0
  91. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-003.json +17 -0
  92. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-004.json +17 -0
  93. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-005.json +17 -0
  94. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-006.json +18 -0
  95. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3501-edge-cloudflare-access-jwt-validator.json +31 -0
  96. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3502-edge-cloudflare-access-application-declaration.json +33 -0
  97. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3503-edge-cloudflare-access-policy-shape.json +25 -0
  98. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3504-edge-cloudflare-access-audit-sink.json +25 -0
  99. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34101.json +27 -0
  100. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34102.json +28 -0
  101. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34103.json +27 -0
  102. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34104.json +27 -0
  103. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34105.json +27 -0
  104. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34106.json +27 -0
  105. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34107.json +27 -0
  106. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34108.json +27 -0
  107. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34109.json +27 -0
  108. package/blueprints/edge-cloudflare-access/docs/topics.md +71 -0
  109. package/blueprints/edge-cloudflare-access/guide/edge-cloudflare-access.md +180 -0
  110. package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +10 -0
  111. package/blueprints/edge-cloudflare-rate-limiting/README.md +73 -0
  112. package/blueprints/edge-cloudflare-rate-limiting/blueprint.json +174 -0
  113. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3701-edge-cloudflare-rate-limiting-throttle-contract.json +14 -0
  114. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3702-edge-cloudflare-rate-limiting-layering.json +14 -0
  115. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3703-edge-cloudflare-rate-limiting-manifest-shape.json +14 -0
  116. package/blueprints/edge-cloudflare-rate-limiting/contributions/adrs/adr-3704-edge-cloudflare-rate-limiting-drift-audit-cadence.json +14 -0
  117. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/event-secrecy.mjs +104 -0
  118. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/manifest-presence.mjs +95 -0
  119. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/manifest-schema-validate.mjs +130 -0
  120. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/probe-utils.mjs +111 -0
  121. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/real-account-burst-and-429.mjs +104 -0
  122. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-event-secrecy.mjs +5 -0
  123. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-manifest-presence.mjs +5 -0
  124. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-manifest-schema-validate.mjs +5 -0
  125. package/blueprints/edge-cloudflare-rate-limiting/contributions/probes/run-real-account-burst-and-429.mjs +5 -0
  126. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-001.json +17 -0
  127. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-002.json +17 -0
  128. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-003.json +17 -0
  129. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-004.json +17 -0
  130. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-005.json +17 -0
  131. package/blueprints/edge-cloudflare-rate-limiting/contributions/schemas/rate-limit-rule.schema.json +67 -0
  132. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json +31 -0
  133. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json +25 -0
  134. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json +26 -0
  135. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36101.json +27 -0
  136. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36102.json +27 -0
  137. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36103.json +27 -0
  138. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36104.json +27 -0
  139. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36105.json +27 -0
  140. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36106.json +27 -0
  141. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36107.json +27 -0
  142. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36108.json +27 -0
  143. package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +71 -0
  144. package/blueprints/edge-cloudflare-rate-limiting/guide/edge-cloudflare-rate-limiting.md +88 -0
  145. package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +13 -0
  146. package/blueprints/edge-cloudflare-tunnel/README.md +257 -0
  147. package/blueprints/edge-cloudflare-tunnel/blueprint.json +168 -0
  148. package/blueprints/edge-cloudflare-tunnel/contributions/adrs/adr-4001-edge-cloudflare-tunnel-ingress-bridge-contract.json +23 -0
  149. package/blueprints/edge-cloudflare-tunnel/contributions/adrs/adr-4002-edge-cloudflare-tunnel-connector-runtime.json +19 -0
  150. package/blueprints/edge-cloudflare-tunnel/contributions/adrs/adr-4003-edge-cloudflare-tunnel-hostname-mode.json +19 -0
  151. package/blueprints/edge-cloudflare-tunnel/contributions/probes/aud-presence-check.mjs +114 -0
  152. package/blueprints/edge-cloudflare-tunnel/contributions/probes/cloudflared-config-lint.mjs +80 -0
  153. package/blueprints/edge-cloudflare-tunnel/contributions/probes/manifest-schema-validate.mjs +234 -0
  154. package/blueprints/edge-cloudflare-tunnel/contributions/probes/probe-utils.mjs +231 -0
  155. package/blueprints/edge-cloudflare-tunnel/contributions/probes/real-account-connector-healthy.mjs +54 -0
  156. package/blueprints/edge-cloudflare-tunnel/contributions/probes/real-account-tunnel-hostname-routes.mjs +73 -0
  157. package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-aud-presence-check.mjs +4 -0
  158. package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-cloudflared-config-lint.mjs +4 -0
  159. package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-manifest-schema-validate.mjs +4 -0
  160. package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-real-account-connector-healthy.mjs +4 -0
  161. package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-real-account-tunnel-hostname-routes.mjs +4 -0
  162. package/blueprints/edge-cloudflare-tunnel/contributions/probes/tunnel-manifest.schema.json +55 -0
  163. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-001.json +18 -0
  164. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-002.json +18 -0
  165. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-003.json +18 -0
  166. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-004.json +18 -0
  167. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-005.json +18 -0
  168. package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4001-edge-cloudflare-tunnel-connector-shape.json +26 -0
  169. package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4002-edge-cloudflare-tunnel-manifest-schema.json +26 -0
  170. package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4003-edge-cloudflare-tunnel-access-binding.json +25 -0
  171. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39101.json +24 -0
  172. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39102.json +24 -0
  173. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39103.json +24 -0
  174. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39104.json +24 -0
  175. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39105.json +24 -0
  176. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39106.json +24 -0
  177. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39107.json +24 -0
  178. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39108.json +24 -0
  179. package/blueprints/edge-cloudflare-tunnel/docs/topics.md +72 -0
  180. package/blueprints/edge-cloudflare-tunnel/guide/edge-cloudflare-tunnel.md +204 -0
  181. package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +20 -0
  182. package/blueprints/edge-cloudflare-turnstile/README.md +95 -0
  183. package/blueprints/edge-cloudflare-turnstile/blueprint.json +161 -0
  184. package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3601-edge-cloudflare-turnstile-verifier-contract.json +14 -0
  185. package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3602-edge-cloudflare-turnstile-widget-mode.json +14 -0
  186. package/blueprints/edge-cloudflare-turnstile/contributions/adrs/adr-3603-edge-cloudflare-turnstile-refuse-shape.json +14 -0
  187. package/blueprints/edge-cloudflare-turnstile/contributions/probes/event-secrecy.mjs +51 -0
  188. package/blueprints/edge-cloudflare-turnstile/contributions/probes/guard-shape-scan.mjs +48 -0
  189. package/blueprints/edge-cloudflare-turnstile/contributions/probes/probe-utils.mjs +139 -0
  190. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-event-secrecy.mjs +5 -0
  191. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-guard-shape-scan.mjs +5 -0
  192. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-secret-shape-scan.mjs +5 -0
  193. package/blueprints/edge-cloudflare-turnstile/contributions/probes/run-siteverify-fixture.mjs +5 -0
  194. package/blueprints/edge-cloudflare-turnstile/contributions/probes/secret-shape-scan.mjs +77 -0
  195. package/blueprints/edge-cloudflare-turnstile/contributions/probes/siteverify-fixture.mjs +53 -0
  196. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-001.json +17 -0
  197. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-002.json +17 -0
  198. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-003.json +17 -0
  199. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-004.json +17 -0
  200. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-005.json +17 -0
  201. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json +26 -0
  202. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json +36 -0
  203. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json +25 -0
  204. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35101.json +27 -0
  205. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35102.json +27 -0
  206. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35103.json +27 -0
  207. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35104.json +27 -0
  208. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35105.json +36 -0
  209. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35106.json +27 -0
  210. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35107.json +27 -0
  211. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35108.json +27 -0
  212. package/blueprints/edge-cloudflare-turnstile/docs/topics.md +71 -0
  213. package/blueprints/edge-cloudflare-turnstile/guide/edge-cloudflare-turnstile.md +104 -0
  214. package/blueprints/edge-cloudflare-turnstile/probe-packs/edge-cloudflare-turnstile.pack.mjs +146 -0
  215. package/blueprints/email-smtp-resend/docs/topics.md +10 -1
  216. package/blueprints/jobs-background/docs/topics.md +10 -1
  217. package/blueprints/messaging-queue-cloudflare/docs/topics.md +10 -1
  218. package/blueprints/object-storage-s3/docs/topics.md +10 -1
  219. package/blueprints/observability-essentials/docs/topics.md +10 -1
  220. package/blueprints/observability-logging/docs/topics.md +10 -1
  221. package/blueprints/observability-probe-endpoints/docs/topics.md +10 -1
  222. package/blueprints/persistence-data-d1/docs/topics.md +10 -1
  223. package/blueprints/persistence-data-postgres/docs/topics.md +10 -1
  224. package/blueprints/persistence-data-sqlite/docs/topics.md +10 -1
  225. package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +22 -0
  226. package/blueprints/platform-cloudflare-cron-triggers/README.md +117 -0
  227. package/blueprints/platform-cloudflare-cron-triggers/blueprint.json +85 -0
  228. package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3301-platform-cloudflare-cron-triggers-scheduled-trigger-contract.json +14 -0
  229. package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3302-platform-cloudflare-cron-triggers-dispatcher-mode.json +14 -0
  230. package/blueprints/platform-cloudflare-cron-triggers/contributions/adrs/adr-3303-platform-cloudflare-cron-triggers-skew-tolerance-default.json +14 -0
  231. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/dispatcher-routing.mjs +64 -0
  232. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/event-secrecy.mjs +100 -0
  233. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/probe-utils.mjs +70 -0
  234. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/real-account-scheduled-smoke.mjs +100 -0
  235. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-dispatcher-routing.mjs +5 -0
  236. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-event-secrecy.mjs +5 -0
  237. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-real-account-scheduled-smoke.mjs +5 -0
  238. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-skew-tolerance.mjs +5 -0
  239. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/run-wrangler-test-scheduled.mjs +5 -0
  240. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/skew-tolerance.mjs +130 -0
  241. package/blueprints/platform-cloudflare-cron-triggers/contributions/probes/wrangler-test-scheduled.mjs +129 -0
  242. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-001.json +17 -0
  243. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-002.json +17 -0
  244. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-003.json +17 -0
  245. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-004.json +17 -0
  246. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3301-platform-cloudflare-cron-triggers-scheduled-handler.json +22 -0
  247. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3302-platform-cloudflare-cron-triggers-expression-router.json +22 -0
  248. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3303-platform-cloudflare-cron-triggers-event-sink.json +21 -0
  249. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32101.json +25 -0
  250. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32102.json +34 -0
  251. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32103.json +34 -0
  252. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32104.json +34 -0
  253. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32105.json +25 -0
  254. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32106.json +25 -0
  255. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32107.json +25 -0
  256. package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +74 -0
  257. package/blueprints/platform-cloudflare-cron-triggers/guide/platform-cloudflare-cron-triggers.md +119 -0
  258. package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +23 -0
  259. package/blueprints/platform-cloudflare-durable-objects/README.md +200 -0
  260. package/blueprints/platform-cloudflare-durable-objects/blueprint.json +243 -0
  261. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3401-platform-cloudflare-durable-objects-single-cell-contract.json +14 -0
  262. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3402-platform-cloudflare-durable-objects-websocket-hub-contract.json +14 -0
  263. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3403-platform-cloudflare-durable-objects-storage-backend.json +14 -0
  264. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3404-platform-cloudflare-durable-objects-migrations-shape.json +14 -0
  265. package/blueprints/platform-cloudflare-durable-objects/contributions/adrs/adr-3405-platform-cloudflare-durable-objects-hibernation-posture.json +14 -0
  266. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/alarm-fires-once.mjs +63 -0
  267. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/namespace-facade-ready.mjs +60 -0
  268. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/probe-utils.mjs +105 -0
  269. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/real-account-storage-smoke.mjs +58 -0
  270. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-alarm-fires-once.mjs +5 -0
  271. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-namespace-facade-ready.mjs +5 -0
  272. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-real-account-storage-smoke.mjs +5 -0
  273. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-single-cell-concurrent-increment.mjs +5 -0
  274. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-sole-reader-scan.mjs +5 -0
  275. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-storage-round-trip.mjs +5 -0
  276. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-websocket-hub-broadcast.mjs +5 -0
  277. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/run-wrangler-seam.mjs +5 -0
  278. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/single-cell-concurrent-increment.mjs +56 -0
  279. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/sole-reader-scan.mjs +117 -0
  280. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/storage-round-trip.mjs +87 -0
  281. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/websocket-hub-broadcast.mjs +112 -0
  282. package/blueprints/platform-cloudflare-durable-objects/contributions/probes/wrangler-seam.mjs +257 -0
  283. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-001.json +17 -0
  284. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-002.json +17 -0
  285. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-003.json +17 -0
  286. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-004.json +17 -0
  287. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-005.json +17 -0
  288. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-006.json +17 -0
  289. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-007.json +17 -0
  290. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-008.json +17 -0
  291. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3401-platform-cloudflare-durable-objects-namespace-facade.json +31 -0
  292. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3402-platform-cloudflare-durable-objects-single-cell-shape.json +30 -0
  293. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3403-platform-cloudflare-durable-objects-alarm-handler.json +29 -0
  294. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3404-platform-cloudflare-durable-objects-websocket-hub.json +31 -0
  295. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3405-platform-cloudflare-durable-objects-event-sink.json +24 -0
  296. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33101.json +27 -0
  297. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33102.json +27 -0
  298. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33103.json +27 -0
  299. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33104.json +27 -0
  300. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33105.json +27 -0
  301. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33106.json +27 -0
  302. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33107.json +27 -0
  303. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33108.json +27 -0
  304. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33109.json +27 -0
  305. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33110.json +27 -0
  306. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33111.json +27 -0
  307. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33112.json +27 -0
  308. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33113.json +25 -0
  309. package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +76 -0
  310. package/blueprints/platform-cloudflare-durable-objects/guide/platform-cloudflare-durable-objects.md +237 -0
  311. package/blueprints/platform-cloudflare-kv/CHANGELOG.md +21 -0
  312. package/blueprints/platform-cloudflare-kv/README.md +159 -0
  313. package/blueprints/platform-cloudflare-kv/blueprint.json +87 -0
  314. package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3201-platform-cloudflare-kv-key-value-store-contract.json +14 -0
  315. package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3202-platform-cloudflare-kv-default-cache-ttl.json +14 -0
  316. package/blueprints/platform-cloudflare-kv/contributions/adrs/adr-3203-platform-cloudflare-kv-key-naming-convention.json +14 -0
  317. package/blueprints/platform-cloudflare-kv/contributions/probes/cache-aside-hit-then-miss.mjs +82 -0
  318. package/blueprints/platform-cloudflare-kv/contributions/probes/event-secrecy.mjs +102 -0
  319. package/blueprints/platform-cloudflare-kv/contributions/probes/facade-round-trip.mjs +92 -0
  320. package/blueprints/platform-cloudflare-kv/contributions/probes/list-with-prefix.mjs +52 -0
  321. package/blueprints/platform-cloudflare-kv/contributions/probes/probe-utils.mjs +73 -0
  322. package/blueprints/platform-cloudflare-kv/contributions/probes/real-account-eventual-consistency-smoke.mjs +102 -0
  323. package/blueprints/platform-cloudflare-kv/contributions/probes/run-cache-aside-hit-then-miss.mjs +5 -0
  324. package/blueprints/platform-cloudflare-kv/contributions/probes/run-event-secrecy.mjs +5 -0
  325. package/blueprints/platform-cloudflare-kv/contributions/probes/run-facade-round-trip.mjs +5 -0
  326. package/blueprints/platform-cloudflare-kv/contributions/probes/run-list-with-prefix.mjs +5 -0
  327. package/blueprints/platform-cloudflare-kv/contributions/probes/run-real-account-eventual-consistency-smoke.mjs +5 -0
  328. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-001.json +18 -0
  329. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-002.json +18 -0
  330. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-003.json +18 -0
  331. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-004.json +18 -0
  332. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-005.json +18 -0
  333. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3201-platform-cloudflare-kv-facade.json +27 -0
  334. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3202-platform-cloudflare-kv-cache-aside.json +26 -0
  335. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3203-platform-cloudflare-kv-event-sink.json +25 -0
  336. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31101.json +27 -0
  337. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31102.json +27 -0
  338. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31103.json +36 -0
  339. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31104.json +27 -0
  340. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31105.json +27 -0
  341. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31106.json +27 -0
  342. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31107.json +27 -0
  343. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31108.json +27 -0
  344. package/blueprints/platform-cloudflare-kv/docs/topics.md +74 -0
  345. package/blueprints/platform-cloudflare-kv/guide/platform-cloudflare-kv.md +138 -0
  346. package/blueprints/platform-docker-compose-host/CHANGELOG.md +12 -0
  347. package/blueprints/platform-docker-compose-host/README.md +76 -0
  348. package/blueprints/platform-docker-compose-host/blueprint.json +209 -0
  349. package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3901-platform-docker-compose-host-contract.json +14 -0
  350. package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3902-platform-docker-compose-host-reverse-proxy.json +14 -0
  351. package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3903-platform-docker-compose-host-reject-coolify.json +14 -0
  352. package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3904-platform-docker-compose-host-log-driver.json +14 -0
  353. package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +108 -0
  354. package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +231 -0
  355. package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +185 -0
  356. package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +41 -0
  357. package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +36 -0
  358. package/blueprints/platform-docker-compose-host/contributions/probes/run-caddyfile-validate.mjs +5 -0
  359. package/blueprints/platform-docker-compose-host/contributions/probes/run-compose-config-lint.mjs +5 -0
  360. package/blueprints/platform-docker-compose-host/contributions/probes/run-real-account-minimal-stack-up.mjs +5 -0
  361. package/blueprints/platform-docker-compose-host/contributions/probes/run-real-account-reload-burst.mjs +5 -0
  362. package/blueprints/platform-docker-compose-host/contributions/probes/run-secrets-as-files-scan.mjs +5 -0
  363. package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +116 -0
  364. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-001.json +18 -0
  365. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-002.json +18 -0
  366. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-003.json +18 -0
  367. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-004.json +18 -0
  368. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-005.json +18 -0
  369. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-006.json +18 -0
  370. package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3901-platform-docker-compose-host-compose-layout.json +26 -0
  371. package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3902-platform-docker-compose-host-secrets-mount.json +26 -0
  372. package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3903-platform-docker-compose-host-healthcheck-lint.json +26 -0
  373. package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3904-platform-docker-compose-host-reverse-proxy-artefact.json +26 -0
  374. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38101.json +24 -0
  375. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38102.json +24 -0
  376. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38103.json +24 -0
  377. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38104.json +24 -0
  378. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38105.json +25 -0
  379. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38106.json +24 -0
  380. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38107.json +24 -0
  381. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38108.json +24 -0
  382. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38109.json +24 -0
  383. package/blueprints/platform-docker-compose-host/docs/topics.md +71 -0
  384. package/blueprints/platform-docker-compose-host/guide/platform-docker-compose-host.md +94 -0
  385. package/blueprints/security-auth-clerk/docs/topics.md +10 -1
  386. package/blueprints/security-auth-keycloak/docs/topics.md +10 -1
  387. package/blueprints/security-auth-magic-link/docs/topics.md +10 -1
  388. package/blueprints/security-auth-oauth2/docs/topics.md +10 -1
  389. package/blueprints/security-secrets-management/docs/topics.md +10 -1
  390. package/fixtures/canary-manifest.json +9 -9
  391. package/package.json +1 -1
  392. package/rcf/adrs/adr-2214-application-admin-console-consume-zero-trust-gate.json +13 -0
  393. package/rcf/adrs/adr-3501-edge-cloudflare-access-jwt-gate.json +13 -0
  394. package/rcf/adrs/adr-3502-edge-cloudflare-access-identity-provider.json +13 -0
  395. package/rcf/adrs/adr-3503-edge-cloudflare-access-policy-scope.json +13 -0
  396. package/rcf/adrs/adr-3504-edge-cloudflare-access-audit-retention.json +13 -0
  397. package/rcf/adrs/adr-3601-edge-cloudflare-turnstile-verifier-contract.json +13 -0
  398. package/rcf/adrs/adr-3602-edge-cloudflare-turnstile-widget-mode.json +13 -0
  399. package/rcf/adrs/adr-3603-edge-cloudflare-turnstile-refuse-shape.json +13 -0
  400. package/rcf/adrs/adr-3701-edge-cloudflare-rate-limiting-throttle-contract.json +13 -0
  401. package/rcf/adrs/adr-3702-edge-cloudflare-rate-limiting-layering.json +13 -0
  402. package/rcf/adrs/adr-3703-edge-cloudflare-rate-limiting-manifest-shape.json +13 -0
  403. package/rcf/adrs/adr-3704-edge-cloudflare-rate-limiting-drift-audit-cadence.json +13 -0
  404. package/rcf/adrs/adr-3801-deploy-hetzner-server-cloud-host-contract.json +13 -0
  405. package/rcf/adrs/adr-3802-deploy-hetzner-server-snapshot-cadence.json +13 -0
  406. package/rcf/adrs/adr-3803-deploy-hetzner-server-provisioning-tool.json +13 -0
  407. package/rcf/adrs/adr-3804-deploy-hetzner-server-hardening-baseline.json +13 -0
  408. package/rcf/adrs/adr-3901-platform-docker-compose-host-contract.json +13 -0
  409. package/rcf/adrs/adr-3902-platform-docker-compose-host-reverse-proxy.json +13 -0
  410. package/rcf/adrs/adr-3903-platform-docker-compose-host-reject-coolify.json +13 -0
  411. package/rcf/adrs/adr-3904-platform-docker-compose-host-log-driver.json +13 -0
  412. package/rcf/adrs/adr-4001-edge-cloudflare-tunnel-ingress-bridge-contract.json +13 -0
  413. package/rcf/adrs/adr-4002-edge-cloudflare-tunnel-connector-runtime.json +13 -0
  414. package/rcf/adrs/adr-4003-edge-cloudflare-tunnel-hostname-mode.json +13 -0
  415. package/rcf/code-nodes/cn-230.json +13 -0
  416. package/rcf/code-nodes/cn-231.json +14 -0
  417. package/rcf/code-nodes/cn-232.json +13 -0
  418. package/rcf/code-nodes/cn-233.json +14 -0
  419. package/rcf/code-nodes/cn-234.json +13 -0
  420. package/rcf/code-nodes/cn-260.json +21 -0
  421. package/rcf/code-nodes/cn-261.json +14 -0
  422. package/rcf/code-nodes/cn-262.json +18 -0
  423. package/rcf/code-nodes/cn-263.json +12 -0
  424. package/rcf/code-nodes/cn-264.json +13 -0
  425. package/rcf/code-nodes/cn-265.json +15 -0
  426. package/rcf/code-nodes/cn-266.json +12 -0
  427. package/rcf/code-nodes/cn-267.json +12 -0
  428. package/rcf/code-nodes/cn-290.json +21 -0
  429. package/rcf/code-nodes/cn-291.json +12 -0
  430. package/rcf/code-nodes/cn-292.json +13 -0
  431. package/rcf/code-nodes/cn-293.json +13 -0
  432. package/rcf/code-nodes/cn-294.json +13 -0
  433. package/rcf/code-nodes/cn-295.json +12 -0
  434. package/rcf/code-nodes/cn-296.json +12 -0
  435. package/rcf/code-nodes/cn-297.json +12 -0
  436. package/rcf/code-nodes/cn-298.json +12 -0
  437. package/rcf/code-nodes/cn-299.json +12 -0
  438. package/rcf/code-nodes/cn-300.json +12 -0
  439. package/rcf/code-nodes/cn-301.json +14 -0
  440. package/rcf/code-nodes/cn-302.json +12 -0
  441. package/rcf/code-nodes/cn-303.json +12 -0
  442. package/rcf/code-nodes/cn-304.json +21 -0
  443. package/rcf/code-nodes/cn-320.json +20 -0
  444. package/rcf/code-nodes/cn-321.json +14 -0
  445. package/rcf/code-nodes/cn-350.json +19 -0
  446. package/rcf/code-nodes/cn-380.json +19 -0
  447. package/rcf/code-nodes/cn-410.json +20 -0
  448. package/rcf/code-nodes/cn-440.json +20 -0
  449. package/rcf/code-nodes/cn-470.json +19 -0
  450. package/rcf/fbs/fbs-070.json +24 -0
  451. package/rcf/fbs/fbs-080.json +24 -0
  452. package/rcf/fbs/fbs-090.json +24 -0
  453. package/rcf/fbs/fbs-100.json +23 -0
  454. package/rcf/fbs/fbs-101.json +16 -0
  455. package/rcf/fbs/fbs-110.json +23 -0
  456. package/rcf/fbs/fbs-120.json +22 -0
  457. package/rcf/fbs/fbs-130.json +23 -0
  458. package/rcf/fbs/fbs-140.json +23 -0
  459. package/rcf/fbs/fbs-150.json +22 -0
  460. package/rcf/requirements/req-050.json +18 -0
  461. package/rcf/requirements/req-051.json +18 -0
  462. package/rcf/requirements/req-052.json +18 -0
  463. package/rcf/requirements/req-053.json +18 -0
  464. package/rcf/requirements/req-054.json +18 -0
  465. package/rcf/requirements/req-060.json +20 -0
  466. package/rcf/requirements/req-061.json +18 -0
  467. package/rcf/requirements/req-062.json +20 -0
  468. package/rcf/requirements/req-063.json +20 -0
  469. package/rcf/requirements/req-070.json +18 -0
  470. package/rcf/requirements/req-071.json +18 -0
  471. package/rcf/requirements/req-072.json +18 -0
  472. package/rcf/requirements/req-073.json +18 -0
  473. package/rcf/requirements/req-074.json +18 -0
  474. package/rcf/requirements/req-075.json +18 -0
  475. package/rcf/requirements/req-076.json +18 -0
  476. package/rcf/requirements/req-077.json +18 -0
  477. package/rcf/requirements/req-080.json +18 -0
  478. package/rcf/requirements/req-081.json +18 -0
  479. package/rcf/requirements/req-082.json +18 -0
  480. package/rcf/requirements/req-083.json +18 -0
  481. package/rcf/requirements/req-084.json +18 -0
  482. package/rcf/requirements/req-085.json +18 -0
  483. package/rcf/requirements/req-086.json +18 -0
  484. package/rcf/requirements/req-090.json +44 -0
  485. package/rcf/requirements/req-091.json +53 -0
  486. package/rcf/requirements/req-092.json +32 -0
  487. package/rcf/requirements/req-093.json +52 -0
  488. package/rcf/requirements/req-094.json +32 -0
  489. package/rcf/requirements/req-100.json +13 -0
  490. package/rcf/requirements/req-101.json +13 -0
  491. package/rcf/requirements/req-102.json +13 -0
  492. package/rcf/requirements/req-103.json +13 -0
  493. package/rcf/requirements/req-104.json +13 -0
  494. package/rcf/requirements/req-110.json +58 -0
  495. package/rcf/requirements/req-111.json +32 -0
  496. package/rcf/requirements/req-112.json +42 -0
  497. package/rcf/requirements/req-113.json +33 -0
  498. package/rcf/requirements/req-114.json +20 -0
  499. package/rcf/requirements/req-115.json +38 -0
  500. package/rcf/requirements/req-120.json +20 -0
  501. package/rcf/requirements/req-121.json +20 -0
  502. package/rcf/requirements/req-122.json +20 -0
  503. package/rcf/requirements/req-123.json +42 -0
  504. package/rcf/requirements/req-124.json +27 -0
  505. package/rcf/requirements/req-125.json +20 -0
  506. package/rcf/requirements/req-130.json +32 -0
  507. package/rcf/requirements/req-131.json +54 -0
  508. package/rcf/requirements/req-132.json +27 -0
  509. package/rcf/requirements/req-133.json +20 -0
  510. package/rcf/requirements/req-134.json +42 -0
  511. package/rcf/tacs/tac-2214-application-admin-console-access-gated-signin-surface.json +15 -0
  512. package/rcf/tacs/tac-3501-edge-cloudflare-access-jwt-validator.json +15 -0
  513. package/rcf/tacs/tac-3502-edge-cloudflare-access-application-declaration.json +15 -0
  514. package/rcf/tacs/tac-3503-edge-cloudflare-access-policy-shape.json +15 -0
  515. package/rcf/tacs/tac-3504-edge-cloudflare-access-audit-sink.json +15 -0
  516. package/rcf/tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json +15 -0
  517. package/rcf/tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json +15 -0
  518. package/rcf/tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json +15 -0
  519. package/rcf/tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json +16 -0
  520. package/rcf/tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json +15 -0
  521. package/rcf/tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json +16 -0
  522. package/rcf/tacs/tac-3801-deploy-hetzner-server-provisioner.json +17 -0
  523. package/rcf/tacs/tac-3802-deploy-hetzner-server-manifest-schema.json +17 -0
  524. package/rcf/tacs/tac-3803-deploy-hetzner-server-cloud-init-template.json +17 -0
  525. package/rcf/tacs/tac-3804-deploy-hetzner-server-firewall-shape.json +16 -0
  526. package/rcf/tacs/tac-3901-platform-docker-compose-host-compose-layout.json +17 -0
  527. package/rcf/tacs/tac-3902-platform-docker-compose-host-secrets-mount.json +17 -0
  528. package/rcf/tacs/tac-3903-platform-docker-compose-host-healthcheck-lint.json +17 -0
  529. package/rcf/tacs/tac-3904-platform-docker-compose-host-reverse-proxy-artefact.json +17 -0
  530. package/rcf/tacs/tac-4001-edge-cloudflare-tunnel-connector-shape.json +17 -0
  531. package/rcf/tacs/tac-4002-edge-cloudflare-tunnel-manifest-schema.json +17 -0
  532. package/rcf/tacs/tac-4003-edge-cloudflare-tunnel-access-binding.json +16 -0
  533. package/rcf/test-suites/ts-052.json +58 -8
  534. package/rcf/test-suites/ts-080.json +22 -0
  535. package/rcf/test-suites/ts-081.json +22 -0
  536. package/rcf/test-suites/ts-082.json +30 -0
  537. package/rcf/test-suites/ts-083.json +22 -0
  538. package/rcf/test-suites/ts-084.json +30 -0
  539. package/rcf/test-suites/ts-085.json +22 -0
  540. package/rcf/test-suites/ts-086.json +22 -0
  541. package/rcf/test-suites/ts-087.json +22 -0
  542. package/rcf/test-suites/ts-090.json +22 -0
  543. package/rcf/test-suites/ts-091.json +22 -0
  544. package/rcf/test-suites/ts-092.json +22 -0
  545. package/rcf/test-suites/ts-093.json +30 -0
  546. package/rcf/test-suites/ts-094.json +30 -0
  547. package/rcf/test-suites/ts-095.json +30 -0
  548. package/rcf/test-suites/ts-096.json +22 -0
  549. package/rcf/test-suites/ts-100.json +22 -0
  550. package/rcf/test-suites/ts-101.json +22 -0
  551. package/rcf/test-suites/ts-102.json +22 -0
  552. package/rcf/test-suites/ts-103.json +22 -0
  553. package/rcf/test-suites/ts-104.json +22 -0
  554. package/rcf/test-suites/ts-105.json +22 -0
  555. package/rcf/test-suites/ts-106.json +22 -0
  556. package/rcf/test-suites/ts-107.json +22 -0
  557. package/rcf/test-suites/ts-108.json +22 -0
  558. package/rcf/test-suites/ts-109.json +22 -0
  559. package/rcf/test-suites/ts-110.json +22 -0
  560. package/rcf/test-suites/ts-111.json +22 -0
  561. package/rcf/test-suites/ts-112.json +22 -0
  562. package/rcf/test-suites/ts-113.json +22 -0
  563. package/rcf/test-suites/ts-114.json +22 -0
  564. package/rcf/test-suites/ts-115.json +22 -0
  565. package/rcf/test-suites/ts-116.json +22 -0
  566. package/rcf/test-suites/ts-117.json +22 -0
  567. package/rcf/test-suites/ts-118.json +22 -0
  568. package/rcf/test-suites/ts-119.json +30 -0
  569. package/rcf/test-suites/ts-120.json +22 -0
  570. package/rcf/test-suites/ts-121.json +22 -0
  571. package/rcf/test-suites/ts-122.json +22 -0
  572. package/rcf/test-suites/ts-123.json +22 -0
  573. package/rcf/test-suites/ts-124.json +22 -0
  574. package/rcf/test-suites/ts-125.json +22 -0
  575. package/rcf/test-suites/ts-126.json +22 -0
  576. package/rcf/test-suites/ts-127.json +22 -0
  577. package/rcf/test-suites/ts-130.json +22 -0
  578. package/rcf/test-suites/ts-131.json +22 -0
  579. package/rcf/test-suites/ts-132.json +22 -0
  580. package/rcf/test-suites/ts-133.json +22 -0
  581. package/rcf/test-suites/ts-134.json +22 -0
  582. package/rcf/test-suites/ts-135.json +22 -0
  583. package/rcf/test-suites/ts-136.json +22 -0
  584. package/rcf/test-suites/ts-137.json +22 -0
  585. package/rcf/test-suites/ts-140.json +86 -0
  586. package/rcf/test-suites/ts-150.json +86 -0
  587. package/rcf/test-suites/ts-160.json +78 -0
  588. package/rcf/user-stories/us-10001.json +23 -0
  589. package/rcf/user-stories/us-10101.json +23 -0
  590. package/rcf/user-stories/us-10201.json +23 -0
  591. package/rcf/user-stories/us-10301.json +23 -0
  592. package/rcf/user-stories/us-10401.json +23 -0
  593. package/rcf/user-stories/us-10601.json +23 -0
  594. package/rcf/user-stories/us-10701.json +23 -0
  595. package/rcf/user-stories/us-10801.json +23 -0
  596. package/rcf/user-stories/us-11001.json +23 -0
  597. package/rcf/user-stories/us-11101.json +23 -0
  598. package/rcf/user-stories/us-11102.json +24 -0
  599. package/rcf/user-stories/us-11201.json +23 -0
  600. package/rcf/user-stories/us-11202.json +23 -0
  601. package/rcf/user-stories/us-11301.json +24 -0
  602. package/rcf/user-stories/us-11401.json +23 -0
  603. package/rcf/user-stories/us-11402.json +23 -0
  604. package/rcf/user-stories/us-11501.json +23 -0
  605. package/rcf/user-stories/us-12001.json +23 -0
  606. package/rcf/user-stories/us-12101.json +23 -0
  607. package/rcf/user-stories/us-12102.json +23 -0
  608. package/rcf/user-stories/us-12201.json +23 -0
  609. package/rcf/user-stories/us-12202.json +24 -0
  610. package/rcf/user-stories/us-12301.json +23 -0
  611. package/rcf/user-stories/us-12401.json +23 -0
  612. package/rcf/user-stories/us-12402.json +23 -0
  613. package/rcf/user-stories/us-12501.json +23 -0
  614. package/rcf/user-stories/us-13001.json +23 -0
  615. package/rcf/user-stories/us-13002.json +23 -0
  616. package/rcf/user-stories/us-13101.json +23 -0
  617. package/rcf/user-stories/us-13102.json +23 -0
  618. package/rcf/user-stories/us-13201.json +23 -0
  619. package/rcf/user-stories/us-13301.json +23 -0
  620. package/rcf/user-stories/us-13302.json +23 -0
  621. package/rcf/user-stories/us-13401.json +23 -0
  622. package/rcf/user-stories/us-5001.json +27 -0
  623. package/rcf/user-stories/us-5002.json +27 -0
  624. package/rcf/user-stories/us-5101.json +36 -0
  625. package/rcf/user-stories/us-5102.json +27 -0
  626. package/rcf/user-stories/us-5201.json +36 -0
  627. package/rcf/user-stories/us-5301.json +27 -0
  628. package/rcf/user-stories/us-5302.json +27 -0
  629. package/rcf/user-stories/us-5401.json +27 -0
  630. package/rcf/user-stories/us-6001.json +27 -0
  631. package/rcf/user-stories/us-6002.json +27 -0
  632. package/rcf/user-stories/us-6003.json +27 -0
  633. package/rcf/user-stories/us-6101.json +36 -0
  634. package/rcf/user-stories/us-6201.json +36 -0
  635. package/rcf/user-stories/us-6301.json +36 -0
  636. package/rcf/user-stories/us-6302.json +27 -0
  637. package/rcf/user-stories/us-7001.json +27 -0
  638. package/rcf/user-stories/us-7002.json +27 -0
  639. package/rcf/user-stories/us-7101.json +27 -0
  640. package/rcf/user-stories/us-7201.json +27 -0
  641. package/rcf/user-stories/us-7301.json +27 -0
  642. package/rcf/user-stories/us-7401.json +27 -0
  643. package/rcf/user-stories/us-7402.json +27 -0
  644. package/rcf/user-stories/us-7501.json +27 -0
  645. package/rcf/user-stories/us-7601.json +27 -0
  646. package/rcf/user-stories/us-7701.json +27 -0
  647. package/rcf/user-stories/us-8001.json +24 -0
  648. package/rcf/user-stories/us-8002.json +24 -0
  649. package/rcf/user-stories/us-8003.json +24 -0
  650. package/rcf/user-stories/us-8101.json +24 -0
  651. package/rcf/user-stories/us-8201.json +24 -0
  652. package/rcf/user-stories/us-8301.json +24 -0
  653. package/rcf/user-stories/us-8401.json +24 -0
  654. package/rcf/user-stories/us-8501.json +24 -0
  655. package/rcf/user-stories/us-8502.json +24 -0
  656. package/rcf/user-stories/us-8601.json +24 -0
  657. package/rcf/user-stories/us-8602.json +24 -0
  658. package/rcf/user-stories/us-9001.json +27 -0
  659. package/rcf/user-stories/us-9002.json +27 -0
  660. package/rcf/user-stories/us-9101.json +27 -0
  661. package/rcf/user-stories/us-9102.json +27 -0
  662. package/rcf/user-stories/us-9201.json +27 -0
  663. package/rcf/user-stories/us-9301.json +27 -0
  664. package/rcf/user-stories/us-9302.json +27 -0
  665. package/rcf/user-stories/us-9401.json +27 -0
  666. package/releases/releases.yaml +21 -1
@@ -0,0 +1,185 @@
1
+ // Shared helpers for platform-docker-compose-host probes.
2
+ //
3
+ // Runtime-dependency posture:
4
+ // - compose-config-lint shells to docker compose config against the applied
5
+ // fixture compose.yaml; the docker daemon must be reachable locally for
6
+ // the lint stage (skipped-with-warn when the CLI is absent so a
7
+ // review machine without docker can still see the source-tree assertions).
8
+ // - secrets-as-files-scan runs in-process against the fixture; no external
9
+ // engine required.
10
+ // - caddyfile-validate shells to caddy validate. When a local caddy binary
11
+ // is not on PATH the probe runs the vendor container caddy:2 via docker
12
+ // run --rm; when docker is also absent it skips-with-warn.
13
+ // - real-account-* probes call the fixture's provision.mjs, drive docker
14
+ // compose over ssh against the throwaway server, and tear down in
15
+ // always(). Without CI_HAS_HETZNER_ACCOUNT they record accountBoundSkipped:
16
+ // true and the aggregate flips to pass per hetzner-round-7-spec section 3.5.
17
+
18
+ import { mkdir, writeFile, readFile } from 'node:fs/promises';
19
+ import { dirname, resolve, join } from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
21
+ import { spawnSync } from 'node:child_process';
22
+
23
+ const HERE = dirname(fileURLToPath(import.meta.url));
24
+ export const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
25
+ export const FIXTURE_DIR = resolve(
26
+ PROJECT_ROOT,
27
+ 'packages/rcf-lite/test/fixtures/hetzner-throwaway-server',
28
+ );
29
+ export const COMPOSE_PATH = resolve(FIXTURE_DIR, 'compose.yaml');
30
+ export const CADDYFILE_PATH = resolve(FIXTURE_DIR, 'caddy/Caddyfile');
31
+ export const SECRET_PATH = resolve(FIXTURE_DIR, 'secrets/web-token');
32
+ export const ENV_PATH = resolve(FIXTURE_DIR, '.env');
33
+ export const REPORT_DIR = resolve(
34
+ PROJECT_ROOT,
35
+ '.rcf/reports/blueprints/platform-docker-compose-host',
36
+ );
37
+
38
+ export function aggregate(results) {
39
+ if (results.some((r) => r.verdict === 'fail')) return 'fail';
40
+ if (results.some((r) => r.verdict === 'warn')) return 'warn';
41
+ return 'pass';
42
+ }
43
+
44
+ export function isSkipped(results) {
45
+ return results.length > 0 && results.every((r) => r.accountBoundSkipped === true);
46
+ }
47
+
48
+ export async function writeReport({ probeName, engine, results, extra }) {
49
+ await mkdir(REPORT_DIR, { recursive: true });
50
+ const rawVerdict = aggregate(results);
51
+ const aggregateVerdict = isSkipped(results) ? 'pass' : rawVerdict;
52
+ const report = {
53
+ slug: 'platform-docker-compose-host',
54
+ probeName,
55
+ runAt: new Date().toISOString(),
56
+ engine,
57
+ results,
58
+ aggregateVerdict,
59
+ ...(extra ?? {}),
60
+ };
61
+ const path = resolve(REPORT_DIR, `${probeName}.json`);
62
+ await writeFile(path, JSON.stringify(report, null, 2) + '\n', 'utf8');
63
+ return { report, path };
64
+ }
65
+
66
+ export async function runShim(probeName, engine, mainFn) {
67
+ try {
68
+ const outcome = (await mainFn()) ?? { results: [] };
69
+ const { results, extra } = outcome;
70
+ const { report, path } = await writeReport({ probeName, engine, results, extra });
71
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
72
+ process.stdout.write(`report written to ${path}\n`);
73
+ if (report.aggregateVerdict === 'fail') process.exitCode = 1;
74
+ } catch (err) {
75
+ const results = [{
76
+ anchorAcId: 'unknown',
77
+ verdict: 'fail',
78
+ detail: `probe threw: ${err && err.message ? err.message : String(err)}`,
79
+ }];
80
+ const { report, path } = await writeReport({ probeName, engine, results });
81
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
82
+ process.stderr.write(`probe error: ${err && err.stack ? err.stack : String(err)}\n`);
83
+ process.stderr.write(`report written to ${path}\n`);
84
+ process.exitCode = 1;
85
+ }
86
+ }
87
+
88
+ export function accountBoundSkippedResult(anchorAcId, note) {
89
+ return {
90
+ anchorAcId,
91
+ verdict: 'skipped',
92
+ accountBoundSkipped: true,
93
+ detail: `accountBound: CI_HAS_HETZNER_ACCOUNT unset; ${note}`,
94
+ };
95
+ }
96
+
97
+ // Small YAML subset parser tuned for the fixture compose.yaml shape.
98
+ // The fixture keeps compose.yaml intentionally simple (two-space indent,
99
+ // no anchors, no flow-style scalars) so the probes stay dependency-free.
100
+ // If a probe needs a full parser later, this returns a shape sufficient
101
+ // for the assertions the ACs make (services, networks, volumes, secrets,
102
+ // env_file, healthcheck presence, restart, logging.driver).
103
+ export function parseComposeYaml(text) {
104
+ const doc = {};
105
+ const lines = text.split(/\r?\n/);
106
+ const stack = [{ indent: -1, node: doc }];
107
+ const inlineListRe = /^\[(.*)\]$/;
108
+ function decodeScalar(raw) {
109
+ if (raw === '' || raw === undefined) return null;
110
+ if (raw === 'true') return true;
111
+ if (raw === 'false') return false;
112
+ if (raw === 'null' || raw === '~') return null;
113
+ const m = raw.match(inlineListRe);
114
+ if (m) return m[1].split(',').map((s) => decodeScalar(s.trim()));
115
+ return raw.replace(/^"([^"\\]*)"$/, '$1').replace(/^'([^'\\]*)'$/, '$1');
116
+ }
117
+ for (let raw of lines) {
118
+ if (raw.trim() === '' || raw.trim().startsWith('#')) continue;
119
+ const indentMatch = raw.match(/^(\s*)/);
120
+ const indent = indentMatch ? indentMatch[1].length : 0;
121
+ while (stack.length > 1 && indent <= stack[stack.length - 1].indent) stack.pop();
122
+ const parent = stack[stack.length - 1].node;
123
+ const body = raw.slice(indent);
124
+ if (body.startsWith('- ')) {
125
+ const rest = body.slice(2);
126
+ const kv = rest.match(/^([A-Za-z0-9_.-]+):\s*(.*)$/);
127
+ if (kv) {
128
+ const [, key, val] = kv;
129
+ const obj = {};
130
+ if (val === '') {
131
+ const child = {};
132
+ obj[key] = child;
133
+ parent.push(obj);
134
+ stack.push({ indent, node: child });
135
+ } else {
136
+ obj[key] = decodeScalar(val.trim());
137
+ parent.push(obj);
138
+ }
139
+ } else {
140
+ parent.push(decodeScalar(rest.trim()));
141
+ }
142
+ continue;
143
+ }
144
+ const kv = body.match(/^([A-Za-z0-9_.-]+):\s*(.*)$/);
145
+ if (!kv) continue;
146
+ const [, key, val] = kv;
147
+ if (val === '') {
148
+ // Peek: next non-empty non-comment line starting with '- ' means list.
149
+ let peekIsList = false;
150
+ for (let j = lines.indexOf(raw) + 1; j < lines.length; j++) {
151
+ const nxt = lines[j];
152
+ if (!nxt || nxt.trim() === '' || nxt.trim().startsWith('#')) continue;
153
+ const nxtIndentMatch = nxt.match(/^(\s*)/);
154
+ const nxtIndent = nxtIndentMatch ? nxtIndentMatch[1].length : 0;
155
+ if (nxtIndent <= indent) break;
156
+ peekIsList = nxt.slice(nxtIndent).startsWith('- ');
157
+ break;
158
+ }
159
+ const child = peekIsList ? [] : {};
160
+ parent[key] = child;
161
+ stack.push({ indent, node: child });
162
+ } else if (val.trim().match(inlineListRe)) {
163
+ parent[key] = decodeScalar(val.trim());
164
+ } else {
165
+ parent[key] = decodeScalar(val.trim());
166
+ }
167
+ }
168
+ return doc;
169
+ }
170
+
171
+ export async function readCompose() {
172
+ const text = await readFile(COMPOSE_PATH, 'utf8');
173
+ const doc = parseComposeYaml(text);
174
+ return { text, doc };
175
+ }
176
+
177
+ export function whichDocker() {
178
+ const r = spawnSync('docker', ['version', '--format', '{{.Client.Version}}'], { encoding: 'utf8' });
179
+ return r.status === 0 ? (r.stdout || '').trim() : null;
180
+ }
181
+
182
+ export function whichCaddy() {
183
+ const r = spawnSync('caddy', ['version'], { encoding: 'utf8' });
184
+ return r.status === 0 ? (r.stdout || '').trim() : null;
185
+ }
@@ -0,0 +1,41 @@
1
+ // Probe: real-account-minimal-stack-up.
2
+ //
3
+ // anchorAcId: AC-composeHost-upClean.
4
+ // accountBound: true.
5
+ //
6
+ // On the shared throwaway-Hetzner-server fixture (spec 3.3), when
7
+ // CI_HAS_HETZNER_ACCOUNT is set: provisions the server, scps the
8
+ // compose.yaml and referenced files, runs docker compose up -d --wait,
9
+ // asserts every declared service reaches healthy inside the elicited
10
+ // timeout, tears the stack down and destroys the server in always().
11
+ // Without CI_HAS_HETZNER_ACCOUNT the probe records accountBoundSkipped:
12
+ // true and the aggregate flips to pass per hetzner-round-7-spec section 3.5.
13
+
14
+ import { runShim, accountBoundSkippedResult } from './probe-utils.mjs';
15
+
16
+ export const anchorAcId = 'AC-composeHost-upClean';
17
+ export const accountBound = true;
18
+
19
+ export default async function runProbe() {
20
+ const results = [];
21
+ const extra = { skipped: process.env.CI_HAS_HETZNER_ACCOUNT !== 'true' };
22
+ if (process.env.CI_HAS_HETZNER_ACCOUNT !== 'true') {
23
+ results.push(accountBoundSkippedResult(anchorAcId, 'no throwaway server provisioned; minimal-stack-up not exercised'));
24
+ return { results, extra };
25
+ }
26
+ // Real-account path (not run in this environment; requires a Hetzner
27
+ // token via the fixture's provision.mjs and ssh access to the created
28
+ // server). The full driver lives with the round-close real-account
29
+ // gate work item; see hetzner-round-7-spec-2026-09-07 section 3.3 and
30
+ // the T-2 followup w-2026-09-08-dave-001.
31
+ results.push({
32
+ anchorAcId, verdict: 'warn',
33
+ detail: 'CI_HAS_HETZNER_ACCOUNT is set but the driver is not wired in this environment; run against the throwaway server via the round-close real-account gate',
34
+ });
35
+ return { results, extra };
36
+ }
37
+
38
+ const engine = { kind: 'throwaway-server', image: 'hetzner cx23 in fsn1 via provision.mjs', healthy: true };
39
+ if (import.meta.url === `file://${process.argv[1]}`) {
40
+ await runShim('real-account-minimal-stack-up', engine, runProbe);
41
+ }
@@ -0,0 +1,36 @@
1
+ // Probe: real-account-reload-burst.
2
+ //
3
+ // anchorAcId: AC-composeHost-zeroDowntimeReload.
4
+ // accountBound: true.
5
+ //
6
+ // On the shared throwaway-Hetzner-server fixture with the T-2 compose
7
+ // stack running: fires an undici burst against the caddy service while
8
+ // docker compose exec caddy caddy reload runs. Asserts every request
9
+ // returns a 2xx status inside the elicited reload window (10 s default)
10
+ // and no connection is dropped. Tears the stack down in always().
11
+ // Without CI_HAS_HETZNER_ACCOUNT the probe records accountBoundSkipped:
12
+ // true and the aggregate flips to pass.
13
+
14
+ import { runShim, accountBoundSkippedResult } from './probe-utils.mjs';
15
+
16
+ export const anchorAcId = 'AC-composeHost-zeroDowntimeReload';
17
+ export const accountBound = true;
18
+
19
+ export default async function runProbe() {
20
+ const results = [];
21
+ const extra = { skipped: process.env.CI_HAS_HETZNER_ACCOUNT !== 'true' };
22
+ if (process.env.CI_HAS_HETZNER_ACCOUNT !== 'true') {
23
+ results.push(accountBoundSkippedResult(anchorAcId, 'no throwaway server provisioned; reload-burst not exercised'));
24
+ return { results, extra };
25
+ }
26
+ results.push({
27
+ anchorAcId, verdict: 'warn',
28
+ detail: 'CI_HAS_HETZNER_ACCOUNT is set but the driver is not wired in this environment; run against the throwaway server via the round-close real-account gate',
29
+ });
30
+ return { results, extra };
31
+ }
32
+
33
+ const engine = { kind: 'throwaway-server-burst', image: 'undici burst against caddy in the throwaway compose stack', healthy: true };
34
+ if (import.meta.url === `file://${process.argv[1]}`) {
35
+ await runShim('real-account-reload-burst', engine, runProbe);
36
+ }
@@ -0,0 +1,5 @@
1
+ import runProbe from './caddyfile-validate.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'caddyfile-validate', image: 'platform-docker-compose-host fixture', healthy: true };
5
+ runShim('caddyfile-validate', engine, runProbe);
@@ -0,0 +1,5 @@
1
+ import runProbe from './compose-config-lint.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'compose-config-lint', image: 'platform-docker-compose-host fixture', healthy: true };
5
+ runShim('compose-config-lint', engine, runProbe);
@@ -0,0 +1,5 @@
1
+ import runProbe from './real-account-minimal-stack-up.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'real-account-minimal-stack-up', image: 'platform-docker-compose-host fixture', healthy: true };
5
+ runShim('real-account-minimal-stack-up', engine, runProbe);
@@ -0,0 +1,5 @@
1
+ import runProbe from './real-account-reload-burst.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'real-account-reload-burst', image: 'platform-docker-compose-host fixture', healthy: true };
5
+ runShim('real-account-reload-burst', engine, runProbe);
@@ -0,0 +1,5 @@
1
+ import runProbe from './secrets-as-files-scan.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'secrets-as-files-scan', image: 'platform-docker-compose-host fixture', healthy: true };
5
+ runShim('secrets-as-files-scan', engine, runProbe);
@@ -0,0 +1,116 @@
1
+ // Probe: secrets-as-files-scan.
2
+ //
3
+ // anchorAcId: AC-composeHost-secretsAreFiles (primary), AC-composeHost-secretShape.
4
+ // accountBound: false.
5
+ //
6
+ // Passes when:
7
+ // - every secret declared under the compose top-level secrets: key
8
+ // references a file: source (never inline).
9
+ // - no line in compose.yaml or any referenced service config carries a
10
+ // plaintext token pattern matching (secretName, secretValue).
11
+ //
12
+ // Mutation:
13
+ // - SIMULATE_PLAINTEXT_SECRET=true writes the fixture web-token literal
14
+ // into compose.yaml (as an environment entry on the web service) and
15
+ // the probe FAILS naming the file and the literal.
16
+
17
+ import { readFile, cp, rm, mkdir } from 'node:fs/promises';
18
+ import { tmpdir } from 'node:os';
19
+ import { join } from 'node:path';
20
+ import { runShim, readCompose, COMPOSE_PATH, SECRET_PATH, FIXTURE_DIR } from './probe-utils.mjs';
21
+
22
+ export const anchorAcIds = [
23
+ 'AC-composeHost-secretsAreFiles',
24
+ 'AC-composeHost-secretShape',
25
+ ];
26
+ export const accountBound = false;
27
+
28
+ async function applyPlaintextMutation() {
29
+ const scratch = join(tmpdir(), `rcf-lite-t2-secrets-scan-${Date.now()}`);
30
+ await mkdir(scratch, { recursive: true });
31
+ await cp(FIXTURE_DIR, scratch, { recursive: true });
32
+ const composePath = join(scratch, 'compose.yaml');
33
+ let text = await readFile(composePath, 'utf8');
34
+ const secret = (await readFile(SECRET_PATH, 'utf8')).trim();
35
+ // Inject WEB_TOKEN=<literal> as an environment entry on the web service.
36
+ text = text.replace(/(\n env_file:\n)/, `\n environment:\n - WEB_TOKEN=${secret}\n$1`);
37
+ const { writeFile } = await import('node:fs/promises');
38
+ await writeFile(composePath, text, 'utf8');
39
+ return { scratch, composePath };
40
+ }
41
+
42
+ async function scanForLiteral({ composePath, secret, secretName }) {
43
+ const text = await readFile(composePath, 'utf8');
44
+ const lines = text.split('\n');
45
+ const hits = [];
46
+ for (let i = 0; i < lines.length; i++) {
47
+ if (lines[i].includes(secret)) {
48
+ hits.push({ file: composePath, line: i + 1, snippet: lines[i].trim() });
49
+ }
50
+ }
51
+ return hits;
52
+ }
53
+
54
+ export default async function runProbe() {
55
+ const results = [];
56
+ const extra = {};
57
+ const secret = (await readFile(SECRET_PATH, 'utf8')).trim();
58
+ const mutationOn = process.env.SIMULATE_PLAINTEXT_SECRET === 'true';
59
+ extra.mutations = { plaintextSecret: mutationOn };
60
+ let composePathToScan = COMPOSE_PATH;
61
+ let scratchToClean = null;
62
+ if (mutationOn) {
63
+ const m = await applyPlaintextMutation();
64
+ composePathToScan = m.composePath;
65
+ scratchToClean = m.scratch;
66
+ }
67
+ try {
68
+ // Secret-shape scan: every declared secret has a file: source.
69
+ const { doc } = await readCompose();
70
+ const secretsBlock = doc.secrets ?? {};
71
+ const secretNames = Object.keys(secretsBlock);
72
+ extra.declaredSecrets = secretNames;
73
+ for (const name of secretNames) {
74
+ const spec = secretsBlock[name] ?? {};
75
+ if (!spec.file) {
76
+ results.push({
77
+ anchorAcId: 'AC-composeHost-secretShape',
78
+ verdict: 'fail',
79
+ detail: `compose secret '${name}' is not a file: source`,
80
+ });
81
+ } else {
82
+ results.push({
83
+ anchorAcId: 'AC-composeHost-secretShape',
84
+ verdict: 'pass',
85
+ detail: `compose secret '${name}' -> file: ${spec.file}`,
86
+ });
87
+ }
88
+ }
89
+ // Plaintext-literal scan.
90
+ const hits = await scanForLiteral({ composePath: composePathToScan, secret, secretName: 'web-token' });
91
+ if (hits.length > 0) {
92
+ for (const h of hits) {
93
+ results.push({
94
+ anchorAcId: 'AC-composeHost-secretsAreFiles',
95
+ verdict: 'fail',
96
+ detail: `plaintext secret literal for 'web-token' found in ${h.file}:${h.line} (snippet: ${h.snippet})`,
97
+ });
98
+ }
99
+ } else {
100
+ results.push({
101
+ anchorAcId: 'AC-composeHost-secretsAreFiles',
102
+ verdict: 'pass',
103
+ detail: `no plaintext secret literal for 'web-token' found in the scanned compose.yaml`,
104
+ });
105
+ }
106
+ extra.hits = hits.map((h) => ({ file: h.file, line: h.line }));
107
+ } finally {
108
+ if (scratchToClean) await rm(scratchToClean, { recursive: true, force: true });
109
+ }
110
+ return { results, extra };
111
+ }
112
+
113
+ const engine = { kind: 'source-scan', image: 'in-process compose + secret grep', healthy: true };
114
+ if (import.meta.url === `file://${process.argv[1]}`) {
115
+ await runShim('secrets-as-files-scan', engine, runProbe);
116
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "reqId": "platform-docker-compose-host-REQ-001",
3
+ "prdId": "PRD-001",
4
+ "title": "The compose.yaml at the applying repo root is the single-source runtime topology, with service-per-container, named networks and volumes, and .env for non-secret config",
5
+ "description": "The applying project runs its containerised services from a single compose.yaml at the repo root. Every entry under services: is one image running as one container (service-per-container). Networks and volumes are declared with explicit names under the top-level networks: and volumes: keys. Non-secret configuration values live in a colocated .env file loaded by compose, never inlined into service environment blocks. The container host reads compose.yaml as the topology source of truth and refuses to bring the stack up on layout drift.",
6
+ "category": "functional",
7
+ "domain": "platform",
8
+ "priority": "must",
9
+ "rationale": "Ratified in the Hetzner round 7 spec (2026-09-07 section 5.2 REQ-001). Ships as v1.0.0 of platform-docker-compose-host.",
10
+ "tags": [
11
+ "blueprint:platform-docker-compose-host",
12
+ "capability:containerHost"
13
+ ],
14
+ "version": "1.0.0",
15
+ "status": "approved",
16
+ "createdAt": "2026-09-08T00:00:00.000Z",
17
+ "updatedAt": "2026-09-08T00:00:00.000Z"
18
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "reqId": "platform-docker-compose-host-REQ-002",
3
+ "prdId": "PRD-001",
4
+ "title": "Every secret is injected via a docker compose secrets file mount; the compose file carries no plaintext secret literal (grep-refuse); references security-secrets-management when applied",
5
+ "description": "Every secret referenced by any compose service is declared under the top-level secrets: key with a file: source, and the service references it through its service-level secrets: array so docker mounts the value at 0o400 inside the container. The compose file contains no plaintext secret literal on any argument, environment entry, or command clause (grep-refuse). When security-secrets-management is applied, the secret source path resolves through that facade; when it is not, the guide documents a file-based fallback path.",
6
+ "category": "functional",
7
+ "domain": "platform",
8
+ "priority": "must",
9
+ "rationale": "Ratified in the Hetzner round 7 spec (2026-09-07 section 5.2 REQ-002). Ships as v1.0.0 of platform-docker-compose-host.",
10
+ "tags": [
11
+ "blueprint:platform-docker-compose-host",
12
+ "capability:containerHost"
13
+ ],
14
+ "version": "1.0.0",
15
+ "status": "approved",
16
+ "createdAt": "2026-09-08T00:00:00.000Z",
17
+ "updatedAt": "2026-09-08T00:00:00.000Z"
18
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "reqId": "platform-docker-compose-host-REQ-003",
3
+ "prdId": "PRD-001",
4
+ "title": "Every HTTP-terminating compose service declares a healthcheck; docker compose config refuses on missing",
5
+ "description": "Every service under services: whose image terminates HTTP declares a healthcheck: block. The compose-config-lint refuses at docker compose config time on any HTTP-terminating service missing the block, naming the service. Healthcheck defaults per service kind are elicited (http default, tcp and command alternatives). The stack is not considered up until every declared service reaches healthy inside the elicited timeout.",
6
+ "category": "functional",
7
+ "domain": "platform",
8
+ "priority": "must",
9
+ "rationale": "Ratified in the Hetzner round 7 spec (2026-09-07 section 5.2 REQ-003). Ships as v1.0.0 of platform-docker-compose-host.",
10
+ "tags": [
11
+ "blueprint:platform-docker-compose-host",
12
+ "capability:containerHost"
13
+ ],
14
+ "version": "1.0.0",
15
+ "status": "approved",
16
+ "createdAt": "2026-09-08T00:00:00.000Z",
17
+ "updatedAt": "2026-09-08T00:00:00.000Z"
18
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "reqId": "platform-docker-compose-host-REQ-004",
3
+ "prdId": "PRD-001",
4
+ "title": "Restart discipline enforced at lint time: unless-stopped on long-running services, on-failure on jobs; unclassified value refuses",
5
+ "description": "Every service declares a restart policy. Long-running services declare restart: unless-stopped. Jobs (short-lived services that exit after completion) declare restart: on-failure. Any service that declares neither, or declares a value outside the two allowed policies, refuses at the compose-config-lint gate before docker compose up runs. The lint names the service and the offending value.",
6
+ "category": "functional",
7
+ "domain": "platform",
8
+ "priority": "must",
9
+ "rationale": "Ratified in the Hetzner round 7 spec (2026-09-07 section 5.2 REQ-004). Ships as v1.0.0 of platform-docker-compose-host.",
10
+ "tags": [
11
+ "blueprint:platform-docker-compose-host",
12
+ "capability:containerHost"
13
+ ],
14
+ "version": "1.0.0",
15
+ "status": "approved",
16
+ "createdAt": "2026-09-08T00:00:00.000Z",
17
+ "updatedAt": "2026-09-08T00:00:00.000Z"
18
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "reqId": "platform-docker-compose-host-REQ-005",
3
+ "prdId": "PRD-001",
4
+ "title": "Zero-downtime reverse-proxy reload via bind-mounted config artefact; verb per proxy; no non-2xx or dropped connection inside the elicited window",
5
+ "description": "The reverse-proxy config file (caddy/Caddyfile when reverseProxy=caddy, traefik/traefik.yaml when reverseProxy=traefik) is a first-class checked-in artefact. The compose runtime bind-mounts the artefact read-only into the proxy service. The reload verb is docker compose exec caddy caddy reload for Caddy, or the documented Traefik equivalent. During the elicited reload window (10 s default) a client burst against the proxy sees no non-2xx and no dropped connection.",
6
+ "category": "functional",
7
+ "domain": "platform",
8
+ "priority": "must",
9
+ "rationale": "Ratified in the Hetzner round 7 spec (2026-09-07 section 5.2 REQ-005). Ships as v1.0.0 of platform-docker-compose-host.",
10
+ "tags": [
11
+ "blueprint:platform-docker-compose-host",
12
+ "capability:containerHost"
13
+ ],
14
+ "version": "1.0.0",
15
+ "status": "approved",
16
+ "createdAt": "2026-09-08T00:00:00.000Z",
17
+ "updatedAt": "2026-09-08T00:00:00.000Z"
18
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "reqId": "platform-docker-compose-host-REQ-006",
3
+ "prdId": "PRD-001",
4
+ "title": "Log shipping to the elicited observability-logging sink: journald default matching Debian 12 and Ubuntu 24.04 baseline; loki opt-in when the project runs Grafana",
5
+ "description": "Every container writes stdout and stderr through the elicited log driver. Journald is the shipped default matching the Debian 12 and Ubuntu 24.04 baselines T-1 cloud-init sets up. Loki is the opt-in alternative when the applying project runs Grafana. When observability-logging is applied, the compose file wires the elicited driver to that companion. The compose-config-lint asserts every service declares a logging driver whose value is one of journald or loki.",
6
+ "category": "functional",
7
+ "domain": "platform",
8
+ "priority": "must",
9
+ "rationale": "Ratified in the Hetzner round 7 spec (2026-09-07 section 5.2 REQ-006). Ships as v1.0.0 of platform-docker-compose-host.",
10
+ "tags": [
11
+ "blueprint:platform-docker-compose-host",
12
+ "capability:containerHost"
13
+ ],
14
+ "version": "1.0.0",
15
+ "status": "approved",
16
+ "createdAt": "2026-09-08T00:00:00.000Z",
17
+ "updatedAt": "2026-09-08T00:00:00.000Z"
18
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "tacId": "TAC-3901-platform-docker-compose-host-compose-layout",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "approved",
7
+ "name": "Platform-docker-compose-host compose layout",
8
+ "purpose": "The applying project ships one compose.yaml at the repo root whose services key names every container the stack runs. Every entry is one image running one container; networks and volumes are top-level named entries; a colocated .env carries non-secret configuration values (never inline). The container host reads compose.yaml as the runtime topology source and refuses to bring the stack up on layout drift.",
9
+ "responsibilities": [
10
+ "Serve compose.yaml at the repo root as the sole topology surface (AC-composeHost-topologyValid, AC-composeHost-upClean).",
11
+ "Guarantee service-per-container: each entry under services: runs one image (AC-composeHost-topologyValid).",
12
+ "Declare all networks and volumes as top-level named entries: no bare defaults (AC-composeHost-topologyValid).",
13
+ "Bind non-secret configuration through a colocated .env: no inline literals (AC-composeHost-topologyValid)."
14
+ ],
15
+ "internalStructure": "One module exporting a compose.yaml discovery helper that resolves the applied fixture root and returns the parsed document; consumers scan services/networks/volumes/env-file/logging by walking the parsed document.",
16
+ "interfaces": [
17
+ {
18
+ "name": "default export",
19
+ "kind": "facade",
20
+ "summary": "Compose stack scan facade exported from the applied fixture module."
21
+ }
22
+ ],
23
+ "dependencies": [],
24
+ "createdAt": "2026-09-08T00:00:00.000Z",
25
+ "updatedAt": "2026-09-08T00:00:00.000Z"
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "tacId": "TAC-3902-platform-docker-compose-host-secrets-mount",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "approved",
7
+ "name": "Platform-docker-compose-host secrets mount",
8
+ "purpose": "The compose file declares each secret under its top-level secrets: key with a file: source. Services reference secrets through their service-level secrets: array so docker mounts them as files at 0o400 inside the container. When security-secrets-management is applied, the source path resolves through that facade; when it is not, the guide names a file-based fallback. No plaintext secret literal appears anywhere in compose.yaml or a referenced service config (grep-refuse).",
9
+ "responsibilities": [
10
+ "Declare every secret through a compose secrets: file mount (AC-composeHost-secretShape, AC-composeHost-secretsAreFiles).",
11
+ "Refuse a plaintext secret literal anywhere in compose.yaml (AC-composeHost-secretsAreFiles).",
12
+ "Mount each secret file at 0o400 inside the container (AC-composeHost-secretShape).",
13
+ "Bind to security-secrets-management when applied; document the file-based fallback (AC-composeHost-secretShape)."
14
+ ],
15
+ "internalStructure": "The secrets-as-files-scan probe module walks the parsed compose document plus the referenced service config files and asserts the secret shape; the mutation switch drives the failure path.",
16
+ "interfaces": [
17
+ {
18
+ "name": "default export",
19
+ "kind": "facade",
20
+ "summary": "Compose stack scan facade exported from the applied fixture module."
21
+ }
22
+ ],
23
+ "dependencies": [],
24
+ "createdAt": "2026-09-08T00:00:00.000Z",
25
+ "updatedAt": "2026-09-08T00:00:00.000Z"
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "tacId": "TAC-3903-platform-docker-compose-host-healthcheck-lint",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "approved",
7
+ "name": "Platform-docker-compose-host healthcheck and lifecycle lint",
8
+ "purpose": "A lint pass runs before docker compose up. It asserts every HTTP-terminating service declares a healthcheck: block; every service declares a restart: policy whose value is one of unless-stopped or on-failure; every service declares a logging: driver: entry whose value is one of journald or loki. The lint refuses on any missing or unclassified line, naming the service and the offending field.",
9
+ "responsibilities": [
10
+ "Assert every HTTP-terminating service declares a healthcheck: block (AC-composeHost-healthcheckLint).",
11
+ "Assert every service declares a restart policy in the allowed set (AC-composeHost-restartClassification).",
12
+ "Assert every service declares a logging driver in the allowed set (AC-composeHost-logDriverClassification).",
13
+ "Refuse on missing or unclassified fields, naming the service (AC-composeHost-healthcheckLint, AC-composeHost-restartClassification, AC-composeHost-logDriverClassification)."
14
+ ],
15
+ "internalStructure": "The compose-config-lint probe module orchestrates docker compose config, healthcheck presence, restart classification and logging driver classification through one parsed compose document; mutation switches drive the four failure paths.",
16
+ "interfaces": [
17
+ {
18
+ "name": "default export",
19
+ "kind": "facade",
20
+ "summary": "Compose stack scan facade exported from the applied fixture module."
21
+ }
22
+ ],
23
+ "dependencies": [],
24
+ "createdAt": "2026-09-08T00:00:00.000Z",
25
+ "updatedAt": "2026-09-08T00:00:00.000Z"
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "tacId": "TAC-3904-platform-docker-compose-host-reverse-proxy-artefact",
3
+ "prdId": "PRD-001",
4
+ "tadId": "TAD-001",
5
+ "version": "1.0.0",
6
+ "status": "approved",
7
+ "name": "Platform-docker-compose-host reverse-proxy artefact",
8
+ "purpose": "The reverse-proxy config file (caddy/Caddyfile when reverseProxy=caddy, traefik/traefik.yaml when reverseProxy=traefik) lives as a first-class checked-in artefact under the applying repo. The compose file bind-mounts the artefact read-only into the proxy service. The gate runs the vendor validator against the artefact and refuses on an invalid directive. Under the reload verb (docker compose exec caddy caddy reload or the Traefik equivalent), a burst against the proxy inside the elicited window sees no non-2xx and no dropped connection.",
9
+ "responsibilities": [
10
+ "Ship the reverse-proxy config as a checked-in artefact bind-mounted into the proxy (AC-composeHost-reverseProxyArtefactValid).",
11
+ "Validate the artefact with the vendor validator at gate time (AC-composeHost-reverseProxyArtefactValid).",
12
+ "Prove zero-downtime reload with a real-account burst (AC-composeHost-zeroDowntimeReload).",
13
+ "Name the reload verb per proxy in the guide and the fixture README (AC-composeHost-reverseProxyArtefactValid, AC-composeHost-zeroDowntimeReload)."
14
+ ],
15
+ "internalStructure": "The caddyfile-validate probe shells to caddy validate (local binary or caddy:2 container image) with SIMULATE_INVALID_CADDYFILE writing a broken directive into a scratch copy; the real-account-reload-burst probe drives an undici burst on the throwaway server while docker compose exec caddy caddy reload runs.",
16
+ "interfaces": [
17
+ {
18
+ "name": "default export",
19
+ "kind": "facade",
20
+ "summary": "Compose stack scan facade exported from the applied fixture module."
21
+ }
22
+ ],
23
+ "dependencies": [],
24
+ "createdAt": "2026-09-08T00:00:00.000Z",
25
+ "updatedAt": "2026-09-08T00:00:00.000Z"
26
+ }