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,69 +1,221 @@
1
- // Probe: manifest schema validate.
1
+ // Probe: manifest schema validate (v1.1.8).
2
2
  //
3
- // anchorAcId: AC-37102-1 (also covers AC-37106-1 firewall shape and
4
- // AC-37107-1 snapshot cadence enum via the same schema). accountBound: false.
3
+ // This is an offline schema validator: it reads the shipped fixture
4
+ // manifests and checks them against `hetzner-server.schema.json`.
5
+ // It has no engine-minted identifier - the sha256 of a manifest is
6
+ // computed by this probe with Node's `createHash` and therefore
7
+ // does not satisfy the semantic anatomy identifier rule; the
8
+ // manifest name and JSON path are the probe's own choices.
9
+ // Every result row is a `conformanceOnly` de-claim naming the
10
+ // shipped AC clause the offline check does not observe:
5
11
  //
6
- // Validates every hetzner/servers/*.json under the shared throwaway-server
7
- // fixture against blueprints/deploy-hetzner-server/contributions/schemas/
8
- // hetzner-server.schema.json. A lightweight in-process draft-07 subset
9
- // validator ships with the probe so the shelf gains no runtime dependency
10
- // on ajv or similar. See validate() at the bottom.
12
+ // - AC-37102-1 general nine-required-fields schema shape,
13
+ // - AC-37106-1 firewall rule shape (ssh restricted, 80/443 open,
14
+ // no other inbound),
15
+ // - AC-37107-1 snapshotCadence enum {weekly, daily, off}.
11
16
  //
12
- // Purity: the probe reads only the manifest dir and the shipped schema;
13
- // no process.env.SIMULATE_ switch is read here. The fixture-side shim
14
- // packages/rcf-lite/test/fixtures/hetzner-throwaway-server/
15
- // run-manifest-schema-validate.mjs is the sole reader of
16
- // SIMULATE_MANIFEST_INVALID and it mutates INPUT (a temp manifest dir
17
- // pointed at via RCF_FIXTURE_MANIFEST_DIR) only; the probe then FAILS
18
- // naming the offending field per hetzner-round-7-spec-2026-09-07.md
19
- // section 3.4 lesson 4. (2026-09-08).
17
+ // A single manifest emits ONE row per property, each carrying its
18
+ // own `evidence` object. The hash of the manifest bytes and the
19
+ // validator output stay on the row as derived context.
20
+ //
21
+ // Purity: no process.env.SIMULATE_ switch is read. Fixture-side
22
+ // mutations live in the fixture-side run-manifest-schema-validate.mjs
23
+ // shim; the probe reads only the schema and manifest tree.
20
24
 
21
25
  import { readFile } from 'node:fs/promises';
26
+ import { createHash } from 'node:crypto';
22
27
  import { readManifestFiles, SCHEMA_PATH } from './probe-utils.mjs';
23
28
 
24
- export const anchorAcId = 'AC-37102-1';
29
+ function sha256(text) {
30
+ return createHash('sha256').update(text, 'utf8').digest('hex');
31
+ }
32
+
33
+ export const anchorAcId = null;
25
34
  export const accountBound = false;
26
35
 
