rcf-lite 0.27.0 → 0.28.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 (601) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +10 -0
  3. package/bin/rcf.js +2 -0
  4. package/blueprints/application-account-settings/CHANGELOG.md +35 -6
  5. package/blueprints/application-account-settings/README.md +1 -1
  6. package/blueprints/application-account-settings/blueprint.json +4 -2
  7. package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +1 -1
  8. package/blueprints/application-account-settings/contributions/probes/probe-utils.mjs +177 -0
  9. package/blueprints/application-account-settings/contributions/probes/profile-form-autocomplete.mjs +67 -0
  10. package/blueprints/application-account-settings/contributions/probes/run-profile-form-autocomplete.mjs +5 -0
  11. package/blueprints/application-account-settings/contributions/probes/run-sessions-adapter-uniform.mjs +5 -0
  12. package/blueprints/application-account-settings/contributions/probes/run-sessions-surface-shape.mjs +5 -0
  13. package/blueprints/application-account-settings/contributions/probes/run-shell-tablist-per-capability.mjs +5 -0
  14. package/blueprints/application-account-settings/contributions/probes/run-theme-radiogroup.mjs +5 -0
  15. package/blueprints/application-account-settings/contributions/probes/sessions-adapter-uniform.mjs +130 -0
  16. package/blueprints/application-account-settings/contributions/probes/sessions-surface-shape.mjs +70 -0
  17. package/blueprints/application-account-settings/contributions/probes/shell-tablist-per-capability.mjs +60 -0
  18. package/blueprints/application-account-settings/contributions/probes/theme-radiogroup.mjs +126 -0
  19. package/blueprints/application-admin-console/CHANGELOG.md +32 -6
  20. package/blueprints/application-admin-console/README.md +1 -1
  21. package/blueprints/application-admin-console/blueprint.json +4 -2
  22. package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +1 -1
  23. package/blueprints/application-admin-console/contributions/probes/audit-log-surface.mjs +79 -0
  24. package/blueprints/application-admin-console/contributions/probes/org-switcher-surface.mjs +83 -0
  25. package/blueprints/application-admin-console/contributions/probes/permission-matrix-grid.mjs +67 -0
  26. package/blueprints/application-admin-console/contributions/probes/probe-utils.mjs +177 -0
  27. package/blueprints/application-admin-console/contributions/probes/run-audit-log-surface.mjs +5 -0
  28. package/blueprints/application-admin-console/contributions/probes/run-org-switcher-surface.mjs +5 -0
  29. package/blueprints/application-admin-console/contributions/probes/run-permission-matrix-grid.mjs +5 -0
  30. package/blueprints/application-admin-console/contributions/probes/run-sign-in-access-gated-surface.mjs +5 -0
  31. package/blueprints/application-admin-console/contributions/probes/run-users-directory-surface.mjs +5 -0
  32. package/blueprints/application-admin-console/contributions/probes/sign-in-access-gated-surface.mjs +117 -0
  33. package/blueprints/application-admin-console/contributions/probes/users-directory-surface.mjs +145 -0
  34. package/blueprints/application-api-rest/CHANGELOG.md +16 -8
  35. package/blueprints/application-api-rest/README.md +3 -3
  36. package/blueprints/application-api-rest/blueprint.json +3 -2
  37. package/blueprints/application-api-rest/contributions/adrs/adr-302-application-api-rest-auth-model.json +1 -1
  38. package/blueprints/application-api-rest/contributions/probes/cursor-pagination-round-trip.mjs +154 -0
  39. package/blueprints/application-api-rest/contributions/probes/health-probes-distinct.mjs +124 -0
  40. package/blueprints/application-api-rest/contributions/probes/probe-utils.mjs +177 -0
  41. package/blueprints/application-api-rest/contributions/probes/problem-details-on-error.mjs +77 -0
  42. package/blueprints/application-api-rest/contributions/probes/request-id-echoed.mjs +76 -0
  43. package/blueprints/application-api-rest/contributions/probes/run-cursor-pagination-round-trip.mjs +5 -0
  44. package/blueprints/application-api-rest/contributions/probes/run-health-probes-distinct.mjs +5 -0
  45. package/blueprints/application-api-rest/contributions/probes/run-problem-details-on-error.mjs +5 -0
  46. package/blueprints/application-api-rest/contributions/probes/run-request-id-echoed.mjs +5 -0
  47. package/blueprints/application-api-rest/docs/topics.md +1 -1
  48. package/blueprints/application-charts/CHANGELOG.md +35 -9
  49. package/blueprints/application-charts/README.md +6 -6
  50. package/blueprints/application-charts/blueprint.json +5 -3
  51. package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +1 -1
  52. package/blueprints/application-charts/contributions/probes/keyboard-traversal.mjs +151 -0
  53. package/blueprints/application-charts/contributions/probes/non-colour-distinction.mjs +67 -0
  54. package/blueprints/application-charts/contributions/probes/probe-utils.mjs +177 -0
  55. package/blueprints/application-charts/contributions/probes/run-keyboard-traversal.mjs +5 -0
  56. package/blueprints/application-charts/contributions/probes/run-non-colour-distinction.mjs +5 -0
  57. package/blueprints/application-charts/contributions/probes/run-text-alternative-table.mjs +5 -0
  58. package/blueprints/application-charts/contributions/probes/text-alternative-table.mjs +139 -0
  59. package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +1 -1
  60. package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +1 -1
  61. package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +5 -5
  62. package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +1 -1
  63. package/blueprints/application-charts/guide/application-charts.md +1 -1
  64. package/blueprints/application-dashboard/CHANGELOG.md +20 -10
  65. package/blueprints/application-dashboard/README.md +6 -6
  66. package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +2 -2
  67. package/blueprints/application-dashboard/blueprint.json +3 -2
  68. package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +1 -1
  69. package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +1 -1
  70. package/blueprints/application-dashboard/contributions/probes/export-handle-formats.mjs +75 -0
  71. package/blueprints/application-dashboard/contributions/probes/four-tile-states.mjs +75 -0
  72. package/blueprints/application-dashboard/contributions/probes/primary-kpi-top-left.mjs +58 -0
  73. package/blueprints/application-dashboard/contributions/probes/probe-utils.mjs +177 -0
  74. package/blueprints/application-dashboard/contributions/probes/run-export-handle-formats.mjs +4 -0
  75. package/blueprints/application-dashboard/contributions/probes/run-four-tile-states.mjs +4 -0
  76. package/blueprints/application-dashboard/contributions/probes/run-primary-kpi-top-left.mjs +4 -0
  77. package/blueprints/application-dashboard/contributions/probes/run-shell-five-regions.mjs +4 -0
  78. package/blueprints/application-dashboard/contributions/probes/shell-five-regions.mjs +93 -0
  79. package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +1 -1
  80. package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +1 -1
  81. package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +1 -1
  82. package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +2 -2
  83. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +2 -2
  84. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +2 -2
  85. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +1 -1
  86. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +1 -1
  87. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +1 -1
  88. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +2 -2
  89. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +5 -5
  90. package/blueprints/application-dashboard/docs/topics.md +2 -2
  91. package/blueprints/application-dashboard/guide/application-dashboard.md +2 -2
  92. package/blueprints/application-datatable/CHANGELOG.md +19 -9
  93. package/blueprints/application-datatable/README.md +2 -2
  94. package/blueprints/application-datatable/blueprint.json +3 -2
  95. package/blueprints/application-datatable/contributions/probes/apg-table-shape.mjs +57 -0
  96. package/blueprints/application-datatable/contributions/probes/four-states-regions.mjs +80 -0
  97. package/blueprints/application-datatable/contributions/probes/probe-utils.mjs +177 -0
  98. package/blueprints/application-datatable/contributions/probes/run-apg-table-shape.mjs +4 -0
  99. package/blueprints/application-datatable/contributions/probes/run-four-states-regions.mjs +4 -0
  100. package/blueprints/application-datatable/contributions/probes/run-search-adapter-round-trip.mjs +4 -0
  101. package/blueprints/application-datatable/contributions/probes/run-sort-adapter-round-trip.mjs +4 -0
  102. package/blueprints/application-datatable/contributions/probes/search-adapter-round-trip.mjs +58 -0
  103. package/blueprints/application-datatable/contributions/probes/sort-adapter-round-trip.mjs +60 -0
  104. package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +1 -1
  105. package/blueprints/application-datatable/docs/topics.md +1 -1
  106. package/blueprints/application-empty-error-states/CHANGELOG.md +33 -3
  107. package/blueprints/application-empty-error-states/blueprint.json +4 -2
  108. package/blueprints/application-empty-error-states/contributions/probes/empty-list-and-no-search.mjs +66 -0
  109. package/blueprints/application-empty-error-states/contributions/probes/error-boundary-alert.mjs +65 -0
  110. package/blueprints/application-empty-error-states/contributions/probes/forbidden-and-server-error.mjs +167 -0
  111. package/blueprints/application-empty-error-states/contributions/probes/not-found-and-recovery.mjs +61 -0
  112. package/blueprints/application-empty-error-states/contributions/probes/permission-denied-and-offline.mjs +155 -0
  113. package/blueprints/application-empty-error-states/contributions/probes/probe-utils.mjs +177 -0
  114. package/blueprints/application-empty-error-states/contributions/probes/run-empty-list-and-no-search.mjs +5 -0
  115. package/blueprints/application-empty-error-states/contributions/probes/run-error-boundary-alert.mjs +5 -0
  116. package/blueprints/application-empty-error-states/contributions/probes/run-forbidden-and-server-error.mjs +5 -0
  117. package/blueprints/application-empty-error-states/contributions/probes/run-not-found-and-recovery.mjs +5 -0
  118. package/blueprints/application-empty-error-states/contributions/probes/run-permission-denied-and-offline.mjs +5 -0
  119. package/blueprints/application-error-handling/CHANGELOG.md +45 -6
  120. package/blueprints/application-error-handling/blueprint.json +3 -2
  121. package/blueprints/application-error-handling/contributions/probes/category-vocabulary.mjs +90 -0
  122. package/blueprints/application-error-handling/contributions/probes/probe-utils.mjs +177 -0
  123. package/blueprints/application-error-handling/contributions/probes/record-shape-adr-1701.mjs +78 -0
  124. package/blueprints/application-error-handling/contributions/probes/run-category-vocabulary.mjs +5 -0
  125. package/blueprints/application-error-handling/contributions/probes/run-record-shape-adr-1701.mjs +5 -0
  126. package/blueprints/application-error-handling/contributions/probes/run-two-boundaries-registered.mjs +5 -0
  127. package/blueprints/application-error-handling/contributions/probes/two-boundaries-registered.mjs +343 -0
  128. package/blueprints/application-file-upload/CHANGELOG.md +28 -6
  129. package/blueprints/application-file-upload/README.md +1 -1
  130. package/blueprints/application-file-upload/blueprint.json +3 -2
  131. package/blueprints/application-file-upload/contributions/probes/assertive-completion-slot.mjs +78 -0
  132. package/blueprints/application-file-upload/contributions/probes/chunked-transport-endpoints.mjs +173 -0
  133. package/blueprints/application-file-upload/contributions/probes/per-file-progressbar.mjs +124 -0
  134. package/blueprints/application-file-upload/contributions/probes/probe-utils.mjs +177 -0
  135. package/blueprints/application-file-upload/contributions/probes/run-assertive-completion-slot.mjs +4 -0
  136. package/blueprints/application-file-upload/contributions/probes/run-chunked-transport-endpoints.mjs +4 -0
  137. package/blueprints/application-file-upload/contributions/probes/run-per-file-progressbar.mjs +4 -0
  138. package/blueprints/application-file-upload/contributions/probes/run-upload-surface-shape.mjs +4 -0
  139. package/blueprints/application-file-upload/contributions/probes/upload-surface-shape.mjs +55 -0
  140. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +1 -1
  141. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +1 -1
  142. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +1 -1
  143. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +1 -1
  144. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +1 -1
  145. package/blueprints/application-file-upload/probe-packs/application-file-upload.pack.mjs +1 -1
  146. package/blueprints/application-forms-wizard/CHANGELOG.md +20 -6
  147. package/blueprints/application-forms-wizard/README.md +2 -2
  148. package/blueprints/application-forms-wizard/blueprint.json +3 -2
  149. package/blueprints/application-forms-wizard/contributions/probes/draft-persistence-round-trip.mjs +110 -0
  150. package/blueprints/application-forms-wizard/contributions/probes/probe-utils.mjs +177 -0
  151. package/blueprints/application-forms-wizard/contributions/probes/run-draft-persistence-round-trip.mjs +4 -0
  152. package/blueprints/application-forms-wizard/contributions/probes/run-step-page-shape.mjs +4 -0
  153. package/blueprints/application-forms-wizard/contributions/probes/run-task-list-surface.mjs +4 -0
  154. package/blueprints/application-forms-wizard/contributions/probes/step-page-shape.mjs +61 -0
  155. package/blueprints/application-forms-wizard/contributions/probes/task-list-surface.mjs +109 -0
  156. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +1 -1
  157. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +1 -1
  158. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +1 -1
  159. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +1 -1
  160. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +1 -1
  161. package/blueprints/application-forms-wizard/probe-packs/application-forms-wizard.pack.mjs +1 -1
  162. package/blueprints/application-notifications-in-app/CHANGELOG.md +38 -5
  163. package/blueprints/application-notifications-in-app/README.md +4 -4
  164. package/blueprints/application-notifications-in-app/blueprint.json +4 -2
  165. package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +1 -1
  166. package/blueprints/application-notifications-in-app/contributions/probes/centre-acknowledge-round-trip.mjs +210 -0
  167. package/blueprints/application-notifications-in-app/contributions/probes/live-region-preseeding.mjs +93 -0
  168. package/blueprints/application-notifications-in-app/contributions/probes/probe-utils.mjs +177 -0
  169. package/blueprints/application-notifications-in-app/contributions/probes/run-centre-acknowledge-round-trip.mjs +5 -0
  170. package/blueprints/application-notifications-in-app/contributions/probes/run-live-region-preseeding.mjs +5 -0
  171. package/blueprints/application-notifications-in-app/contributions/probes/run-toast-contract.mjs +5 -0
  172. package/blueprints/application-notifications-in-app/contributions/probes/toast-contract.mjs +92 -0
  173. package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +3 -3
  174. package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +1 -1
  175. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +1 -1
  176. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +1 -1
  177. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +1 -1
  178. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +1 -1
  179. package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +3 -3
  180. package/blueprints/application-onboarding-tour/CHANGELOG.md +31 -5
  181. package/blueprints/application-onboarding-tour/README.md +1 -1
  182. package/blueprints/application-onboarding-tour/blueprint.json +5 -3
  183. package/blueprints/application-onboarding-tour/contributions/probes/checklist-anchor-open.mjs +81 -0
  184. package/blueprints/application-onboarding-tour/contributions/probes/completion-persistence.mjs +159 -0
  185. package/blueprints/application-onboarding-tour/contributions/probes/first-run-detection.mjs +67 -0
  186. package/blueprints/application-onboarding-tour/contributions/probes/probe-utils.mjs +177 -0
  187. package/blueprints/application-onboarding-tour/contributions/probes/run-checklist-anchor-open.mjs +5 -0
  188. package/blueprints/application-onboarding-tour/contributions/probes/run-completion-persistence.mjs +5 -0
  189. package/blueprints/application-onboarding-tour/contributions/probes/run-first-run-detection.mjs +5 -0
  190. package/blueprints/application-onboarding-tour/contributions/probes/run-stepper-role-dialog.mjs +5 -0
  191. package/blueprints/application-onboarding-tour/contributions/probes/stepper-role-dialog.mjs +45 -0
  192. package/blueprints/application-spa/CHANGELOG.md +20 -11
  193. package/blueprints/application-spa/README.md +9 -10
  194. package/blueprints/application-spa/blueprint.json +3 -2
  195. package/blueprints/application-spa/contributions/adrs/adr-202-application-spa-theming.json +1 -1
  196. package/blueprints/application-spa/contributions/adrs/adr-206-application-spa-iconography.json +1 -1
  197. package/blueprints/application-spa/contributions/probes/designed-empty-state.mjs +72 -0
  198. package/blueprints/application-spa/contributions/probes/probe-utils.mjs +177 -0
  199. package/blueprints/application-spa/contributions/probes/route-inventory-published.mjs +185 -0
  200. package/blueprints/application-spa/contributions/probes/run-designed-empty-state.mjs +5 -0
  201. package/blueprints/application-spa/contributions/probes/run-route-inventory-published.mjs +5 -0
  202. package/blueprints/application-spa/contributions/probes/run-shell-nav-present.mjs +5 -0
  203. package/blueprints/application-spa/contributions/probes/shell-nav-present.mjs +69 -0
  204. package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +1 -1
  205. package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +2 -2
  206. package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +3 -3
  207. package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +2 -2
  208. package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +2 -2
  209. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +1 -1
  210. package/blueprints/application-spa/docs/topics.md +1 -1
  211. package/blueprints/delivery-ci-workflows/CHANGELOG.md +31 -11
  212. package/blueprints/delivery-ci-workflows/README.md +3 -3
  213. package/blueprints/delivery-ci-workflows/blueprint.json +3 -2
  214. package/blueprints/delivery-ci-workflows/contributions/adrs/adr-702-delivery-ci-workflows-strict-coverage-gate.json +2 -2
  215. package/blueprints/delivery-ci-workflows/contributions/probes/node-gate-entrypoint.mjs +76 -0
  216. package/blueprints/delivery-ci-workflows/contributions/probes/probe-utils.mjs +56 -0
  217. package/blueprints/delivery-ci-workflows/contributions/probes/real-account-github-actions-run-record.mjs +139 -0
  218. package/blueprints/delivery-ci-workflows/contributions/probes/run-node-gate-entrypoint.mjs +3 -0
  219. package/blueprints/delivery-ci-workflows/contributions/probes/run-real-account-github-actions-run-record.mjs +3 -0
  220. package/blueprints/delivery-ci-workflows/contributions/probes/run-workflow-template-shape.mjs +3 -0
  221. package/blueprints/delivery-ci-workflows/contributions/probes/workflow-template-shape.mjs +94 -0
  222. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-004.json +1 -1
  223. package/blueprints/delivery-ci-workflows/docs/topics.md +2 -3
  224. package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +4 -4
  225. package/blueprints/deploy-cloudflare-workers/README.md +3 -3
  226. package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +2 -2
  227. package/blueprints/deploy-cloudflare-workers/docs/topics.md +2 -2
  228. package/blueprints/deploy-hetzner-server/CHANGELOG.md +98 -7
  229. package/blueprints/deploy-hetzner-server/blueprint.json +7 -6
  230. package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +46 -21
  231. package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +344 -83
  232. package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +211 -42
  233. package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +140 -22
  234. package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +111 -30
  235. package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +158 -30
  236. package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +154 -32
  237. package/blueprints/edge-cloudflare-access/CHANGELOG.md +6 -5
  238. package/blueprints/edge-cloudflare-access/blueprint.json +1 -1
  239. package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +9 -1
  240. package/blueprints/edge-cloudflare-access/docs/topics.md +1 -1
  241. package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +4 -7
  242. package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +1 -1
  243. package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +4 -6
  244. package/blueprints/edge-cloudflare-tunnel/README.md +1 -2
  245. package/blueprints/edge-cloudflare-tunnel/docs/topics.md +1 -1
  246. package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +2 -3
  247. package/blueprints/edge-cloudflare-turnstile/docs/topics.md +1 -1
  248. package/blueprints/email-smtp-resend/CHANGELOG.md +24 -8
  249. package/blueprints/email-smtp-resend/README.md +2 -2
  250. package/blueprints/email-smtp-resend/blueprint.json +3 -2
  251. package/blueprints/email-smtp-resend/contributions/probes/probe-utils.mjs +50 -0
  252. package/blueprints/email-smtp-resend/contributions/probes/real-account-resend-send.mjs +50 -0
  253. package/blueprints/email-smtp-resend/contributions/probes/run-real-account-resend-send.mjs +3 -0
  254. package/blueprints/email-smtp-resend/contributions/probes/run-smtp-round-trip.mjs +3 -0
  255. package/blueprints/email-smtp-resend/contributions/probes/run-unverified-sender-refusal.mjs +3 -0
  256. package/blueprints/email-smtp-resend/contributions/probes/smtp-round-trip.mjs +43 -0
  257. package/blueprints/email-smtp-resend/contributions/probes/unverified-sender-refusal.mjs +99 -0
  258. package/blueprints/email-smtp-resend/docs/topics.md +2 -3
  259. package/blueprints/jobs-background/CHANGELOG.md +66 -5
  260. package/blueprints/jobs-background/README.md +2 -2
  261. package/blueprints/jobs-background/blueprint.json +3 -2
  262. package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +38 -10
  263. package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +28 -6
  264. package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +16 -2
  265. package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +102 -21
  266. package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +10 -2
  267. package/blueprints/jobs-background/contributions/probes/retry-and-fail-real-account.mjs +355 -0
  268. package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +33 -2
  269. package/blueprints/jobs-background/contributions/probes/run-retry-and-fail-real-account.mjs +12 -0
  270. package/blueprints/jobs-background/docs/topics.md +1 -1
  271. package/blueprints/jobs-background/guide/jobs-background.md +1 -1
  272. package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +25 -19
  273. package/blueprints/messaging-queue-cloudflare/README.md +12 -12
  274. package/blueprints/messaging-queue-cloudflare/blueprint.json +1 -1
  275. package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +2 -2
  276. package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +1 -1
  277. package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +180 -12
  278. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +1 -1
  279. package/blueprints/messaging-queue-cloudflare/docs/topics.md +2 -2
  280. package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +2 -2
  281. package/blueprints/object-storage-s3/CHANGELOG.md +75 -4
  282. package/blueprints/object-storage-s3/blueprint.json +3 -2
  283. package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +73 -12
  284. package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +55 -7
  285. package/blueprints/object-storage-s3/contributions/probes/hetzner-object-storage-round-trip.mjs +102 -18
  286. package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +105 -36
  287. package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +104 -55
  288. package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +129 -7
  289. package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +80 -18
  290. package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +291 -37
  291. package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +8 -2
  292. package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +5 -5
  293. package/blueprints/object-storage-s3/contributions/probes/run-hetzner-object-storage-round-trip.mjs +8 -5
  294. package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +8 -2
  295. package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +8 -2
  296. package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +6 -3
  297. package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +10 -2
  298. package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +1 -1
  299. package/blueprints/object-storage-s3/docs/topics.md +1 -1
  300. package/blueprints/object-storage-s3/guide/object-storage-s3.md +1 -1
  301. package/blueprints/observability-essentials/CHANGELOG.md +23 -7
  302. package/blueprints/observability-essentials/README.md +2 -2
  303. package/blueprints/observability-essentials/assets/probe-samples/probe-response-baseline.v2.json +1 -1
  304. package/blueprints/observability-essentials/blueprint.json +3 -2
  305. package/blueprints/observability-essentials/contributions/probes/liveness-probe.mjs +84 -0
  306. package/blueprints/observability-essentials/contributions/probes/metrics-endpoint.mjs +96 -0
  307. package/blueprints/observability-essentials/contributions/probes/probe-utils.mjs +52 -0
  308. package/blueprints/observability-essentials/contributions/probes/readiness-probe.mjs +171 -0
  309. package/blueprints/observability-essentials/contributions/probes/run-liveness-probe.mjs +3 -0
  310. package/blueprints/observability-essentials/contributions/probes/run-metrics-endpoint.mjs +3 -0
  311. package/blueprints/observability-essentials/contributions/probes/run-readiness-probe.mjs +3 -0
  312. package/blueprints/observability-essentials/docs/topics.md +2 -3
  313. package/blueprints/observability-logging/CHANGELOG.md +29 -4
  314. package/blueprints/observability-logging/README.md +2 -2
  315. package/blueprints/observability-logging/blueprint.json +3 -2
  316. package/blueprints/observability-logging/contributions/probes/correlation-id-flow.mjs +173 -0
  317. package/blueprints/observability-logging/contributions/probes/line-shape-and-fields.mjs +82 -0
  318. package/blueprints/observability-logging/contributions/probes/probe-utils.mjs +47 -0
  319. package/blueprints/observability-logging/contributions/probes/redaction-boundary.mjs +130 -0
  320. package/blueprints/observability-logging/contributions/probes/run-correlation-id-flow.mjs +3 -0
  321. package/blueprints/observability-logging/contributions/probes/run-line-shape-and-fields.mjs +3 -0
  322. package/blueprints/observability-logging/contributions/probes/run-redaction-boundary.mjs +3 -0
  323. package/blueprints/observability-probe-endpoints/CHANGELOG.md +23 -8
  324. package/blueprints/observability-probe-endpoints/README.md +3 -3
  325. package/blueprints/observability-probe-endpoints/blueprint.json +3 -2
  326. package/blueprints/observability-probe-endpoints/contributions/probes/kubernetes-startup-enabled.mjs +80 -0
  327. package/blueprints/observability-probe-endpoints/contributions/probes/partial-profile-refusal.mjs +101 -0
  328. package/blueprints/observability-probe-endpoints/contributions/probes/probe-utils.mjs +49 -0
  329. package/blueprints/observability-probe-endpoints/contributions/probes/profile-boot-materialisation.mjs +69 -0
  330. package/blueprints/observability-probe-endpoints/contributions/probes/run-kubernetes-startup-enabled.mjs +3 -0
  331. package/blueprints/observability-probe-endpoints/contributions/probes/run-partial-profile-refusal.mjs +3 -0
  332. package/blueprints/observability-probe-endpoints/contributions/probes/run-profile-boot-materialisation.mjs +3 -0
  333. package/blueprints/observability-probe-endpoints/docs/topics.md +2 -2
  334. package/blueprints/persistence-data-d1/CHANGELOG.md +16 -3
  335. package/blueprints/persistence-data-d1/README.md +2 -2
  336. package/blueprints/persistence-data-d1/blueprint.json +3 -2
  337. package/blueprints/persistence-data-d1/contributions/adrs/adr-1404-persistence-data-d1-store-boundary.json +1 -1
  338. package/blueprints/persistence-data-d1/contributions/probes/facade-round-trip.mjs +140 -0
  339. package/blueprints/persistence-data-d1/contributions/probes/migrations-forward-only.mjs +66 -0
  340. package/blueprints/persistence-data-d1/contributions/probes/probe-utils.mjs +51 -0
  341. package/blueprints/persistence-data-d1/contributions/probes/real-account-d1-round-trip.mjs +133 -0
  342. package/blueprints/persistence-data-d1/contributions/probes/run-facade-round-trip.mjs +3 -0
  343. package/blueprints/persistence-data-d1/contributions/probes/run-migrations-forward-only.mjs +3 -0
  344. package/blueprints/persistence-data-d1/contributions/probes/run-real-account-d1-round-trip.mjs +3 -0
  345. package/blueprints/persistence-data-d1/docs/topics.md +2 -3
  346. package/blueprints/persistence-data-postgres/CHANGELOG.md +84 -4
  347. package/blueprints/persistence-data-postgres/README.md +2 -2
  348. package/blueprints/persistence-data-postgres/blueprint.json +3 -2
  349. package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +1 -1
  350. package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +87 -12
  351. package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +245 -19
  352. package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +109 -26
  353. package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +151 -38
  354. package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +24 -6
  355. package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +261 -48
  356. package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +76 -20
  357. package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +1 -1
  358. package/blueprints/persistence-data-postgres/docs/topics.md +1 -1
  359. package/blueprints/persistence-data-sqlite/CHANGELOG.md +16 -2
  360. package/blueprints/persistence-data-sqlite/README.md +2 -2
  361. package/blueprints/persistence-data-sqlite/blueprint.json +3 -2
  362. package/blueprints/persistence-data-sqlite/contributions/probes/boot-open-migrate.mjs +90 -0
  363. package/blueprints/persistence-data-sqlite/contributions/probes/facade-round-trip.mjs +82 -0
  364. package/blueprints/persistence-data-sqlite/contributions/probes/probe-utils.mjs +83 -0
  365. package/blueprints/persistence-data-sqlite/contributions/probes/run-boot-open-migrate.mjs +5 -0
  366. package/blueprints/persistence-data-sqlite/contributions/probes/run-facade-round-trip.mjs +5 -0
  367. package/blueprints/persistence-data-sqlite/contributions/probes/run-wal-checkpoint.mjs +5 -0
  368. package/blueprints/persistence-data-sqlite/contributions/probes/wal-checkpoint.mjs +137 -0
  369. package/blueprints/persistence-data-sqlite/docs/topics.md +2 -3
  370. package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +5 -5
  371. package/blueprints/platform-cloudflare-cron-triggers/README.md +2 -3
  372. package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +1 -1
  373. package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +6 -10
  374. package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +1 -1
  375. package/blueprints/platform-cloudflare-kv/CHANGELOG.md +16 -12
  376. package/blueprints/platform-cloudflare-kv/README.md +2 -4
  377. package/blueprints/platform-cloudflare-kv/blueprint.json +2 -2
  378. package/blueprints/platform-cloudflare-kv/docs/topics.md +1 -1
  379. package/blueprints/platform-docker-compose-host/CHANGELOG.md +92 -5
  380. package/blueprints/platform-docker-compose-host/blueprint.json +2 -2
  381. package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +116 -29
  382. package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +181 -109
  383. package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +146 -26
  384. package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +238 -24
  385. package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +207 -21
  386. package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +246 -42
  387. package/blueprints/platform-docker-compose-host/docs/topics.md +1 -1
  388. package/blueprints/security-auth-clerk/CHANGELOG.md +18 -6
  389. package/blueprints/security-auth-clerk/README.md +3 -3
  390. package/blueprints/security-auth-clerk/assets/wiring/workers-wrangler-toml-shape.md +1 -1
  391. package/blueprints/security-auth-clerk/blueprint.json +3 -2
  392. package/blueprints/security-auth-clerk/contributions/probes/hosted-identity-ui-config.mjs +61 -0
  393. package/blueprints/security-auth-clerk/contributions/probes/probe-utils.mjs +188 -0
  394. package/blueprints/security-auth-clerk/contributions/probes/real-account-principal-directory-round-trip.mjs +216 -0
  395. package/blueprints/security-auth-clerk/contributions/probes/real-account-session-inventory.mjs +260 -0
  396. package/blueprints/security-auth-clerk/contributions/probes/role-model-adapter.mjs +53 -0
  397. package/blueprints/security-auth-clerk/contributions/probes/run-hosted-identity-ui-config.mjs +4 -0
  398. package/blueprints/security-auth-clerk/contributions/probes/run-real-account-principal-directory-round-trip.mjs +4 -0
  399. package/blueprints/security-auth-clerk/contributions/probes/run-real-account-session-inventory.mjs +4 -0
  400. package/blueprints/security-auth-clerk/contributions/probes/run-role-model-adapter.mjs +4 -0
  401. package/blueprints/security-auth-clerk/docs/topics.md +2 -3
  402. package/blueprints/security-auth-keycloak/CHANGELOG.md +18 -7
  403. package/blueprints/security-auth-keycloak/README.md +2 -2
  404. package/blueprints/security-auth-keycloak/blueprint.json +3 -2
  405. package/blueprints/security-auth-keycloak/contributions/probes/discovery-shape.mjs +68 -0
  406. package/blueprints/security-auth-keycloak/contributions/probes/introspection-shape.mjs +88 -0
  407. package/blueprints/security-auth-keycloak/contributions/probes/jwt-verifier-shape.mjs +86 -0
  408. package/blueprints/security-auth-keycloak/contributions/probes/probe-utils.mjs +180 -0
  409. package/blueprints/security-auth-keycloak/contributions/probes/real-account-realm-round-trip.mjs +91 -0
  410. package/blueprints/security-auth-keycloak/contributions/probes/role-adapter-shape.mjs +69 -0
  411. package/blueprints/security-auth-keycloak/contributions/probes/run-discovery-shape.mjs +4 -0
  412. package/blueprints/security-auth-keycloak/contributions/probes/run-introspection-shape.mjs +4 -0
  413. package/blueprints/security-auth-keycloak/contributions/probes/run-jwt-verifier-shape.mjs +4 -0
  414. package/blueprints/security-auth-keycloak/contributions/probes/run-real-account-realm-round-trip.mjs +4 -0
  415. package/blueprints/security-auth-keycloak/contributions/probes/run-role-adapter-shape.mjs +4 -0
  416. package/blueprints/security-auth-keycloak/docs/topics.md +1 -2
  417. package/blueprints/security-auth-magic-link/CHANGELOG.md +15 -4
  418. package/blueprints/security-auth-magic-link/README.md +2 -2
  419. package/blueprints/security-auth-magic-link/assets/principal-registry-samples/single-address.md +1 -1
  420. package/blueprints/security-auth-magic-link/blueprint.json +3 -2
  421. package/blueprints/security-auth-magic-link/contributions/probes/probe-utils.mjs +174 -0
  422. package/blueprints/security-auth-magic-link/contributions/probes/real-account-magic-link-send.mjs +139 -0
  423. package/blueprints/security-auth-magic-link/contributions/probes/run-real-account-magic-link-send.mjs +4 -0
  424. package/blueprints/security-auth-magic-link/contributions/probes/run-token-entropy-shape.mjs +4 -0
  425. package/blueprints/security-auth-magic-link/contributions/probes/run-token-issue-verify.mjs +4 -0
  426. package/blueprints/security-auth-magic-link/contributions/probes/token-entropy-shape.mjs +60 -0
  427. package/blueprints/security-auth-magic-link/contributions/probes/token-issue-verify.mjs +90 -0
  428. package/blueprints/security-auth-magic-link/docs/topics.md +1 -1
  429. package/blueprints/security-auth-oauth2/CHANGELOG.md +16 -5
  430. package/blueprints/security-auth-oauth2/README.md +2 -2
  431. package/blueprints/security-auth-oauth2/blueprint.json +3 -2
  432. package/blueprints/security-auth-oauth2/contributions/probes/authorisation-code-flow-shape.mjs +259 -0
  433. package/blueprints/security-auth-oauth2/contributions/probes/pkce-challenge-shape.mjs +58 -0
  434. package/blueprints/security-auth-oauth2/contributions/probes/probe-utils.mjs +190 -0
  435. package/blueprints/security-auth-oauth2/contributions/probes/provider-adapter-shape.mjs +64 -0
  436. package/blueprints/security-auth-oauth2/contributions/probes/real-account-authorisation-code-flow.mjs +93 -0
  437. package/blueprints/security-auth-oauth2/contributions/probes/run-authorisation-code-flow-shape.mjs +4 -0
  438. package/blueprints/security-auth-oauth2/contributions/probes/run-pkce-challenge-shape.mjs +4 -0
  439. package/blueprints/security-auth-oauth2/contributions/probes/run-provider-adapter-shape.mjs +4 -0
  440. package/blueprints/security-auth-oauth2/contributions/probes/run-real-account-authorisation-code-flow.mjs +4 -0
  441. package/blueprints/security-auth-oauth2/contributions/probes/run-session-bridge-shape.mjs +4 -0
  442. package/blueprints/security-auth-oauth2/contributions/probes/session-bridge-shape.mjs +78 -0
  443. package/blueprints/security-auth-oauth2/docs/topics.md +1 -2
  444. package/blueprints/security-secrets-management/CHANGELOG.md +15 -4
  445. package/blueprints/security-secrets-management/README.md +2 -2
  446. package/blueprints/security-secrets-management/blueprint.json +3 -2
  447. package/blueprints/security-secrets-management/contributions/probes/add-recipient-rotation.mjs +107 -0
  448. package/blueprints/security-secrets-management/contributions/probes/encrypt-decrypt-round-trip.mjs +122 -0
  449. package/blueprints/security-secrets-management/contributions/probes/key-rotation.mjs +93 -0
  450. package/blueprints/security-secrets-management/contributions/probes/mismatched-key-refusal.mjs +74 -0
  451. package/blueprints/security-secrets-management/contributions/probes/probe-utils.mjs +214 -0
  452. package/blueprints/security-secrets-management/contributions/probes/run-add-recipient-rotation.mjs +4 -0
  453. package/blueprints/security-secrets-management/contributions/probes/run-encrypt-decrypt-round-trip.mjs +4 -0
  454. package/blueprints/security-secrets-management/contributions/probes/run-key-rotation.mjs +4 -0
  455. package/blueprints/security-secrets-management/contributions/probes/run-mismatched-key-refusal.mjs +4 -0
  456. package/blueprints/security-secrets-management/docs/topics.md +2 -3
  457. package/fixtures/canary-manifest.json +9 -9
  458. package/guidance/harness-template.md +25 -0
  459. package/guidance/managed/agent-instructions-block.hash +1 -1
  460. package/guidance/managed/agent-instructions-block.md +25 -0
  461. package/package.json +2 -2
  462. package/rcf/adrs/adr-4101-feedback-store-gitignored.json +20 -0
  463. package/rcf/adrs/adr-4102-fingerprint-and-labels.json +25 -0
  464. package/rcf/adrs/adr-4103-redaction-rule-based.json +20 -0
  465. package/rcf/adrs/adr-4104-destination-on-library.json +25 -0
  466. package/rcf/adrs/adr-4105-gh-ambient-auth.json +20 -0
  467. package/rcf/adrs/adr-4106-bundled-entries-terminal.json +20 -0
  468. package/rcf/adrs/adr-4107-stop-is-ask-event.json +30 -0
  469. package/rcf/adrs/adr-4108-hooks-in-committed-config.json +25 -0
  470. package/rcf/adrs/adr-4109-referee-validate-adr-crosslinks.json +25 -0
  471. package/rcf/adrs/adr-4110-referee-coverage-strict-by-default.json +25 -0
  472. package/rcf/adrs/adr-4111-referee-finalise-refusals.json +20 -0
  473. package/rcf/adrs/adr-4112-referee-finalise-verified-invariant.json +30 -0
  474. package/rcf/code-nodes/cn-600.json +45 -0
  475. package/rcf/code-nodes/cn-601.json +18 -0
  476. package/rcf/code-nodes/cn-602.json +15 -0
  477. package/rcf/code-nodes/cn-603.json +12 -0
  478. package/rcf/code-nodes/cn-604.json +14 -0
  479. package/rcf/code-nodes/cn-605.json +17 -0
  480. package/rcf/code-nodes/cn-606.json +12 -0
  481. package/rcf/code-nodes/cn-607.json +12 -0
  482. package/rcf/code-nodes/cn-608.json +14 -0
  483. package/rcf/code-nodes/cn-609.json +17 -0
  484. package/rcf/code-nodes/cn-620.json +18 -0
  485. package/rcf/code-nodes/cn-621.json +14 -0
  486. package/rcf/code-nodes/cn-622.json +15 -0
  487. package/rcf/code-nodes/cn-623.json +16 -0
  488. package/rcf/code-nodes/cn-624.json +14 -0
  489. package/rcf/code-nodes/cn-625.json +15 -0
  490. package/rcf/code-nodes/cn-626.json +13 -0
  491. package/rcf/code-nodes/cn-627.json +13 -0
  492. package/rcf/code-nodes/cn-628.json +14 -0
  493. package/rcf/code-nodes/cn-629.json +12 -0
  494. package/rcf/code-nodes/cn-630.json +12 -0
  495. package/rcf/code-nodes/cn-631.json +13 -0
  496. package/rcf/code-nodes/cn-632.json +13 -0
  497. package/rcf/fbs/fbs-180.json +45 -0
  498. package/rcf/fbs/fbs-181.json +45 -0
  499. package/rcf/fbs/fbs-182.json +42 -0
  500. package/rcf/fbs/fbs-183.json +50 -0
  501. package/rcf/fbs/fbs-184.json +49 -0
  502. package/rcf/fbs/fbs-185.json +34 -0
  503. package/rcf/fbs/fbs-186.json +16 -0
  504. package/rcf/fbs/fbs-187.json +17 -0
  505. package/rcf/fbs/fbs-188.json +17 -0
  506. package/rcf/fbs/fbs-189.json +17 -0
  507. package/rcf/requirements/req-155.json +13 -0
  508. package/rcf/requirements/req-156.json +13 -0
  509. package/rcf/requirements/req-157.json +13 -0
  510. package/rcf/requirements/req-158.json +13 -0
  511. package/rcf/requirements/req-159.json +13 -0
  512. package/rcf/requirements/req-160.json +13 -0
  513. package/rcf/requirements/req-161.json +13 -0
  514. package/rcf/requirements/req-162.json +13 -0
  515. package/rcf/requirements/req-163.json +13 -0
  516. package/rcf/requirements/req-164.json +13 -0
  517. package/rcf/requirements/req-165.json +13 -0
  518. package/rcf/tacs/tac-4101-feedback-cli.json +77 -0
  519. package/rcf/tacs/tac-4102-feedback-store.json +50 -0
  520. package/rcf/tacs/tac-4103-feedback-redact.json +39 -0
  521. package/rcf/tacs/tac-4104-feedback-fingerprint.json +33 -0
  522. package/rcf/tacs/tac-4105-feedback-render.json +45 -0
  523. package/rcf/tacs/tac-4106-feedback-destination.json +39 -0
  524. package/rcf/tacs/tac-4107-feedback-gh.json +43 -0
  525. package/rcf/tacs/tac-4108-feedback-hook.json +46 -0
  526. package/rcf/tacs/tac-4109-referee-validate-adr-crosslinks.json +20 -0
  527. package/rcf/tacs/tac-4110-referee-coverage-mode-selector.json +21 -0
  528. package/rcf/tacs/tac-4111-referee-finalise-per-ac-refusals.json +21 -0
  529. package/rcf/tacs/tac-4112-referee-finalise-verified-invariant.json +22 -0
  530. package/rcf/test-suites/ts-140.json +9 -9
  531. package/rcf/test-suites/ts-150.json +9 -9
  532. package/rcf/test-suites/ts-185.json +54 -0
  533. package/rcf/test-suites/ts-186.json +58 -0
  534. package/rcf/test-suites/ts-187.json +44 -0
  535. package/rcf/test-suites/ts-188.json +166 -0
  536. package/rcf/test-suites/ts-189.json +38 -0
  537. package/rcf/test-suites/ts-190.json +30 -0
  538. package/rcf/test-suites/ts-191.json +51 -0
  539. package/rcf/test-suites/ts-192.json +37 -0
  540. package/rcf/test-suites/ts-193.json +60 -0
  541. package/rcf/test-suites/ts-194.json +67 -0
  542. package/rcf/test-suites/ts-195.json +52 -0
  543. package/rcf/test-suites/ts-196.json +58 -0
  544. package/rcf/test-suites/ts-197.json +66 -0
  545. package/rcf/test-suites/ts-198.json +87 -0
  546. package/rcf/test-suites/ts-199.json +51 -0
  547. package/rcf/test-suites/ts-200.json +30 -0
  548. package/rcf/test-suites/ts-201.json +38 -0
  549. package/rcf/test-suites/ts-202.json +38 -0
  550. package/rcf/test-suites/ts-203.json +38 -0
  551. package/rcf/user-stories/us-15501.json +60 -0
  552. package/rcf/user-stories/us-15502.json +33 -0
  553. package/rcf/user-stories/us-15503.json +33 -0
  554. package/rcf/user-stories/us-15601.json +51 -0
  555. package/rcf/user-stories/us-15701.json +42 -0
  556. package/rcf/user-stories/us-15801.json +42 -0
  557. package/rcf/user-stories/us-15802.json +33 -0
  558. package/rcf/user-stories/us-15901.json +33 -0
  559. package/rcf/user-stories/us-15902.json +51 -0
  560. package/rcf/user-stories/us-16001.json +51 -0
  561. package/rcf/user-stories/us-16101.json +42 -0
  562. package/rcf/user-stories/us-16102.json +33 -0
  563. package/rcf/user-stories/us-16103.json +42 -0
  564. package/rcf/user-stories/us-16104.json +42 -0
  565. package/rcf/user-stories/us-16201.json +33 -0
  566. package/rcf/user-stories/us-16301.json +36 -0
  567. package/rcf/user-stories/us-16401.json +45 -0
  568. package/rcf/user-stories/us-16501.json +45 -0
  569. package/rcf/user-stories/us-16502.json +45 -0
  570. package/releases/releases.yaml +11 -1
  571. package/src/blueprint/library-loader.js +48 -0
  572. package/src/blueprint/library-registry.js +13 -0
  573. package/src/browser-verify/pack-runner.js +7 -12
  574. package/src/build/mark.js +1 -1
  575. package/src/cli/blueprint-library.js +149 -0
  576. package/src/cli/coverage.js +49 -24
  577. package/src/cli/doctor.js +195 -7
  578. package/src/cli/feedback.js +2204 -0
  579. package/src/cli/finalise.js +158 -1
  580. package/src/cli/help.js +6 -0
  581. package/src/cli/init.js +63 -0
  582. package/src/cli/update.js +21 -1
  583. package/src/core/store/walker.js +33 -0
  584. package/src/core/store/writer.js +23 -0
  585. package/src/feedback/destination.js +361 -0
  586. package/src/feedback/fingerprint.js +132 -0
  587. package/src/feedback/gh.js +376 -0
  588. package/src/feedback/hook.js +183 -0
  589. package/src/feedback/labels.js +87 -0
  590. package/src/feedback/redact-allowlist.json +14 -0
  591. package/src/feedback/redact.js +1108 -0
  592. package/src/feedback/render.js +267 -0
  593. package/src/feedback/store.js +604 -0
  594. package/src/finalise/index.js +4 -0
  595. package/src/finalise/ingest.js +61 -0
  596. package/src/finalise/ship-without-eval.js +19 -7
  597. package/src/mcp/tools.js +8 -2
  598. package/src/setup/feedback-hooks.js +397 -0
  599. package/src/setup/managed-gitignore.js +3 -0
  600. package/src/view/html-page.js +5 -5
  601. package/src/view/style.css +2 -2
