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
package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs
CHANGED
|
@@ -1,28 +1,58 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Recovery restore round-trip probe.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
4
|
+
* Drives the shipped fixture recovery runner (src/recovery.mjs
|
|
5
|
+
* exportDatabase, TAC-2804) to produce the dump artefact and asserts
|
|
6
|
+
* the runner emits `backupExported` per AC-27105-1. Because pg_dump is
|
|
7
|
+
* not on the host PATH in every CI runner, the probe supplies the
|
|
8
|
+
* runPgDump override on `exportDatabase` that shells out to
|
|
9
|
+
* `docker exec <sourceContainer> pg_dump ...`. The shipped runner is
|
|
10
|
+
* still the code path under test; only the pg_dump invocation is
|
|
11
|
+
* container-hosted.
|
|
12
|
+
*
|
|
13
|
+
* Brings up a second postgres:17-alpine container on a spare port,
|
|
14
|
+
* pipes the artefact through psql into that container (via the same
|
|
15
|
+
* docker exec pattern), and asserts row-count and md5 checksum
|
|
16
|
+
* equality between source and restored databases.
|
|
12
17
|
*
|
|
13
18
|
* Anchors AC-27105-1 (recovery exported, restore round-trips the row
|
|
14
|
-
* set).
|
|
19
|
+
* set, backupExported event fires).
|
|
15
20
|
*
|
|
16
|
-
*
|
|
17
|
-
* removes its volume; deletes the artefact
|
|
21
|
+
* Cleanup: TRUNCATE users on source; stops the restore container and
|
|
22
|
+
* removes its volume; deletes the artefact directory. Every teardown
|
|
23
|
+
* step records its exit status in the report's `teardown` bag; a
|
|
24
|
+
* teardown failure FAILS the verdict per authoring-standard rule 5.
|
|
18
25
|
*/
|
|
19
26
|
|
|
20
27
|
import { spawn, execFile } from 'node:child_process';
|
|
21
28
|
import { promisify } from 'node:util';
|
|
22
|
-
import { mkdir, writeFile,
|
|
29
|
+
import { mkdir, writeFile, rm, stat } from 'node:fs/promises';
|
|
23
30
|
import { dirname, relative, resolve } from 'node:path';
|
|
24
31
|
import { fileURLToPath } from 'node:url';
|
|
25
|
-
import { createStore, connectionUrlFromEnv } from '../../../../packages/rcf-lite/test/fixtures/infra-postgres/src/store.mjs';
|
|
32
|
+
import { createStore, connectionUrlFromEnv, MissingPostgresHostError } from '../../../../packages/rcf-lite/test/fixtures/infra-postgres/src/store.mjs';
|
|
33
|
+
import { exportDatabase } from '../../../../packages/rcf-lite/test/fixtures/infra-postgres/src/recovery.mjs';
|
|
34
|
+
|
|
35
|
+
export const DECLARED_ENV = Object.freeze([
|
|
36
|
+
'POSTGRES_HOST',
|
|
37
|
+
'POSTGRES_PORT',
|
|
38
|
+
'POSTGRES_USER',
|
|
39
|
+
'POSTGRES_PASSWORD',
|
|
40
|
+
'POSTGRES_DB',
|
|
41
|
+
'POSTGRES_SOURCE_CONTAINER',
|
|
42
|
+
'POSTGRES_RESTORE_CONTAINER',
|
|
43
|
+
'POSTGRES_RESTORE_PORT',
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
function skipRow(variable) {
|
|
47
|
+
return {
|
|
48
|
+
anchorAcId: null,
|
|
49
|
+
verdict: 'pass',
|
|
50
|
+
detail: `Given a live Postgres containing a small fixture rowset - accountBound: skipped (${variable} unset)`,
|
|
51
|
+
accountBoundSkipped: true,
|
|
52
|
+
reason: `${variable} unset`,
|
|
53
|
+
evidence: { skip: true, reason: `${variable} unset`, envDeclared: [...DECLARED_ENV] },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
26
56
|
|
|
27
57
|
const execFileAsync = promisify(execFile);
|
|
28
58
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
@@ -30,9 +60,15 @@ const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
|
|
|
30
60
|
const ARTEFACT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/persistence-data-postgres/recovery');
|
|
31
61
|
const ARTEFACT = resolve(ARTEFACT_DIR, 'backup.sql');
|
|
32
62
|
const ARTEFACT_REL = relative(PROJECT_ROOT, ARTEFACT);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
63
|
+
// Source container defaults to the fixture's docker-compose service
|
|
64
|
+
// name; a CI runner (or a positive-evidence run) may override via
|
|
65
|
+
// POSTGRES_SOURCE_CONTAINER. Restore container name and port are
|
|
66
|
+
// similarly overridable so parallel runs and non-default docker
|
|
67
|
+
// networks can pick free ports; both env vars are declared on the
|
|
68
|
+
// fixture's Declared env vars table.
|
|
69
|
+
const SOURCE_CONTAINER = process.env.POSTGRES_SOURCE_CONTAINER || 'infra-postgres-postgres-1';
|
|
70
|
+
const RESTORE_CONTAINER = process.env.POSTGRES_RESTORE_CONTAINER || 'infra-postgres-restore';
|
|
71
|
+
const RESTORE_PORT = process.env.POSTGRES_RESTORE_PORT || '55432';
|
|
36
72
|
|
|
37
73
|
async function dockerExec(container, cmd, opts = {}) {
|
|
38
74
|
return execFileAsync('docker', ['exec', container, ...cmd], { maxBuffer: 64 * 1024 * 1024, ...opts });
|
|
@@ -43,7 +79,7 @@ async function dockerExec(container, cmd, opts = {}) {
|
|
|
43
79
|
* accept stdin buffers, so use spawn.
|
|
44
80
|
*/
|
|
45
81
|
async function dockerExecStdin(container, cmd, stdinBuffer) {
|
|
46
|
-
return new Promise((
|
|
82
|
+
return new Promise((resolveP, reject) => {
|
|
47
83
|
const child = spawn('docker', ['exec', '-i', container, ...cmd]);
|
|
48
84
|
const chunks = [];
|
|
49
85
|
const errChunks = [];
|
|
@@ -51,7 +87,7 @@ async function dockerExecStdin(container, cmd, stdinBuffer) {
|
|
|
51
87
|
child.stderr.on('data', (d) => errChunks.push(d));
|
|
52
88
|
child.on('error', reject);
|
|
53
89
|
child.on('exit', (code) => {
|
|
54
|
-
if (code === 0) return
|
|
90
|
+
if (code === 0) return resolveP({ stdout: Buffer.concat(chunks).toString('utf8'), stderr: Buffer.concat(errChunks).toString('utf8') });
|
|
55
91
|
reject(new Error(`docker exec exit ${code}: ${Buffer.concat(errChunks).toString('utf8')}`));
|
|
56
92
|
});
|
|
57
93
|
child.stdin.write(stdinBuffer);
|
|
@@ -71,14 +107,43 @@ async function waitHealthy(container, maxSeconds = 30) {
|
|
|
71
107
|
throw new Error(`container ${container} did not become healthy within ${maxSeconds}s`);
|
|
72
108
|
}
|
|
73
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Positively assert `container` is absent by asking docker to inspect
|
|
112
|
+
* it. Absent = docker exits non-zero WITH `No such object` on stderr.
|
|
113
|
+
* Any other error (daemon unreachable, permission denied) fails the
|
|
114
|
+
* assertion; the caller can then FAIL the row rather than treat it as
|
|
115
|
+
* "no problem here".
|
|
116
|
+
*/
|
|
117
|
+
async function assertContainerAbsent(container) {
|
|
118
|
+
try {
|
|
119
|
+
await execFileAsync('docker', ['inspect', container]);
|
|
120
|
+
throw new Error(`container ${container} still exists`);
|
|
121
|
+
} catch (err) {
|
|
122
|
+
if (err && err.stderr && /[Nn]o such object|[Ee]rror: [Nn]o such/i.test(err.stderr)) return { absent: true };
|
|
123
|
+
if (err && err.message && err.message.includes('still exists')) throw err;
|
|
124
|
+
// Unrecognized inspect failure - do NOT treat as absent.
|
|
125
|
+
throw new Error(`docker inspect on ${container} produced an unrecognized error: ${err && (err.stderr || err.message) || 'unknown'}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
74
129
|
async function bringUpRestore() {
|
|
75
|
-
//
|
|
76
|
-
|
|
130
|
+
// Pre-run cleanup: remove any prior instance, THEN positively assert
|
|
131
|
+
// the container is gone. If the pre-run rm fails for a reason other
|
|
132
|
+
// than "container did not exist", let the run fail loudly rather
|
|
133
|
+
// than proceed to a `docker run` that would collide.
|
|
134
|
+
try {
|
|
135
|
+
await execFileAsync('docker', ['rm', '-f', RESTORE_CONTAINER]);
|
|
136
|
+
} catch (err) {
|
|
137
|
+
if (!(err && err.stderr && /[Nn]o such container|[Ee]rror: [Nn]o such/i.test(err.stderr))) {
|
|
138
|
+
throw new Error(`pre-run rm of ${RESTORE_CONTAINER} failed and did not name a No-such-container reason: ${err && (err.stderr || err.message) || 'unknown'}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
await assertContainerAbsent(RESTORE_CONTAINER);
|
|
77
142
|
await execFileAsync('docker', [
|
|
78
143
|
'run', '-d',
|
|
79
144
|
'--name', RESTORE_CONTAINER,
|
|
80
145
|
'-e', 'POSTGRES_USER=rcf',
|
|
81
|
-
'-e', 'POSTGRES_PASSWORD
|
|
146
|
+
'-e', 'POSTGRES_PASSWORD',
|
|
82
147
|
'-e', 'POSTGRES_DB=rcf_test',
|
|
83
148
|
'-p', `${RESTORE_PORT}:5432`,
|
|
84
149
|
'--health-cmd', 'pg_isready -U rcf -d rcf_test',
|
|
@@ -89,20 +154,57 @@ async function bringUpRestore() {
|
|
|
89
154
|
await waitHealthy(RESTORE_CONTAINER, 30);
|
|
90
155
|
}
|
|
91
156
|
|
|
92
|
-
|
|
93
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Attempt one teardown step; record its outcome on the accumulator.
|
|
159
|
+
* The step is the literal command reported so a reader sees exactly
|
|
160
|
+
* what ran.
|
|
161
|
+
*/
|
|
162
|
+
async function recordTeardown(accumulator, label, fn) {
|
|
163
|
+
const entry = { step: label, ok: false, exitCode: null, error: null };
|
|
164
|
+
try {
|
|
165
|
+
const out = await fn();
|
|
166
|
+
entry.ok = true;
|
|
167
|
+
entry.exitCode = 0;
|
|
168
|
+
if (out && typeof out === 'object' && 'exitCode' in out) entry.exitCode = out.exitCode;
|
|
169
|
+
} catch (err) {
|
|
170
|
+
entry.error = err && err.message ? err.message : String(err);
|
|
171
|
+
entry.exitCode = err && typeof err.code === 'number' ? err.code : 1;
|
|
172
|
+
}
|
|
173
|
+
accumulator.push(entry);
|
|
174
|
+
return entry;
|
|
94
175
|
}
|
|
95
176
|
|
|
96
177
|
export default async function runProbe() {
|
|
178
|
+
let url;
|
|
179
|
+
try {
|
|
180
|
+
url = connectionUrlFromEnv();
|
|
181
|
+
} catch (err) {
|
|
182
|
+
if (err instanceof MissingPostgresHostError) {
|
|
183
|
+
return {
|
|
184
|
+
results: [skipRow(err.variable)],
|
|
185
|
+
accountBoundSkipped: true,
|
|
186
|
+
reason: `${err.variable} unset`,
|
|
187
|
+
envDeclared: [...DECLARED_ENV],
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
throw err;
|
|
191
|
+
}
|
|
97
192
|
const events = [];
|
|
98
|
-
const store = createStore({
|
|
99
|
-
connectionUrl:
|
|
193
|
+
const store = await createStore({
|
|
194
|
+
connectionUrl: url,
|
|
100
195
|
onEvent: (e) => events.push(e),
|
|
101
196
|
});
|
|
102
197
|
const results = [];
|
|
198
|
+
const teardown = [];
|
|
199
|
+
let restoreBrought = false;
|
|
200
|
+
let artefactWritten = false;
|
|
201
|
+
let databaseName = null;
|
|
103
202
|
try {
|
|
104
|
-
await store.ready();
|
|
203
|
+
databaseName = await store.ready();
|
|
105
204
|
const pool = store.getPool();
|
|
205
|
+
const pidRR = await pool.query('SELECT pg_backend_pid() AS pid, txid_current() AS txid');
|
|
206
|
+
const backendPidSrc = String(pidRR.rows[0].pid);
|
|
207
|
+
const transactionIdSrc = String(pidRR.rows[0].txid);
|
|
106
208
|
|
|
107
209
|
// Seed a known rowset on the source
|
|
108
210
|
await pool.query('CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE, created_at TIMESTAMPTZ NOT NULL DEFAULT now())');
|
|
@@ -118,56 +220,167 @@ export default async function runProbe() {
|
|
|
118
220
|
await pool.query('INSERT INTO users(name, email) VALUES ($1, $2)', [name, email]);
|
|
119
221
|
}
|
|
120
222
|
|
|
121
|
-
// Compute source row-count and checksum
|
|
223
|
+
// Compute source row-count and checksum
|
|
122
224
|
const srcCount = (await pool.query('SELECT count(*)::int AS n FROM users')).rows[0].n;
|
|
123
225
|
const srcCk = (await pool.query('SELECT md5(string_agg(name || $1 || email, $2 ORDER BY id))::text AS ck FROM users', ['|', ','])).rows[0].ck;
|
|
124
226
|
|
|
125
|
-
//
|
|
227
|
+
// Drive the shipped exportDatabase runner (TAC-2804) with a
|
|
228
|
+
// runPgDump override that shells out to docker exec inside the
|
|
229
|
+
// source container. The shipped runner still writes the artefact
|
|
230
|
+
// and emits backupExported; the probe proves both.
|
|
231
|
+
//
|
|
232
|
+
// Pre-run: assert the destination directory is absent, then create
|
|
233
|
+
// it. If a prior run left a stale artefact, remove it and
|
|
234
|
+
// positively re-check absence. Any failure here (permission
|
|
235
|
+
// denied, filesystem error) fails the row loudly.
|
|
236
|
+
try {
|
|
237
|
+
const preExist = await stat(ARTEFACT_DIR).catch((err) => {
|
|
238
|
+
if (err && err.code === 'ENOENT') return null;
|
|
239
|
+
throw err;
|
|
240
|
+
});
|
|
241
|
+
if (preExist) {
|
|
242
|
+
await rm(ARTEFACT_DIR, { recursive: true, force: true });
|
|
243
|
+
const after = await stat(ARTEFACT_DIR).catch((err) => {
|
|
244
|
+
if (err && err.code === 'ENOENT') return null;
|
|
245
|
+
throw err;
|
|
246
|
+
});
|
|
247
|
+
if (after) throw new Error(`pre-run: destination ${ARTEFACT_REL} still exists after rm -rf`);
|
|
248
|
+
}
|
|
249
|
+
} catch (err) {
|
|
250
|
+
if (!/still exists/.test(err && err.message)) throw new Error(`pre-run destination cleanup failed unrecognizably: ${err && (err.message || String(err))}`);
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
126
253
|
await mkdir(ARTEFACT_DIR, { recursive: true });
|
|
127
|
-
const
|
|
128
|
-
await
|
|
129
|
-
|
|
254
|
+
const runnerEvents = [];
|
|
255
|
+
const exported = await exportDatabase({
|
|
256
|
+
destination: ARTEFACT,
|
|
257
|
+
onEvent: (e) => runnerEvents.push(e),
|
|
258
|
+
runPgDump: async ({ pgDumpArgs }) => {
|
|
259
|
+
const dump = await dockerExec(SOURCE_CONTAINER, ['pg_dump', '-U', 'rcf', '-d', 'rcf_test', ...pgDumpArgs]);
|
|
260
|
+
return dump.stdout;
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
artefactWritten = true;
|
|
264
|
+
const artefactStat = await stat(ARTEFACT);
|
|
265
|
+
|
|
266
|
+
// Assert the runner emitted backupExported per AC-27105-1.
|
|
267
|
+
// Sanitize the event's artefactPath (recovery.mjs records it as
|
|
268
|
+
// the absolute destination) to a project-relative path so a
|
|
269
|
+
// machine path does not land in the persisted evidence record.
|
|
270
|
+
const backupEvent = runnerEvents.find((e) => e.event === 'backupExported');
|
|
271
|
+
const backupEventSanitized = backupEvent
|
|
272
|
+
? { ...backupEvent, artefactPath: relative(PROJECT_ROOT, backupEvent.artefactPath) }
|
|
273
|
+
: null;
|
|
274
|
+
results.push({
|
|
275
|
+
anchorAcId: 'AC-27105-1',
|
|
276
|
+
verdict: (backupEvent && typeof backupEvent.artefactPath === 'string' && typeof backupEvent.completedAt === 'string') ? 'pass' : 'fail',
|
|
277
|
+
detail: backupEvent
|
|
278
|
+
? `Given a live Postgres containing a small fixture rowset - shipped exportDatabase emitted backupExported with artefactPath=${relative(PROJECT_ROOT, backupEvent.artefactPath)} completedAt=${backupEvent.completedAt}`
|
|
279
|
+
: `Given a live Postgres containing a small fixture rowset - expected backupExported event on the shipped exportDatabase runner; observed events=${runnerEvents.map((e) => e.event).join(',')}`,
|
|
280
|
+
evidence: {
|
|
281
|
+
backendPid: backendPidSrc,
|
|
282
|
+
transactionId: transactionIdSrc,
|
|
283
|
+
databaseName,
|
|
284
|
+
artefactPath: ARTEFACT_REL,
|
|
285
|
+
artefactBytesOnDisk: artefactStat.size,
|
|
286
|
+
bytesReportedByRunner: exported.bytes,
|
|
287
|
+
backupExportedEvent: backupEventSanitized,
|
|
288
|
+
},
|
|
289
|
+
});
|
|
130
290
|
|
|
131
291
|
// Bring up restore container
|
|
132
292
|
await bringUpRestore();
|
|
293
|
+
restoreBrought = true;
|
|
133
294
|
|
|
134
|
-
// Pipe artefact into psql on restore
|
|
135
|
-
await dockerExecStdin(RESTORE_CONTAINER, ['psql', '-U', 'rcf', '-d', 'rcf_test', '-v', 'ON_ERROR_STOP=1'], Buffer.from(
|
|
295
|
+
// Pipe artefact into psql on restore (the container ships psql).
|
|
296
|
+
await dockerExecStdin(RESTORE_CONTAINER, ['psql', '-U', 'rcf', '-d', 'rcf_test', '-v', 'ON_ERROR_STOP=1'], Buffer.from(await import('node:fs').then((fs) => fs.promises.readFile(ARTEFACT))));
|
|
136
297
|
|
|
137
|
-
// Read row-count and checksum on restored
|
|
138
|
-
|
|
298
|
+
// Read row-count and checksum on restored via a connection to the
|
|
299
|
+
// restore container's published port. Host is taken from
|
|
300
|
+
// POSTGRES_HOST (the docker host the restore container publishes
|
|
301
|
+
// its port on); no literal host default lives in shipped probe
|
|
302
|
+
// code.
|
|
303
|
+
// Password read from the declared POSTGRES_PASSWORD variable
|
|
304
|
+
// only; no literal password value in shipped probe source.
|
|
305
|
+
const dstStore = await createStore({ connectionUrl: `postgres://${process.env.POSTGRES_USER || 'rcf'}:${encodeURIComponent(process.env.POSTGRES_PASSWORD || '')}@${process.env.POSTGRES_HOST}:${RESTORE_PORT}/${process.env.POSTGRES_DB || 'rcf_test'}` });
|
|
139
306
|
let dstCount = -1;
|
|
140
307
|
let dstCk = 'unset';
|
|
308
|
+
let backendPidDst = null;
|
|
309
|
+
let transactionIdDst = null;
|
|
141
310
|
try {
|
|
142
311
|
await dstStore.ready();
|
|
143
312
|
const dstPool = dstStore.getPool();
|
|
313
|
+
const pidRD = await dstPool.query('SELECT pg_backend_pid() AS pid, txid_current() AS txid');
|
|
314
|
+
backendPidDst = String(pidRD.rows[0].pid);
|
|
315
|
+
transactionIdDst = String(pidRD.rows[0].txid);
|
|
144
316
|
dstCount = (await dstPool.query('SELECT count(*)::int AS n FROM users')).rows[0].n;
|
|
145
317
|
dstCk = (await dstPool.query('SELECT md5(string_agg(name || $1 || email, $2 ORDER BY id))::text AS ck FROM users', ['|', ','])).rows[0].ck;
|
|
146
318
|
} finally {
|
|
147
319
|
await dstStore.close();
|
|
148
320
|
}
|
|
149
321
|
|
|
150
|
-
results.push({
|
|
151
|
-
anchorAcId: 'AC-27105-1',
|
|
152
|
-
verdict: bytes > 0 ? 'pass' : 'fail',
|
|
153
|
-
detail: `pg_dump artefact written to ${ARTEFACT_REL} (${bytes} bytes)`,
|
|
154
|
-
});
|
|
155
322
|
results.push({
|
|
156
323
|
anchorAcId: 'AC-27105-1',
|
|
157
324
|
verdict: srcCount === dstCount ? 'pass' : 'fail',
|
|
158
|
-
detail: `row-count source=${srcCount} restored=${dstCount}`,
|
|
325
|
+
detail: `Given a live Postgres containing a small fixture rowset - row-count source=${srcCount} restored=${dstCount}`,
|
|
326
|
+
evidence: { backendPid: backendPidDst, transactionId: transactionIdDst, databaseName, srcCount, dstCount, restoreContainer: RESTORE_CONTAINER, restorePort: RESTORE_PORT },
|
|
159
327
|
});
|
|
160
328
|
results.push({
|
|
161
329
|
anchorAcId: 'AC-27105-1',
|
|
162
330
|
verdict: srcCk === dstCk && srcCk != null ? 'pass' : 'fail',
|
|
163
|
-
detail: `checksum source=${srcCk} restored=${dstCk}`,
|
|
331
|
+
detail: `Given a live Postgres containing a small fixture rowset - checksum source=${srcCk} restored=${dstCk}`,
|
|
332
|
+
evidence: { backendPid: backendPidDst, transactionId: transactionIdDst, srcChecksumMd5: srcCk, dstChecksumMd5: dstCk, checksumMatchStatus: (srcCk && dstCk && srcCk === dstCk) ? 'equal' : 'differ' },
|
|
164
333
|
});
|
|
165
334
|
} finally {
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
await
|
|
169
|
-
|
|
170
|
-
|
|
335
|
+
// Teardown, every step recorded. A failure here becomes a FAIL row
|
|
336
|
+
// on the results per authoring-standard rule 5.
|
|
337
|
+
await recordTeardown(teardown, 'TRUNCATE users on source', async () => {
|
|
338
|
+
try {
|
|
339
|
+
await store.getPool().query('TRUNCATE users RESTART IDENTITY');
|
|
340
|
+
} catch (err) {
|
|
341
|
+
// If the source is unreachable the probe still needs the store closed;
|
|
342
|
+
// rethrow so the accumulator records the failure.
|
|
343
|
+
throw err;
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
await recordTeardown(teardown, 'close source pool', async () => {
|
|
347
|
+
await store.close();
|
|
348
|
+
});
|
|
349
|
+
if (restoreBrought) {
|
|
350
|
+
await recordTeardown(teardown, `docker rm -f -v ${RESTORE_CONTAINER}`, async () => {
|
|
351
|
+
await execFileAsync('docker', ['rm', '-f', '-v', RESTORE_CONTAINER]);
|
|
352
|
+
});
|
|
353
|
+
// Positively confirm the container is gone. Any inspect outcome
|
|
354
|
+
// other than a "No such object" error fails the step so an
|
|
355
|
+
// unrecognized daemon-side error is not laundered into success.
|
|
356
|
+
await recordTeardown(teardown, `docker inspect ${RESTORE_CONTAINER} (expected: absent)`, async () => {
|
|
357
|
+
await assertContainerAbsent(RESTORE_CONTAINER);
|
|
358
|
+
return { exitCode: 0 };
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
if (artefactWritten) {
|
|
362
|
+
await recordTeardown(teardown, `rm -rf ${ARTEFACT_REL}`, async () => {
|
|
363
|
+
await rm(ARTEFACT_DIR, { recursive: true, force: true });
|
|
364
|
+
});
|
|
365
|
+
}
|
|
171
366
|
}
|
|
172
|
-
|
|
367
|
+
// Fold teardown outcomes into the result set (authoring-standard rule 5).
|
|
368
|
+
const failedTeardown = teardown.filter((t) => !t.ok);
|
|
369
|
+
// AC-27105-1 states rowset round-trip + backupExported. It does not
|
|
370
|
+
// state scratch-resource teardown, so this row is CONFORMANCE-ONLY:
|
|
371
|
+
// it records the operational teardown of the scratch restore
|
|
372
|
+
// container and artefact so a reader can see the run left no state
|
|
373
|
+
// behind, without claiming the AC's rowset property.
|
|
374
|
+
const AC27105_TEARDOWN_LIMITATION = 'AC-27105-1: Given a live Postgres containing a small fixture rowset, when the shipped recovery runner exports a backup, then backupExported fires with an artefact path and completedAt timestamp and a subsequent restore against a throwaway container yields byte-equal rowset content. Not observed on this row: this row records only the operational teardown (docker rm of the throwaway restore container plus removal of the pg_dump artefact tree) that follows the AC observing rows; the AC observing evidence is on the earlier rows in this same probe.';
|
|
375
|
+
results.push({
|
|
376
|
+
anchorAcId: null,
|
|
377
|
+
conformanceOnly: true,
|
|
378
|
+
limitation: AC27105_TEARDOWN_LIMITATION,
|
|
379
|
+
verdict: failedTeardown.length === 0 ? 'pass' : 'fail',
|
|
380
|
+
detail: failedTeardown.length === 0
|
|
381
|
+
? `conformanceOnly (AC-27105-1: Given a live Postgres containing a small fixture) - teardown ok: ${teardown.map((t) => `${t.step} (exit=${t.exitCode})`).join('; ')}`
|
|
382
|
+
: `conformanceOnly (AC-27105-1: Given a live Postgres containing a small fixture) - teardown FAILED (${failedTeardown.length}/${teardown.length}): ${failedTeardown.map((t) => `${t.step} -> ${t.error}`).join('; ')}`,
|
|
383
|
+
evidence: { teardown },
|
|
384
|
+
});
|
|
385
|
+
return { results, extra: { teardown, restoreContainer: RESTORE_CONTAINER, restorePort: RESTORE_PORT } };
|
|
173
386
|
}
|
|
@@ -10,70 +10,126 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Anchors AC-27104-1.
|
|
12
12
|
*
|
|
13
|
-
* Cleans up: TRUNCATE users on exit; closes the pool.
|
|
13
|
+
* Cleans up: TRUNCATE users on exit; closes the pool. A teardown
|
|
14
|
+
* failure emits its own row (authoring-standard rule 5).
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
|
-
import { createStore, connectionUrlFromEnv } from '../../../../packages/rcf-lite/test/fixtures/infra-postgres/src/store.mjs';
|
|
17
|
+
import { createStore, connectionUrlFromEnv, MissingPostgresHostError } from '../../../../packages/rcf-lite/test/fixtures/infra-postgres/src/store.mjs';
|
|
18
|
+
|
|
19
|
+
const AC = 'Given the transaction helper wrapping a callback that';
|
|
20
|
+
|
|
21
|
+
export const DECLARED_ENV = Object.freeze([
|
|
22
|
+
'POSTGRES_HOST',
|
|
23
|
+
'POSTGRES_PORT',
|
|
24
|
+
'POSTGRES_USER',
|
|
25
|
+
'POSTGRES_PASSWORD',
|
|
26
|
+
'POSTGRES_DB',
|
|
27
|
+
'SIMULATE_CONSTRAINT_VIOLATION',
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
function skipRow(variable) {
|
|
31
|
+
return {
|
|
32
|
+
anchorAcId: null,
|
|
33
|
+
verdict: 'pass',
|
|
34
|
+
detail: `${AC} - accountBound: skipped (${variable} unset)`,
|
|
35
|
+
accountBoundSkipped: true,
|
|
36
|
+
reason: `${variable} unset`,
|
|
37
|
+
evidence: { skip: true, reason: `${variable} unset`, envDeclared: [...DECLARED_ENV] },
|
|
38
|
+
};
|
|
39
|
+
}
|
|
17
40
|
|
|
18
41
|
export default async function runProbe() {
|
|
42
|
+
let url;
|
|
43
|
+
try {
|
|
44
|
+
url = connectionUrlFromEnv();
|
|
45
|
+
} catch (err) {
|
|
46
|
+
if (err instanceof MissingPostgresHostError) {
|
|
47
|
+
return {
|
|
48
|
+
results: [skipRow(err.variable)],
|
|
49
|
+
accountBoundSkipped: true,
|
|
50
|
+
reason: `${err.variable} unset`,
|
|
51
|
+
envDeclared: [...DECLARED_ENV],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
19
56
|
const events = [];
|
|
20
|
-
const store = createStore({
|
|
21
|
-
connectionUrl:
|
|
57
|
+
const store = await createStore({
|
|
58
|
+
connectionUrl: url,
|
|
22
59
|
onEvent: (e) => events.push(e),
|
|
23
60
|
});
|
|
24
61
|
const results = [];
|
|
62
|
+
let databaseName = null;
|
|
25
63
|
try {
|
|
26
|
-
await store.ready();
|
|
64
|
+
databaseName = await store.ready();
|
|
27
65
|
const pool = store.getPool();
|
|
28
|
-
// Ensure schema and empty state
|
|
29
66
|
await pool.query('CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE, created_at TIMESTAMPTZ NOT NULL DEFAULT now())');
|
|
30
67
|
await pool.query('TRUNCATE users');
|
|
31
|
-
|
|
68
|
+
const pidRT = await pool.query('SELECT pg_backend_pid() AS pid, txid_current() AS txid');
|
|
69
|
+
const backendPid = String(pidRT.rows[0].pid);
|
|
70
|
+
const transactionId = String(pidRT.rows[0].txid);
|
|
32
71
|
const email = 'transaction-atomicity@rcf.test';
|
|
33
72
|
let caught = null;
|
|
34
73
|
try {
|
|
35
74
|
await store.withTransaction(async (tx) => {
|
|
36
75
|
await tx.query('INSERT INTO users(name, email) VALUES ($1, $2)', ['first-user', email]);
|
|
37
|
-
// Same email violates UNIQUE constraint on the second insert
|
|
38
76
|
await tx.query('INSERT INTO users(name, email) VALUES ($1, $2)', ['second-user', email]);
|
|
39
77
|
});
|
|
40
78
|
} catch (err) {
|
|
41
79
|
caught = err;
|
|
42
80
|
}
|
|
43
|
-
|
|
44
81
|
const errorThrown = caught !== null;
|
|
45
82
|
results.push({
|
|
46
83
|
anchorAcId: 'AC-27104-1',
|
|
47
84
|
verdict: errorThrown ? 'pass' : 'fail',
|
|
48
85
|
detail: errorThrown
|
|
49
|
-
?
|
|
50
|
-
:
|
|
86
|
+
? `${AC} - withTransaction re-threw underlying error code=${caught.code}`
|
|
87
|
+
: `${AC} - withTransaction did not throw on the constraint violation`,
|
|
88
|
+
evidence: { backendPid, transactionId, databaseName, thrownErrorCode: caught && caught.code, thrownMessage: caught && caught.message },
|
|
51
89
|
});
|
|
52
|
-
|
|
53
90
|
const rolledBackEvent = events.find((e) => e.event === 'transactionRolledBack');
|
|
54
91
|
const indexIsOne = rolledBackEvent && rolledBackEvent.statementIndex === 1;
|
|
55
92
|
results.push({
|
|
56
93
|
anchorAcId: 'AC-27104-1',
|
|
57
94
|
verdict: indexIsOne ? 'pass' : 'fail',
|
|
58
95
|
detail: rolledBackEvent
|
|
59
|
-
?
|
|
60
|
-
:
|
|
96
|
+
? `${AC} - transactionRolledBack fired with statementIndex=${rolledBackEvent.statementIndex} code=${rolledBackEvent.code}`
|
|
97
|
+
: `${AC} - transactionRolledBack did not fire; events=${events.map((e) => e.event).join(',')}`,
|
|
98
|
+
evidence: { backendPid, transactionId, databaseName, transactionRolledBackEvent: rolledBackEvent || null, allEvents: events, rolledBackTimestamp: rolledBackEvent ? new Date(rolledBackEvent.ts).toISOString() : null, rolledBackVerificationOk: !!rolledBackEvent && rolledBackEvent.statementIndex === 1 },
|
|
61
99
|
});
|
|
62
|
-
|
|
63
100
|
const count = await store.countUsers();
|
|
64
101
|
const noRowsPersist = count === 0;
|
|
65
102
|
results.push({
|
|
66
103
|
anchorAcId: 'AC-27104-1',
|
|
67
104
|
verdict: noRowsPersist ? 'pass' : 'fail',
|
|
68
105
|
detail: noRowsPersist
|
|
69
|
-
?
|
|
70
|
-
:
|
|
106
|
+
? `${AC} - users table empty after rollback (no partial commit landed)`
|
|
107
|
+
: `${AC} - users table carries ${count} row(s) after rollback (partial commit leaked)`,
|
|
108
|
+
evidence: { backendPid, transactionId, databaseName, postRollbackUserCount: count, postRollbackVerificationOk: count === 0 },
|
|
71
109
|
});
|
|
72
110
|
} finally {
|
|
111
|
+
const teardown = [];
|
|
73
112
|
try {
|
|
74
113
|
await store.getPool().query('TRUNCATE users');
|
|
75
|
-
|
|
76
|
-
|
|
114
|
+
teardown.push({ step: 'TRUNCATE users on close', ok: true });
|
|
115
|
+
} catch (err) {
|
|
116
|
+
teardown.push({ step: 'TRUNCATE users on close', ok: false, error: err && err.message });
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
await store.close();
|
|
120
|
+
teardown.push({ step: 'close pool', ok: true });
|
|
121
|
+
} catch (err) {
|
|
122
|
+
teardown.push({ step: 'close pool', ok: false, error: err && err.message });
|
|
123
|
+
}
|
|
124
|
+
const failed = teardown.filter((t) => !t.ok);
|
|
125
|
+
if (failed.length > 0) {
|
|
126
|
+
results.push({
|
|
127
|
+
anchorReqId: 'persistence-data-postgres-REQ-004',
|
|
128
|
+
verdict: 'fail',
|
|
129
|
+
detail: `The facade exposes a transaction helper - teardown FAILED: ${failed.map((t) => `${t.step} -> ${t.error}`).join('; ')}`,
|
|
130
|
+
evidence: { teardown },
|
|
131
|
+
});
|
|
132
|
+
}
|
|
77
133
|
}
|
|
78
|
-
return results;
|
|
134
|
+
return { results };
|
|
79
135
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"reqId": "persistence-data-postgres-REQ-003",
|
|
3
3
|
"prdId": "PRD-001",
|
|
4
4
|
"title": "Prepared-statement discipline: every pg.query first argument is a static string literal with $N parameters",
|
|
5
|
-
"description": "Every call to pg.query (whether via the pool, a client, or a transaction helper) inside the facade module passes a static string literal as its first argument and supplies parameters as an array of values that the driver binds to $1, $2, ... $N placeholders in the string, per the node-postgres parameterised-queries contract at https://node-postgres.com/features/queries. No call site inside the facade passes a template literal with an interpolated expression as the first argument; no call site builds a query string via string concatenation or template-literal interpolation with consumer-supplied values. A call site that violates the discipline refuses at author-side
|
|
5
|
+
"description": "Every call to pg.query (whether via the pool, a client, or a transaction helper) inside the facade module passes a static string literal as its first argument and supplies parameters as an array of values that the driver binds to $1, $2, ... $N placeholders in the string, per the node-postgres parameterised-queries contract at https://node-postgres.com/features/queries. No call site inside the facade passes a template literal with an interpolated expression as the first argument; no call site builds a query string via string concatenation or template-literal interpolation with consumer-supplied values. A call site that violates the discipline refuses at the author-side check; the prepared-statement-scan probe surfaces the violation at gate time via a source-tree AST scan (per the persistence-data-d1 pattern).",
|
|
6
6
|
"category": "technical",
|
|
7
7
|
"domain": "persistence",
|
|
8
8
|
"priority": "must",
|
|
@@ -60,7 +60,7 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
60
60
|
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
61
61
|
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
62
62
|
|
|
63
|
-
US 27101-27110 sit at the LOW end of the 27101-27899 band on purpose
|
|
63
|
+
US 27101-27110 sit at the LOW end of the 27101-27899 band on purpose. A project-side story mechanically derived from a persistence-data-postgres REQ id into the number 27110 would collide against the shipped US-27110; band headroom (27111-27899) leaves that space.
|
|
64
64
|
|
|
65
65
|
Postgres suffixes for this blueprint use the 2801-2899 block, continuing the widening pattern (persistence-data-sqlite 6xx, persistence-data-d1 14xx, and persistence-data-postgres 28xx).
|
|
66
66
|
|
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.5 - 2026-09-11
|
|
4
|
+
|
|
5
|
+
Strengthens the shared probe anatomy helper the seven core-shelf blueprints all lean on: rows whose only signal is a parsed log object with a message, a linesExcerpt array, a parsed component list, a rendered-state or -order list, a perFile / entries / commitEntries list, or a locally invented callTrackingId are refused as identifier evidence; retained anchor ids are checked against the applicable blueprint's shipped AC set; the WARN row shortcut that accepted a bare unobservableReason is removed and every WARN must now satisfy exact-skip, notObservableHere (browser-only) or identifier-plus-derived. No SQLite probe change was needed; SQLite remains GREEN.
|
|
6
|
+
|
|
7
|
+
## 1.1.4 - 2026-09-11
|
|
8
|
+
|
|
9
|
+
wal-checkpoint AC-5105-3 anchor now observes the complete durability posture (PRAGMA journal_mode=wal + PRAGMA synchronous>=NORMAL + consumer-source grep) with a real integer rowId from a seed put through the facade; boot-open-migrate AC-5101-3 also carries a real rowId. Fixture store.mjs sets PRAGMA synchronous=NORMAL at open time and exposes synchronousNow(). Shared anatomy helper tightened per the strict-evidence contract (strict identifier set, existence check for shipped-AC limitation and notObservableHere.ac, exact-variable skip reason wire-up in all seven anatomy tests, notObservableHere is now refused for non-browser-only ACs, acceptedProfile removed from identifier lists, single JSON log-line string is derived only).
|
|
10
|
+
|
|
11
|
+
## 1.1.3 - 2026-09-11
|
|
12
|
+
|
|
13
|
+
Adds a contributions/probes/ pack (boot-open-migrate, facade-round-trip, wal-checkpoint) with a fixture-side node:sqlite store facade under packages/rcf-lite/test/fixtures/probe-pack-persistence-data-sqlite/. Probes run against the real node:sqlite engine on Node 24; record real integer row ids, applied-migration lists, and wal_checkpoint(TRUNCATE) counters with the WAL sidecar shrink after truncate. No account gate.
|
|
14
|
+
|
|
15
|
+
Anchoring: boot-open-migrate anchors AC-5101-3 (open returns only after migrations run); the AC-5101-1 export-order row and the AC-5101-2 path-from-config row are de-claimed (conformanceOnly, anchorAcId=null) with limitations naming their respective ACs; the reopen row de-claims from AC-5101-3. wal-checkpoint anchors AC-5105-3 (durability posture set at open); the size-transition row and the walCheckpoint event row de-claim from AC-5105-1 and AC-5106-1 respectively. facade-round-trip anchors AC-5107-2 as its module anchor with the runtime CRUD rows de-claiming from AC-5107-2 (facade surface not exhaustively scanned) and the event row de-claiming from AC-5106-1. probe-utils normalisation and thrown-error rows carry an evidence object; the fallback anchorAcId is null (harnessError marks the row) rather than any placeholder id.
|
|
16
|
+
|
|
3
17
|
## 1.1.1 (register-sweep patch, 2026-09-10)
|
|
4
18
|
|
|
5
19
|
- Register: neutral wording in shipped prose (no capability change).
|
|
6
20
|
|
|
7
21
|
## 1.1.0 - 2026-09-09
|
|
8
|
-
Adds deliveredBy on REQ-001. Adds ownerRef on AC-5106-1 and AC-5110-2 (onEvent).
|
|
22
|
+
Adds deliveredBy on REQ-001. Adds ownerRef on AC-5106-1 and AC-5110-2 (onEvent). US-5109 AC-5109-3 recovers a defective committed migration via a new numbered forward-only file (never editing the committed file in place), aligning with TAC-603 and the migration catalog's forward-only rule. Adds disposition to every AC.
|
|
9
23
|
|
|
10
24
|
|
|
11
25
|
|
|
12
|
-
|
|
26
|
+
Version bumped from 1.0.1 to 1.1.0 to reflect the net-added AC contributions on existing stories (permission-denied and concurrent-WAL failure paths added under US-5101; disk-full mid-migration added under US-5104).
|
|
13
27
|
|
|
14
28
|
Adds deliveredBy on REQ-002 through REQ-011 (ten of eleven mandatory REQs).
|
|
@@ -27,9 +27,9 @@ The doc set is contributions (copied into the project tree by `rcf define bluepr
|
|
|
27
27
|
|
|
28
28
|
## What it contributes, and what it deliberately does not
|
|
29
29
|
|
|
30
|
-
Contributed kinds: REQ, US (with inline ACs), TAC, ADR. Adherence is expressed as ACs; the blueprint ships no test files (
|
|
30
|
+
Contributed kinds: REQ, US (with inline ACs), TAC, ADR. Adherence is expressed as ACs; the blueprint ships no test files (shipped policy 5) and no code.
|
|
31
31
|
|
|
32
|
-
No FBS contributions, as a matter of principle (
|
|
32
|
+
No FBS contributions, as a matter of principle (policy): FBSs are the work of the implementing agent, not the blueprint; project constraints have to be applied at the time of creation. The blueprint contributes the WHAT (the store facade contract, the migration runner contract, the migration catalog shape, the backup runner contract, the event log discipline); the implementing agent derives the HOW-tasks (FBS) in the host project, where the ACs contributed here get picked up by the project's own build sequencing.
|
|
33
33
|
|
|
34
34
|
Deliberately not contributed: the domain schema (the tables the project's own entities live in are project-authored, not blueprint-authored; the blueprint governs the store facade and the migration discipline, not the domain shape); ORMs, query builders, and any framework-shaped abstraction above the named CRUD verbs (the facade is a project-authored surface; how it internally implements its verbs is not blueprint-owned); a Postgres engine TAC (deferred; see ADR-601's alternatives and the guide 'when it does not fit'); logical schema-aware dumps (out of scope; see ADR-605's alternatives); connection pooling (an implementation detail of the facade when a project selects an engine that benefits from it, not a blueprint contribution).
|
|
35
35
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"slug": "persistence-data-sqlite",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"category": "persistence",
|
|
5
5
|
"contributions": [
|
|
6
6
|
{
|
|
@@ -162,5 +162,6 @@
|
|
|
162
162
|
"kind": "adr",
|
|
163
163
|
"path": "adrs/adr-605-persistence-data-sqlite-backup-model.json"
|
|
164
164
|
}
|
|
165
|
-
]
|
|
165
|
+
],
|
|
166
|
+
"updatedAt": "2026-09-11"
|
|
166
167
|
}
|