36
+ const NINE_REQUIRED = [
37
+ 'name', 'serverType', 'location', 'image', 'sshKeyIds',
38
+ 'firewallId', 'cloudInitPath', 'labels', 'firewallRules', 'snapshotCadence',
39
+ ];
40
+
41
+ const LIMIT_37102 = 'AC-37102-1: manifest schema shape is validated offline against the shipped hetzner-server.schema.json; the live observation (a real-account apply that consumes the same manifest) is carried by real-account-throwaway-server-provision.';
42
+ const LIMIT_37106 = 'AC-37106-1: firewall rule shape is validated offline against the shipped schema and the TAC-3804 binding; the live-account observation (a `hcloud firewall describe` on the applied firewall) would live on a real-account firewall probe.';
43
+ const LIMIT_37107 = 'AC-37107-1: snapshotCadence enum is validated offline against the shipped schema enum; the live observation (a real-account server label matching the manifest cadence) lives on real-account-snapshot-on-demand.';
44
+
27
45
  export default async function runProbe() {
28
46
  const schema = JSON.parse(await readFile(SCHEMA_PATH, 'utf8'));
29
47
  const { present, files } = await readManifestFiles();
30
48
  if (!present) {
31
49
  return {
32
50
  results: [{
33
- anchorAcId,
51
+ anchorAcId: null,
52
+ conformanceOnly: true,
53
+ limitation: LIMIT_37102,
34
54
  verdict: 'fail',
35
- detail: 'fixture hetzner/servers/ holds zero JSON files; ship at least ci-throwaway.json.',
55
+ detail: 'offline manifest scan: fixture hetzner/servers/ holds zero JSON files; ship at least ci-throwaway.json.',
56
+ evidence: { manifestCount: 0 },
36
57
  }],
37
58
  };
38
59
  }
39
60
  const results = [];
40
61
  for (const f of files) {
62
+ const manifestSha256 = sha256(f.text);
41
63
  let doc;
42
64
  try {
43
65
  doc = JSON.parse(f.text);
44
66
  } catch (err) {
45
67
  results.push({
46
- anchorAcId,
68
+ anchorAcId: null,
69
+ conformanceOnly: true,
70
+ limitation: LIMIT_37102,
47
71
  verdict: 'fail',
48
- detail: `manifest ${f.name} does not parse: ${err.message}`,
72
+ detail: `offline manifest scan: manifest ${f.name} does not parse: ${err.message}`,
73
+ evidence: { manifestSha256, manifestName: f.name, parseError: err.message },
49
74
  });
50
75
  continue;
51
76
  }
52
77
  const errors = validate(schema, doc, `#/${f.name}`);
53
- if (errors.length > 0) {
54
- for (const e of errors) {
55
- const anchor = anchorForError(e);
78
+ // General schema errors that are neither firewall- nor snapshot-
79
+ // scoped anchor to AC-37102-1 (as their limitation).
80
+ const generalErrors = errors.filter((e) => (
81
+ e.field !== 'firewallRules' && !(e.path || '').includes('firewallRules')
82
+ && e.field !== 'snapshotCadence' && !(e.path || '').includes('snapshotCadence')
83
+ ));
84
+ if (generalErrors.length > 0) {
85
+ for (const e of generalErrors) {
56
86
  results.push({
57
- anchorAcId: anchor,
87
+ anchorAcId: null,
88
+ conformanceOnly: true,
89
+ limitation: LIMIT_37102,
58
90
  verdict: 'fail',
59
- detail: `manifest ${f.name} schema violation at ${e.path}: ${e.message}`,
91
+ detail: `offline manifest scan: manifest ${f.name} schema violation at ${e.path}: ${e.message}`,
92
+ evidence: { manifestSha256, manifestName: f.name, jsonPath: e.path, message: e.message, field: e.field || null },
60
93
  });
61
94
  }
62
95
  } else {
96
+ const observedKeys = Object.keys(doc).sort();
63
97
  results.push({
64
- anchorAcId,
98
+ anchorAcId: null,
99
+ conformanceOnly: true,
100
+ limitation: LIMIT_37102,
65
101
  verdict: 'pass',
66
- detail: `manifest ${f.name} validates against hetzner-server.schema.json (nine required fields, firewall rule shape, snapshotCadence enum all satisfied).`,
102
+ detail: `offline manifest scan: manifest ${f.name} carries the nine required fields per hetzner-server.schema.json.`,
103
+ evidence: {
104
+ manifestSha256,
105
+ manifestName: f.name,
106
+ requiredFields: NINE_REQUIRED,
107
+ observedKeys,
108
+ },
109
+ });
110
+ }
111
+ const firewallErrors = errors.filter((e) => e.field === 'firewallRules' || (e.path || '').includes('firewallRules'));
112
+ if (firewallErrors.length > 0) {
113
+ for (const e of firewallErrors) {
114
+ results.push({
115
+ anchorAcId: null,
116
+ conformanceOnly: true,
117
+ limitation: LIMIT_37106,
118
+ verdict: 'fail',
119
+ detail: `offline firewall shape scan: manifest ${f.name} firewall rule shape violation at ${e.path}: ${e.message}`,
120
+ evidence: { manifestSha256, manifestName: f.name, jsonPath: e.path, message: e.message },
121
+ });
122
+ }
123
+ } else if (Array.isArray(doc.firewallRules)) {
124
+ const rules = doc.firewallRules;
125
+ const REQUIRED_BINDING = {
126
+ ssh: { protocol: 'tcp', direction: 'in', port: 22, sourceMustOpen: false },
127
+ http: { protocol: 'tcp', direction: 'in', port: 80, sourceMustOpen: true },
128
+ https: { protocol: 'tcp', direction: 'in', port: 443, sourceMustOpen: true },
129
+ };
130
+ const nameCounts = {};
131
+ for (const r of rules) if (r && typeof r.name === 'string') nameCounts[r.name] = (nameCounts[r.name] || 0) + 1;
132
+ const duplicates = Object.entries(nameCounts).filter(([, n]) => n > 1).map(([n]) => n);
133
+ const bindingErrors = [];
134
+ const bindingEvidence = {};
135
+ for (const [name, want] of Object.entries(REQUIRED_BINDING)) {
136
+ const rule = rules.find((r) => r && r.name === name);
137
+ if (!rule) {
138
+ bindingErrors.push(`missing required rule '${name}'`);
139
+ continue;
140
+ }
141
+ const observed = {
142
+ name, protocol: rule.protocol, direction: rule.direction,
143
+ port: rule.port, sourceIps: Array.isArray(rule.sourceIps) ? rule.sourceIps : [],
144
+ };
145
+ bindingEvidence[name] = observed;
146
+ if (rule.protocol !== want.protocol) bindingErrors.push(`'${name}' protocol '${rule.protocol}' != required '${want.protocol}'`);
147
+ if (rule.direction !== want.direction) bindingErrors.push(`'${name}' direction '${rule.direction}' != required '${want.direction}'`);
148
+ if (rule.port !== want.port) bindingErrors.push(`'${name}' port ${rule.port} != required ${want.port}`);
149
+ if (!Array.isArray(rule.sourceIps) || rule.sourceIps.length === 0) {
150
+ bindingErrors.push(`'${name}' sourceIps empty or not array`);
151
+ } else if (want.sourceMustOpen) {
152
+ const hasOpen = rule.sourceIps.includes('0.0.0.0/0');
153
+ if (!hasOpen) bindingErrors.push(`'${name}' must include '0.0.0.0/0' per open-service contract`);
154
+ } else if (name === 'ssh') {
155
+ const openLeak = rule.sourceIps.filter((s) => s === '0.0.0.0/0' || s === '::/0');
156
+ if (openLeak.length > 0) bindingErrors.push(`'ssh' sourceIps must not include ${openLeak.join(', ')}; use operator-nominated set per TAC-3804`);
157
+ }
158
+ }
159
+ if (duplicates.length > 0) bindingErrors.push(`duplicate rule names: ${duplicates.join(', ')}`);
160
+ if (bindingErrors.length > 0) {
161
+ results.push({
162
+ anchorAcId: null,
163
+ conformanceOnly: true,
164
+ limitation: LIMIT_37106,
165
+ verdict: 'fail',
166
+ detail: `offline firewall shape scan: manifest ${f.name} firewall rule shape violation: ${bindingErrors.join('; ')}.`,
167
+ evidence: {
168
+ manifestSha256,
169
+ manifestName: f.name,
170
+ ruleNames: rules.map((r) => r && r.name).filter(Boolean),
171
+ observedBinding: bindingEvidence,
172
+ duplicates,
173
+ errors: bindingErrors,
174
+ },
175
+ });
176
+ } else {
177
+ const ssh = rules.find((r) => r && r.name === 'ssh');
178
+ results.push({
179
+ anchorAcId: null,
180
+ conformanceOnly: true,
181
+ limitation: LIMIT_37106,
182
+ verdict: 'pass',
183
+ detail: `offline firewall shape scan: manifest ${f.name} firewall rule shape valid: ssh (tcp/in/22, restricted to ${(ssh && ssh.sourceIps || []).join(', ')}, no 0.0.0.0/0), http (tcp/in/80, open), https (tcp/in/443, open); no duplicates.`,
184
+ evidence: {
185
+ manifestSha256,
186
+ manifestName: f.name,
187
+ ruleNames: rules.map((r) => r && r.name).filter(Boolean),
188
+ observedBinding: bindingEvidence,
189
+ duplicates: [],
190
+ },
191
+ });
192
+ }
193
+ }
194
+ const snapshotErrors = errors.filter((e) => e.field === 'snapshotCadence' || (e.path || '').includes('snapshotCadence'));
195
+ if (snapshotErrors.length > 0) {
196
+ for (const e of snapshotErrors) {
197
+ results.push({
198
+ anchorAcId: null,
199
+ conformanceOnly: true,
200
+ limitation: LIMIT_37107,
201
+ verdict: 'fail',
202
+ detail: `offline snapshotCadence scan: manifest ${f.name} snapshotCadence violation at ${e.path}: ${e.message}`,
203
+ evidence: { manifestSha256, manifestName: f.name, jsonPath: e.path, message: e.message },
204
+ });
205
+ }
206
+ } else if (typeof doc.snapshotCadence === 'string') {
207
+ results.push({
208
+ anchorAcId: null,
209
+ conformanceOnly: true,
210
+ limitation: LIMIT_37107,
211
+ verdict: 'pass',
212
+ detail: `offline snapshotCadence scan: manifest ${f.name} snapshotCadence "${doc.snapshotCadence}" is in the shipped enum {weekly, daily, off}.`,
213
+ evidence: {
214
+ manifestSha256,
215
+ manifestName: f.name,
216
+ snapshotCadence: doc.snapshotCadence,
217
+ shippedEnum: ['weekly', 'daily', 'off'],
218
+ },
67
219
  });
68
220
  }
69
221
  }
@@ -76,20 +228,8 @@ export default async function runProbe() {
76
228
  };
77
229
  }
78
230
 
79
- function anchorForError(err) {
80
- if (err.field === 'firewallRules' || (err.path || '').includes('firewallRules')) {
81
- return 'AC-37106-1';
82
- }
83
- if (err.field === 'snapshotCadence' || (err.path || '').includes('snapshotCadence')) {
84
- return 'AC-37107-1';
85
- }
86
- return 'AC-37102-1';
87
- }
88
-
89
- // Draft-07 subset validator: required, type, enum, minLength, minItems,
90
- // additionalProperties, items, properties, required-on-array-items.
91
- // Extra rule: on firewallRules the ssh rule sourceIps must NOT include
92
- // 0.0.0.0/0 (per TAC-3804); handled after schema validation.
231
+ // Draft-07 subset validator (unchanged from v1.1.3 apart from the
232
+ // caller splitting per-property).
93
233
  export function validate(schema, doc, pathPrefix = '#') {
94
234
  const errors = [];
95
235
  walk(schema, doc, pathPrefix, errors);
@@ -112,6 +252,35 @@ export function validate(schema, doc, pathPrefix = '#') {
112
252
  });
113
253
  }
114
254
  }