@@ -1,37 +1,251 @@
1
- // Probe: real-account-minimal-stack-up.
2
- //
1
+ // Probe: real-account-minimal-stack-up (v1.1.5).
2
+
3
3
  // anchorAcId: AC-composeHost-upClean.
4
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 the real-account gate contract, section 3.5.
13
5
 
14
- import { runShim, accountBoundSkippedResult } from './probe-utils.mjs';
6
+ // Contract:
7
+ // - First-tier gate CI_HAS_HETZNER_ACCOUNT must equal exactly the
8
+ // string "true"; anything else records an honest skip row.
9
+ // - Second-tier HCLOUD_TOKEN missing carries its own honest skip row.
10
+ // - The AC-composeHost-upClean pass row carries an `evidence`
11
+ // object with the created server id, the compose ps service
12
+ // list, the on-server HTTP response (statusCode and body
13
+ // excerpt) proving the deployed stack URL answers, and the
14
+ // root-path body sample that reads the mounted secret file
15
+ // (`tokenPresence`).
16
+ // - After the stack is up, the probe emits one additional row per
17
+ // mounted secret anchored to AC-composeHost-secretShape whose
18
+ // evidence carries the in-container mode observed via
19
+ // `docker exec <container> stat -c %a /run/secrets/<name>`; this
20
+ // is the "mounted at mode 0o400" observation the offline scan
21
+ // cannot make. The row FAILS if the observed mode is anything
22
+ // other than 400.
23
+ // - Teardown failure FAILS the verdict.
24
+
25
+ import { spawn } from 'node:child_process';
26
+ import { resolve } from 'node:path';
27
+ import {
28
+ runShim, firstTierGateSkipResult, secondTierMissingSkipResult, FIXTURE_DIR,
29
+ } from './probe-utils.mjs';
15
30
 
