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
@@ -0,0 +1,65 @@
1
+ // application-empty-error-states probe: error-boundary state
2
+ // (AC-22108-1). AC-22108-1 explicitly permits the sample-app
3
+ // /probe/error-boundary?crash=1 route as the observation trigger; the
4
+ // probe drives that route and observes the active crash state
5
+ // (role="alert" region, [data-recovery="retry"] control, class-level
6
+ // error label). The prior standby-absence row was removed under the
7
+ // positive-anchor cleanup (positive-anchor on absence is void).
8
+
9
+ import { fixtureFetch, startFixture, excerpt } from './probe-utils.mjs';
10
+
11
+ export const anchorAcId = 'application-empty-error-states-AC-22108-1';
12
+ export const accountBound = false;
13
+
14
+ function stripHtml(html) {
15
+ return String(html)
16
+ .replace(/<script[^]*?<\/script>/gi, ' ')
17
+ .replace(/<style[^]*?<\/style>/gi, ' ')
18
+ .replace(/<[^>]+>/g, ' ')
19
+ .replace(/\s+/g, ' ')
20
+ .trim();
21
+ }
22
+
23
+ function stackFramePresent(text) {
24
+ // Backtrace frame ("at fn (file:line:col)"), a source path ending in
25
+ // a JS-family extension, an env-var key shape, or a node_modules
26
+ // segment. Correlation-id tokens are not stack frames.
27
+ if (/\bat\s+[A-Za-z_$][A-Za-z0-9_$.]*\s*\([^)]+:\d+:\d+\)/.test(text)) return true;
28
+ if (/(^|\s)(\.\.?\/|\/)[A-Za-z0-9_./-]+\.(js|mjs|cjs|ts|tsx|jsx)\b/i.test(text)) return true;
29
+ if (/process\.env\.[A-Z_][A-Z0-9_]*/.test(text)) return true;
30
+ if (/\bnode_modules\//.test(text)) return true;
31
+ return false;
32
+ }
33
+
34
+ export default async function runProbe() {
35
+ const fixture = await startFixture();
36
+ const results = [];
37
+ try {
38
+ const crash = await fixtureFetch(fixture.url, '/probe/error-boundary?crash=1');
39
+ const surfaceText = stripHtml(crash.body);
40
+ const alertRegion = /data-surface="error-boundary"[^>]*role="alert"/.test(crash.body);
41
+ const retryControl = /data-recovery="retry"/.test(crash.body);
42
+ const errorClass = /data-error-class="render-failure"/.test(crash.body);
43
+ const plainSummary = /Widget failed to render/.test(surfaceText);
44
+ const noStack = !stackFramePresent(surfaceText);
45
+ const crashPass = crash.status === 200 && !!crash.requestId && alertRegion && retryControl && errorClass && plainSummary && noStack;
46
+ results.push({
47
+ anchorAcId: null,
48
+ conformanceOnly: true,
49
+ limitation: 'application-empty-error-states-AC-22108-1: varied-input plain-summary derivation against a shipped origin (framework internal frames, arbitrary env keys the origin might have leaked) is not observed by this Node HTTP probe against a fixed fixture; the error-boundary alert + retry + error-class + plain-summary + no-stack-frame walk is a partial observation of AC-22108-1',
50
+ verdict: crashPass ? 'warn' : 'fail',
51
+ detail: crashPass
52
+ ? `Given a synthetic client-side render exception thrown via the sample-app /probe/error-boundary?crash=1 route: observed role="alert" region, [data-recovery="retry"] control, data-error-class="render-failure" label and plain summary "Widget failed to render" on the rendered surface; no stack-frame pattern hit; x-fixture-request-id=${crash.requestId}`
53
+ : `Given a synthetic client-side render exception thrown via /probe/error-boundary?crash=1 (evidence gap): status=${crash.status} rid=${crash.requestId} alert=${alertRegion} retry=${retryControl} errorClass=${errorClass} summary=${plainSummary} noStack=${noStack}`,
54
+ evidence: {
55
+ requestId: crash.requestId,
56
+ responseStatus: crash.status,
57
+ bodyExcerpt: excerpt(surfaceText),
58
+ derived: { alertRegion, retryControl, errorClass, plainSummary, noStack },
59
+ },
60
+ });
61
+ } finally {
62
+ await fixture.kill();
63
+ }
64
+ return { results };
65
+ }
@@ -0,0 +1,167 @@
1
+ // application-empty-error-states probe: 403 forbidden and 500 server
2
+ // error states (AC-22102-1, AC-22103-1).
3
+ //
4
+ // AC-22102-1 requires the forbidden state to render inside role="region"
5
+ // with a keyboard-reachable [data-action="request-access"] control that
6
+ // POSTs to /api/request-access; the rendered surface must NOT contain
7
+ // any sensitive-pattern hit (resource id shape, resource name shape,
8
+ // path-shape strings starting with /).
9
+ //
10
+ // AC-22103-1 requires the server-error state to render inside
11
+ // role="region" with a keyboard-reachable [data-recovery="retry"] control;
12
+ // the rendered surface must NOT contain a backtrace-frame prefix
13
+ // ("at " + function + file:line), a source path starting with /, ./
14
+ // or ../, an environment-variable key shape (NAME= or process.env.NAME),
15
+ // or a framework-internal frame prefix.
16
+ //
17
+ // Positive-anchor rows only: broken-variant rows on absence were removed
18
+ // under the positive-anchor cleanup (they positively-anchor on absence and are void).
19
+
20
+ import { fixtureFetch, startFixture, excerpt } from './probe-utils.mjs';
21
+ import { randomUUID } from 'node:crypto';
22
+
23
+ export const anchorAcId = 'application-empty-error-states-AC-22102-1';
24
+ export const accountBound = false;
25
+
26
+ function stripHtml(html) {
27
+ return String(html)
28
+ .replace(/<script[^]*?<\/script>/gi, ' ')
29
+ .replace(/<style[^]*?<\/style>/gi, ' ')
30
+ .replace(/<[^>]+>/g, ' ')
31
+ .replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&#39;/g, "'")
32
+ .replace(/\s+/g, ' ')
33
+ .trim();
34
+ }
35
+
36
+ function forbiddenSensitiveHit(text) {
37
+ // Sensitive-pattern list per AC-22102-1: resource id shape (kind-digits-slug,
38
+ // e.g. widget-2039-alpha), a resource-name slug (kind-slug-slug preceded
39
+ // by resource identifiers), or a URL path-shape string with 2+ segments.
40
+ // A request-id shape (letters-letters-digits) is a correlation id, not a
41
+ // resource id, and is not sensitive.
42
+ if (/\b[a-z]+-\d{3,}-[a-z][a-z0-9]*\b/i.test(text)) return true;
43
+ if (/\b(resource|id|widget|entity)=[a-z0-9-]+/i.test(text)) return true;
44
+ if (/(^|\s)\/[a-z][a-z0-9_-]+\/[a-z0-9_-]+/i.test(text)) return true;
45
+ return false;
46
+ }
47
+
48
+ function serverErrorSensitiveHit(text) {
49
+ // Sensitive-pattern list per AC-22103-1: backtrace frame, source
50
+ // path (with file extension), env-var key shape (either process.env.NAME
51
+ // or a bare NAME=value form), framework-internal frame. Correlation-id
52
+ // tokens without file:line context are not stack frames and are ignored.
53
+ if (/\bat\s+[A-Za-z_$][A-Za-z0-9_$.]*\s*\([^)]+:\d+:\d+\)/.test(text)) return true;
54
+ if (/(^|\s)(\.\.?\/|\/)[A-Za-z0-9_./-]+\.(js|mjs|cjs|ts|tsx|jsx)\b/i.test(text)) return true;
55
+ if (/process\.env\.[A-Z_][A-Z0-9_]*/.test(text)) return true;
56
+ // Bare NAME=value: an uppercase env-key style token followed by '=' and a
57
+ // non-whitespace value. Matches leaked lines like "DB_PASSWORD=hunter2"
58
+ // that a naive error handler might have echoed back to the surface.
59
+ if (/(^|[^A-Z0-9_])[A-Z][A-Z0-9_]{2,}=[^\s]+/.test(text)) return true;
60
+ if (/\bnode_modules\//.test(text)) return true;
61
+ return false;
62
+ }
63
+
64
+ export default async function runProbe() {
65
+ const fixture = await startFixture();
66
+ const results = [];
67
+ try {
68
+ // Mint varied sensitive tokens per run and inject them into the
69
+ // request that drives the 403. The confidentiality property under
70
+ // AC-22102-1 holds when none of the injected tokens appears in the
71
+ // rendered error copy (a real varied-input observation, not a fixed
72
+ // safe-copy self-agreement).
73
+ const leakToken = 'sk-live-' + randomUUID().replace(/-/g, '');
74
+ const leakResourceId = 'widget-' + Math.floor(Math.random() * 1_000_000) + '-' + randomUUID().slice(0, 6);
75
+ const leakEmail = 'probe-leak-' + randomUUID().slice(0, 8) + '@example.test';
76
+ const leakEnvKey = 'PROBE_LEAK_' + randomUUID().replace(/-/g, '').slice(0, 8).toUpperCase();
77
+ const leakEnvValue = 'v-' + randomUUID().slice(0, 12);
78
+ const leakEnvPair = `${leakEnvKey}=${leakEnvValue}`;
79
+
80
+ const injectedForbidden = new URLSearchParams({
81
+ 'leak-token': leakToken,
82
+ 'leak-resource-id': leakResourceId,
83
+ 'leak-email': leakEmail,
84
+ 'leak-env': leakEnvPair,
85
+ 'x-injected-name': leakEnvKey,
86
+ 'x-injected-value': leakEnvValue,
87
+ }).toString();
88
+ const forbidden = await fixtureFetch(fixture.url, `/probe/forbidden?${injectedForbidden}`, {
89
+ headers: { 'x-probe-leak-token': leakToken, 'x-probe-leak-email': leakEmail, 'x-probe-leak-env': leakEnvPair },
90
+ });
91
+ const surfaceText = stripHtml(forbidden.body);
92
+ const region = /data-surface="forbidden"[^>]*role="region"/.test(forbidden.body);
93
+ const control = /data-action="request-access"/.test(forbidden.body);
94
+ const stateCopyPresent = /You do not have scope on this workspace/.test(surfaceText);
95
+ const noSensitivePatternHit = !forbiddenSensitiveHit(surfaceText);
96
+ const injectedAbsent = !forbidden.body.includes(leakToken)
97
+ && !forbidden.body.includes(leakResourceId)
98
+ && !forbidden.body.includes(leakEmail)
99
+ && !forbidden.body.includes(leakEnvPair)
100
+ && !forbidden.body.includes(leakEnvValue);
101
+ const post = await fixtureFetch(fixture.url, '/api/request-access', { method: 'POST', headers: { 'content-type': 'application/json' }, body: '{}' });
102
+ let postBody = null; try { postBody = JSON.parse(post.body); } catch (_) { /* parse */ }
103
+ const roundTrip = post.status === 200 && !!post.requestId && postBody && postBody.ok === true;
104
+ const forbiddenPass = forbidden.status === 403 && !!forbidden.requestId
105
+ && region && control && stateCopyPresent
106
+ && noSensitivePatternHit && injectedAbsent && roundTrip;
107
+ results.push({
108
+ anchorAcId: 'application-empty-error-states-AC-22102-1',
109
+ verdict: forbiddenPass ? 'pass' : 'fail',
110
+ detail: forbiddenPass
111
+ ? `Given a 403 response, the forbidden state renders inside role="region" with a keyboard-reachable [data-action="request-access"] control that POSTs to /api/request-access; the probe minted varied sensitive input per run (token, resource id, email, NAME=value pair) and injected them via query and headers into the request that triggered the 403; the rendered document text contains none of the injected tokens and no sensitive-pattern hit on the surface; POST /api/request-access returned 200 with ok=true; x-fixture-request-id (state)=${forbidden.requestId}, (action)=${post.requestId}`
112
+ : `Given a 403 response, the forbidden state renders (evidence gap): status=${forbidden.status} rid=${forbidden.requestId} region=${region} control=${control} stateCopy=${stateCopyPresent} noSensitivePattern=${noSensitivePatternHit} injectedAbsent=${injectedAbsent} roundTrip=${roundTrip}`,
113
+ evidence: {
114
+ requestId: forbidden.requestId,
115
+ responseStatus: forbidden.status,
116
+ bodyExcerpt: excerpt(surfaceText),
117
+ derived: { region, control, stateCopyPresent, noSensitivePatternHit, injectedAbsent, injectedTokens: { leakToken, leakResourceId, leakEmail, leakEnvPair }, actionStatus: post.status, actionOk: !!(postBody && postBody.ok) },
118
+ },
119
+ });
120
+
121
+ // Mint a fresh set of tokens for the 500 leg and inject via query +
122
+ // headers into the request that triggers the server-error surface.
123
+ const svLeakStack = `at leakedFn__${randomUUID().slice(0, 6)} (/opt/leak/${randomUUID().slice(0, 8)}.js:${Math.floor(Math.random() * 500) + 1}:${Math.floor(Math.random() * 80) + 1})`;
124
+ const svLeakEnvKey = 'SV_LEAK_' + randomUUID().replace(/-/g, '').slice(0, 8).toUpperCase();
125
+ const svLeakEnvValue = randomUUID().slice(0, 12);
126
+ const svLeakEnvPair = `${svLeakEnvKey}=${svLeakEnvValue}`;
127
+ const svLeakPath = `/opt/leak/${randomUUID().slice(0, 8)}.mjs`;
128
+ const svInjected = new URLSearchParams({
129
+ 'leak-stack': svLeakStack,
130
+ 'leak-env': svLeakEnvPair,
131
+ 'leak-path': svLeakPath,
132
+ }).toString();
133
+ const server = await fixtureFetch(fixture.url, `/probe/server-error?${svInjected}`, {
134
+ headers: { 'x-probe-leak-stack': svLeakStack, 'x-probe-leak-env': svLeakEnvPair, 'x-probe-leak-path': svLeakPath },
135
+ });
136
+ const svText = stripHtml(server.body);
137
+ const svRegion = /data-surface="server-error"[^>]*role="region"/.test(server.body);
138
+ const svRetry = /data-recovery="retry"/.test(server.body);
139
+ const svStateCopy = /The server hit an internal failure/.test(svText);
140
+ const svNoPatternHit = !serverErrorSensitiveHit(svText);
141
+ const svInjectedAbsent = !server.body.includes(svLeakStack)
142
+ && !server.body.includes(svLeakEnvPair)
143
+ && !server.body.includes(svLeakEnvValue)
144
+ && !server.body.includes(svLeakPath);
145
+ // The matcher itself must catch a bare NAME=value form: probe it here so
146
+ // regressions on the matcher are surfaced as a hard fail on this row.
147
+ const matcherCatchesBareName = serverErrorSensitiveHit('the payload was DB_PASSWORD=hunter2 rest');
148
+ const svPass = server.status === 500 && !!server.requestId && svRegion && svRetry && svStateCopy
149
+ && svNoPatternHit && svInjectedAbsent && matcherCatchesBareName;
150
+ results.push({
151
+ anchorAcId: 'application-empty-error-states-AC-22103-1',
152
+ verdict: svPass ? 'pass' : 'fail',
153
+ detail: svPass
154
+ ? `Given a mocked 500 response, the server-error state renders inside role="region" with a keyboard-reachable [data-recovery="retry"] control; the probe minted varied sensitive input per run (backtrace-frame line, bare NAME=value env-key pair, source path) and injected them via query and headers into the request that triggered the 500; the rendered document text contains none of the injected tokens and no backtrace/source-path/env-var/framework-frame hit on the surface; the sensitive-value matcher positively catches a bare NAME=value form; x-fixture-request-id=${server.requestId}`
155
+ : `Given a mocked 500 response, the server-error state renders (evidence gap): status=${server.status} rid=${server.requestId} region=${svRegion} retry=${svRetry} stateCopy=${svStateCopy} noPatternHit=${svNoPatternHit} injectedAbsent=${svInjectedAbsent} matcherCatchesBareName=${matcherCatchesBareName}`,
156
+ evidence: {
157
+ requestId: server.requestId,
158
+ responseStatus: server.status,
159
+ bodyExcerpt: excerpt(svText),
160
+ derived: { region: svRegion, retry: svRetry, stateCopy: svStateCopy, noPatternHit: svNoPatternHit, injectedAbsent: svInjectedAbsent, matcherCatchesBareName, injectedTokens: { svLeakStack, svLeakEnvPair, svLeakPath } },
161
+ },
162
+ });
163
+ } finally {
164
+ await fixture.kill();
165
+ }
166
+ return { results };
167
+ }
@@ -0,0 +1,61 @@
1
+ // application-empty-error-states probe: 404 not-found state
2
+ // (AC-22101-1). AC-22101-1 requires a role="region" with an
3
+ // accessible name for the missing resource kind, a keyboard-reachable
4
+ // recovery link to the parent surface, plus a search input as an
5
+ // alternate recovery.
6
+ //
7
+ // The probe:
8
+ // - GETs /probe/not-found and derives status=404, the region role
9
+ // wrapper, the parent-surface recovery link and the search input.
10
+ // - Follows the parent-surface link and asserts the linked route
11
+ // responds (200): the derived observable of "recovery link works"
12
+ // is a two-request round-trip, not a magic string match.
13
+
14
+ import { fixtureFetch, startFixture, excerpt } from './probe-utils.mjs';
15
+
16
+ export const anchorAcId = 'application-empty-error-states-AC-22101-1';
17
+ export const accountBound = false;
18
+
19
+ export default async function runProbe() {
20
+ const fixture = await startFixture();
21
+ const results = [];
22
+ try {
23
+ const nf = await fixtureFetch(fixture.url, '/probe/not-found');
24
+ const regionPresent = /data-surface="not-found"[^>]*role="region"/.test(nf.body);
25
+ const parentLinkMatch = nf.body.match(/href="([^"]+)"[^>]*data-recovery="parent-surface"/);
26
+ const parentHref = parentLinkMatch ? parentLinkMatch[1] : null;
27
+ const searchInput = /data-recovery="search"[^>]*>[^]*<input[^>]*type="search"/.test(nf.body);
28
+ const statusOk = nf.status === 404;
29
+ const regionCheckPass = statusOk && !!nf.requestId && regionPresent && !!parentHref && searchInput;
30
+
31
+ // Follow the recovery link (varied input: a second request derived
32
+ // from the first response) and assert the target route responds.
33
+ let followStatus = null;
34
+ let followRid = null;
35
+ if (parentHref) {
36
+ const follow = await fixtureFetch(fixture.url, parentHref);
37
+ followStatus = follow.status;
38
+ followRid = follow.requestId;
39
+ }
40
+ const roundTripPass = regionCheckPass && followStatus === 200 && !!followRid;
41
+
42
+ results.push({
43
+ anchorAcId: null,
44
+ conformanceOnly: true,
45
+ limitation: 'application-empty-error-states-AC-22101-1: browser document-title state reflecting the missing resource kind and assistive-tech accessible-name resolution (the AC clauses beyond the DOM shape) are browser + AT driven and not observed by this Node HTTP probe; the 404 region + parent-link follow-through walk is a partial observation of AC-22101-1',
46
+ verdict: roundTripPass ? 'warn' : 'fail',
47
+ detail: roundTripPass
48
+ ? `Given a 404 response on a route the SPA declares: observed role="region" named for the missing resource, [data-recovery="parent-surface"] link (${parentHref}) and [data-recovery="search"] input on the rendered surface; follow-through GET ${parentHref} returned 200; x-fixture-request-id (not-found)=${nf.requestId}, (parent)=${followRid}`
49
+ : `Given a 404 response on a route the SPA declares (evidence gap): status=${nf.status} rid=${nf.requestId} region=${regionPresent} parentHref=${parentHref} searchInput=${searchInput} followStatus=${followStatus}`,
50
+ evidence: {
51
+ requestId: nf.requestId,
52
+ responseStatus: nf.status,
53
+ bodyExcerpt: excerpt((nf.body.match(/data-surface="not-found"[^]{0,200}/) || [''])[0]),
54
+ derived: { statusOk, regionPresent, parentHref, followStatus, followRequestId: followRid, searchInput },
55
+ },
56
+ });
57
+ } finally {
58
+ await fixture.kill();
59
+ }
60
+ return { results };
61
+ }
@@ -0,0 +1,155 @@
1
+ // application-empty-error-states probe: permission-denied
2
+ // (AC-22104-1) and the offline buffer lifecycle (AC-22105-1).
3
+ //
4
+ // AC-22105-1 requires observing the buffered-write lifecycle
5
+ // (intercepted-write when the transport is offline, buffered with
6
+ // idempotency-per-token, flushed on reconnect, delivered count
7
+ // visible). The lifecycle is server-observable via the fixture's
8
+ // /probe/offline/state, /probe/offline/buffer and
9
+ // /probe/offline/reconnect endpoints - a probe can flip the state
10
+ // to offline, POST a varied idempotency token, verify the count
11
+ // increased and the token deduplicates a duplicate POST, trigger
12
+ // reconnect, then verify the buffer drained and the delivered
13
+ // count rose. The polite live-region announcement of the flushed
14
+ // count is browser-driven (client script wires the announce) and
15
+ // is not part of what this row observes.
16
+
17
+ import { fixtureFetch, startFixture, excerpt } from './probe-utils.mjs';
18
+ import { randomUUID } from 'node:crypto';
19
+
20
+ export const anchorAcId = 'application-empty-error-states-AC-22104-1';
21
+ export const accountBound = false;
22
+
23
+ export default async function runProbe() {
24
+ const fixture = await startFixture();
25
+ const results = [];
26
+ try {
27
+ const pd = await fixtureFetch(fixture.url, '/probe/permission-denied');
28
+ const region = /data-surface="permission-denied"[^>]*role="region"/.test(pd.body);
29
+ const causeMatch = pd.body.match(/<span data-cause>([^<]+)<\/span>/);
30
+ const causeText = causeMatch ? causeMatch[1] : '';
31
+ // AC-22104-1 requires a class-level cause string with no digits-run
32
+ // of 4 or more and no per-resource identifier shape.
33
+ const causeShape = causeText.length > 0 && !/\d{4,}/.test(causeText);
34
+ const action = /data-action="request-access"/.test(pd.body);
35
+ const causeClass = /data-cause-class="scope-missing"/.test(pd.body);
36
+ const pass = pd.status === 403 && !!pd.requestId && region && causeShape && action && causeClass;
37
+ results.push({
38
+ anchorAcId: null,
39
+ conformanceOnly: true,
40
+ limitation: 'application-empty-error-states-AC-22104-1: the exact cause-shape regex (no UUID form, no identifier-prefixed slug) demanded by the AC is not enforced by this Node HTTP probe; the 403 + region + request-access + class-level-cause walk is a partial observation of AC-22104-1',
41
+ verdict: pass ? 'warn' : 'fail',
42
+ detail: pass
43
+ ? `Given a mocked 403 response with a per-resource cause: observed role="region", class-level cause "${causeText}" (no 4+ digit run), [data-action="request-access"] control and data-cause-class="scope-missing" on the rendered surface; x-fixture-request-id=${pd.requestId}`
44
+ : `Given a mocked 403 response with a per-resource cause (evidence gap): status=${pd.status} rid=${pd.requestId} region=${region} cause="${causeText}" causeShape=${causeShape} action=${action} causeClass=${causeClass}`,
45
+ evidence: {
46
+ requestId: pd.requestId,
47
+ responseStatus: pd.status,
48
+ bodyExcerpt: excerpt((pd.body.match(/data-surface="permission-denied"[^]{0,220}/) || [''])[0]),
49
+ derived: { region, causeText, causeShape, action, causeClass },
50
+ },
51
+ });
52
+
53
+ // AC-22105-1 server-observable buffer lifecycle: flip state
54
+ // offline, POST a varied idempotency token, verify buffer grew,
55
+ // POST the same token and verify dedupe, POST a second distinct
56
+ // token, trigger reconnect and verify the buffer drained with
57
+ // the expected delivered count. Every step drives a varied
58
+ // input the fixture cannot see coming, and every assertion is on
59
+ // a derived output the fixture had no choice about.
60
+ const principalId = 'probe-offline-' + randomUUID();
61
+ // Baseline read (fresh principal begins with the seeded buffer of size 1).
62
+ const initial = await fixtureFetch(fixture.url, `/probe/offline/state?principal-id=${principalId}`);
63
+ const initialState = JSON.parse(initial.body || '{}');
64
+ // Flip to offline.
65
+ const flipOffline = await fixtureFetch(fixture.url, `/probe/offline/state?principal-id=${principalId}`, {
66
+ method: 'POST',
67
+ headers: { 'content-type': 'application/json' },
68
+ body: JSON.stringify({ state: 'offline' }),
69
+ });
70
+ // Enqueue a distinct token.
71
+ const tokenA = 'probe-write-' + randomUUID();
72
+ const enqA1 = await fixtureFetch(fixture.url, `/probe/offline/buffer?principal-id=${principalId}`, {
73
+ method: 'POST',
74
+ headers: { 'content-type': 'application/json' },
75
+ body: JSON.stringify({ idempotencyToken: tokenA, payload: { kind: 'note', body: 'first' } }),
76
+ });
77
+ const enqA1Body = JSON.parse(enqA1.body || '{}');
78
+ // Duplicate write with the SAME token must dedupe (no count increase).
79
+ const enqA2 = await fixtureFetch(fixture.url, `/probe/offline/buffer?principal-id=${principalId}`, {
80
+ method: 'POST',
81
+ headers: { 'content-type': 'application/json' },
82
+ body: JSON.stringify({ idempotencyToken: tokenA, payload: { kind: 'note', body: 'first-again' } }),
83
+ });
84
+ const enqA2Body = JSON.parse(enqA2.body || '{}');
85
+ // Enqueue a second distinct token (count must go up).
86
+ const tokenB = 'probe-write-' + randomUUID();
87
+ const enqB = await fixtureFetch(fixture.url, `/probe/offline/buffer?principal-id=${principalId}`, {
88
+ method: 'POST',
89
+ headers: { 'content-type': 'application/json' },
90
+ body: JSON.stringify({ idempotencyToken: tokenB, payload: { kind: 'note', body: 'second' } }),
91
+ });
92
+ const enqBBody = JSON.parse(enqB.body || '{}');
93
+ // Reconnect and drain.
94
+ const reconnect = await fixtureFetch(fixture.url, `/probe/offline/reconnect?principal-id=${principalId}`, { method: 'POST' });
95
+ const reconnectBody = JSON.parse(reconnect.body || '{}');
96
+ // Final GET reads state after reconnect: buffer drained.
97
+ const finalState = await fixtureFetch(fixture.url, `/probe/offline/state?principal-id=${principalId}`);
98
+ const finalStateBody = JSON.parse(finalState.body || '{}');
99
+ // Expectations per AC-22105-1:
100
+ // - offline enqueue grows the buffer count on distinct token
101
+ // - duplicate token does not grow the count (dedupe)
102
+ // - reconnect returns flushed count === buffer count at reconnect time
103
+ // - final state shows buffer empty and delivered count rose by the
104
+ // flushed count
105
+ const seededCount = initialState.bufferCount ?? 0;
106
+ const bufferAfterA1 = enqA1Body.bufferCount ?? 0;
107
+ const bufferAfterA2 = enqA2Body.bufferCount ?? 0;
108
+ const bufferAfterB = enqBBody.bufferCount ?? 0;
109
+ const flushedCount = reconnectBody.flushedCount ?? -1;
110
+ const deliveredAfter = finalStateBody.deliveredCount ?? -1;
111
+ const enqueueGrew = bufferAfterA1 === seededCount + 1;
112
+ const deduped = bufferAfterA2 === bufferAfterA1 && enqA2Body.deduped === true;
113
+ const secondEnqueueGrew = bufferAfterB === bufferAfterA1 + 1;
114
+ const flushedMatches = flushedCount === bufferAfterB;
115
+ const drained = (finalStateBody.bufferCount ?? -1) === 0 && finalStateBody.state === 'online';
116
+ const deliveredMatches = deliveredAfter === flushedCount;
117
+ const bufferPass = initial.status === 200 && !!initial.requestId
118
+ && flipOffline.status === 200
119
+ && enqA1.status === 200 && enqA2.status === 200 && enqB.status === 200
120
+ && reconnect.status === 200 && finalState.status === 200
121
+ && enqueueGrew && deduped && secondEnqueueGrew && flushedMatches && drained && deliveredMatches;
122
+ results.push({
123
+ anchorAcId: null,
124
+ conformanceOnly: true,
125
+ limitation: 'application-empty-error-states-AC-22105-1: the polite live-region announcement of the flushed count and the rendered banner / buffer-count visible on the SPA (the AC clauses beyond the server-side buffer lifecycle) are browser-driven and not observed by this Node HTTP probe; the offline-flip / enqueue / dedupe / reconnect / drain lifecycle is a partial observation of AC-22105-1',
126
+ verdict: bufferPass ? 'warn' : 'fail',
127
+ detail: bufferPass
128
+ ? `Given navigator.onLine simulated false via the runtime seam: with the server-side buffer keyed to a fresh principalId, POST /probe/offline/state{state:offline} flipped the state; two distinct idempotency tokens enqueued (buffer count seededCount=${seededCount} -> ${bufferAfterA1} -> ${bufferAfterB}); duplicate token deduped (deduped=${enqA2Body.deduped}, count stayed ${bufferAfterA2}); POST /probe/offline/reconnect drained ${flushedCount} writes; final state shows bufferCount=0, state=online, deliveredCount=${deliveredAfter} equal to flushedCount; x-fixture-request-id (initial GET)=${initial.requestId}`
129
+ : `Given navigator.onLine simulated false via the runtime seam (evidence gap): seeded=${seededCount} afterA1=${bufferAfterA1} afterA2=${bufferAfterA2} afterB=${bufferAfterB} flushed=${flushedCount} delivered=${deliveredAfter} state=${finalStateBody.state} enqueueGrew=${enqueueGrew} deduped=${deduped} secondGrew=${secondEnqueueGrew} flushedMatches=${flushedMatches} drained=${drained} deliveredMatches=${deliveredMatches}`,
130
+ evidence: {
131
+ requestId: initial.requestId,
132
+ responseStatus: initial.status,
133
+ bodyExcerpt: excerpt(JSON.stringify({ initial: initialState, afterEnq: enqBBody, reconnect: reconnectBody, final: finalStateBody })),
134
+ derived: {
135
+ principalId,
136
+ seededCount,
137
+ bufferAfterA1,
138
+ bufferAfterA2,
139
+ bufferAfterB,
140
+ flushedCount,
141
+ deliveredAfter,
142
+ enqueueGrew,
143
+ deduped,
144
+ secondEnqueueGrew,
145
+ flushedMatches,
146
+ drained,
147
+ deliveredMatches,
148
+ },
149
+ },
150
+ });
151
+ } finally {
152
+ await fixture.kill();
153
+ }
154
+ return { results };
155
+ }
@@ -0,0 +1,177 @@
1
+ // Shared helpers for application-empty-error-states contributions/probes/.
2
+ //
3
+ // The real engine for every probe in this pack is the fixture HTTP
4
+ // server at packages/rcf-lite/test/fixtures/probe-pack-application-empty-error-states/server.js
5
+ // booted on a scratch port from the family range 47630-47639.
6
+ // The fixture echoes a per-request x-fixture-request-id header on
7
+ // every response; probes record that id and a response body excerpt
8
+ // as positive evidence per rule 7d.
9
+ //
10
+ // No account credentials or network calls: every probe is
11
+ // local-fixture-driven, so no probe carries an account-bound branch
12
+ // or a CI_HAS_* gate. Declared env vars are the fixture's own
13
+ // PORT and (where the fixture reads them) the CAPS/state switches
14
+ // the probes drive via query string.
15
+
16
+ import { spawn } from 'node:child_process';
17
+ import { mkdir, writeFile } from 'node:fs/promises';
18
+ import { createServer } from 'node:net';
19
+ import { dirname, resolve } from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
21
+
22
+ const HERE = dirname(fileURLToPath(import.meta.url));
23
+
24
+ export const SLUG = 'application-empty-error-states';
25
+ export const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
26
+ export const FIXTURE_DIR = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/probe-pack-application-empty-error-states');
27
+ export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/application-empty-error-states');
28
+ export const PORT_RANGE_START = 47630;
29
+ export const PORT_RANGE_END = 47639;
30
+ export const DECLARED_ENV = Object.freeze(['PORT', 'EMPTY_ERROR_STATES_BREAK', 'PROBE_BREAK']);
31
+ export const REQUEST_ID_HEADER = 'x-fixture-request-id';
32
+
33
+ // Pick a free port from the fixture family range. Falls back to
34
+ // asking the OS for an ephemeral port only if the whole range is
35
+ // held by other workers (never expected on a single-machine run).
36
+ export async function pickPort() {
37
+ for (let port = PORT_RANGE_START; port <= PORT_RANGE_END; port += 1) {
38
+ if (await canBind(port)) return port;
39
+ }
40
+ return await bindEphemeral();
41
+ }
42
+
43
+ function canBind(port) {
44
+ return new Promise((res) => {
45
+ const s = createServer();
46
+ s.once('error', () => res(false));
47
+ s.listen(port, '127.0.0.1', () => {
48
+ const bound = s.address();
49
+ s.close(() => res(!!bound));
50
+ });
51
+ });
52
+ }
53
+
54
+ function bindEphemeral() {
55
+ return new Promise((res) => {
56
+ const s = createServer();
57
+ s.listen(0, '127.0.0.1', () => {
58
+ const port = s.address().port;
59
+ s.close(() => res(port));
60
+ });
61
+ });
62
+ }
63
+
64
+ // Spawns the fixture server as a child on `port` with the given
65
+ // env overlay; resolves once the fixture has printed LISTENING and
66
+ // returns { child, url, kill } (kill is synchronous best-effort).
67
+ export async function startFixture({ port, env = {} } = {}) {
68
+ const boundPort = port ?? await pickPort();
69
+ const child = spawn(process.execPath, ['server.js'], {
70
+ cwd: FIXTURE_DIR,
71
+ env: { ...process.env, PORT: String(boundPort), ...env },
72
+ stdio: ['ignore', 'pipe', 'pipe'],
73
+ });
74
+ await new Promise((res, rej) => {
75
+ const timer = setTimeout(() => rej(new Error(`fixture did not print LISTENING within 4s on port ${boundPort}`)), 4000);
76
+ let stderrBuf = '';
77
+ child.stderr.on('data', (chunk) => { stderrBuf += String(chunk); });
78
+ child.on('exit', (code) => rej(new Error(`fixture exited early (code=${code}) stderr=${stderrBuf.slice(0, 400)}`)));
79
+ child.stdout.on('data', (chunk) => {
80
+ if (String(chunk).includes(`LISTENING ${boundPort}`)) { clearTimeout(timer); res(); }
81
+ });
82
+ });
83
+ const url = new URL(`http://127.0.0.1:${boundPort}`);
84
+ return {
85
+ child,
86
+ url,
87
+ port: boundPort,
88
+ // Await child exit and propagate any error. A teardown failure
89
+ // must fail the verdict (the teardown-propagation rule);
90
+ // no swallowed errors here.
91
+ kill: () => new Promise((res, rej) => {
92
+ let settled = false;
93
+ const done = (err) => { if (settled) return; settled = true; err ? rej(err) : res(); };
94
+ child.once('exit', () => done());
95
+ child.once('error', (err) => done(err));
96
+ try { child.kill('SIGTERM'); } catch (err) { return done(err); }
97
+ setTimeout(() => {
98
+ if (settled) return;
99
+ try { child.kill('SIGKILL'); } catch (err) { return done(err); }
100
+ }, 4000);
101
+ }),
102
+ };
103
+ }
104
+
105
+ // Issue an HTTP request against the fixture and return
106
+ // { status, headers, body, requestId }.
107
+ export async function fixtureFetch(url, pathAndQuery, init = {}) {
108
+ const target = new URL(pathAndQuery, url);
109
+ const res = await fetch(target, init);
110
+ const body = await res.text();
111
+ const requestId = res.headers.get(REQUEST_ID_HEADER);
112
+ return { status: res.status, headers: Object.fromEntries(res.headers.entries()), body, requestId };
113
+ }
114
+
115
+ export function excerpt(body, maxLen = 240) {
116
+ if (typeof body !== 'string') return '';
117
+ return body.length <= maxLen ? body : body.slice(0, maxLen) + '…';
118
+ }
119
+
120
+ export function aggregate(results) {
121
+ // Positive-evidence rule: no-checks-ran is a fail.
122
+ if (!Array.isArray(results) || results.length === 0) return 'fail';
123
+ if (results.some((r) => r.verdict === 'fail')) return 'fail';
124
+ // Any warn row lifts the aggregate to warn, including honest
125
+ // notObservableHere de-claims. A probe whose rows are all warn
126
+ // aggregates to warn, not pass; the shelf reads amber and the tally
127
+ // accepts a warn aggregate as problems=0 when no fail row is present.
128
+ if (results.some((r) => r && r.verdict === 'warn')) return 'warn';
129
+ return 'pass';
130
+ }
131
+
132
+ export async function writeReport({ probeName, engine, results, extra }) {
133
+ await mkdir(REPORT_DIR, { recursive: true });
134
+ const report = {
135
+ slug: SLUG,
136
+ probeName,
137
+ runAt: new Date().toISOString(),
138
+ engine,
139
+ results,
140
+ aggregateVerdict: aggregate(results),
141
+ ...(extra ?? {}),
142
+ };
143
+ const filepath = resolve(REPORT_DIR, `${probeName}.json`);
144
+ await writeFile(filepath, JSON.stringify(report, null, 2) + '\n', 'utf8');
145
+ return { report, path: filepath };
146
+ }
147
+
148
+ export async function runShim(probeName, engine, mainFn) {
149
+ try {
150
+ const outcome = (await mainFn()) ?? { results: [] };
151
+ const { results, extra } = outcome;
152
+ const { report, path: filepath } = await writeReport({ probeName, engine, results, extra });
153
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
154
+ process.stdout.write(`report written to ${filepath}\n`);
155
+ if (report.aggregateVerdict === 'fail') process.exitCode = 1;
156
+ } catch (err) {
157
+ // Positive-evidence rule (exception fallback): exception rows have no
158
+ // observed AC; anchor null (never a fabricated id like
159
+ // "unknown"), carry an evidence object with the error excerpt.
160
+ const message = err && err.message ? err.message : String(err);
161
+ const stack = err && err.stack ? err.stack : String(err);
162
+ const results = [{
163
+ anchorAcId: null,
164
+ verdict: 'fail',
165
+ detail: `probe threw: ${message}`,
166
+ evidence: {
167
+ errorMessage: message,
168
+ errorExcerpt: excerpt(stack, 480),
169
+ },
170
+ }];
171
+ const { report, path: filepath } = await writeReport({ probeName, engine, results });
172
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
173
+ process.stderr.write(`probe error: ${stack}\n`);
174
+ process.stderr.write(`report written to ${filepath}\n`);
175
+ process.exitCode = 1;
176
+ }
177
+ }
@@ -0,0 +1,5 @@
1
+ import runProbe from './empty-list-and-no-search.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'fixture', image: 'test/fixtures/probe-pack-application-empty-error-states/server.js', healthy: true };
5
+ runShim('empty-list-and-no-search', engine, runProbe);
@@ -0,0 +1,5 @@
1
+ import runProbe from './error-boundary-alert.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'fixture', image: 'test/fixtures/probe-pack-application-empty-error-states/server.js', healthy: true };
5
+ runShim('error-boundary-alert', engine, runProbe);
@@ -0,0 +1,5 @@
1
+ import runProbe from './forbidden-and-server-error.mjs';
2
+ import { runShim } from './probe-utils.mjs';
3
+
4
+ const engine = { kind: 'fixture', image: 'test/fixtures/probe-pack-application-empty-error-states/server.js', healthy: true };
5
+ runShim('forbidden-and-server-error', engine, runProbe);