255
+ // Reject duplicate rule names (defect: firewall
256
+ // validation must prohibit duplicates).
257
+ const counts = {};
258
+ for (const r of doc.firewallRules) if (r && typeof r.name === 'string') counts[r.name] = (counts[r.name] || 0) + 1;
259
+ for (const [name, n] of Object.entries(counts)) {
260
+ if (n > 1) {
261
+ errors.push({
262
+ path: `${pathPrefix}/firewallRules`,
263
+ field: 'firewallRules',
264
+ message: `firewallRules contains a duplicate rule named '${name}' (${n} occurrences); each of {ssh, http, https} must appear exactly once.`,
265
+ });
266
+ }
267
+ }
268
+ // Bind each required rule name to protocol/direction/port
269
+ // (defect).
270
+ const bindings = { ssh: { protocol: 'tcp', direction: 'in', port: 22 }, http: { protocol: 'tcp', direction: 'in', port: 80 }, https: { protocol: 'tcp', direction: 'in', port: 443 } };
271
+ for (const [name, want] of Object.entries(bindings)) {
272
+ const rule = doc.firewallRules.find((r) => r && r.name === name);
273
+ if (!rule) continue;
274
+ for (const k of ['protocol', 'direction', 'port']) {
275
+ if (rule[k] !== want[k]) {
276
+ errors.push({
277
+ path: `${pathPrefix}/firewallRules/${name}/${k}`,
278
+ field: 'firewallRules',
279
+ message: `firewallRules '${name}' ${k} '${rule[k]}' does not match required '${want[k]}' per TAC-3804.`,
280
+ });
281
+ }
282
+ }
283
+ }
115
284
  }