16
31
  export const anchorAcId = 'AC-composeHost-upClean';
17
32
  export const accountBound = true;
18
33
 
34
+ function hcloudJson(argv, { timeoutMs = 60_000 } = {}) {
35
+ return new Promise((resolvePromise, reject) => {
36
+ const p = spawn('hcloud', argv, { stdio: ['ignore', 'pipe', 'pipe'] });
37
+ let stdout = '';
38
+ let stderr = '';
39
+ const timer = setTimeout(() => { try { p.kill('SIGKILL'); } catch (_) {} reject(new Error(`hcloud ${argv.join(' ')} timed out after ${timeoutMs}ms`)); }, timeoutMs);
40
+ p.stdout.on('data', (d) => { stdout += d.toString(); });
41
+ p.stderr.on('data', (d) => { stderr += d.toString(); });
42
+ p.on('error', (err) => { clearTimeout(timer); reject(err); });
43
+ p.on('close', (code) => {
44
+ clearTimeout(timer);
45
+ if (code !== 0) return reject(new Error(`hcloud ${argv.join(' ')} exited ${code}: ${stderr}`));
46
+ const trimmed = stdout.trim();
47
+ if (trimmed.length === 0) return resolvePromise([]);
48
+ try {
49
+ const parsed = JSON.parse(trimmed);
50
+ resolvePromise(Array.isArray(parsed) ? parsed : (parsed.servers || []));
51
+ } catch (err) {
52
+ reject(new Error(`hcloud stdout not JSON: ${err.message}`));
53
+ }
54
+ });
55
+ });
56
+ }
57
+
19
58
  export default async function runProbe() {
20
- const results = [];
21
- const extra = { skipped: process.env.CI_HAS_HETZNER_ACCOUNT !== 'true' };
22
59
  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 };
