rcf-lite 0.27.0 → 0.28.1

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 +39 -0
  2. package/README.md +19 -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 +46 -0
  475. package/rcf/code-nodes/cn-601.json +18 -0
  476. package/rcf/code-nodes/cn-602.json +16 -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 +18 -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 +46 -0
  499. package/rcf/fbs/fbs-182.json +43 -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 +40 -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 +40 -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 +174 -0
  536. package/rcf/test-suites/ts-189.json +60 -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 +60 -0
  555. package/rcf/user-stories/us-15701.json +42 -0
  556. package/rcf/user-stories/us-15801.json +51 -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 +21 -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 +2213 -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 +455 -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 +1148 -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,455 @@
1
+ // Feedback destination resolver (TAC-4106-feedback-destination,
2
+ // ADR-4104-destination-on-library). Slice 3 (FBS-182): given a pending
3
+ // entry plus the project's manifest and library registry, work out
4
+ // which GitHub repo the finding should be filed against and whether it
5
+ // is public or private. The resolver is pure: no i/o, no network,
6
+ // nothing that would slow preview or submit down to disk speed.
7
+ //
8
+ // Resolution order (design section 3.3):
9
+ // 1. --kind core -> CORE_REPO (public)
10
+ // 2. --kind blueprint, no libraryPrefix -> library-slug inference
11
+ // (AC-15801-4 / design amendment R5a): if the applied slug is
12
+ // owned by exactly one registered library that resolves to a
13
+ // destination (issuesRepo or derivable sourceRef), route there
14
+ // with source: 'library-slug-inference'; if two or more libraries
15
+ // own the slug and resolve, return unresolved with reason
16
+ // 'ambiguous-library-slug' and a candidates[] array of prefixes;
17
+ // otherwise fall through to CORE_REPO (shelf; public).
18
+ // 3. --kind blueprint, libraryPrefix -> registry entry issuesRepo
19
+ // (declared destination wins;
20
+ // visibility from the entry)
21
+ // 4. registry entry with no issuesRepo -> derive from sourceRef when
22
+ // it parses as
23
+ // git+https://github.com/OWNER/REPO(.git)#ref
24
+ // (marked derived: true;
25
+ // visibility defaults to
26
+ // public unless the entry
27
+ // already asserted private)
28
+ // 5. anything else -> unresolved (reason names
29
+ // the why, publisherContact
30
+ // carries the registry
31
+ // contact when known)
32
+ //
33
+ // The CORE_REPO constant is derived from packages/rcf-lite/package.json
34
+ // bugs.url. Because a resolver call is on the hot path of preview and
35
+ // submit, and because reading package.json every call is wasteful and
36
+ // hard to test in isolation, the value is cached at module load time.
37
+ // A dedicated `resolveCoreRepo()` helper (also exported) does the
38
+ // parse; consumers with their own package.json can call it directly
39
+ // and the resolver's CORE_REPO getter reads through it.
40
+
41
+ import { readFile } from 'node:fs/promises';
42
+ import { dirname, resolve as resolvePath } from 'node:path';
43
+ import { fileURLToPath } from 'node:url';
44
+
45
+ const here = dirname(fileURLToPath(import.meta.url));
46
+ // packages/rcf-lite/src/feedback -> packages/rcf-lite/package.json.
47
+ const PACKAGE_JSON_PATH = resolvePath(here, '..', '..', 'package.json');
48
+ const CORE_REPO_FALLBACK = 'Stravica/rcf-lite';
49
+
50
+ /**
51
+ * The Stravica/rcf-lite constant that every core-kind entry and every
52
+ * shelf-blueprint entry routes to. Sourced from
53
+ * `packages/rcf-lite/package.json:bugs.url` at module load so a rename
54
+ * only ripples through one file; a matching unit test pins the constant
55
+ * to the package.json value at test time so a drift is caught in CI.
56
+ *
57
+ * @type {string}
58
+ */
59
+ export let CORE_REPO = CORE_REPO_FALLBACK;
60
+
61
+ /** Guard against double-init during test loops. */
62
+ let coreRepoInitialised = false;
63
+
64
+ /**
65
+ * Parse `bugs.url` from a package.json object and return `OWNER/REPO`.
66
+ * Accepts the trailing `/issues`, an `.git` suffix and either the
67
+ * string or the object shape npm allows on `bugs`.
68
+ *
69
+ * @param {object | undefined | null} pkg
70
+ * @returns {string | null}
71
+ */
72
+ export function parseBugsRepo(pkg) {
73
+ if (pkg == null) return null;
74
+ const bugs = typeof pkg.bugs === 'string' ? pkg.bugs : pkg?.bugs?.url;
75
+ if (typeof bugs !== 'string' || bugs.length === 0) return null;
76
+ const withIssues = bugs.match(/github\.com\/([^/]+)\/([^/#?]+?)(?:\.git)?\/issues\/?(?:[/?#].*)?$/i);
77
+ if (withIssues) return `${withIssues[1]}/${withIssues[2]}`;
78
+ const bare = bugs.match(/github\.com\/([^/]+)\/([^/#?]+?)(?:\.git)?\/?$/i);
79
+ if (bare) return `${bare[1]}/${bare[2]}`;
80
+ return null;
81
+ }
82
+
83
+ /**
84
+ * Read `packages/rcf-lite/package.json` and populate `CORE_REPO`. Safe
85
+ * to call more than once; a failed read leaves the fallback in place.
86
+ * The resolver auto-inits on first `resolve()` call, so most callers
87
+ * never touch this directly; tests call it to force a fresh read.
88
+ *
89
+ * @returns {Promise<string>}
90
+ */
91
+ export async function initCoreRepo() {
92
+ try {
93
+ const text = await readFile(PACKAGE_JSON_PATH, 'utf8');
94
+ const pkg = JSON.parse(text);
95
+ const parsed = parseBugsRepo(pkg);
96
+ if (parsed) CORE_REPO = parsed;
97
+ } catch {
98
+ // Missing or unreadable package.json leaves the fallback active.
99
+ // A dedicated test pins the value in CI so this branch never ships.
100
+ }
101
+ coreRepoInitialised = true;
102
+ return CORE_REPO;
103
+ }
104
+
105
+ /**
106
+ * Parse a git sourceRef of the shape `git+https://github.com/OWNER/REPO(.git)#ref`
107
+ * (or `git+ssh://git@github.com:OWNER/REPO.git#ref`, the two shapes
108
+ * `library add` accepts) into `OWNER/REPO`. Anything else returns null;
109
+ * the resolver treats that as "cannot derive", not as an error.
110
+ *
111
+ * @param {string} sourceRef
112
+ * @returns {string | null}
113
+ */
114
+ export function parseGithubSource(sourceRef) {
115
+ if (typeof sourceRef !== 'string' || sourceRef.length === 0) return null;
116
+ // git+https://github.com/OWNER/REPO(.git)(#ref)
117
+ const https = sourceRef.match(/^git\+https?:\/\/github\.com\/([^/]+)\/([^/#?]+?)(?:\.git)?(?:#.*)?$/i);
118
+ if (https) return `${https[1]}/${https[2]}`;
119
+ // git+ssh://git@github.com:OWNER/REPO.git(#ref) or git+ssh://git@github.com/OWNER/REPO.git(#ref)
120
+ const ssh = sourceRef.match(/^git\+ssh:\/\/git@github\.com[:\/]([^/]+)\/([^/#?]+?)(?:\.git)?(?:#.*)?$/i);
121
+ if (ssh) return `${ssh[1]}/${ssh[2]}`;
122
+ return null;
123
+ }
124
+
125
+ /**
126
+ * Look up a blueprint record on `manifest.blueprints[]` by ref. Accepts
127
+ * the shelf slug (`security-auth-magic-link`), the prefix:slug form
128
+ * (`wsd:std-error-envelope`) and the effective slug already stamped
129
+ * onto the record (`wsd-std-error-envelope`).
130
+ *
131
+ * F-slice-3-01: a QUALIFIED ref (`prefix:slug`) must resolve to a
132
+ * record whose libraryPrefix matches the qualifier. Falling back to
133
+ * an unqualified shelf record on slug collision would route a
134
+ * private WSD finding to the public Stravica/rcf-lite repo. The
135
+ * matcher therefore has two passes: first, any record whose stamped
136
+ * effectiveSlug OR (slug + libraryPrefix) matches the qualifier
137
+ * wins; only when the ref is unqualified do bare-slug matches apply.
138
+ *
139
+ * @param {object | null | undefined} manifest
140
+ * @param {string} ref
141
+ * @returns {object | null}
142
+ */
143
+ export function findBlueprintRecord(manifest, ref) {
144
+ const list = Array.isArray(manifest?.blueprints) ? manifest.blueprints : [];
145
+ if (typeof ref !== 'string' || ref.length === 0) return null;
146
+
147
+ // Qualified `prefix:slug` (and the equivalent `prefix-slug`
148
+ // effective-slug shape) must NEVER match a shelf record whose
149
+ // libraryPrefix does not equal the qualifier. F-slice-3-01: a
150
+ // qualified WSD ref must not fall back to a public shelf record
151
+ // on slug collision.
152
+ if (ref.includes(':')) {
153
+ const [pre, slug] = ref.split(':');
154
+ if (pre && slug) {
155
+ const effective = `${pre}-${slug}`;
156
+ for (const r of list) {
157
+ if (!r || typeof r !== 'object') continue;
158
+ if (r.libraryPrefix !== pre) continue;
159
+ const candidates = recordCandidates(r);
160
+ if (candidates.includes(ref) || candidates.includes(effective) || candidates.includes(slug)) return r;
161
+ }
162
+ return null;
163
+ }
164
+ }
165
+
166
+ // Unqualified ref: match by any candidate. A record with a
167
+ // libraryPrefix still matches, but only through its stamped
168
+ // canonical effective slug (`libraryPrefix-slug`) - never through
169
+ // a bare, unqualified slug that could collide with a shelf record.
170
+ for (const r of list) {
171
+ if (!r || typeof r !== 'object') continue;
172
+ const isQualifiedRecord = typeof r.libraryPrefix === 'string' && r.libraryPrefix.length > 0;
173
+ if (isQualifiedRecord) {
174
+ const canonical = recordEffectiveSlug(r);
175
+ if (canonical && ref === canonical) return r;
176
+ continue;
177
+ }
178
+ const candidates = recordCandidates(r);
179
+ if (candidates.includes(ref)) return r;
180
+ }
181
+ return null;
182
+ }
183
+
184
+ /**
185
+ * The candidate name set stamped on a manifest record: any of
186
+ * effectiveSlug, slug, name that are non-empty strings.
187
+ *
188
+ * @param {object} record
189
+ * @returns {string[]}
190
+ */
191
+ function recordCandidates(record) {
192
+ return [record.effectiveSlug, record.slug, record.name].filter(
193
+ (s) => typeof s === 'string' && s.length > 0,
194
+ );
195
+ }
196
+
197
+ /**
198
+ * The canonical effective slug for a qualified manifest record. If
199
+ * the record already carries `effectiveSlug`, that wins; otherwise
200
+ * synthesise it from `libraryPrefix` + `slug` (either the slug is
201
+ * already prefixed, or we prepend the prefix).
202
+ *
203
+ * @param {object} record
204
+ * @returns {string | null}
205
+ */
206
+ function recordEffectiveSlug(record) {
207
+ if (typeof record.effectiveSlug === 'string' && record.effectiveSlug.length > 0) return record.effectiveSlug;
208
+ const pre = typeof record.libraryPrefix === 'string' ? record.libraryPrefix : '';
209
+ const slug = typeof record.slug === 'string' ? record.slug : '';
210
+ if (!pre || !slug) return null;
211
+ return slug.startsWith(`${pre}-`) ? slug : `${pre}-${slug}`;
212
+ }
213
+
214
+ /**
215
+ * @typedef {object} Destination
216
+ * @property {string | null} repo OWNER/REPO or null when unresolved
217
+ * @property {'public' | 'private' | 'unresolved'} visibility
218
+ * @property {'core' | 'shelf' | 'library'} kind
219
+ * @property {boolean} derived true when repo came from sourceRef derivation
220
+ * @property {string} [reason] filled on unresolved: 'no-issues-field' | 'no-github-source' | 'no-libraryprefix-record' | 'unknown-target' | 'ambiguous-library-slug'
221
+ * @property {string[]} [candidates] filled on unresolved with reason 'ambiguous-library-slug': sorted library prefixes owning the slug
222
+ * @property {string} [publisherContact] registry entry's publisher.contact (bundle uses it)
223
+ * @property {string} [source] 'library-manifest' | 'sourceRef-derivation' | 'package-bugs-url' | 'shelf-constant' | 'library-slug-inference'
224
+ */
225
+
226
+ /**
227
+ * Resolve one entry to its destination shape. Pure over the inputs.
228
+ *
229
+ * @param {object} entry a feedback entry (design §4.1)
230
+ * @param {object} [context]
231
+ * @param {object} [context.manifest] parsed rcf/manifest.json
232
+ * @param {object} [context.registry] parsed rcf/blueprint-libraries.json
233
+ * @returns {Promise<Destination>}
234
+ */
235
+ export async function resolve(entry, context = {}) {
236
+ if (!coreRepoInitialised) await initCoreRepo();
237
+ const manifest = context.manifest ?? null;
238
+ const registry = context.registry ?? { libraries: [] };
239
+ const kind = entry?.kind;
240
+
241
+ if (kind === 'core') {
242
+ return {
243
+ repo: CORE_REPO,
244
+ visibility: 'public',
245
+ kind: 'core',
246
+ derived: false,
247
+ source: 'package-bugs-url',
248
+ };
249
+ }
250
+ if (kind !== 'blueprint') {
251
+ return {
252
+ repo: null,
253
+ visibility: 'unresolved',
254
+ kind: 'library',
255
+ derived: false,
256
+ reason: 'unknown-target',
257
+ };
258
+ }
259
+
260
+ const ref = entry?.target?.ref;
261
+ const record = findBlueprintRecord(manifest, ref);
262
+ if (!record) {
263
+ return {
264
+ repo: null,
265
+ visibility: 'unresolved',
266
+ kind: 'library',
267
+ derived: false,
268
+ reason: 'unknown-target',
269
+ };
270
+ }
271
+
272
+ const libraryPrefix = record.libraryPrefix ?? entry?.target?.libraryPrefix ?? null;
273
+
274
+ // Shelf blueprint (no libraryPrefix on the manifest record). Before
275
+ // falling through to the shelf constant, cross-check the registry:
276
+ // if exactly one registered library owns a blueprint with the applied
277
+ // slug AND that library resolves to a destination, route to that
278
+ // library so a bare-slug apply of a library-shared name still lands
279
+ // on the library owner's repo (design amendment R5, AC-15801-4).
280
+ if (!libraryPrefix) {
281
+ const inferred = inferLibraryFromSlug(record, registry);
282
+ if (inferred.kind === 'single') {
283
+ return inferred.destination;
284
+ }
285
+ if (inferred.kind === 'ambiguous') {
286
+ return {
287
+ repo: null,
288
+ visibility: 'unresolved',
289
+ kind: 'library',
290
+ derived: false,
291
+ reason: 'ambiguous-library-slug',
292
+ candidates: inferred.candidates,
293
+ };
294
+ }
295
+ return {
296
+ repo: CORE_REPO,
297
+ visibility: 'public',
298
+ kind: 'shelf',
299
+ derived: false,
300
+ source: 'package-bugs-url',
301
+ };
302
+ }
303
+
304
+ const libEntry = findLibraryEntry(registry, libraryPrefix);
305
+ if (!libEntry) {
306
+ return {
307
+ repo: null,
308
+ visibility: 'unresolved',
309
+ kind: 'library',
310
+ derived: false,
311
+ reason: 'no-libraryprefix-record',
312
+ };
313
+ }
314
+
315
+ const contact = typeof libEntry?.publisher?.contact === 'string'
316
+ ? libEntry.publisher.contact
317
+ : undefined;
318
+
319
+ // Declared destination wins.
320
+ if (typeof libEntry.issuesRepo === 'string' && libEntry.issuesRepo.length > 0) {
321
+ const declaredVisibility = libEntry.issuesVisibility === 'private' ? 'private'
322
+ : libEntry.issuesVisibility === 'public' ? 'public'
323
+ : 'public';
324
+ return {
325
+ repo: libEntry.issuesRepo,
326
+ visibility: declaredVisibility,
327
+ kind: 'library',
328
+ derived: false,
329
+ source: 'library-manifest',
330
+ ...(contact ? { publisherContact: contact } : {}),
331
+ };
332
+ }
333
+
334
+ // Fallback: derive from sourceRef when it parses as a github URL.
335
+ const derived = parseGithubSource(libEntry.sourceRef ?? '');
336
+ if (derived) {
337
+ return {
338
+ repo: derived,
339
+ visibility: 'public',
340
+ kind: 'library',
341
+ derived: true,
342
+ source: 'sourceRef-derivation',
343
+ ...(contact ? { publisherContact: contact } : {}),
344
+ };
345
+ }
346
+
347
+ // Neither declared nor derivable: unresolved.
348
+ return {
349
+ repo: null,
350
+ visibility: 'unresolved',
351
+ kind: 'library',
352
+ derived: false,
353
+ reason: libEntry.sourceRef ? 'no-github-source' : 'no-issues-field',
354
+ ...(contact ? { publisherContact: contact } : {}),
355
+ };
356
+ }
357
+
358
+ /**
359
+ * Enumerate every registered library and flag the ones the resolver
360
+ * cannot produce a destination for (no issues field and no derivable
361
+ * github source). Doctor's `feedback-destinations` check consumes this;
362
+ * the shape is `{ libraryPrefix, reason, publisherContact? }`.
363
+ *
364
+ * @param {object} registry
365
+ * @returns {Array<{ libraryPrefix: string, reason: 'no-issues-field' | 'no-github-source', publisherContact?: string }>}
366
+ */
367
+ export function listUnresolvedLibraries(registry) {
368
+ const out = [];
369
+ const libs = Array.isArray(registry?.libraries) ? registry.libraries : [];
370
+ for (const lib of libs) {
371
+ if (typeof lib?.libraryPrefix !== 'string') continue;
372
+ if (typeof lib.issuesRepo === 'string' && lib.issuesRepo.length > 0) continue;
373
+ const derived = parseGithubSource(lib.sourceRef ?? '');
374
+ if (derived) continue;
375
+ const contact = typeof lib?.publisher?.contact === 'string' ? lib.publisher.contact : undefined;
376
+ out.push({
377
+ libraryPrefix: lib.libraryPrefix,
378
+ reason: lib.sourceRef ? 'no-github-source' : 'no-issues-field',
379
+ ...(contact ? { publisherContact: contact } : {}),
380
+ });
381
+ }
382
+ return out;
383
+ }
384
+
385
+ function findLibraryEntry(registry, libraryPrefix) {
386
+ const libs = Array.isArray(registry?.libraries) ? registry.libraries : [];
387
+ return libs.find((l) => l?.libraryPrefix === libraryPrefix) ?? null;
388
+ }
389
+
390
+ /**
391
+ * AC-15801-4 / design amendment R5a: given a manifest record with no
392
+ * libraryPrefix, cross-check the registry to see whether the applied
393
+ * slug is owned by exactly one registered library that resolves to a
394
+ * destination. Returns:
395
+ * { kind: 'none' } no library owns the slug (or none resolve)
396
+ * { kind: 'single', destination } exactly one library owns the slug and resolves
397
+ * { kind: 'ambiguous', candidates: string[] } two or more libraries own the slug and resolve
398
+ *
399
+ * The resolver only calls this on the shelf-constant fall-through
400
+ * branch, so it never overrides an existing libraryPrefix resolution.
401
+ *
402
+ * @param {object} record manifest.blueprints[] record
403
+ * @param {object | null | undefined} registry parsed rcf/blueprint-libraries.json
404
+ */
405
+ function inferLibraryFromSlug(record, registry) {
406
+ const slug = typeof record?.slug === 'string' ? record.slug : null;
407
+ if (!slug) return { kind: 'none' };
408
+ const libs = Array.isArray(registry?.libraries) ? registry.libraries : [];
409
+ const owners = [];
410
+ for (const lib of libs) {
411
+ if (!lib || typeof lib !== 'object') continue;
412
+ if (typeof lib.libraryPrefix !== 'string' || lib.libraryPrefix.length === 0) continue;
413
+ const bps = Array.isArray(lib.blueprints) ? lib.blueprints : [];
414
+ const owns = bps.some((b) => b && typeof b.slug === 'string' && b.slug === slug);
415
+ if (!owns) continue;
416
+ const declared = typeof lib.issuesRepo === 'string' && lib.issuesRepo.length > 0 ? lib.issuesRepo : null;
417
+ const derivedRepo = declared ? null : parseGithubSource(lib.sourceRef ?? '');
418
+ if (!declared && !derivedRepo) continue;
419
+ const contact = typeof lib?.publisher?.contact === 'string' ? lib.publisher.contact : undefined;
420
+ owners.push({ lib, declared, derivedRepo, contact });
421
+ }
422
+ if (owners.length === 0) return { kind: 'none' };
423
+ if (owners.length === 1) {
424
+ const [o] = owners;
425
+ if (o.declared) {
426
+ const declaredVisibility = o.lib.issuesVisibility === 'private' ? 'private'
427
+ : o.lib.issuesVisibility === 'public' ? 'public'
428
+ : 'public';
429
+ return {
430
+ kind: 'single',
431
+ destination: {
432
+ repo: o.declared,
433
+ visibility: declaredVisibility,
434
+ kind: 'library',
435
+ derived: false,
436
+ source: 'library-slug-inference',
437
+ ...(o.contact ? { publisherContact: o.contact } : {}),
438
+ },
439
+ };
440
+ }
441
+ return {
442
+ kind: 'single',
443
+ destination: {
444
+ repo: o.derivedRepo,
445
+ visibility: 'public',
446
+ kind: 'library',
447
+ derived: true,
448
+ source: 'library-slug-inference',
449
+ ...(o.contact ? { publisherContact: o.contact } : {}),
450
+ },
451
+ };
452
+ }
453
+ const candidates = owners.map((o) => o.lib.libraryPrefix).sort();
454
+ return { kind: 'ambiguous', candidates };
455
+ }
@@ -0,0 +1,132 @@
1
+ // Feedback fingerprint (TAC-4104-feedback-fingerprint, ADR-4102).
2
+ // Deterministic 12-hex fingerprint per entry that keys the same-defect
3
+ // fold when the submit path (slice 4) files issues.
4
+ //
5
+ // Canonical input (design section 6):
6
+ // sha-256("<kind>|<targetKey>|<anchor>|<symptomClass>") -> first 12 hex
7
+ // where
8
+ // - targetKey is the effective slug for blueprints (no version) or
9
+ // the verb path for core; a target that came in as
10
+ // `prefix:slug` is normalised to `prefix-slug`.
11
+ // - anchor is upper-cased, or `-` when absent.
12
+ // - symptomClass is one of the closed enum.
13
+ //
14
+ // Fallback (when the entry has no anchor): the canonical input becomes
15
+ // sha-256("<kind>|<targetKey>|<symptomClass>|<normalisedTitle>")
16
+ // where normalisedTitle is the first eight tokens of the title
17
+ // lower-cased, punctuation stripped and stop-words removed.
18
+ //
19
+ // Blueprint version is not part of the fingerprint (§6, §9) so a
20
+ // defect that persists across versions folds into one issue with the
21
+ // versions in the comments.
22
+
23
+ import { createHash } from 'node:crypto';
24
+
25
+ /** Length of the truncated fingerprint (hex chars). */
26
+ export const FINGERPRINT_HEX_LEN = 12;
27
+
28
+ /** Cheap English stop-word list used by the fallback title tokeniser. */
29
+ const STOP_WORDS = new Set([
30
+ 'a', 'an', 'the', 'and', 'or', 'but', 'if', 'of', 'in', 'on', 'at',
31
+ 'to', 'for', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
32
+ 'it', 'this', 'that', 'these', 'those', 'as', 'by', 'with', 'from',
33
+ 'into', 'over', 'under', 'up', 'down', 'not', 'no', 'do', 'does',
34
+ 'did', 'has', 'have', 'had',
35
+ ]);
36
+
37
+ /**
38
+ * Compute an entry fingerprint. Accepts the entry shape written by
39
+ * `rcf feedback add` (see src/feedback/store.js FeedbackEntry) and
40
+ * emits a 12-hex string keyed on the fields listed above.
41
+ *
42
+ * @param {object} entry
43
+ * @returns {string} 12 lower-case hex chars
44
+ */
45
+ export function fingerprint(entry) {
46
+ const input = fingerprintInput(entry);
47
+ return createHash('sha256').update(input, 'utf8').digest('hex').slice(0, FINGERPRINT_HEX_LEN);
48
+ }
49
+
50
+ /**
51
+ * Return the exact canonical string that hashes to the fingerprint.
52
+ * Exposed for the disclosure line on `preview` and for the test
53
+ * corpus, so a maintainer can reproduce the value by hand.
54
+ *
55
+ * @param {object} entry
56
+ * @returns {string}
57
+ */
58
+ export function fingerprintInput(entry) {
59
+ const kind = String(entry?.kind ?? '').toLowerCase();
60
+ const targetKey = deriveTargetKey(entry);
61
+ const anchor = normaliseAnchor(entry?.anchor);
62
+ const symptomClass = String(entry?.symptomClass ?? 'other');
63
+ if (anchor === '-') {
64
+ const normalisedTitle = normaliseTitle(entry?.title ?? '');
65
+ return `${kind}|${targetKey}|${symptomClass}|${normalisedTitle}`;
66
+ }
67
+ return `${kind}|${targetKey}|${anchor}|${symptomClass}`;
68
+ }
69
+
70
+ /**
71
+ * Derive the targetKey portion of the canonical input.
72
+ *
73
+ * blueprint: effectiveSlug from the entry.target if present, else
74
+ * a normalised form of the ref (`wsd:std-error-envelope`
75
+ * becomes `wsd-std-error-envelope`; already-dashed
76
+ * refs pass through unchanged).
77
+ * core: the verb path from entry.target.ref, lower-cased with
78
+ * whitespace collapsed to single spaces.
79
+ *
80
+ * @param {object} entry
81
+ * @returns {string}
82
+ */
83
+ export function deriveTargetKey(entry) {
84
+ const t = entry?.target ?? {};
85
+ const kind = String(entry?.kind ?? '').toLowerCase();
86
+ if (kind === 'blueprint') {
87
+ if (typeof t.effectiveSlug === 'string' && t.effectiveSlug.length > 0) {
88
+ return t.effectiveSlug;
89
+ }
90
+ const ref = String(t.ref ?? '');
91
+ if (ref.includes(':')) return ref.replace(':', '-');
92
+ return ref;
93
+ }
94
+ const ref = String(t.ref ?? '');
95
+ return ref.trim().replace(/\s+/g, ' ').toLowerCase();
96
+ }
97
+
98
+ /**
99
+ * Normalise the anchor: upper-case, trim; return `-` when the value
100
+ * is nullish, empty or whitespace-only.
101
+ *
102
+ * @param {string | null | undefined} anchor
103
+ * @returns {string}
104
+ */
105
+ export function normaliseAnchor(anchor) {
106
+ if (anchor == null) return '-';
107
+ const trimmed = String(anchor).trim();
108
+ if (trimmed === '') return '-';
109
+ return trimmed.toUpperCase();
110
+ }
111
+
112
+ /**
113
+ * Normalise a title for the fallback fingerprint: lower-case, strip
114
+ * punctuation, remove stop-words, keep the first eight remaining
115
+ * tokens joined by single spaces.
116
+ *
117
+ * @param {string} title
118
+ * @returns {string}
119
+ */
120
+ export function normaliseTitle(title) {
121
+ // F-slice-2-11: normalise every non-ASCII dash variant (em, en,
122
+ // figure, horizontal bar, hyphen, non-breaking hyphen, minus) to
123
+ // an ASCII hyphen first, then strip ALL punctuation including
124
+ // ASCII hyphens. "probe-fails" and its em-dash sibling
125
+ // "probe—fails" then hash the same.
126
+ const dashNormalised = String(title ?? '').replace(/[‐-―−-]/g, ' ');
127
+ const lowered = dashNormalised.toLowerCase();
128
+ const cleaned = lowered.replace(/[^a-z0-9\s]/g, ' ').replace(/\s+/g, ' ').trim();
129
+ if (cleaned === '') return '';
130
+ const tokens = cleaned.split(' ').filter((t) => t.length > 0 && !STOP_WORDS.has(t));
131
+ return tokens.slice(0, 8).join(' ');
132
+ }