116
285
  return errors;
117
286
  }
@@ -1,4 +1,12 @@
1
- // Shared helpers for deploy-hetzner-server probes.
1
+ // Shared helpers for deploy-hetzner-server probes (v1.1.4, criterion e
2
+ // v1.1.5, 2026-09-11).
3
+ //
4
+ // Every result row a probe returns MUST carry either an `evidence`
5
+ // object naming the observed artefact (server id, inventory-diff,
6
+ // response body excerpt, deploy record) OR `accountBoundSkipped: true`
7
+ // with a `reason` field naming exactly one unset variable. Empty or
8
+ // null probe outcomes FAIL with detail exactly `no checks ran` per
9
+ // binding rule 3 of the criterion e .
2
10
  //
3
11
  // Runtime-dependency posture:
4
12
  // - cloud-init-render-lint, manifest-schema-validate and
@@ -7,9 +15,10 @@
7
15
  // server/. No real API call fires; hcloud is mocked via
8
16
  // src/hcloud-mock.mjs so the shim never crosses the process boundary.
9
17
  // - real-account-* probes call the fixture's provision.mjs / destroy.mjs
10
- // / snapshot verbs. Without CI_HAS_HETZNER_ACCOUNT they record
11
- // accountBoundSkipped: true and the aggregate flips to pass per
12
- // hetzner-round-7-spec-2026-09-07.md section 3.5.
18
+ // / snapshot verbs. Without CI_HAS_HETZNER_ACCOUNT set to exactly the
19
+ // string "true", each probe records accountBoundSkipped: true and a
20
+ // reason naming CI_HAS_HETZNER_ACCOUNT (set-but-not-true is reported
21
+ // as such, distinguished from unset).
13
22
 