60
+ return {
61
+ results: [firstTierGateSkipResult(
62
+ anchorAcId,
63
+ 'CI_HAS_HETZNER_ACCOUNT',
64
+ 'real-account minimal-stack-up skipped; run with CI_HAS_HETZNER_ACCOUNT=true to exercise the compose stack against a throwaway cx23.',
65
+ )],
66
+ extra: { skipped: true, missingEnv: ['CI_HAS_HETZNER_ACCOUNT'] },
67
+ };
25
68
  }
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, per the real-account gate contract, section 3.3.
30
- results.push({
31
- anchorAcId, verdict: 'warn',
32
- 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',
33
- });
34
- return { results, extra };
69
+ if (!process.env.HCLOUD_TOKEN) {
70
+ return {
71
+ results: [secondTierMissingSkipResult(
72
+ anchorAcId,
73
+ 'HCLOUD_TOKEN',
74
+ 'the throwaway cx23 cannot be provisioned without HCLOUD_TOKEN.',
75
+ )],
76
+ extra: { skipped: true, missingEnv: ['HCLOUD_TOKEN'] },
77
+ };
78
+ }
79
+ const { provisionThrowawayServer } = await import(resolve(FIXTURE_DIR, 'provision.mjs'));
80
+ const { destroyThrowawayServer } = await import(resolve(FIXTURE_DIR, 'destroy.mjs'));
81
+ const { bringUpStack, httpProbe, httpProbeOnServer, tearDownStack, observeSecretModes } = await import(resolve(FIXTURE_DIR, 'src/compose-stack-driver.mjs'));
82
+
83
+ const evidence = {};
84
+ const resultRow = { anchorAcId, verdict: 'fail', detail: '', evidence };
85
+ const extraRows = [];
86
+ let provisioned = null;
87
+ try {
88
+ provisioned = await provisionThrowawayServer({ runId: process.env.GITHUB_RUN_ID ?? `local-${Date.now()}` });
89
+ evidence.serverId = provisioned.id;
90
+ evidence.primaryIpv4 = provisioned.primaryIpv4;
91
+ const brought = await bringUpStack(provisioned);
92
+ evidence.services = brought.services;
93
+ evidence.declaredServices = brought.declared;
94
+ evidence.observedNames = brought.observedNames;
95
+ evidence.eventTrail = brought.events;
96
+ evidence.elicitedTimeoutSeconds = brought.elicitedTimeoutSeconds;
97
+ if (!brought.ok) {
98
+ resultRow.verdict = 'fail';
99
+ const detailPieces = [`stack failed at phase ${brought.phase} on server ${provisioned.id} (elicited timeout ${brought.elicitedTimeoutSeconds}s)`];
100
+ if (brought.missingServices && brought.missingServices.length > 0) {
101
+ detailPieces.push(`missing services: ${brought.missingServices.map((m) => m.name).join(', ')}`);
102
+ evidence.missingServices = brought.missingServices;
103
+ }
104
+ if (brought.unhealthy && brought.unhealthy.length > 0) {
105
+ detailPieces.push(`unhealthy services: ${brought.unhealthy.map((u) => `${u.service}(${u.reason})`).join('; ')}`);
106
+ evidence.unhealthyServices = brought.unhealthy;
107
+ }
108
+ resultRow.detail = `${detailPieces.join('; ')}. Trailer: ${JSON.stringify(brought).slice(0, 400)}`;
109
+ return { results: [resultRow], extra: evidence };
110
+ }
111
+ const onServer = await httpProbeOnServer(provisioned, '/live');
112
+ const onServerRoot = await httpProbeOnServer(provisioned, '/');
113
+ const externalUrl = `http://${provisioned.primaryIpv4}/live`;
114
+ const external = await httpProbe(externalUrl, { timeoutMs: 5000 });
115
+ evidence.onServer = {
116
+ target: onServer.target, statusCode: onServer.statusCode,
117
+ bodyExcerpt: onServer.bodyExcerpt, elapsedSeconds: onServer.elapsedSeconds,
118
+ requestId: onServer.requestId,
119
+ };
120
+ evidence.onServerRoot = {
121
+ target: onServerRoot.target, statusCode: onServerRoot.statusCode,
122
+ bodyExcerpt: onServerRoot.bodyExcerpt,
123
+ };
124
+ evidence.external = {
125
+ url: externalUrl, statusCode: external.statusCode, error: external.error || null,
126
+ note: 'off-host fetch expected to fail under the deploy-hetzner-server DOCKER-USER hardening',
127
+ };
128
+ if (!onServer.ok || onServer.statusCode !== 200) {
129
+ resultRow.verdict = 'fail';
130
+ resultRow.detail = `caddy /live did not return 200 on ${onServer.target}: statusCode=${onServer.statusCode} error=${onServer.error || 'none'} bodyExcerpt=${onServer.bodyExcerpt || ''}`;
131
+ return { results: [resultRow], extra: evidence };
132
+ }
133
+ resultRow.verdict = 'pass';
134
+ resultRow.detail = `stack up on server ${provisioned.id} (${provisioned.primaryIpv4}); ${brought.services.length} services declared; caddy answered ${onServer.target} with ${onServer.statusCode} body="${(onServer.bodyExcerpt || '').replace(/\n/g, ' ')}" elapsed=${onServer.elapsedSeconds}s; root ${onServerRoot.target} returned ${onServerRoot.statusCode}.`;
135
+
136
+ // In-container secret mode observation. AC-composeHost-secretShape
137
+ // requires the mounted secret file to land at mode 0o400 inside
138
+ // the container; the offline scan cannot see that. Run
139
+ // `docker exec ... stat -c %a /run/secrets/<name>` for every
140
+ // consuming service.
141
+ try {
142
+ const modes = await observeSecretModes(provisioned);
143
+ evidence.observedSecretModes = modes;
144
+ for (const obs of modes.observations) {
145
+ const modePass = obs.mode === '400';
146
+ extraRows.push({
147
+ anchorAcId: 'AC-composeHost-secretShape',
148
+ verdict: modePass ? 'pass' : 'fail',
149
+ detail: modePass
150
+ ? `service '${obs.service}' secret '${obs.secretName}' mounted at ${obs.mountPath} with observed mode ${obs.mode} inside container ${obs.containerName} (id ${obs.containerId}, docker exec stat -c %a)`
151
+ : `service '${obs.service}' secret '${obs.secretName}' mounted at ${obs.mountPath} with observed mode ${obs.mode}; AC-composeHost-secretShape requires 0o400 (400)`,
152
+ evidence: {
153
+ service: obs.service,
154
+ secretName: obs.secretName,
155
+ mode: obs.mode,
156
+ mountPath: obs.mountPath,
157
+ containerId: obs.containerId,
158
+ containerName: obs.containerName,
159
+ source: 'docker exec stat -c %a; container id via docker inspect --format {{.Id}}',
160
+ },
161
+ });
162
+ }
163
+ for (const err of modes.errors) {
164
+ extraRows.push({
165
+ anchorAcId: 'AC-composeHost-secretShape',
166
+ verdict: 'fail',
167
+ detail: `could not observe in-container mode for service '${err.service}' secret '${err.secretName}': ${err.error}`,
168
+ evidence: {
169
+ service: err.service,
170
+ secretName: err.secretName,
171
+ error: err.error,
172
+ containerName: err.containerName || null,
173
+ source: 'docker exec stat -c %a',
174
+ },
175
+ });
176
+ }
177
+ // Every top-level secret must be consumed by at least one
178
+ // service (an orphan is a defect the offline scan also catches;
179
+ // this real-account row confirms the same on the live compose
180
+ // graph).
181
+ for (const [secretName, consumers] of Object.entries(modes.consumingServicesBySecret)) {
182
+ if (!consumers.length) {
183
+ extraRows.push({
184
+ anchorAcId: 'AC-composeHost-secretShape',
185
+ verdict: 'fail',
186
+ detail: `top-level secret '${secretName}' has no consuming service in the applied compose graph`,
187
+ evidence: { secretName, consumingServices: [], source: 'live docker compose ps + compose.yaml services block' },
188
+ });
189
+ }
190
+ }
191
+ if (extraRows.some((r) => r.verdict === 'fail')) {
192
+ resultRow.verdict = 'fail';
193
+ resultRow.detail = `${resultRow.detail} SECRET MODE observation carries at least one fail row; see evidence.observedSecretModes.`;
194
+ }
195
+ } catch (err) {
196
+ extraRows.push({
197
+ anchorAcId: 'AC-composeHost-secretShape',
198
+ verdict: 'fail',
199
+ detail: `observeSecretModes threw: ${err.message}`,
200
+ evidence: { error: err.message, source: 'docker exec stat -c %a' },
201
+ });
202
+ resultRow.verdict = 'fail';
203
+ resultRow.detail = `${resultRow.detail} SECRET MODE observation threw: ${err.message}.`;
204
+ }
205
+ } catch (err) {
206
+ resultRow.verdict = 'fail';
207
+ resultRow.detail = `minimal-stack-up threw: ${err.message}`;
208
+ evidence.error = err.stack || err.message;
209
+ return { results: [resultRow], extra: evidence };
210
+ } finally {
211
+ if (provisioned && provisioned.id) {
212
+ let tearDownDown = null;
213
+ try {
214
+ tearDownDown = await tearDownStack(provisioned);
215
+ evidence.composeDown = { code: tearDownDown && tearDownDown.code, stderrExcerpt: (tearDownDown && tearDownDown.stderr || '').slice(0, 300) };
216
+ if (tearDownDown && tearDownDown.code !== 0) {
217
+ resultRow.verdict = 'fail';
218
+ resultRow.detail = `${resultRow.detail} TEARDOWN docker compose down exited ${tearDownDown.code}: ${(tearDownDown.stderr || '').slice(0, 300)}`;
219
+ }
220
+ } catch (err) {
221
+ resultRow.verdict = 'fail';
222
+ resultRow.detail = `${resultRow.detail} TEARDOWN docker compose down failed: ${err.message}`;
223
+ evidence.composeDownError = err.message;
224
+ }
225
+ try {
226
+ await destroyThrowawayServer(provisioned);
227
+ evidence.teardown = { destroyed: provisioned.id };
228
+ try {
229
+ const postList = await hcloudJson(['server', 'list', '--output', 'json']);
230
+ evidence.postTeardownServerIds = postList.map((s) => s.id);
231
+ if (postList.some((s) => s.id === provisioned.id)) {
232
+ resultRow.verdict = 'fail';
233
+ resultRow.detail = `${resultRow.detail} TEARDOWN INCOMPLETE: server ${provisioned.id} still present in hcloud server list.`;
234
+ }
235
+ } catch (err) {
236
+ evidence.postTeardownListError = err.message;
237
+ resultRow.verdict = 'fail';
238
+ resultRow.detail = `${resultRow.detail} TEARDOWN CONFIRMATION FAILED: post-teardown hcloud server list threw (${err.message}); cannot confirm server ${provisioned.id} was removed.`;
239
+ }
240
+ } catch (err) {
241
+ resultRow.verdict = 'fail';
242
+ resultRow.detail = `${resultRow.detail} TEARDOWN FAILED for server ${provisioned.id}: ${err.message}.`;
243
+ evidence.teardownError = err.message;
244
+ evidence.orphanServerId = provisioned.id;
245
+ }
246
+ }
247
+ }
248
+ return { results: [resultRow, ...extraRows], extra: evidence };
35
249
  }
