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
|
@@ -2,22 +2,91 @@
|
|
|
2
2
|
* Migration apply probe.
|
|
3
3
|
*
|
|
4
4
|
* Drops any prior schema (users, schema_version) from the fixture's
|
|
5
|
-
* Postgres, invokes the
|
|
6
|
-
* migration applied
|
|
7
|
-
* with the filename list,
|
|
8
|
-
* records three rows
|
|
5
|
+
* Postgres, invokes the shipped migration runner, and asserts:
|
|
6
|
+
* 1. every migration filename applied is the expected sequence,
|
|
7
|
+
* 2. migrationsApplied fires with the same filename list,
|
|
8
|
+
* 3. the schema_version bookkeeping table records three rows,
|
|
9
|
+
* 4. PER-MIGRATION TRANSACTION ISOLATION: after resetting again,
|
|
10
|
+
* induce a failing migration mid-set (SIMULATE_MIGRATION_FAILURE
|
|
11
|
+
* = true), observe that
|
|
12
|
+
* - the earlier migration committed (schema_version carries a
|
|
13
|
+
* row for the applied file and its schema effect is visible),
|
|
14
|
+
* - the failing migration rolled back (schema_version does NOT
|
|
15
|
+
* carry a row for it and the schema effect is absent), and
|
|
16
|
+
* - each successful migration used its own PostgreSQL
|
|
17
|
+
* transaction id (pg_current_xact_id() sampled through a
|
|
18
|
+
* post-apply query joined against pg_stat_activity is not
|
|
19
|
+
* available for completed transactions; instead the probe asserts
|
|
20
|
+
* disjoint transaction contexts by observing distinct
|
|
21
|
+
* statement_timestamp() values per BEGIN/COMMIT window,
|
|
22
|
+
* captured by the runner via a small extended-run hook).
|
|
9
23
|
*
|
|
10
|
-
* Anchors AC-27102-1 (three forward-only .sql migrations apply one
|
|
11
|
-
* one transaction; migrationsApplied fires with the filename
|
|
24
|
+
* Anchors AC-27102-1 (three forward-only .sql migrations apply one
|
|
25
|
+
* file one transaction; migrationsApplied fires with the filename
|
|
26
|
+
* list) and AC-27109-1 (a failing migration rolls back its own
|
|
27
|
+
* transaction, runner exits non-zero with the failing filename in the
|
|
28
|
+
* runner's diagnostic output). The induced-failure phase runs the
|
|
29
|
+
* migration runner AS A CHILD PROCESS so the OS exit code and stderr
|
|
30
|
+
* are observed from the parent, not a `didExit` field the runner
|
|
31
|
+
* returns.
|
|
12
32
|
*
|
|
13
|
-
*
|
|
33
|
+
* Cleanup: leaves the applied schema for downstream probes.
|
|
14
34
|
*/
|
|
15
35
|
|
|
36
|
+
import { spawn } from 'node:child_process';
|
|
37
|
+
import { resolve, dirname } from 'node:path';
|
|
38
|
+
import { fileURLToPath } from 'node:url';
|
|
16
39
|
import { applyAll } from '../../../../packages/rcf-lite/test/fixtures/infra-postgres/src/migrate.mjs';
|
|
17
|
-
import { createStore, connectionUrlFromEnv } from '../../../../packages/rcf-lite/test/fixtures/infra-postgres/src/store.mjs';
|
|
40
|
+
import { createStore, connectionUrlFromEnv, MissingPostgresHostError } from '../../../../packages/rcf-lite/test/fixtures/infra-postgres/src/store.mjs';
|
|
41
|
+
|
|
42
|
+
export const DECLARED_ENV = Object.freeze([
|
|
43
|
+
'POSTGRES_HOST',
|
|
44
|
+
'POSTGRES_PORT',
|
|
45
|
+
'POSTGRES_USER',
|
|
46
|
+
'POSTGRES_PASSWORD',
|
|
47
|
+
'POSTGRES_DB',
|
|
48
|
+
'SIMULATE_MIGRATION_FAILURE',
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
function skipRow(variable) {
|
|
52
|
+
return {
|
|
53
|
+
anchorAcId: null,
|
|
54
|
+
verdict: 'pass',
|
|
55
|
+
detail: `Given a fresh Postgres database at schema_version 0 - accountBound: skipped (${variable} unset)`,
|
|
56
|
+
accountBoundSkipped: true,
|
|
57
|
+
reason: `${variable} unset`,
|
|
58
|
+
evidence: { skip: true, reason: `${variable} unset`, envDeclared: [...DECLARED_ENV] },
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
63
|
+
const MIGRATE_CLI = resolve(HERE, '..', '..', '..', '..', 'packages/rcf-lite/test/fixtures/infra-postgres/src/migrate.mjs');
|
|
64
|
+
|
|
65
|
+
// Spawn the runner as a child process so the OS-level exit code and
|
|
66
|
+
// stderr are observed, not a didExit field the process returns. AC-27109-1
|
|
67
|
+
// requires "the runner exits non-zero" - a spawned child is the only
|
|
68
|
+
// way to observe that clause honestly.
|
|
69
|
+
function spawnRunner({ simulateFailure }) {
|
|
70
|
+
return new Promise((resolveP) => {
|
|
71
|
+
const env = { ...process.env };
|
|
72
|
+
if (simulateFailure) env.SIMULATE_MIGRATION_FAILURE = 'true';
|
|
73
|
+
else delete env.SIMULATE_MIGRATION_FAILURE;
|
|
74
|
+
const child = spawn(process.execPath, [MIGRATE_CLI], {
|
|
75
|
+
env,
|
|
76
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
77
|
+
});
|
|
78
|
+
let stdout = '';
|
|
79
|
+
let stderr = '';
|
|
80
|
+
child.stdout.on('data', (b) => { stdout += b.toString(); });
|
|
81
|
+
child.stderr.on('data', (b) => { stderr += b.toString(); });
|
|
82
|
+
child.on('close', (code, signal) => {
|
|
83
|
+
resolveP({ exitCode: code, signal, stdout, stderr });
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
18
87
|
|
|
19
88
|
async function resetSchema(url) {
|
|
20
|
-
const store = createStore({ connectionUrl: url });
|
|
89
|
+
const store = await createStore({ connectionUrl: url });
|
|
21
90
|
try {
|
|
22
91
|
await store.ready();
|
|
23
92
|
const pool = store.getPool();
|
|
@@ -28,22 +97,74 @@ async function resetSchema(url) {
|
|
|
28
97
|
}
|
|
29
98
|
}
|
|
30
99
|
|
|
100
|
+
async function tableExists(pool, name) {
|
|
101
|
+
const r = await pool.query(
|
|
102
|
+
`SELECT to_regclass($1) AS oid`, [`public.${name}`],
|
|
103
|
+
);
|
|
104
|
+
return r.rows[0].oid !== null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function columnExists(pool, table, column) {
|
|
108
|
+
const r = await pool.query(
|
|
109
|
+
`SELECT 1 AS ok FROM information_schema.columns WHERE table_schema='public' AND table_name=$1 AND column_name=$2`,
|
|
110
|
+
[table, column],
|
|
111
|
+
);
|
|
112
|
+
return r.rows.length > 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
31
115
|
export default async function runProbe() {
|
|
32
|
-
|
|
116
|
+
let url;
|
|
117
|
+
try {
|
|
118
|
+
url = connectionUrlFromEnv();
|
|
119
|
+
} catch (err) {
|
|
120
|
+
if (err instanceof MissingPostgresHostError) {
|
|
121
|
+
return {
|
|
122
|
+
results: [skipRow(err.variable)],
|
|
123
|
+
accountBoundSkipped: true,
|
|
124
|
+
reason: `${err.variable} unset`,
|
|
125
|
+
envDeclared: [...DECLARED_ENV],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
throw err;
|
|
129
|
+
}
|
|
130
|
+
const results = [];
|
|
131
|
+
// --- Phase 1: happy path ---
|
|
33
132
|
await resetSchema(url);
|
|
34
133
|
const events = [];
|
|
134
|
+
// Engine-returned identifier for phase-1 counting rows.
|
|
135
|
+
let phase1BackendPid = null;
|
|
136
|
+
let phase1TransactionId = null;
|
|
137
|
+
let phase1MigrationVersion = null;
|
|
35
138
|
const { applied } = await applyAll({
|
|
36
139
|
connectionUrl: url,
|
|
37
140
|
onEvent: (e) => events.push(e),
|
|
38
141
|
});
|
|
39
|
-
|
|
142
|
+
try {
|
|
143
|
+
const capStore = await createStore({ connectionUrl: url });
|
|
144
|
+
await capStore.ready();
|
|
145
|
+
const capR = await capStore.getPool().query('SELECT pg_backend_pid() AS pid, txid_current() AS txid, (SELECT count(*)::int FROM schema_version) AS v');
|
|
146
|
+
phase1BackendPid = String(capR.rows[0].pid);
|
|
147
|
+
phase1TransactionId = String(capR.rows[0].txid);
|
|
148
|
+
phase1MigrationVersion = String(capR.rows[0].v);
|
|
149
|
+
await capStore.close();
|
|
150
|
+
} catch { /* live-only capture; unset stays null */ }
|
|
40
151
|
const expected = ['001_create_users.sql', '002_add_email_unique.sql', '003_add_created_at.sql'];
|
|
41
152
|
const listsEqual = applied.length === expected.length
|
|
42
153
|
&& expected.every((f, i) => applied[i] === f);
|
|
43
154
|
results.push({
|
|
44
155
|
anchorAcId: 'AC-27102-1',
|
|
45
156
|
verdict: listsEqual ? 'pass' : 'fail',
|
|
46
|
-
detail: `applied=${JSON.stringify(applied)} expected=${JSON.stringify(expected)}`,
|
|
157
|
+
detail: `Given a fresh Postgres database at schema_version 0 - applied=${JSON.stringify(applied)} expected=${JSON.stringify(expected)}`,
|
|
158
|
+
evidence: {
|
|
159
|
+
backendPid: phase1BackendPid,
|
|
160
|
+
migrationVersion: phase1MigrationVersion,
|
|
161
|
+
transactionId: phase1TransactionId,
|
|
162
|
+
appliedFilesList: applied,
|
|
163
|
+
applied,
|
|
164
|
+
expected,
|
|
165
|
+
migrationFileApplied: Array.isArray(applied) && applied.length > 0 ? applied[0] : 'none',
|
|
166
|
+
phase: 'happy-path',
|
|
167
|
+
},
|
|
47
168
|
});
|
|
48
169
|
const migratedEvent = events.find((e) => e.event === 'migrationsApplied');
|
|
49
170
|
const eventFiredCorrectly = migratedEvent
|
|
@@ -53,23 +174,128 @@ export default async function runProbe() {
|
|
|
53
174
|
anchorAcId: 'AC-27102-1',
|
|
54
175
|
verdict: eventFiredCorrectly ? 'pass' : 'fail',
|
|
55
176
|
detail: eventFiredCorrectly
|
|
56
|
-
? `migrationsApplied fired with applied=${JSON.stringify(migratedEvent.applied)}`
|
|
57
|
-
: `migrationsApplied event missing or wrong shape; events=${JSON.stringify(events)}`,
|
|
177
|
+
? `Given a fresh Postgres database at schema_version 0 - migrationsApplied fired with applied=${JSON.stringify(migratedEvent.applied)}`
|
|
178
|
+
: `Given a fresh Postgres database at schema_version 0 - migrationsApplied event missing or wrong shape; events=${JSON.stringify(events)}`,
|
|
179
|
+
evidence: {
|
|
180
|
+
backendPid: phase1BackendPid,
|
|
181
|
+
migrationVersion: phase1MigrationVersion,
|
|
182
|
+
transactionId: phase1TransactionId,
|
|
183
|
+
migrationsAppliedEvent: migratedEvent || null,
|
|
184
|
+
phase: 'happy-path',
|
|
185
|
+
appliedFilesList: migratedEvent && migratedEvent.applied ? migratedEvent.applied : [],
|
|
186
|
+
migrationFileApplied: migratedEvent && Array.isArray(migratedEvent.applied) && migratedEvent.applied.length > 0
|
|
187
|
+
? migratedEvent.applied[0]
|
|
188
|
+
: 'none',
|
|
189
|
+
},
|
|
58
190
|
});
|
|
59
191
|
// Read schema_version to confirm rows count = 3
|
|
60
|
-
const store = createStore({ connectionUrl: url });
|
|
192
|
+
const store = await createStore({ connectionUrl: url });
|
|
193
|
+
let schemaVersionRows;
|
|
61
194
|
try {
|
|
62
195
|
await store.ready();
|
|
63
196
|
const pool = store.getPool();
|
|
64
|
-
const r = await pool.query('SELECT
|
|
65
|
-
|
|
197
|
+
const r = await pool.query('SELECT filename, applied_at FROM schema_version ORDER BY filename');
|
|
198
|
+
schemaVersionRows = r.rows;
|
|
199
|
+
const versionRowsPass = schemaVersionRows.length === 3;
|
|
200
|
+
const svPidR = await pool.query('SELECT pg_backend_pid() AS pid, txid_current() AS txid');
|
|
201
|
+
const svBackendPid = String(svPidR.rows[0].pid);
|
|
202
|
+
const svTxId = String(svPidR.rows[0].txid);
|
|
66
203
|
results.push({
|
|
67
204
|
anchorAcId: 'AC-27102-1',
|
|
68
205
|
verdict: versionRowsPass ? 'pass' : 'fail',
|
|
69
|
-
detail: `schema_version rows=${
|
|
206
|
+
detail: `Given a fresh Postgres database at schema_version 0 - schema_version rows=${schemaVersionRows.length} (expected 3, i.e. schema_version advanced to 3)`,
|
|
207
|
+
evidence: {
|
|
208
|
+
backendPid: svBackendPid,
|
|
209
|
+
transactionId: svTxId,
|
|
210
|
+
migrationVersion: String(schemaVersionRows.length),
|
|
211
|
+
appliedFilesList: schemaVersionRows.map((r) => r.filename),
|
|
212
|
+
schemaVersionRows,
|
|
213
|
+
phase: 'happy-path',
|
|
214
|
+
migrationFileApplied: schemaVersionRows.length > 0 ? schemaVersionRows[0].filename : 'none',
|
|
215
|
+
},
|
|
70
216
|
});
|
|
71
217
|
} finally {
|
|
72
218
|
await store.close();
|
|
73
219
|
}
|
|
74
|
-
|
|
220
|
+
|
|
221
|
+
// --- Phase 2: per-migration transaction-isolation induced failure ---
|
|
222
|
+
// Reset and re-run the migration runner AS A CHILD PROCESS with
|
|
223
|
+
// SIMULATE_MIGRATION_FAILURE=true so 002 fails in flight. Positive
|
|
224
|
+
// proof (AC-27109-1 clauses): the child's OS exit code is non-zero,
|
|
225
|
+
// the failing filename appears in the child's stderr, 001 committed
|
|
226
|
+
// and its schema effect is visible, 002 rolled back and its schema
|
|
227
|
+
// effect is absent, schema_version carries a row for 001 only.
|
|
228
|
+
await resetSchema(url);
|
|
229
|
+
const childRun = await spawnRunner({ simulateFailure: true });
|
|
230
|
+
const failingFilename = childRun.stderr.match(/migration failed at (\S+):/);
|
|
231
|
+
const stderrFailingFilename = failingFilename ? failingFilename[1] : null;
|
|
232
|
+
const store2 = await createStore({ connectionUrl: url });
|
|
233
|
+
let atomicityEvidence = null;
|
|
234
|
+
let inducedBackendPid = null;
|
|
235
|
+
let inducedTransactionId = null;
|
|
236
|
+
let inducedMigrationVersion = null;
|
|
237
|
+
try {
|
|
238
|
+
await store2.ready();
|
|
239
|
+
const pool = store2.getPool();
|
|
240
|
+
const usersExists = await tableExists(pool, 'users');
|
|
241
|
+
const emailUnique = usersExists ? await columnExists(pool, 'users', 'email') : false;
|
|
242
|
+
// 002 adds a UNIQUE constraint on email; if 002 rolled back, the
|
|
243
|
+
// constraint should NOT exist. Prove this positively by inspecting
|
|
244
|
+
// pg_constraint.
|
|
245
|
+
const constraintRows = usersExists ? (await pool.query(
|
|
246
|
+
`SELECT c.conname, c.contype FROM pg_constraint c
|
|
247
|
+
JOIN pg_class t ON c.conrelid = t.oid
|
|
248
|
+
WHERE t.relname = 'users' AND c.contype = 'u'`,
|
|
249
|
+
)).rows : [];
|
|
250
|
+
const svRows = (await pool.query('SELECT filename FROM schema_version ORDER BY filename')).rows;
|
|
251
|
+
const inducedR = await pool.query('SELECT pg_backend_pid() AS pid, txid_current() AS txid, (SELECT count(*)::int FROM schema_version) AS v');
|
|
252
|
+
inducedBackendPid = String(inducedR.rows[0].pid);
|
|
253
|
+
inducedTransactionId = String(inducedR.rows[0].txid);
|
|
254
|
+
inducedMigrationVersion = String(inducedR.rows[0].v);
|
|
255
|
+
atomicityEvidence = {
|
|
256
|
+
backendPid: inducedBackendPid,
|
|
257
|
+
transactionId: inducedTransactionId,
|
|
258
|
+
migrationVersion: inducedMigrationVersion,
|
|
259
|
+
childExitCode: childRun.exitCode,
|
|
260
|
+
childSignal: childRun.signal,
|
|
261
|
+
childStderrExcerpt: childRun.stderr.slice(0, 400),
|
|
262
|
+
childStdoutExcerpt: childRun.stdout.slice(0, 200),
|
|
263
|
+
stderrFailingFilename,
|
|
264
|
+
usersExists,
|
|
265
|
+
emailColumnExists: emailUnique,
|
|
266
|
+
uniqueConstraintsOnUsers: constraintRows,
|
|
267
|
+
schemaVersionRows: svRows,
|
|
268
|
+
};
|
|
269
|
+
// Isolation assertions per AC-27109-1:
|
|
270
|
+
// 1. runner exits non-zero (child OS exit code observed)
|
|
271
|
+
const exitNonZero = typeof childRun.exitCode === 'number' && childRun.exitCode !== 0;
|
|
272
|
+
// 2. failing filename in child stderr matches 002_add_email_unique.sql
|
|
273
|
+
const failingRecorded = stderrFailingFilename === '002_add_email_unique.sql';
|
|
274
|
+
// 3. 002 rolled back: schema_version has NO row for 002_add_email_unique.sql
|
|
275
|
+
const isolationRolledBack = !svRows.some((r) => r.filename === '002_add_email_unique.sql');
|
|
276
|
+
// 4. 001 committed independently: users table exists AND its row is on schema_version
|
|
277
|
+
const oneCommitted = usersExists && svRows.some((r) => r.filename === '001_create_users.sql');
|
|
278
|
+
// 5. The UNIQUE constraint (introduced by 002) is absent, proving 002's DDL rolled back
|
|
279
|
+
const uniqueAbsent = constraintRows.length === 0;
|
|
280
|
+
const isolationPass = exitNonZero && failingRecorded && isolationRolledBack && oneCommitted && uniqueAbsent;
|
|
281
|
+
// Induced-failure row anchors AC-27109-1 (the first file commits,
|
|
282
|
+
// the second file's transaction rolls back on the invalid statement,
|
|
283
|
+
// the runner exits non-zero, and the failing filename appears in
|
|
284
|
+
// the runner's diagnostic output).
|
|
285
|
+
results.push({
|
|
286
|
+
anchorAcId: 'AC-27109-1',
|
|
287
|
+
verdict: isolationPass ? 'pass' : 'fail',
|
|
288
|
+
detail: isolationPass
|
|
289
|
+
? `Given a migrations directory whose second file contains an invalid SQL statement (simulated in the fixture by the SIMULATE_MIGRATION_FAILURE switch), the runner exited non-zero (${childRun.exitCode}) with '${stderrFailingFilename}' in stderr, 001 committed (users exists, schema_version carries 001), 002 rolled back (schema_version has no row for 002, no UNIQUE constraint on users.email), only the first file's row on schema_version.`
|
|
290
|
+
: `Given a migrations directory whose second file contains an invalid SQL statement - AC clauses did NOT all pass: exitNonZero=${exitNonZero} (code=${childRun.exitCode}) failingRecorded=${failingRecorded} (stderr filename=${stderrFailingFilename}) isolationRolledBack=${isolationRolledBack} oneCommitted=${oneCommitted} uniqueAbsent=${uniqueAbsent}`,
|
|
291
|
+
evidence: atomicityEvidence,
|
|
292
|
+
});
|
|
293
|
+
} finally {
|
|
294
|
+
await store2.close();
|
|
295
|
+
}
|
|
296
|
+
// Reset to a clean, happy-path state for downstream probes.
|
|
297
|
+
await resetSchema(url);
|
|
298
|
+
await applyAll({ connectionUrl: url });
|
|
299
|
+
|
|
300
|
+
return { results, extra: { happyPath: { applied, schemaVersionRows }, atomicity: atomicityEvidence } };
|
|
75
301
|
}
|
|
@@ -2,55 +2,138 @@
|
|
|
2
2
|
* Pool posture smoke probe.
|
|
3
3
|
*
|
|
4
4
|
* Opens two facade instances against the same postgres:17-alpine
|
|
5
|
-
* container each configured at pool size 5,
|
|
5
|
+
* container each configured at pool size 5, checks out twenty
|
|
6
6
|
* concurrent SELECT queries across the two facades, asserts all
|
|
7
7
|
* twenty return with no timeout inside the shipped
|
|
8
|
-
* connectionTimeoutMillis budget
|
|
8
|
+
* connectionTimeoutMillis budget AND the OBSERVED maximum concurrent
|
|
9
|
+
* in-use count on each pool is <= configured max at any sample.
|
|
10
|
+
*
|
|
11
|
+
* The observed peak is sampled at ~5ms intervals while the query
|
|
12
|
+
* promises are in flight; each sample computes `totalCount -
|
|
13
|
+
* idleCount` on the shipped pg.Pool. Configured `.options.max` is
|
|
14
|
+
* recorded on the evidence bag alongside the observed peak, but the
|
|
15
|
+
* assertion is on the OBSERVED peak (per AC-27106-1).
|
|
9
16
|
*
|
|
10
17
|
* Anchors AC-27106-1.
|
|
11
18
|
*
|
|
12
|
-
* Cleans up: closes both pools
|
|
19
|
+
* Cleans up: closes both pools; a close failure is recorded on the
|
|
20
|
+
* teardown row and fails the aggregate.
|
|
13
21
|
*/
|
|
14
22
|
|
|
15
|
-
import { createStore, connectionUrlFromEnv } from '../../../../packages/rcf-lite/test/fixtures/infra-postgres/src/store.mjs';
|
|
23
|
+
import { createStore, connectionUrlFromEnv, MissingPostgresHostError } from '../../../../packages/rcf-lite/test/fixtures/infra-postgres/src/store.mjs';
|
|
24
|
+
|
|
25
|
+
export const DECLARED_ENV = Object.freeze([
|
|
26
|
+
'POSTGRES_HOST',
|
|
27
|
+
'POSTGRES_PORT',
|
|
28
|
+
'POSTGRES_USER',
|
|
29
|
+
'POSTGRES_PASSWORD',
|
|
30
|
+
'POSTGRES_DB',
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
function skipRow(variable) {
|
|
34
|
+
return {
|
|
35
|
+
anchorAcId: null,
|
|
36
|
+
verdict: 'pass',
|
|
37
|
+
detail: `Given two facade instances opened concurrently against the - accountBound: skipped (${variable} unset)`,
|
|
38
|
+
accountBoundSkipped: true,
|
|
39
|
+
reason: `${variable} unset`,
|
|
40
|
+
evidence: { skip: true, reason: `${variable} unset`, envDeclared: [...DECLARED_ENV] },
|
|
41
|
+
};
|
|
42
|
+
}
|
|
16
43
|
|
|
17
44
|
export default async function runProbe() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
45
|
+
let url;
|
|
46
|
+
try {
|
|
47
|
+
url = connectionUrlFromEnv();
|
|
48
|
+
} catch (err) {
|
|
49
|
+
if (err instanceof MissingPostgresHostError) {
|
|
50
|
+
return {
|
|
51
|
+
results: [skipRow(err.variable)],
|
|
52
|
+
accountBoundSkipped: true,
|
|
53
|
+
reason: `${err.variable} unset`,
|
|
54
|
+
envDeclared: [...DECLARED_ENV],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
const storeA = await createStore({ connectionUrl: url, poolConfig: { max: 5 } });
|
|
60
|
+
const storeB = await createStore({ connectionUrl: url, poolConfig: { max: 5 } });
|
|
21
61
|
const results = [];
|
|
62
|
+
const teardown = [];
|
|
63
|
+
let databaseName = null;
|
|
22
64
|
try {
|
|
23
|
-
await Promise.all([storeA.ready(), storeB.ready()]);
|
|
65
|
+
const [dbA] = await Promise.all([storeA.ready(), storeB.ready()]);
|
|
66
|
+
databaseName = dbA;
|
|
67
|
+
const poolA = storeA.getPool();
|
|
68
|
+
const poolB = storeB.getPool();
|
|
69
|
+
const pidRP = await poolA.query('SELECT pg_backend_pid() AS pid, txid_current() AS txid');
|
|
70
|
+
const backendPid = String(pidRP.rows[0].pid);
|
|
71
|
+
const transactionId = String(pidRP.rows[0].txid);
|
|
72
|
+
const samplesA = [];
|
|
73
|
+
const samplesB = [];
|
|
74
|
+
let sampling = true;
|
|
75
|
+
const sampler = (async () => {
|
|
76
|
+
while (sampling) {
|
|
77
|
+
samplesA.push(poolA.totalCount - poolA.idleCount);
|
|
78
|
+
samplesB.push(poolB.totalCount - poolB.idleCount);
|
|
79
|
+
await new Promise((r) => setTimeout(r, 5));
|
|
80
|
+
}
|
|
81
|
+
})();
|
|
24
82
|
const started = Date.now();
|
|
25
83
|
const promises = [];
|
|
26
84
|
for (let i = 0; i < 10; i++) {
|
|
27
|
-
promises.push(
|
|
28
|
-
promises.push(
|
|
85
|
+
promises.push(poolA.query('SELECT $1::int AS n, pg_sleep(0.05)', [i]));
|
|
86
|
+
promises.push(poolB.query('SELECT $1::int AS n, pg_sleep(0.05)', [10 + i]));
|
|
29
87
|
}
|
|
30
88
|
const settled = await Promise.allSettled(promises);
|
|
89
|
+
sampling = false;
|
|
90
|
+
await sampler;
|
|
31
91
|
const elapsed = Date.now() - started;
|
|
32
92
|
const succeeded = settled.filter((s) => s.status === 'fulfilled').length;
|
|
33
93
|
const failed = settled.filter((s) => s.status === 'rejected').length;
|
|
94
|
+
const observedPeakA = Math.max(0, ...samplesA);
|
|
95
|
+
const observedPeakB = Math.max(0, ...samplesB);
|
|
96
|
+
const configuredMax = 5;
|
|
97
|
+
const cappedA = observedPeakA <= configuredMax && observedPeakA > 0;
|
|
98
|
+
const cappedB = observedPeakB <= configuredMax && observedPeakB > 0;
|
|
99
|
+
// AC-27106-1: 20 concurrent queries return, and observed max
|
|
100
|
+
// in-use on each pool is at most configured max.
|
|
34
101
|
results.push({
|
|
35
102
|
anchorAcId: 'AC-27106-1',
|
|
36
|
-
verdict: succeeded === 20 && failed === 0 ? 'pass' : 'fail',
|
|
37
|
-
detail: `
|
|
103
|
+
verdict: (succeeded === 20 && failed === 0 && cappedA && cappedB) ? 'pass' : 'fail',
|
|
104
|
+
detail: `Given two facade instances opened concurrently against the - 20 checked-out, ${succeeded} returned, ${failed} rejected, wall-clock ${elapsed}ms; observed peak in-use A=${observedPeakA} B=${observedPeakB} (configured max=${configuredMax}); samplesA=${samplesA.length} samplesB=${samplesB.length}`,
|
|
105
|
+
evidence: {
|
|
106
|
+
backendPid,
|
|
107
|
+
transactionId,
|
|
108
|
+
databaseName,
|
|
109
|
+
checkedOut: 20,
|
|
110
|
+
succeeded,
|
|
111
|
+
failed,
|
|
112
|
+
elapsedMs: elapsed,
|
|
113
|
+
observedPeakInUseA: observedPeakA,
|
|
114
|
+
observedPeakInUseB: observedPeakB,
|
|
115
|
+
configuredMax,
|
|
116
|
+
sampleCountA: samplesA.length,
|
|
117
|
+
sampleCountB: samplesB.length,
|
|
118
|
+
poolPostureStatus: (cappedA && cappedB) ? 'capped-both-pools' : 'uncapped',
|
|
119
|
+
poolConfigurationMetadata: { poolAConfiguredMax: configuredMax, poolBConfiguredMax: configuredMax, queryCountPerPool: 10 },
|
|
120
|
+
},
|
|
38
121
|
});
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
122
|
+
} finally {
|
|
123
|
+
const closeA = await storeA.close().catch((err) => err);
|
|
124
|
+
const closeB = await storeB.close().catch((err) => err);
|
|
125
|
+
teardown.push({ step: 'close pool A', ok: !(closeA instanceof Error), error: closeA instanceof Error ? closeA.message : null });
|
|
126
|
+
teardown.push({ step: 'close pool B', ok: !(closeB instanceof Error), error: closeB instanceof Error ? closeB.message : null });
|
|
127
|
+
}
|
|
128
|
+
const failedTeardown = teardown.filter((t) => !t.ok);
|
|
129
|
+
if (failedTeardown.length > 0) {
|
|
130
|
+
// Teardown failure fails the verdict (authoring-standard rule 5).
|
|
46
131
|
results.push({
|
|
47
|
-
|
|
48
|
-
verdict:
|
|
49
|
-
detail: `
|
|
132
|
+
anchorReqId: 'persistence-data-postgres-REQ-006',
|
|
133
|
+
verdict: 'fail',
|
|
134
|
+
detail: `The facade opens a long-lived pg.Pool for the - teardown FAILED (${failedTeardown.length}/${teardown.length}): ${failedTeardown.map((t) => `${t.step} -> ${t.error}`).join('; ')}`,
|
|
135
|
+
evidence: { teardown },
|
|
50
136
|
});
|
|
51
|
-
} finally {
|
|
52
|
-
await storeA.close();
|
|
53
|
-
await storeB.close();
|
|
54
137
|
}
|
|
55
|
-
return results;
|
|
138
|
+
return { results };
|
|
56
139
|
}
|