14
23
  import { mkdir, writeFile, readFile, readdir } from 'node:fs/promises';
15
24
  import { dirname, resolve, join } from 'node:path';
@@ -21,39 +30,83 @@ export const FIXTURE_DIR = resolve(
21
30
  PROJECT_ROOT,
22
31
  'packages/rcf-lite/test/fixtures/hetzner-throwaway-server',
23
32
  );
24
- // Config override, not a mutation switch: the fixture-side shim for
25
- // manifest-schema-validate may write a mutated copy to a scratch dir
26
- // and point MANIFEST_DIR at it via RCF_FIXTURE_MANIFEST_DIR so the
27
- // probe stays SIMULATE-free (mutation-purity gate row, 2026-09-08).
28
33
  export const MANIFEST_DIR = process.env.RCF_FIXTURE_MANIFEST_DIR
29
34
  ? resolve(process.env.RCF_FIXTURE_MANIFEST_DIR)
30
35
  : resolve(FIXTURE_DIR, 'hetzner/servers');
31
36
  export const SCHEMA_PATH = resolve(HERE, '..', 'schemas', 'hetzner-server.schema.json');
32
- export const REPORT_DIR = resolve(
33
- PROJECT_ROOT,
34
- '.rcf/reports/blueprints/deploy-hetzner-server',
35
- );
37
+ export const REPORT_DIR = process.env.RCF_REPORT_DIR_OVERRIDE
38
+ ? resolve(process.env.RCF_REPORT_DIR_OVERRIDE, 'blueprints/deploy-hetzner-server')
39
+ : resolve(PROJECT_ROOT, '.rcf/reports/blueprints/deploy-hetzner-server');
40
+ export const BLUEPRINT_JSON_PATH = resolve(HERE, '..', '..', 'blueprint.json');
36
41
 