36
250
 
37
251
  const engine = { kind: 'throwaway-server', image: 'hetzner cx23 in fsn1 via provision.mjs', healthy: true };
@@ -1,36 +1,222 @@
1
- // Probe: real-account-reload-burst.
2
- //
1
+ // Probe: real-account-reload-burst (v1.1.5).
2
+
3
3
  // anchorAcId: AC-composeHost-zeroDowntimeReload.
4
4
  // accountBound: true.
5
- //
6
- // On the shared throwaway-Hetzner-server fixture with the container-host 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
5
 
14
- import { runShim, accountBoundSkippedResult } from './probe-utils.mjs';
6
+ // Contract:
7
+ // - First-tier gate CI_HAS_HETZNER_ACCOUNT must equal exactly the
8
+ // string "true"; anything else records an honest skip row.
9
+ // - Second-tier HCLOUD_TOKEN missing carries its own honest skip row.
10
+ // - The pass row carries an `evidence` object with the created
11
+ // server id, the warm baseline response, the burst counters (total,
12
+ // 2xx, drops, reload duration), the reload exit and the elicited
13
+ // window (RELOAD_WINDOW_SECONDS, default 10s per AC).
14
+ // - The AC requires the elicited 10-second window to bound the
15
+ // reload duration; a reload that exceeds the window FAILS.
16
+ // - Teardown failure FAILS the verdict (the shape rule).
17
+
18
+ import { spawn } from 'node:child_process';
19
+ import { resolve } from 'node:path';
20
+ import {
21
+ runShim, firstTierGateSkipResult, secondTierMissingSkipResult, FIXTURE_DIR,
22
+ } from './probe-utils.mjs';
15
23
 
