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.
- package/CHANGELOG.md +23 -0
- package/README.md +10 -0
- package/bin/rcf.js +2 -0
- package/blueprints/application-account-settings/CHANGELOG.md +35 -6
- package/blueprints/application-account-settings/README.md +1 -1
- package/blueprints/application-account-settings/blueprint.json +4 -2
- package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +1 -1
- package/blueprints/application-account-settings/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-account-settings/contributions/probes/profile-form-autocomplete.mjs +67 -0
- package/blueprints/application-account-settings/contributions/probes/run-profile-form-autocomplete.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-adapter-uniform.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-surface-shape.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-shell-tablist-per-capability.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-theme-radiogroup.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-adapter-uniform.mjs +130 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-surface-shape.mjs +70 -0
- package/blueprints/application-account-settings/contributions/probes/shell-tablist-per-capability.mjs +60 -0
- package/blueprints/application-account-settings/contributions/probes/theme-radiogroup.mjs +126 -0
- package/blueprints/application-admin-console/CHANGELOG.md +32 -6
- package/blueprints/application-admin-console/README.md +1 -1
- package/blueprints/application-admin-console/blueprint.json +4 -2
- package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +1 -1
- package/blueprints/application-admin-console/contributions/probes/audit-log-surface.mjs +79 -0
- package/blueprints/application-admin-console/contributions/probes/org-switcher-surface.mjs +83 -0
- package/blueprints/application-admin-console/contributions/probes/permission-matrix-grid.mjs +67 -0
- package/blueprints/application-admin-console/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-admin-console/contributions/probes/run-audit-log-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-org-switcher-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-permission-matrix-grid.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-sign-in-access-gated-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-users-directory-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/sign-in-access-gated-surface.mjs +117 -0
- package/blueprints/application-admin-console/contributions/probes/users-directory-surface.mjs +145 -0
- package/blueprints/application-api-rest/CHANGELOG.md +16 -8
- package/blueprints/application-api-rest/README.md +3 -3
- package/blueprints/application-api-rest/blueprint.json +3 -2
- package/blueprints/application-api-rest/contributions/adrs/adr-302-application-api-rest-auth-model.json +1 -1
- package/blueprints/application-api-rest/contributions/probes/cursor-pagination-round-trip.mjs +154 -0
- package/blueprints/application-api-rest/contributions/probes/health-probes-distinct.mjs +124 -0
- package/blueprints/application-api-rest/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-api-rest/contributions/probes/problem-details-on-error.mjs +77 -0
- package/blueprints/application-api-rest/contributions/probes/request-id-echoed.mjs +76 -0
- package/blueprints/application-api-rest/contributions/probes/run-cursor-pagination-round-trip.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-health-probes-distinct.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-problem-details-on-error.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-request-id-echoed.mjs +5 -0
- package/blueprints/application-api-rest/docs/topics.md +1 -1
- package/blueprints/application-charts/CHANGELOG.md +35 -9
- package/blueprints/application-charts/README.md +6 -6
- package/blueprints/application-charts/blueprint.json +5 -3
- package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +1 -1
- package/blueprints/application-charts/contributions/probes/keyboard-traversal.mjs +151 -0
- package/blueprints/application-charts/contributions/probes/non-colour-distinction.mjs +67 -0
- package/blueprints/application-charts/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-charts/contributions/probes/run-keyboard-traversal.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-non-colour-distinction.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-text-alternative-table.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/text-alternative-table.mjs +139 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +1 -1
- package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +1 -1
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +5 -5
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +1 -1
- package/blueprints/application-charts/guide/application-charts.md +1 -1
- package/blueprints/application-dashboard/CHANGELOG.md +20 -10
- package/blueprints/application-dashboard/README.md +6 -6
- package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +2 -2
- package/blueprints/application-dashboard/blueprint.json +3 -2
- package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +1 -1
- package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +1 -1
- package/blueprints/application-dashboard/contributions/probes/export-handle-formats.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/four-tile-states.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/primary-kpi-top-left.mjs +58 -0
- package/blueprints/application-dashboard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-dashboard/contributions/probes/run-export-handle-formats.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-four-tile-states.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-primary-kpi-top-left.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-shell-five-regions.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/shell-five-regions.mjs +93 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +1 -1
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +5 -5
- package/blueprints/application-dashboard/docs/topics.md +2 -2
- package/blueprints/application-dashboard/guide/application-dashboard.md +2 -2
- package/blueprints/application-datatable/CHANGELOG.md +19 -9
- package/blueprints/application-datatable/README.md +2 -2
- package/blueprints/application-datatable/blueprint.json +3 -2
- package/blueprints/application-datatable/contributions/probes/apg-table-shape.mjs +57 -0
- package/blueprints/application-datatable/contributions/probes/four-states-regions.mjs +80 -0
- package/blueprints/application-datatable/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-datatable/contributions/probes/run-apg-table-shape.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-four-states-regions.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-search-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-sort-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/search-adapter-round-trip.mjs +58 -0
- package/blueprints/application-datatable/contributions/probes/sort-adapter-round-trip.mjs +60 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +1 -1
- package/blueprints/application-datatable/docs/topics.md +1 -1
- package/blueprints/application-empty-error-states/CHANGELOG.md +33 -3
- package/blueprints/application-empty-error-states/blueprint.json +4 -2
- package/blueprints/application-empty-error-states/contributions/probes/empty-list-and-no-search.mjs +66 -0
- package/blueprints/application-empty-error-states/contributions/probes/error-boundary-alert.mjs +65 -0
- package/blueprints/application-empty-error-states/contributions/probes/forbidden-and-server-error.mjs +167 -0
- package/blueprints/application-empty-error-states/contributions/probes/not-found-and-recovery.mjs +61 -0
- package/blueprints/application-empty-error-states/contributions/probes/permission-denied-and-offline.mjs +155 -0
- package/blueprints/application-empty-error-states/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-empty-list-and-no-search.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-error-boundary-alert.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-forbidden-and-server-error.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-not-found-and-recovery.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-permission-denied-and-offline.mjs +5 -0
- package/blueprints/application-error-handling/CHANGELOG.md +45 -6
- package/blueprints/application-error-handling/blueprint.json +3 -2
- package/blueprints/application-error-handling/contributions/probes/category-vocabulary.mjs +90 -0
- package/blueprints/application-error-handling/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-error-handling/contributions/probes/record-shape-adr-1701.mjs +78 -0
- package/blueprints/application-error-handling/contributions/probes/run-category-vocabulary.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-record-shape-adr-1701.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-two-boundaries-registered.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/two-boundaries-registered.mjs +343 -0
- package/blueprints/application-file-upload/CHANGELOG.md +28 -6
- package/blueprints/application-file-upload/README.md +1 -1
- package/blueprints/application-file-upload/blueprint.json +3 -2
- package/blueprints/application-file-upload/contributions/probes/assertive-completion-slot.mjs +78 -0
- package/blueprints/application-file-upload/contributions/probes/chunked-transport-endpoints.mjs +173 -0
- package/blueprints/application-file-upload/contributions/probes/per-file-progressbar.mjs +124 -0
- package/blueprints/application-file-upload/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-file-upload/contributions/probes/run-assertive-completion-slot.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-chunked-transport-endpoints.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-per-file-progressbar.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-upload-surface-shape.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/upload-surface-shape.mjs +55 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +1 -1
- package/blueprints/application-file-upload/probe-packs/application-file-upload.pack.mjs +1 -1
- package/blueprints/application-forms-wizard/CHANGELOG.md +20 -6
- package/blueprints/application-forms-wizard/README.md +2 -2
- package/blueprints/application-forms-wizard/blueprint.json +3 -2
- package/blueprints/application-forms-wizard/contributions/probes/draft-persistence-round-trip.mjs +110 -0
- package/blueprints/application-forms-wizard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-draft-persistence-round-trip.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-step-page-shape.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-task-list-surface.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/step-page-shape.mjs +61 -0
- package/blueprints/application-forms-wizard/contributions/probes/task-list-surface.mjs +109 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +1 -1
- package/blueprints/application-forms-wizard/probe-packs/application-forms-wizard.pack.mjs +1 -1
- package/blueprints/application-notifications-in-app/CHANGELOG.md +38 -5
- package/blueprints/application-notifications-in-app/README.md +4 -4
- package/blueprints/application-notifications-in-app/blueprint.json +4 -2
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/probes/centre-acknowledge-round-trip.mjs +210 -0
- package/blueprints/application-notifications-in-app/contributions/probes/live-region-preseeding.mjs +93 -0
- package/blueprints/application-notifications-in-app/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-centre-acknowledge-round-trip.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-live-region-preseeding.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-toast-contract.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/toast-contract.mjs +92 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +3 -3
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +1 -1
- package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +3 -3
- package/blueprints/application-onboarding-tour/CHANGELOG.md +31 -5
- package/blueprints/application-onboarding-tour/README.md +1 -1
- package/blueprints/application-onboarding-tour/blueprint.json +5 -3
- package/blueprints/application-onboarding-tour/contributions/probes/checklist-anchor-open.mjs +81 -0
- package/blueprints/application-onboarding-tour/contributions/probes/completion-persistence.mjs +159 -0
- package/blueprints/application-onboarding-tour/contributions/probes/first-run-detection.mjs +67 -0
- package/blueprints/application-onboarding-tour/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-checklist-anchor-open.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-completion-persistence.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-first-run-detection.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-stepper-role-dialog.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/stepper-role-dialog.mjs +45 -0
- package/blueprints/application-spa/CHANGELOG.md +20 -11
- package/blueprints/application-spa/README.md +9 -10
- package/blueprints/application-spa/blueprint.json +3 -2
- package/blueprints/application-spa/contributions/adrs/adr-202-application-spa-theming.json +1 -1
- package/blueprints/application-spa/contributions/adrs/adr-206-application-spa-iconography.json +1 -1
- package/blueprints/application-spa/contributions/probes/designed-empty-state.mjs +72 -0
- package/blueprints/application-spa/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-spa/contributions/probes/route-inventory-published.mjs +185 -0
- package/blueprints/application-spa/contributions/probes/run-designed-empty-state.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-route-inventory-published.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-shell-nav-present.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/shell-nav-present.mjs +69 -0
- package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +1 -1
- package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +3 -3
- package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +2 -2
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +1 -1
- package/blueprints/application-spa/docs/topics.md +1 -1
- package/blueprints/delivery-ci-workflows/CHANGELOG.md +31 -11
- package/blueprints/delivery-ci-workflows/README.md +3 -3
- package/blueprints/delivery-ci-workflows/blueprint.json +3 -2
- package/blueprints/delivery-ci-workflows/contributions/adrs/adr-702-delivery-ci-workflows-strict-coverage-gate.json +2 -2
- package/blueprints/delivery-ci-workflows/contributions/probes/node-gate-entrypoint.mjs +76 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/probe-utils.mjs +56 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/real-account-github-actions-run-record.mjs +139 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-node-gate-entrypoint.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-real-account-github-actions-run-record.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-workflow-template-shape.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/workflow-template-shape.mjs +94 -0
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-004.json +1 -1
- package/blueprints/delivery-ci-workflows/docs/topics.md +2 -3
- package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +4 -4
- package/blueprints/deploy-cloudflare-workers/README.md +3 -3
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +2 -2
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +2 -2
- package/blueprints/deploy-hetzner-server/CHANGELOG.md +98 -7
- package/blueprints/deploy-hetzner-server/blueprint.json +7 -6
- package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +46 -21
- package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +344 -83
- package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +211 -42
- package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +140 -22
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +111 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +158 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +154 -32
- package/blueprints/edge-cloudflare-access/CHANGELOG.md +6 -5
- package/blueprints/edge-cloudflare-access/blueprint.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +9 -1
- package/blueprints/edge-cloudflare-access/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +4 -7
- package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +4 -6
- package/blueprints/edge-cloudflare-tunnel/README.md +1 -2
- package/blueprints/edge-cloudflare-tunnel/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +2 -3
- package/blueprints/edge-cloudflare-turnstile/docs/topics.md +1 -1
- package/blueprints/email-smtp-resend/CHANGELOG.md +24 -8
- package/blueprints/email-smtp-resend/README.md +2 -2
- package/blueprints/email-smtp-resend/blueprint.json +3 -2
- package/blueprints/email-smtp-resend/contributions/probes/probe-utils.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/real-account-resend-send.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-real-account-resend-send.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-smtp-round-trip.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-unverified-sender-refusal.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/smtp-round-trip.mjs +43 -0
- package/blueprints/email-smtp-resend/contributions/probes/unverified-sender-refusal.mjs +99 -0
- package/blueprints/email-smtp-resend/docs/topics.md +2 -3
- package/blueprints/jobs-background/CHANGELOG.md +66 -5
- package/blueprints/jobs-background/README.md +2 -2
- package/blueprints/jobs-background/blueprint.json +3 -2
- package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +38 -10
- package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +28 -6
- package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +16 -2
- package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +102 -21
- package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +10 -2
- package/blueprints/jobs-background/contributions/probes/retry-and-fail-real-account.mjs +355 -0
- package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +33 -2
- package/blueprints/jobs-background/contributions/probes/run-retry-and-fail-real-account.mjs +12 -0
- package/blueprints/jobs-background/docs/topics.md +1 -1
- package/blueprints/jobs-background/guide/jobs-background.md +1 -1
- package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +25 -19
- package/blueprints/messaging-queue-cloudflare/README.md +12 -12
- package/blueprints/messaging-queue-cloudflare/blueprint.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +2 -2
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +180 -12
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +1 -1
- package/blueprints/messaging-queue-cloudflare/docs/topics.md +2 -2
- package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +2 -2
- package/blueprints/object-storage-s3/CHANGELOG.md +75 -4
- package/blueprints/object-storage-s3/blueprint.json +3 -2
- package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +73 -12
- package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +55 -7
- package/blueprints/object-storage-s3/contributions/probes/hetzner-object-storage-round-trip.mjs +102 -18
- package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +105 -36
- package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +104 -55
- package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +129 -7
- package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +80 -18
- package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +291 -37
- package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +5 -5
- package/blueprints/object-storage-s3/contributions/probes/run-hetzner-object-storage-round-trip.mjs +8 -5
- package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +6 -3
- package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +10 -2
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +1 -1
- package/blueprints/object-storage-s3/docs/topics.md +1 -1
- package/blueprints/object-storage-s3/guide/object-storage-s3.md +1 -1
- package/blueprints/observability-essentials/CHANGELOG.md +23 -7
- package/blueprints/observability-essentials/README.md +2 -2
- package/blueprints/observability-essentials/assets/probe-samples/probe-response-baseline.v2.json +1 -1
- package/blueprints/observability-essentials/blueprint.json +3 -2
- package/blueprints/observability-essentials/contributions/probes/liveness-probe.mjs +84 -0
- package/blueprints/observability-essentials/contributions/probes/metrics-endpoint.mjs +96 -0
- package/blueprints/observability-essentials/contributions/probes/probe-utils.mjs +52 -0
- package/blueprints/observability-essentials/contributions/probes/readiness-probe.mjs +171 -0
- package/blueprints/observability-essentials/contributions/probes/run-liveness-probe.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-metrics-endpoint.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-readiness-probe.mjs +3 -0
- package/blueprints/observability-essentials/docs/topics.md +2 -3
- package/blueprints/observability-logging/CHANGELOG.md +29 -4
- package/blueprints/observability-logging/README.md +2 -2
- package/blueprints/observability-logging/blueprint.json +3 -2
- package/blueprints/observability-logging/contributions/probes/correlation-id-flow.mjs +173 -0
- package/blueprints/observability-logging/contributions/probes/line-shape-and-fields.mjs +82 -0
- package/blueprints/observability-logging/contributions/probes/probe-utils.mjs +47 -0
- package/blueprints/observability-logging/contributions/probes/redaction-boundary.mjs +130 -0
- package/blueprints/observability-logging/contributions/probes/run-correlation-id-flow.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-line-shape-and-fields.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-redaction-boundary.mjs +3 -0
- package/blueprints/observability-probe-endpoints/CHANGELOG.md +23 -8
- package/blueprints/observability-probe-endpoints/README.md +3 -3
- package/blueprints/observability-probe-endpoints/blueprint.json +3 -2
- package/blueprints/observability-probe-endpoints/contributions/probes/kubernetes-startup-enabled.mjs +80 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/partial-profile-refusal.mjs +101 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/probe-utils.mjs +49 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/profile-boot-materialisation.mjs +69 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-kubernetes-startup-enabled.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-partial-profile-refusal.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-profile-boot-materialisation.mjs +3 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +2 -2
- package/blueprints/persistence-data-d1/CHANGELOG.md +16 -3
- package/blueprints/persistence-data-d1/README.md +2 -2
- package/blueprints/persistence-data-d1/blueprint.json +3 -2
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1404-persistence-data-d1-store-boundary.json +1 -1
- package/blueprints/persistence-data-d1/contributions/probes/facade-round-trip.mjs +140 -0
- package/blueprints/persistence-data-d1/contributions/probes/migrations-forward-only.mjs +66 -0
- package/blueprints/persistence-data-d1/contributions/probes/probe-utils.mjs +51 -0
- package/blueprints/persistence-data-d1/contributions/probes/real-account-d1-round-trip.mjs +133 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-facade-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-migrations-forward-only.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-real-account-d1-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/docs/topics.md +2 -3
- package/blueprints/persistence-data-postgres/CHANGELOG.md +84 -4
- package/blueprints/persistence-data-postgres/README.md +2 -2
- package/blueprints/persistence-data-postgres/blueprint.json +3 -2
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +87 -12
- package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +245 -19
- package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +109 -26
- package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +151 -38
- package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +24 -6
- package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +261 -48
- package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +76 -20
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +1 -1
- package/blueprints/persistence-data-postgres/docs/topics.md +1 -1
- package/blueprints/persistence-data-sqlite/CHANGELOG.md +16 -2
- package/blueprints/persistence-data-sqlite/README.md +2 -2
- package/blueprints/persistence-data-sqlite/blueprint.json +3 -2
- package/blueprints/persistence-data-sqlite/contributions/probes/boot-open-migrate.mjs +90 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/facade-round-trip.mjs +82 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/probe-utils.mjs +83 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-boot-open-migrate.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-facade-round-trip.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-wal-checkpoint.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/wal-checkpoint.mjs +137 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +5 -5
- package/blueprints/platform-cloudflare-cron-triggers/README.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +6 -10
- package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-kv/CHANGELOG.md +16 -12
- package/blueprints/platform-cloudflare-kv/README.md +2 -4
- package/blueprints/platform-cloudflare-kv/blueprint.json +2 -2
- package/blueprints/platform-cloudflare-kv/docs/topics.md +1 -1
- package/blueprints/platform-docker-compose-host/CHANGELOG.md +92 -5
- package/blueprints/platform-docker-compose-host/blueprint.json +2 -2
- package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +116 -29
- package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +181 -109
- package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +146 -26
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +238 -24
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +207 -21
- package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +246 -42
- package/blueprints/platform-docker-compose-host/docs/topics.md +1 -1
- package/blueprints/security-auth-clerk/CHANGELOG.md +18 -6
- package/blueprints/security-auth-clerk/README.md +3 -3
- package/blueprints/security-auth-clerk/assets/wiring/workers-wrangler-toml-shape.md +1 -1
- package/blueprints/security-auth-clerk/blueprint.json +3 -2
- package/blueprints/security-auth-clerk/contributions/probes/hosted-identity-ui-config.mjs +61 -0
- package/blueprints/security-auth-clerk/contributions/probes/probe-utils.mjs +188 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-principal-directory-round-trip.mjs +216 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-session-inventory.mjs +260 -0
- package/blueprints/security-auth-clerk/contributions/probes/role-model-adapter.mjs +53 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-hosted-identity-ui-config.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-principal-directory-round-trip.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-session-inventory.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-role-model-adapter.mjs +4 -0
- package/blueprints/security-auth-clerk/docs/topics.md +2 -3
- package/blueprints/security-auth-keycloak/CHANGELOG.md +18 -7
- package/blueprints/security-auth-keycloak/README.md +2 -2
- package/blueprints/security-auth-keycloak/blueprint.json +3 -2
- package/blueprints/security-auth-keycloak/contributions/probes/discovery-shape.mjs +68 -0
- package/blueprints/security-auth-keycloak/contributions/probes/introspection-shape.mjs +88 -0
- package/blueprints/security-auth-keycloak/contributions/probes/jwt-verifier-shape.mjs +86 -0
- package/blueprints/security-auth-keycloak/contributions/probes/probe-utils.mjs +180 -0
- package/blueprints/security-auth-keycloak/contributions/probes/real-account-realm-round-trip.mjs +91 -0
- package/blueprints/security-auth-keycloak/contributions/probes/role-adapter-shape.mjs +69 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-discovery-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-introspection-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-jwt-verifier-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-real-account-realm-round-trip.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-role-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/docs/topics.md +1 -2
- package/blueprints/security-auth-magic-link/CHANGELOG.md +15 -4
- package/blueprints/security-auth-magic-link/README.md +2 -2
- package/blueprints/security-auth-magic-link/assets/principal-registry-samples/single-address.md +1 -1
- package/blueprints/security-auth-magic-link/blueprint.json +3 -2
- package/blueprints/security-auth-magic-link/contributions/probes/probe-utils.mjs +174 -0
- package/blueprints/security-auth-magic-link/contributions/probes/real-account-magic-link-send.mjs +139 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-real-account-magic-link-send.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-entropy-shape.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-issue-verify.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-entropy-shape.mjs +60 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-issue-verify.mjs +90 -0
- package/blueprints/security-auth-magic-link/docs/topics.md +1 -1
- package/blueprints/security-auth-oauth2/CHANGELOG.md +16 -5
- package/blueprints/security-auth-oauth2/README.md +2 -2
- package/blueprints/security-auth-oauth2/blueprint.json +3 -2
- package/blueprints/security-auth-oauth2/contributions/probes/authorisation-code-flow-shape.mjs +259 -0
- package/blueprints/security-auth-oauth2/contributions/probes/pkce-challenge-shape.mjs +58 -0
- package/blueprints/security-auth-oauth2/contributions/probes/probe-utils.mjs +190 -0
- package/blueprints/security-auth-oauth2/contributions/probes/provider-adapter-shape.mjs +64 -0
- package/blueprints/security-auth-oauth2/contributions/probes/real-account-authorisation-code-flow.mjs +93 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-authorisation-code-flow-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-pkce-challenge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-provider-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-real-account-authorisation-code-flow.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-session-bridge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/session-bridge-shape.mjs +78 -0
- package/blueprints/security-auth-oauth2/docs/topics.md +1 -2
- package/blueprints/security-secrets-management/CHANGELOG.md +15 -4
- package/blueprints/security-secrets-management/README.md +2 -2
- package/blueprints/security-secrets-management/blueprint.json +3 -2
- package/blueprints/security-secrets-management/contributions/probes/add-recipient-rotation.mjs +107 -0
- package/blueprints/security-secrets-management/contributions/probes/encrypt-decrypt-round-trip.mjs +122 -0
- package/blueprints/security-secrets-management/contributions/probes/key-rotation.mjs +93 -0
- package/blueprints/security-secrets-management/contributions/probes/mismatched-key-refusal.mjs +74 -0
- package/blueprints/security-secrets-management/contributions/probes/probe-utils.mjs +214 -0
- package/blueprints/security-secrets-management/contributions/probes/run-add-recipient-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-encrypt-decrypt-round-trip.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-key-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-mismatched-key-refusal.mjs +4 -0
- package/blueprints/security-secrets-management/docs/topics.md +2 -3
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/harness-template.md +25 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +25 -0
- package/package.json +2 -2
- package/rcf/adrs/adr-4101-feedback-store-gitignored.json +20 -0
- package/rcf/adrs/adr-4102-fingerprint-and-labels.json +25 -0
- package/rcf/adrs/adr-4103-redaction-rule-based.json +20 -0
- package/rcf/adrs/adr-4104-destination-on-library.json +25 -0
- package/rcf/adrs/adr-4105-gh-ambient-auth.json +20 -0
- package/rcf/adrs/adr-4106-bundled-entries-terminal.json +20 -0
- package/rcf/adrs/adr-4107-stop-is-ask-event.json +30 -0
- package/rcf/adrs/adr-4108-hooks-in-committed-config.json +25 -0
- package/rcf/adrs/adr-4109-referee-validate-adr-crosslinks.json +25 -0
- package/rcf/adrs/adr-4110-referee-coverage-strict-by-default.json +25 -0
- package/rcf/adrs/adr-4111-referee-finalise-refusals.json +20 -0
- package/rcf/adrs/adr-4112-referee-finalise-verified-invariant.json +30 -0
- package/rcf/code-nodes/cn-600.json +45 -0
- package/rcf/code-nodes/cn-601.json +18 -0
- package/rcf/code-nodes/cn-602.json +15 -0
- package/rcf/code-nodes/cn-603.json +12 -0
- package/rcf/code-nodes/cn-604.json +14 -0
- package/rcf/code-nodes/cn-605.json +17 -0
- package/rcf/code-nodes/cn-606.json +12 -0
- package/rcf/code-nodes/cn-607.json +12 -0
- package/rcf/code-nodes/cn-608.json +14 -0
- package/rcf/code-nodes/cn-609.json +17 -0
- package/rcf/code-nodes/cn-620.json +18 -0
- package/rcf/code-nodes/cn-621.json +14 -0
- package/rcf/code-nodes/cn-622.json +15 -0
- package/rcf/code-nodes/cn-623.json +16 -0
- package/rcf/code-nodes/cn-624.json +14 -0
- package/rcf/code-nodes/cn-625.json +15 -0
- package/rcf/code-nodes/cn-626.json +13 -0
- package/rcf/code-nodes/cn-627.json +13 -0
- package/rcf/code-nodes/cn-628.json +14 -0
- package/rcf/code-nodes/cn-629.json +12 -0
- package/rcf/code-nodes/cn-630.json +12 -0
- package/rcf/code-nodes/cn-631.json +13 -0
- package/rcf/code-nodes/cn-632.json +13 -0
- package/rcf/fbs/fbs-180.json +45 -0
- package/rcf/fbs/fbs-181.json +45 -0
- package/rcf/fbs/fbs-182.json +42 -0
- package/rcf/fbs/fbs-183.json +50 -0
- package/rcf/fbs/fbs-184.json +49 -0
- package/rcf/fbs/fbs-185.json +34 -0
- package/rcf/fbs/fbs-186.json +16 -0
- package/rcf/fbs/fbs-187.json +17 -0
- package/rcf/fbs/fbs-188.json +17 -0
- package/rcf/fbs/fbs-189.json +17 -0
- package/rcf/requirements/req-155.json +13 -0
- package/rcf/requirements/req-156.json +13 -0
- package/rcf/requirements/req-157.json +13 -0
- package/rcf/requirements/req-158.json +13 -0
- package/rcf/requirements/req-159.json +13 -0
- package/rcf/requirements/req-160.json +13 -0
- package/rcf/requirements/req-161.json +13 -0
- package/rcf/requirements/req-162.json +13 -0
- package/rcf/requirements/req-163.json +13 -0
- package/rcf/requirements/req-164.json +13 -0
- package/rcf/requirements/req-165.json +13 -0
- package/rcf/tacs/tac-4101-feedback-cli.json +77 -0
- package/rcf/tacs/tac-4102-feedback-store.json +50 -0
- package/rcf/tacs/tac-4103-feedback-redact.json +39 -0
- package/rcf/tacs/tac-4104-feedback-fingerprint.json +33 -0
- package/rcf/tacs/tac-4105-feedback-render.json +45 -0
- package/rcf/tacs/tac-4106-feedback-destination.json +39 -0
- package/rcf/tacs/tac-4107-feedback-gh.json +43 -0
- package/rcf/tacs/tac-4108-feedback-hook.json +46 -0
- package/rcf/tacs/tac-4109-referee-validate-adr-crosslinks.json +20 -0
- package/rcf/tacs/tac-4110-referee-coverage-mode-selector.json +21 -0
- package/rcf/tacs/tac-4111-referee-finalise-per-ac-refusals.json +21 -0
- package/rcf/tacs/tac-4112-referee-finalise-verified-invariant.json +22 -0
- package/rcf/test-suites/ts-140.json +9 -9
- package/rcf/test-suites/ts-150.json +9 -9
- package/rcf/test-suites/ts-185.json +54 -0
- package/rcf/test-suites/ts-186.json +58 -0
- package/rcf/test-suites/ts-187.json +44 -0
- package/rcf/test-suites/ts-188.json +166 -0
- package/rcf/test-suites/ts-189.json +38 -0
- package/rcf/test-suites/ts-190.json +30 -0
- package/rcf/test-suites/ts-191.json +51 -0
- package/rcf/test-suites/ts-192.json +37 -0
- package/rcf/test-suites/ts-193.json +60 -0
- package/rcf/test-suites/ts-194.json +67 -0
- package/rcf/test-suites/ts-195.json +52 -0
- package/rcf/test-suites/ts-196.json +58 -0
- package/rcf/test-suites/ts-197.json +66 -0
- package/rcf/test-suites/ts-198.json +87 -0
- package/rcf/test-suites/ts-199.json +51 -0
- package/rcf/test-suites/ts-200.json +30 -0
- package/rcf/test-suites/ts-201.json +38 -0
- package/rcf/test-suites/ts-202.json +38 -0
- package/rcf/test-suites/ts-203.json +38 -0
- package/rcf/user-stories/us-15501.json +60 -0
- package/rcf/user-stories/us-15502.json +33 -0
- package/rcf/user-stories/us-15503.json +33 -0
- package/rcf/user-stories/us-15601.json +51 -0
- package/rcf/user-stories/us-15701.json +42 -0
- package/rcf/user-stories/us-15801.json +42 -0
- package/rcf/user-stories/us-15802.json +33 -0
- package/rcf/user-stories/us-15901.json +33 -0
- package/rcf/user-stories/us-15902.json +51 -0
- package/rcf/user-stories/us-16001.json +51 -0
- package/rcf/user-stories/us-16101.json +42 -0
- package/rcf/user-stories/us-16102.json +33 -0
- package/rcf/user-stories/us-16103.json +42 -0
- package/rcf/user-stories/us-16104.json +42 -0
- package/rcf/user-stories/us-16201.json +33 -0
- package/rcf/user-stories/us-16301.json +36 -0
- package/rcf/user-stories/us-16401.json +45 -0
- package/rcf/user-stories/us-16501.json +45 -0
- package/rcf/user-stories/us-16502.json +45 -0
- package/releases/releases.yaml +11 -1
- package/src/blueprint/library-loader.js +48 -0
- package/src/blueprint/library-registry.js +13 -0
- package/src/browser-verify/pack-runner.js +7 -12
- package/src/build/mark.js +1 -1
- package/src/cli/blueprint-library.js +149 -0
- package/src/cli/coverage.js +49 -24
- package/src/cli/doctor.js +195 -7
- package/src/cli/feedback.js +2204 -0
- package/src/cli/finalise.js +158 -1
- package/src/cli/help.js +6 -0
- package/src/cli/init.js +63 -0
- package/src/cli/update.js +21 -1
- package/src/core/store/walker.js +33 -0
- package/src/core/store/writer.js +23 -0
- package/src/feedback/destination.js +361 -0
- package/src/feedback/fingerprint.js +132 -0
- package/src/feedback/gh.js +376 -0
- package/src/feedback/hook.js +183 -0
- package/src/feedback/labels.js +87 -0
- package/src/feedback/redact-allowlist.json +14 -0
- package/src/feedback/redact.js +1108 -0
- package/src/feedback/render.js +267 -0
- package/src/feedback/store.js +604 -0
- package/src/finalise/index.js +4 -0
- package/src/finalise/ingest.js +61 -0
- package/src/finalise/ship-without-eval.js +19 -7
- package/src/mcp/tools.js +8 -2
- package/src/setup/feedback-hooks.js +397 -0
- package/src/setup/managed-gitignore.js +3 -0
- package/src/view/html-page.js +5 -5
- package/src/view/style.css +2 -2
|
@@ -0,0 +1,361 @@
|
|
|
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 -> CORE_REPO (shelf; public)
|
|
11
|
+
// 3. --kind blueprint, libraryPrefix -> registry entry issuesRepo
|
|
12
|
+
// (declared destination wins;
|
|
13
|
+
// visibility from the entry)
|
|
14
|
+
// 4. registry entry with no issuesRepo -> derive from sourceRef when
|
|
15
|
+
// it parses as
|
|
16
|
+
// git+https://github.com/OWNER/REPO(.git)#ref
|
|
17
|
+
// (marked derived: true;
|
|
18
|
+
// visibility defaults to
|
|
19
|
+
// public unless the entry
|
|
20
|
+
// already asserted private)
|
|
21
|
+
// 5. anything else -> unresolved (reason names
|
|
22
|
+
// the why, publisherContact
|
|
23
|
+
// carries the registry
|
|
24
|
+
// contact when known)
|
|
25
|
+
//
|
|
26
|
+
// The CORE_REPO constant is derived from packages/rcf-lite/package.json
|
|
27
|
+
// bugs.url. Because a resolver call is on the hot path of preview and
|
|
28
|
+
// submit, and because reading package.json every call is wasteful and
|
|
29
|
+
// hard to test in isolation, the value is cached at module load time.
|
|
30
|
+
// A dedicated `resolveCoreRepo()` helper (also exported) does the
|
|
31
|
+
// parse; consumers with their own package.json can call it directly
|
|
32
|
+
// and the resolver's CORE_REPO getter reads through it.
|
|
33
|
+
|
|
34
|
+
import { readFile } from 'node:fs/promises';
|
|
35
|
+
import { dirname, resolve as resolvePath } from 'node:path';
|
|
36
|
+
import { fileURLToPath } from 'node:url';
|
|
37
|
+
|
|
38
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
39
|
+
// packages/rcf-lite/src/feedback -> packages/rcf-lite/package.json.
|
|
40
|
+
const PACKAGE_JSON_PATH = resolvePath(here, '..', '..', 'package.json');
|
|
41
|
+
const CORE_REPO_FALLBACK = 'Stravica/rcf-lite';
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The Stravica/rcf-lite constant that every core-kind entry and every
|
|
45
|
+
* shelf-blueprint entry routes to. Sourced from
|
|
46
|
+
* `packages/rcf-lite/package.json:bugs.url` at module load so a rename
|
|
47
|
+
* only ripples through one file; a matching unit test pins the constant
|
|
48
|
+
* to the package.json value at test time so a drift is caught in CI.
|
|
49
|
+
*
|
|
50
|
+
* @type {string}
|
|
51
|
+
*/
|
|
52
|
+
export let CORE_REPO = CORE_REPO_FALLBACK;
|
|
53
|
+
|
|
54
|
+
/** Guard against double-init during test loops. */
|
|
55
|
+
let coreRepoInitialised = false;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Parse `bugs.url` from a package.json object and return `OWNER/REPO`.
|
|
59
|
+
* Accepts the trailing `/issues`, an `.git` suffix and either the
|
|
60
|
+
* string or the object shape npm allows on `bugs`.
|
|
61
|
+
*
|
|
62
|
+
* @param {object | undefined | null} pkg
|
|
63
|
+
* @returns {string | null}
|
|
64
|
+
*/
|
|
65
|
+
export function parseBugsRepo(pkg) {
|
|
66
|
+
if (pkg == null) return null;
|
|
67
|
+
const bugs = typeof pkg.bugs === 'string' ? pkg.bugs : pkg?.bugs?.url;
|
|
68
|
+
if (typeof bugs !== 'string' || bugs.length === 0) return null;
|
|
69
|
+
const withIssues = bugs.match(/github\.com\/([^/]+)\/([^/#?]+?)(?:\.git)?\/issues\/?(?:[/?#].*)?$/i);
|
|
70
|
+
if (withIssues) return `${withIssues[1]}/${withIssues[2]}`;
|
|
71
|
+
const bare = bugs.match(/github\.com\/([^/]+)\/([^/#?]+?)(?:\.git)?\/?$/i);
|
|
72
|
+
if (bare) return `${bare[1]}/${bare[2]}`;
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Read `packages/rcf-lite/package.json` and populate `CORE_REPO`. Safe
|
|
78
|
+
* to call more than once; a failed read leaves the fallback in place.
|
|
79
|
+
* The resolver auto-inits on first `resolve()` call, so most callers
|
|
80
|
+
* never touch this directly; tests call it to force a fresh read.
|
|
81
|
+
*
|
|
82
|
+
* @returns {Promise<string>}
|
|
83
|
+
*/
|
|
84
|
+
export async function initCoreRepo() {
|
|
85
|
+
try {
|
|
86
|
+
const text = await readFile(PACKAGE_JSON_PATH, 'utf8');
|
|
87
|
+
const pkg = JSON.parse(text);
|
|
88
|
+
const parsed = parseBugsRepo(pkg);
|
|
89
|
+
if (parsed) CORE_REPO = parsed;
|
|
90
|
+
} catch {
|
|
91
|
+
// Missing or unreadable package.json leaves the fallback active.
|
|
92
|
+
// A dedicated test pins the value in CI so this branch never ships.
|
|
93
|
+
}
|
|
94
|
+
coreRepoInitialised = true;
|
|
95
|
+
return CORE_REPO;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Parse a git sourceRef of the shape `git+https://github.com/OWNER/REPO(.git)#ref`
|
|
100
|
+
* (or `git+ssh://git@github.com:OWNER/REPO.git#ref`, the two shapes
|
|
101
|
+
* `library add` accepts) into `OWNER/REPO`. Anything else returns null;
|
|
102
|
+
* the resolver treats that as "cannot derive", not as an error.
|
|
103
|
+
*
|
|
104
|
+
* @param {string} sourceRef
|
|
105
|
+
* @returns {string | null}
|
|
106
|
+
*/
|
|
107
|
+
export function parseGithubSource(sourceRef) {
|
|
108
|
+
if (typeof sourceRef !== 'string' || sourceRef.length === 0) return null;
|
|
109
|
+
// git+https://github.com/OWNER/REPO(.git)(#ref)
|
|
110
|
+
const https = sourceRef.match(/^git\+https?:\/\/github\.com\/([^/]+)\/([^/#?]+?)(?:\.git)?(?:#.*)?$/i);
|
|
111
|
+
if (https) return `${https[1]}/${https[2]}`;
|
|
112
|
+
// git+ssh://git@github.com:OWNER/REPO.git(#ref) or git+ssh://git@github.com/OWNER/REPO.git(#ref)
|
|
113
|
+
const ssh = sourceRef.match(/^git\+ssh:\/\/git@github\.com[:\/]([^/]+)\/([^/#?]+?)(?:\.git)?(?:#.*)?$/i);
|
|
114
|
+
if (ssh) return `${ssh[1]}/${ssh[2]}`;
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Look up a blueprint record on `manifest.blueprints[]` by ref. Accepts
|
|
120
|
+
* the shelf slug (`security-auth-magic-link`), the prefix:slug form
|
|
121
|
+
* (`wsd:std-error-envelope`) and the effective slug already stamped
|
|
122
|
+
* onto the record (`wsd-std-error-envelope`).
|
|
123
|
+
*
|
|
124
|
+
* F-slice-3-01: a QUALIFIED ref (`prefix:slug`) must resolve to a
|
|
125
|
+
* record whose libraryPrefix matches the qualifier. Falling back to
|
|
126
|
+
* an unqualified shelf record on slug collision would route a
|
|
127
|
+
* private WSD finding to the public Stravica/rcf-lite repo. The
|
|
128
|
+
* matcher therefore has two passes: first, any record whose stamped
|
|
129
|
+
* effectiveSlug OR (slug + libraryPrefix) matches the qualifier
|
|
130
|
+
* wins; only when the ref is unqualified do bare-slug matches apply.
|
|
131
|
+
*
|
|
132
|
+
* @param {object | null | undefined} manifest
|
|
133
|
+
* @param {string} ref
|
|
134
|
+
* @returns {object | null}
|
|
135
|
+
*/
|
|
136
|
+
export function findBlueprintRecord(manifest, ref) {
|
|
137
|
+
const list = Array.isArray(manifest?.blueprints) ? manifest.blueprints : [];
|
|
138
|
+
if (typeof ref !== 'string' || ref.length === 0) return null;
|
|
139
|
+
|
|
140
|
+
// Qualified `prefix:slug` (and the equivalent `prefix-slug`
|
|
141
|
+
// effective-slug shape) must NEVER match a shelf record whose
|
|
142
|
+
// libraryPrefix does not equal the qualifier. F-slice-3-01: a
|
|
143
|
+
// qualified WSD ref must not fall back to a public shelf record
|
|
144
|
+
// on slug collision.
|
|
145
|
+
if (ref.includes(':')) {
|
|
146
|
+
const [pre, slug] = ref.split(':');
|
|
147
|
+
if (pre && slug) {
|
|
148
|
+
const effective = `${pre}-${slug}`;
|
|
149
|
+
for (const r of list) {
|
|
150
|
+
if (!r || typeof r !== 'object') continue;
|
|
151
|
+
if (r.libraryPrefix !== pre) continue;
|
|
152
|
+
const candidates = recordCandidates(r);
|
|
153
|
+
if (candidates.includes(ref) || candidates.includes(effective) || candidates.includes(slug)) return r;
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Unqualified ref: match by any candidate. A record with a
|
|
160
|
+
// libraryPrefix still matches, but only through its stamped
|
|
161
|
+
// canonical effective slug (`libraryPrefix-slug`) - never through
|
|
162
|
+
// a bare, unqualified slug that could collide with a shelf record.
|
|
163
|
+
for (const r of list) {
|
|
164
|
+
if (!r || typeof r !== 'object') continue;
|
|
165
|
+
const isQualifiedRecord = typeof r.libraryPrefix === 'string' && r.libraryPrefix.length > 0;
|
|
166
|
+
if (isQualifiedRecord) {
|
|
167
|
+
const canonical = recordEffectiveSlug(r);
|
|
168
|
+
if (canonical && ref === canonical) return r;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const candidates = recordCandidates(r);
|
|
172
|
+
if (candidates.includes(ref)) return r;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The candidate name set stamped on a manifest record: any of
|
|
179
|
+
* effectiveSlug, slug, name that are non-empty strings.
|
|
180
|
+
*
|
|
181
|
+
* @param {object} record
|
|
182
|
+
* @returns {string[]}
|
|
183
|
+
*/
|
|
184
|
+
function recordCandidates(record) {
|
|
185
|
+
return [record.effectiveSlug, record.slug, record.name].filter(
|
|
186
|
+
(s) => typeof s === 'string' && s.length > 0,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* The canonical effective slug for a qualified manifest record. If
|
|
192
|
+
* the record already carries `effectiveSlug`, that wins; otherwise
|
|
193
|
+
* synthesise it from `libraryPrefix` + `slug` (either the slug is
|
|
194
|
+
* already prefixed, or we prepend the prefix).
|
|
195
|
+
*
|
|
196
|
+
* @param {object} record
|
|
197
|
+
* @returns {string | null}
|
|
198
|
+
*/
|
|
199
|
+
function recordEffectiveSlug(record) {
|
|
200
|
+
if (typeof record.effectiveSlug === 'string' && record.effectiveSlug.length > 0) return record.effectiveSlug;
|
|
201
|
+
const pre = typeof record.libraryPrefix === 'string' ? record.libraryPrefix : '';
|
|
202
|
+
const slug = typeof record.slug === 'string' ? record.slug : '';
|
|
203
|
+
if (!pre || !slug) return null;
|
|
204
|
+
return slug.startsWith(`${pre}-`) ? slug : `${pre}-${slug}`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @typedef {object} Destination
|
|
209
|
+
* @property {string | null} repo OWNER/REPO or null when unresolved
|
|
210
|
+
* @property {'public' | 'private' | 'unresolved'} visibility
|
|
211
|
+
* @property {'core' | 'shelf' | 'library'} kind
|
|
212
|
+
* @property {boolean} derived true when repo came from sourceRef derivation
|
|
213
|
+
* @property {string} [reason] filled on unresolved: 'no-issues-field' | 'no-github-source' | 'no-libraryprefix-record' | 'unknown-target'
|
|
214
|
+
* @property {string} [publisherContact] registry entry's publisher.contact (bundle uses it)
|
|
215
|
+
* @property {string} [source] 'library-manifest' | 'sourceRef-derivation' | 'package-bugs-url' | 'shelf-constant'
|
|
216
|
+
*/
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Resolve one entry to its destination shape. Pure over the inputs.
|
|
220
|
+
*
|
|
221
|
+
* @param {object} entry a feedback entry (design §4.1)
|
|
222
|
+
* @param {object} [context]
|
|
223
|
+
* @param {object} [context.manifest] parsed rcf/manifest.json
|
|
224
|
+
* @param {object} [context.registry] parsed rcf/blueprint-libraries.json
|
|
225
|
+
* @returns {Promise<Destination>}
|
|
226
|
+
*/
|
|
227
|
+
export async function resolve(entry, context = {}) {
|
|
228
|
+
if (!coreRepoInitialised) await initCoreRepo();
|
|
229
|
+
const manifest = context.manifest ?? null;
|
|
230
|
+
const registry = context.registry ?? { libraries: [] };
|
|
231
|
+
const kind = entry?.kind;
|
|
232
|
+
|
|
233
|
+
if (kind === 'core') {
|
|
234
|
+
return {
|
|
235
|
+
repo: CORE_REPO,
|
|
236
|
+
visibility: 'public',
|
|
237
|
+
kind: 'core',
|
|
238
|
+
derived: false,
|
|
239
|
+
source: 'package-bugs-url',
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
if (kind !== 'blueprint') {
|
|
243
|
+
return {
|
|
244
|
+
repo: null,
|
|
245
|
+
visibility: 'unresolved',
|
|
246
|
+
kind: 'library',
|
|
247
|
+
derived: false,
|
|
248
|
+
reason: 'unknown-target',
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const ref = entry?.target?.ref;
|
|
253
|
+
const record = findBlueprintRecord(manifest, ref);
|
|
254
|
+
if (!record) {
|
|
255
|
+
return {
|
|
256
|
+
repo: null,
|
|
257
|
+
visibility: 'unresolved',
|
|
258
|
+
kind: 'library',
|
|
259
|
+
derived: false,
|
|
260
|
+
reason: 'unknown-target',
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const libraryPrefix = record.libraryPrefix ?? entry?.target?.libraryPrefix ?? null;
|
|
265
|
+
|
|
266
|
+
// Shelf blueprint (no libraryPrefix) -> Stravica/rcf-lite.
|
|
267
|
+
if (!libraryPrefix) {
|
|
268
|
+
return {
|
|
269
|
+
repo: CORE_REPO,
|
|
270
|
+
visibility: 'public',
|
|
271
|
+
kind: 'shelf',
|
|
272
|
+
derived: false,
|
|
273
|
+
source: 'package-bugs-url',
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const libEntry = findLibraryEntry(registry, libraryPrefix);
|
|
278
|
+
if (!libEntry) {
|
|
279
|
+
return {
|
|
280
|
+
repo: null,
|
|
281
|
+
visibility: 'unresolved',
|
|
282
|
+
kind: 'library',
|
|
283
|
+
derived: false,
|
|
284
|
+
reason: 'no-libraryprefix-record',
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const contact = typeof libEntry?.publisher?.contact === 'string'
|
|
289
|
+
? libEntry.publisher.contact
|
|
290
|
+
: undefined;
|
|
291
|
+
|
|
292
|
+
// Declared destination wins.
|
|
293
|
+
if (typeof libEntry.issuesRepo === 'string' && libEntry.issuesRepo.length > 0) {
|
|
294
|
+
const declaredVisibility = libEntry.issuesVisibility === 'private' ? 'private'
|
|
295
|
+
: libEntry.issuesVisibility === 'public' ? 'public'
|
|
296
|
+
: 'public';
|
|
297
|
+
return {
|
|
298
|
+
repo: libEntry.issuesRepo,
|
|
299
|
+
visibility: declaredVisibility,
|
|
300
|
+
kind: 'library',
|
|
301
|
+
derived: false,
|
|
302
|
+
source: 'library-manifest',
|
|
303
|
+
...(contact ? { publisherContact: contact } : {}),
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Fallback: derive from sourceRef when it parses as a github URL.
|
|
308
|
+
const derived = parseGithubSource(libEntry.sourceRef ?? '');
|
|
309
|
+
if (derived) {
|
|
310
|
+
return {
|
|
311
|
+
repo: derived,
|
|
312
|
+
visibility: 'public',
|
|
313
|
+
kind: 'library',
|
|
314
|
+
derived: true,
|
|
315
|
+
source: 'sourceRef-derivation',
|
|
316
|
+
...(contact ? { publisherContact: contact } : {}),
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Neither declared nor derivable: unresolved.
|
|
321
|
+
return {
|
|
322
|
+
repo: null,
|
|
323
|
+
visibility: 'unresolved',
|
|
324
|
+
kind: 'library',
|
|
325
|
+
derived: false,
|
|
326
|
+
reason: libEntry.sourceRef ? 'no-github-source' : 'no-issues-field',
|
|
327
|
+
...(contact ? { publisherContact: contact } : {}),
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Enumerate every registered library and flag the ones the resolver
|
|
333
|
+
* cannot produce a destination for (no issues field and no derivable
|
|
334
|
+
* github source). Doctor's `feedback-destinations` check consumes this;
|
|
335
|
+
* the shape is `{ libraryPrefix, reason, publisherContact? }`.
|
|
336
|
+
*
|
|
337
|
+
* @param {object} registry
|
|
338
|
+
* @returns {Array<{ libraryPrefix: string, reason: 'no-issues-field' | 'no-github-source', publisherContact?: string }>}
|
|
339
|
+
*/
|
|
340
|
+
export function listUnresolvedLibraries(registry) {
|
|
341
|
+
const out = [];
|
|
342
|
+
const libs = Array.isArray(registry?.libraries) ? registry.libraries : [];
|
|
343
|
+
for (const lib of libs) {
|
|
344
|
+
if (typeof lib?.libraryPrefix !== 'string') continue;
|
|
345
|
+
if (typeof lib.issuesRepo === 'string' && lib.issuesRepo.length > 0) continue;
|
|
346
|
+
const derived = parseGithubSource(lib.sourceRef ?? '');
|
|
347
|
+
if (derived) continue;
|
|
348
|
+
const contact = typeof lib?.publisher?.contact === 'string' ? lib.publisher.contact : undefined;
|
|
349
|
+
out.push({
|
|
350
|
+
libraryPrefix: lib.libraryPrefix,
|
|
351
|
+
reason: lib.sourceRef ? 'no-github-source' : 'no-issues-field',
|
|
352
|
+
...(contact ? { publisherContact: contact } : {}),
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
return out;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function findLibraryEntry(registry, libraryPrefix) {
|
|
359
|
+
const libs = Array.isArray(registry?.libraries) ? registry.libraries : [];
|
|
360
|
+
return libs.find((l) => l?.libraryPrefix === libraryPrefix) ?? null;
|
|
361
|
+
}
|
|
@@ -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
|
+
}
|