42
+ // The report's `version` field is read from the blueprint's own
43
+ // blueprint.json at write time; every regenerated record therefore
44
+ // carries the version the shipped code was at when the record was
45
+ // written. The strict walker compares each record's `version` to
46
+ // blueprint.json's `version` and FAILS on any mismatch (a record
47
+ // at an older version fails the walk). The read is deliberately
48
+ // per-call so a version bump between two writes in one process is
49
+ // picked up honestly.
50
+ async function readBlueprintVersion() {
51
+ const raw = await readFile(BLUEPRINT_JSON_PATH, 'utf8');
52
+ const doc = JSON.parse(raw);
53
+ if (typeof doc.version !== 'string' || doc.version.length === 0) {
54
+ throw new Error(`blueprint.json at ${BLUEPRINT_JSON_PATH} carries no string version`);
55
+ }
56
+ return doc.version;
57
+ }
58
+
59
+ // Aggregation rule (the shape rule): an empty results array is never
60
+ // pass; it is a fail with detail `no checks ran`. Callers hand the
61
+ // empty case a synthesised fail row via `emptyResultsFail()` before
62
+ // aggregating so the report body itself carries the row.
37
63
  export function aggregate(results) {
64
+ if (!Array.isArray(results) || results.length === 0) return 'fail';
38
65
  if (results.some((r) => r.verdict === 'fail')) return 'fail';
39
66
  if (results.some((r) => r.verdict === 'warn')) return 'warn';
40
67
  return 'pass';
41
68
  }
42
69
 
70
+ // An empty results array is an honest failure of the probe: no anchor
71
+ // can be manufactured. Callers that KNOW the anchor may pass it in;
72
+ // otherwise the row carries anchorAcId: null so downstream tallies do
73
+ // not see an invented AC id.
74
+ export function emptyResultsFail(anchorAcId = null) {
75
+ return {
76
+ anchorAcId: anchorAcId ?? null,
77
+ verdict: 'fail',
78
+ detail: 'no checks ran',
79
+ evidence: { reason: 'the probe returned zero result rows', probeName: '(unknown at empty-fail construction)' },
80
+ };
81
+ }
82
+
43
83
  export function isSkipped(results) {
44
- return results.length > 0 && results.every((r) => r.accountBoundSkipped === true);
84
+ return Array.isArray(results) && results.length > 0 && results.every((r) => r.accountBoundSkipped === true);
45
85
  }
46
86
 