16
24
  export const anchorAcId = 'AC-composeHost-zeroDowntimeReload';
17
25
  export const accountBound = true;
18
26
 
27
+ function hcloudJson(argv, { timeoutMs = 60_000 } = {}) {
28
+ return new Promise((resolvePromise, reject) => {
29
+ const p = spawn('hcloud', argv, { stdio: ['ignore', 'pipe', 'pipe'] });
30
+ let stdout = '';
31
+ let stderr = '';
32
+ const timer = setTimeout(() => { try { p.kill('SIGKILL'); } catch (_) {} reject(new Error(`hcloud ${argv.join(' ')} timed out after ${timeoutMs}ms`)); }, timeoutMs);
33
+ p.stdout.on('data', (d) => { stdout += d.toString(); });
34
+ p.stderr.on('data', (d) => { stderr += d.toString(); });
35
+ p.on('error', (err) => { clearTimeout(timer); reject(err); });
36
+ p.on('close', (code) => {
37
+ clearTimeout(timer);
38
+ if (code !== 0) return reject(new Error(`hcloud ${argv.join(' ')} exited ${code}: ${stderr}`));
39
+ const trimmed = stdout.trim();
40
+ if (trimmed.length === 0) return resolvePromise([]);
41
+ try {
42
+ const parsed = JSON.parse(trimmed);
43
+ resolvePromise(Array.isArray(parsed) ? parsed : (parsed.servers || []));
44
+ } catch (err) {
45
+ reject(new Error(`hcloud stdout not JSON: ${err.message}`));
46
+ }
47
+ });
48
+ });
49
+ }
50
+
19
51
  export default async function runProbe() {
20
- const results = [];
21
- const extra = { skipped: process.env.CI_HAS_HETZNER_ACCOUNT !== 'true' };
22
52
  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 };