47
87
  export async function writeReport({ probeName, engine, results, extra }) {
48
88
  await mkdir(REPORT_DIR, { recursive: true });
49
- const rawVerdict = aggregate(results);
50
- const aggregateVerdict = isSkipped(results) ? 'pass' : rawVerdict;
89
+ const rows = Array.isArray(results) && results.length > 0 ? results : [emptyResultsFail()];
90
+ // the anchor-prefix rule: every row's detail starts with the first eight
91
+ // words of the anchored AC text. The prepend is idempotent so a
92
+ // caller that already wrapped its detail via `anchored()` does not
93
+ // double up.
94
+ for (const r of rows) {
95
+ const prefix = r && r.anchorAcId && AC_ANCHOR_PREFIX[r.anchorAcId];
96
+ if (prefix && typeof r.detail === 'string' && !r.detail.startsWith(prefix)) {
97
+ r.detail = `${prefix}. ${r.detail}`;
98
+ }
99
+ }
100
+ const rawVerdict = aggregate(rows);
101
+ const aggregateVerdict = isSkipped(rows) ? 'pass' : rawVerdict;
102
+ const version = await readBlueprintVersion();
51
103
  const report = {
52
104
  slug: 'deploy-hetzner-server',
53
105
  probeName,
106
+ version,
54
107
  runAt: new Date().toISOString(),
55
108
  engine,
56
- results,
109
+ results: rows,
57
110
  aggregateVerdict,
58
111
  ...(extra ?? {}),
59
112
  };
@@ -64,17 +117,27 @@ export async function writeReport({ probeName, engine, results, extra }) {
64
117
 
65
118
  export async function runShim(probeName, engine, mainFn) {
66
119
  try {
67
- const outcome = (await mainFn()) ?? { results: [] };
68
- const { results, extra } = outcome;
69
- const { report, path } = await writeReport({ probeName, engine, results, extra });
120
+ const outcome = await mainFn();
121
+ const results = (outcome && Array.isArray(outcome.results)) ? outcome.results : null;
122
+ const extra = outcome && outcome.extra;
123
+ const rows = results && results.length > 0 ? results : [emptyResultsFail()];
124
+ const { report, path } = await writeReport({ probeName, engine, results: rows, extra });
70
125
  process.stdout.write(JSON.stringify(report, null, 2) + '\n');
71
126
  process.stdout.write(`report written to ${path}\n`);
72
127
  if (report.aggregateVerdict === 'fail') process.exitCode = 1;
73
128
  } catch (err) {
129
+ // A probe that throws has no known anchor at this layer; use null
130
+ // rather than the invented "unknown" fallback (defect).
131
+ // The runShim caller carries the probeName so evidence names it.
74
132
  const results = [{
75
- anchorAcId: 'unknown',
133
+ anchorAcId: null,
76
134
  verdict: 'fail',
77
135
  detail: `probe threw: ${err && err.message ? err.message : String(err)}`,
136
+ evidence: {
137
+ probeName,
138
+ errorMessage: err && err.message ? err.message : String(err),
139
+ errorStack: (err && err.stack ? err.stack : String(err)).slice(0, 800),
140
+ },
78
141
  }];
79
142
  const { report, path } = await writeReport({ probeName, engine, results });
80
143
  process.stdout.write(JSON.stringify(report, null, 2) + '\n');
@@ -102,11 +165,66 @@ export async function readManifestFiles(dir = MANIFEST_DIR) {
102
165
  return { present: entries.length > 0, entries, files };
103
166
  }
104
167
 
105
- export function accountBoundSkippedResult(anchorAcId, note) {
168
+ // Skip helper (the shape rule): the reason field names exactly one
169
+ // unset variable. A gate variable set to a value other than 'true'
170
+ // is reported as `set-but-not-true` with the observed value, not as
171
+ // `unset`. Callers hand the exact variable name and a short note.
172
+ export function firstTierGateSkipResult(anchorAcId, varName = 'CI_HAS_HETZNER_ACCOUNT', note = '') {
173
+ const observed = process.env[varName];
174
+ const state = observed === undefined
175
+ ? `unset`
176
+ : `set-but-not-true (observed value ${JSON.stringify(observed)})`;
106
177
  return {
107
178
  anchorAcId,
108
179
  verdict: 'skipped',
109
180
  accountBoundSkipped: true,
110
- detail: `accountBound: CI_HAS_HETZNER_ACCOUNT unset; ${note}`,
181
+ reason: varName,
182
+ gateState: state,
183
+ detail: `accountBoundSkipped: gate variable ${varName} ${state}; ${note || 'run with CI_HAS_HETZNER_ACCOUNT=true to exercise the account-bound branch.'}`,
111
184
  };
112
185
  }
186
+
187
+ // Second-tier skip helper (the shape rule): the account-bound branch
188
+ // requires HCLOUD_TOKEN once the first-tier gate is true. When only the
189
+ // second-tier is missing, the skip row names HCLOUD_TOKEN in `reason`,
190
+ // carries accountBoundSkipped: true, and the aggregate still flips to
191
+ // pass. Missing configuration is a skip, not a failure.
192
+ export function secondTierMissingSkipResult(anchorAcId, varName, note = '') {
193
+ return {
194
+ anchorAcId,
195
+ verdict: 'skipped',
196
+ accountBoundSkipped: true,
197
+ reason: varName,
198
+ gateState: 'unset',
199
+ detail: `accountBoundSkipped: second-tier variable ${varName} unset while CI_HAS_HETZNER_ACCOUNT=true; ${note || 'the probe cannot open the vendor client.'}`,
200
+ };
201
+ }
202
+
203
+ // Legacy shim (kept during the update cutover for callers not yet
204
+ // updated). Prefer firstTierGateSkipResult / secondTierMissingSkipResult.
205
+ export function accountBoundSkippedResult(anchorAcId, note) {
206
+ return firstTierGateSkipResult(anchorAcId, 'CI_HAS_HETZNER_ACCOUNT', note);
207
+ }
208
+
209
+ // the anchor-prefix rule: every result row's detail starts with the first
210
+ // eight words of the anchored AC text. This map holds those prefixes
211
+ // for the deploy-hetzner-server ACs and the shared AC-14501-1 chain
212
+ // artefact (used elsewhere in the estate); callers wrap their detail
213
+ // via `anchored(anchorAcId, detail)`.
214
+ export const AC_ANCHOR_PREFIX = {
215
+ 'AC-37101-1': 'On process boot the provisioner facade opens against',
216
+ 'AC-37102-1': 'manifest-schema-validate.mjs asserts every hetzner/servers/*.json under the shared throwaway-server',
217
+ 'AC-37103-1': 'The real-account-throwaway-server-provision probe (accountBound: true, skipped without CI_HAS_HETZNER_ACCOUNT)',
218
+ 'AC-37104-1': 'cloud-init-render-lint.mjs renders the template with the fixture manifest',
219
+ 'AC-37105-1': 'real-account-cloud-init-hardened.mjs (accountBound: true, skipped without CI_HAS_HETZNER_ACCOUNT) waits for',
220
+ 'AC-37106-1': 'manifest-schema-validate.mjs asserts every fixture manifest carries a firewallRules',
221
+ 'AC-37107-1': 'manifest-schema-validate.mjs asserts every fixture manifest carries snapshotCadence with',
222
+ 'AC-37108-1': 'real-account-snapshot-on-demand.mjs (accountBound: true, skipped without CI_HAS_HETZNER_ACCOUNT) fires the',
223
+ 'AC-37109-1': 'hcloud-dry-run-mock.mjs drives every lifecycle event through the facade',
224
+ 'AC-37109-3': 'Event fires once per lifecycle moment (repeat-run idempotency).',
225
+ };
226
+
227
+ export function anchored(anchorAcId, body) {
228
+ const prefix = AC_ANCHOR_PREFIX[anchorAcId];
229
+ return prefix ? `${prefix}. ${body}` : body;
230
+ }