53
+ return {
54
+ results: [firstTierGateSkipResult(
55
+ anchorAcId,
56
+ 'CI_HAS_HETZNER_ACCOUNT',
57
+ 'real-account reload-burst skipped; run with CI_HAS_HETZNER_ACCOUNT=true to exercise the caddy reload window against a throwaway cx23 stack.',
58
+ )],
59
+ extra: { skipped: true, missingEnv: ['CI_HAS_HETZNER_ACCOUNT'] },
60
+ };
25
61
  }
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 };
62
+ if (!process.env.HCLOUD_TOKEN) {
63
+ return {
64
+ results: [secondTierMissingSkipResult(
65
+ anchorAcId,
66
+ 'HCLOUD_TOKEN',
67
+ 'the throwaway cx23 cannot be provisioned without HCLOUD_TOKEN.',
68
+ )],
69
+ extra: { skipped: true, missingEnv: ['HCLOUD_TOKEN'] },
70
+ };
71
+ }
72
+ const reloadWindowSeconds = Number(process.env.RELOAD_WINDOW_SECONDS ?? 10);
73
+ const reloadWindowMs = Math.round(reloadWindowSeconds * 1000);
74
+ const { provisionThrowawayServer } = await import(resolve(FIXTURE_DIR, 'provision.mjs'));
75
+ const { destroyThrowawayServer } = await import(resolve(FIXTURE_DIR, 'destroy.mjs'));
76
+ const { bringUpStack, reloadBurst, tearDownStack, httpProbeOnServer } = await import(resolve(FIXTURE_DIR, 'src/compose-stack-driver.mjs'));
77
+
78
+ const evidence = { elicitedReloadWindowSeconds: reloadWindowSeconds };
79
+ const resultRow = { anchorAcId, verdict: 'fail', detail: '', evidence };
80
+ let provisioned = null;
81
+ try {
82
+ provisioned = await provisionThrowawayServer({ runId: process.env.GITHUB_RUN_ID ?? `local-${Date.now()}` });
83
+ evidence.serverId = provisioned.id;
84
+ evidence.primaryIpv4 = provisioned.primaryIpv4;
85
+ const brought = await bringUpStack(provisioned);
86
+ evidence.eventTrail = brought.events;
87
+ if (!brought.ok) {
88
+ resultRow.verdict = 'fail';
89
+ resultRow.detail = `stack failed at phase ${brought.phase} on server ${provisioned.id}: ${JSON.stringify(brought).slice(0, 500)}`;
90
+ return { results: [resultRow], extra: evidence };
91
+ }
92
+ const warm = await httpProbeOnServer(provisioned, '/');
93
+ evidence.warm = {
94
+ target: warm.target, statusCode: warm.statusCode,
95
+ bodyExcerpt: warm.bodyExcerpt, elapsedSeconds: warm.elapsedSeconds,
96
+ };
97
+ if (!warm.ok || warm.statusCode !== 200) {
98
+ resultRow.verdict = 'fail';
99
+ resultRow.detail = `caddy did not answer 200 before the burst on ${warm.target}: statusCode=${warm.statusCode} error=${warm.error || 'none'}`;
100
+ return { results: [resultRow], extra: evidence };
101
+ }
102
+ // Zero-downtime reload: undici GETs on the throwaway server
103
+ // (Node global fetch is undici) fired continuously for the
104
+ // elicited reload-window-seconds, wrapping the caddy reload.
105
+ // The burst-request window brackets and per-request timestamps
106
+ // prove the overlap on a single runner clock.
107
+ const burst = await reloadBurst(provisioned, '/', { total: 40, concurrency: 8, mode: 'undici-on-server', reloadWindowMs, burstDurationMs: reloadWindowMs });
108
+ evidence.burst = {
109
+ expectedTotal: burst.expectedTotal,
110
+ total: burst.total,
111
+ twoXx: burst.twoXx, drops: burst.drops,
112
+ reloadDurationMs: burst.reloadDurationMs, reloadExit: burst.reloadExit,
113
+ reloadStartedAt: burst.reloadStartedAt, reloadEndedAt: burst.reloadEndedAt,
114
+ burstStartedAt: burst.burstStartedAt, burstEndedAt: burst.burstEndedAt,
115
+ firstRequestStartedAt: burst.firstRequestStartedAt, lastRequestEndedAt: burst.lastRequestEndedAt,
116
+ burstDurationMs: burst.burstDurationMs,
117
+ burstWindowContainsReloadWindow: burst.burstWindowContainsReloadWindow,
118
+ overlapCount: burst.overlapCount,
119
+ firstOverlapStart: burst.firstOverlapStart, lastOverlapEnd: burst.lastOverlapEnd,
120
+ mode: burst.mode,
121
+ // The fixture returns clockDomain: 'server' to make explicit
122
+ // that every timestamp in the burst object (burstStartedAt,
123
+ // reloadStartedAt, per-request startedAt/endedAt, overlap
124
+ // extrema) originates from the on-server undici script's own
125
+ // Date.now(); the runner does no local-to-remote rebase.
126
+ clockDomain: burst.clockDomain,
127
+ onServerNodeVersion: burst.onServerNodeVersion,
128
+ reloadStderrExcerpt: burst.reloadStderrExcerpt,
129
+ burstStderrExcerpt: burst.burstStderrExcerpt,
130
+ burstParseError: burst.burstParseError,
131
+ elicitedReloadWindowMs: reloadWindowMs,
132
+ };
133
+ if (burst.reloadExit !== 0) {
134
+ resultRow.verdict = 'fail';
135
+ resultRow.detail = `caddy reload exited non-zero (${burst.reloadExit}): ${burst.reloadStderrExcerpt}`;
136
+ return { results: [resultRow], extra: evidence };
137
+ }
138
+ // The duration-based burst runs for the elicited window and
139
+ // fires as many requests as the loopback plus concurrency allow;
140
+ // expectedTotal is a floor (at least this many GETs must be
141
+ // observed inside the window), never a ceiling.
142
+ if (burst.total < burst.expectedTotal) {
143
+ resultRow.verdict = 'fail';
144
+ resultRow.detail = `undici burst produced ${burst.total} outcomes in the ${burst.burstDurationMs}ms burst window, below the ${burst.expectedTotal}-request floor AC-composeHost-zeroDowntimeReload requires.`;
145
+ return { results: [resultRow], extra: evidence };
146
+ }
147
+ if (burst.drops > 0 || burst.twoXx < burst.total) {
148
+ resultRow.verdict = 'fail';
149
+ resultRow.detail = `zero-downtime-reload violated on server ${provisioned.id}: ${burst.twoXx}/${burst.total} 2xx, ${burst.drops} dropped connections during a ${burst.reloadDurationMs}ms reload.`;
150
+ return { results: [resultRow], extra: evidence };
151
+ }
152
+ // Overlap proof: the burst window must contain the reload window
153
+ // (AC-composeHost-zeroDowntimeReload requires undici requests to
154
+ // overlap the reload; the burst being in flight for the whole
155
+ // reload is the strictest reading), and at least one request must
156
+ // have overlapped the reload window.
157
+ if (!burst.burstWindowContainsReloadWindow) {
158
+ resultRow.verdict = 'fail';
159
+ resultRow.detail = `undici burst-request window [${burst.firstRequestStartedAt},${burst.lastRequestEndedAt}] did not contain the reload window [${burst.reloadStartedAt},${burst.reloadEndedAt}]; AC-composeHost-zeroDowntimeReload requires the burst to run WHILE the reload runs.`;
160
+ return { results: [resultRow], extra: evidence };
161
+ }
162
+ if (burst.overlapCount === 0) {
163
+ resultRow.verdict = 'fail';
164
+ resultRow.detail = `undici burst produced ${burst.total} 2xx results but ZERO request windows [startedAt,endedAt] overlapped the reload window [${burst.reloadStartedAt},${burst.reloadEndedAt}]; AC-composeHost-zeroDowntimeReload requires the burst to run WHILE the reload runs.`;
165
+ return { results: [resultRow], extra: evidence };
166
+ }
167
+ if (burst.reloadDurationMs > reloadWindowMs) {
168
+ resultRow.verdict = 'fail';
169
+ resultRow.detail = `caddy reload duration ${burst.reloadDurationMs}ms exceeded the elicited reload-window-seconds ${reloadWindowSeconds}s (${reloadWindowMs}ms); AC-composeHost-zeroDowntimeReload requires the reload to fit inside the elicited window.`;
170
+ return { results: [resultRow], extra: evidence };
171
+ }
172
+ resultRow.verdict = 'pass';
173
+ resultRow.detail = `zero-downtime-reload OBSERVED on server ${provisioned.id}: ${burst.twoXx}/${burst.total} on-server undici 2xx, 0 dropped connections; burst-request window [${burst.firstRequestStartedAt},${burst.lastRequestEndedAt}] contains reload window [${burst.reloadStartedAt},${burst.reloadEndedAt}]; ${burst.overlapCount}/${burst.total} request windows overlap the ${burst.reloadDurationMs}ms reload (under the elicited ${reloadWindowSeconds}s window); warm baseline statusCode=${warm.statusCode}.`;
174
+ } catch (err) {
175
+ resultRow.verdict = 'fail';
176
+ resultRow.detail = `reload-burst threw: ${err.message}`;
177
+ evidence.error = err.stack || err.message;
178
+ return { results: [resultRow], extra: evidence };
179
+ } finally {
180
+ if (provisioned && provisioned.id) {
181
+ try {
182
+ const tearDownDown = await tearDownStack(provisioned);
183
+ evidence.composeDown = { code: tearDownDown && tearDownDown.code, stderrExcerpt: (tearDownDown && tearDownDown.stderr || '').slice(0, 300) };
184
+ if (tearDownDown && tearDownDown.code !== 0) {
185
+ resultRow.verdict = 'fail';
186
+ resultRow.detail = `${resultRow.detail} TEARDOWN docker compose down exited ${tearDownDown.code}: ${(tearDownDown.stderr || '').slice(0, 300)}`;
187
+ }
188
+ } catch (err) {
189
+ resultRow.verdict = 'fail';
190
+ resultRow.detail = `${resultRow.detail} TEARDOWN docker compose down failed: ${err.message}`;
191
+ evidence.composeDownError = err.message;
192
+ }
193
+ try {
194
+ await destroyThrowawayServer(provisioned);
195
+ evidence.teardown = { destroyed: provisioned.id };
196
+ try {
197
+ const postList = await hcloudJson(['server', 'list', '--output', 'json']);
198
+ evidence.postTeardownServerIds = postList.map((s) => s.id);
199
+ if (postList.some((s) => s.id === provisioned.id)) {
200
+ resultRow.verdict = 'fail';
201
+ resultRow.detail = `${resultRow.detail} TEARDOWN INCOMPLETE: server ${provisioned.id} still present in hcloud server list.`;
202
+ }
203
+ } catch (err) {
204
+ evidence.postTeardownListError = err.message;
205
+ resultRow.verdict = 'fail';
206
+ resultRow.detail = `${resultRow.detail} TEARDOWN CONFIRMATION FAILED: post-teardown hcloud server list threw (${err.message}); cannot confirm server ${provisioned.id} was removed.`;
207
+ }
208
+ } catch (err) {
209
+ resultRow.verdict = 'fail';
210
+ resultRow.detail = `${resultRow.detail} TEARDOWN FAILED for server ${provisioned.id}: ${err.message}.`;
211
+ evidence.teardownError = err.message;
212
+ evidence.orphanServerId = provisioned.id;
213
+ }
214
+ }
215
+ }
216
+ return { results: [resultRow], extra: evidence };
31
217
  }
32
218
 
33
- const engine = { kind: 'throwaway-server-burst', image: 'undici burst against caddy in the throwaway compose stack', healthy: true };
219
+ const engine = { kind: 'throwaway-server-burst', image: 'curl burst against caddy in the throwaway compose stack', healthy: true };
34
220
  if (import.meta.url === `file://${process.argv[1]}`) {
35
221
  await runShim('real-account-reload-burst', engine, runProbe);
36
222
  }