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/observability-probe-endpoints/contributions/probes/partial-profile-refusal.mjs
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Partial-profile-refusal probe for observability-probe-endpoints.
|
|
2
|
+
//
|
|
3
|
+
// AC-14103-2 requires the process to exit non-zero when a profile
|
|
4
|
+
// missing a required field is loaded at boot. This probe catches an
|
|
5
|
+
// in-process refusal via refuseIfPartial rather than spawning a
|
|
6
|
+
// child process and observing its OS exit code. Rows de-claimed
|
|
7
|
+
// (conformanceOnly, anchorAcId=null) with the limitation naming
|
|
8
|
+
// AC-14103-2.
|
|
9
|
+
//
|
|
10
|
+
// AC-14103-1 requires every field's value to belong to its enumerated
|
|
11
|
+
// set (not just presence). This row asserts presence only. Row
|
|
12
|
+
// de-claimed with the limitation naming AC-14103-1.
|
|
13
|
+
//
|
|
14
|
+
// AC-14103-3 requires the loadBalancer profile to be materialised
|
|
15
|
+
// and observed to expose exactly one /health handler and no /live
|
|
16
|
+
// or /ready handlers. This row asserts the resolved config shape but
|
|
17
|
+
// does not materialise and probe for extra handlers. Row de-claimed
|
|
18
|
+
// with the limitation naming AC-14103-3.
|
|
19
|
+
|
|
20
|
+
import { refuseIfPartial, resolveProfile } from '../../../../packages/rcf-lite/test/fixtures/probe-pack-observability-probe-endpoints/src/profile-registry.mjs';
|
|
21
|
+
|
|
22
|
+
export const anchorAcId = 'AC-14103-2';
|
|
23
|
+
export const accountBound = false;
|
|
24
|
+
|
|
25
|
+
const SHIPPED_NAMES = ['kubernetes', 'loadBalancer', 'uptimeMonitor', 'systemd', 'dockerHealthcheck', 'reverseProxy'];
|
|
26
|
+
|
|
27
|
+
const LIM_14103_2 = `AC-14103-2: requires the process to exit non-zero when a profile missing a required field is loaded at boot. This row catches an in-process refusal via refuseIfPartial rather than spawning a child process and observing its OS exit code.`;
|
|
28
|
+
const LIM_14103_1 = `AC-14103-1: requires every field's value to belong to its enumerated set (not just presence: transport must be an enum value, paths/command/notify each carry typed contents, semanticModel is one of a small set). This row asserts presence of each field only.`;
|
|
29
|
+
const LIM_14103_3 = `AC-14103-3: requires the loadBalancer profile to be materialised and observed to expose exactly one /health handler and no /live or /ready handlers. This row asserts the resolved config shape but does not materialise the profile and issue HTTP GETs against /live and /ready to prove absence of those handlers.`;
|
|
30
|
+
|
|
31
|
+
export default async function runProbe() {
|
|
32
|
+
const results = [];
|
|
33
|
+
|
|
34
|
+
// AC-14103-2 refusal via refuseIfPartial: strip 'transport' from the
|
|
35
|
+
// kubernetes profile.
|
|
36
|
+
const bad = { ...resolveProfile('kubernetes') };
|
|
37
|
+
delete bad.transport;
|
|
38
|
+
let refusalMessage = null;
|
|
39
|
+
let refusalCode = null;
|
|
40
|
+
let refusalMissing = null;
|
|
41
|
+
try { refuseIfPartial(bad); } catch (e) { refusalMessage = e.message; refusalCode = e.code; refusalMissing = e.missingKey; }
|
|
42
|
+
results.push({
|
|
43
|
+
anchorAcId: null,
|
|
44
|
+
conformanceOnly: true,
|
|
45
|
+
limitation: LIM_14103_2,
|
|
46
|
+
verdict: refusalCode === 'PROBE_PROFILE_INCOMPLETE' && refusalMissing === 'transport' ? 'pass' : 'fail',
|
|
47
|
+
detail: `observed stripped-transport kubernetes profile refused via refuseIfPartial with code='${refusalCode}' missingKey='${refusalMissing}' message='${refusalMessage}'. Process-level non-zero exit not observed here.`,
|
|
48
|
+
evidence: { refusalMessage, refusalCode, missingKey: refusalMissing },
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Second refusal: kubernetes with startupEnabled=true but no paths.startup.
|
|
52
|
+
const bad2 = { ...resolveProfile('kubernetes') };
|
|
53
|
+
bad2.startupEnabled = true;
|
|
54
|
+
let refusalMessage2 = null;
|
|
55
|
+
let refusalCode2 = null;
|
|
56
|
+
let refusalMissing2 = null;
|
|
57
|
+
try { refuseIfPartial(bad2); } catch (e) { refusalMessage2 = e.message; refusalCode2 = e.code; refusalMissing2 = e.missingKey; }
|
|
58
|
+
results.push({
|
|
59
|
+
anchorAcId: null,
|
|
60
|
+
conformanceOnly: true,
|
|
61
|
+
limitation: LIM_14103_2,
|
|
62
|
+
verdict: refusalCode2 === 'PROBE_PROFILE_INCOMPLETE' && refusalMissing2 === 'paths.startup' ? 'pass' : 'fail',
|
|
63
|
+
detail: `observed kubernetes with startupEnabled but no paths.startup refused via refuseIfPartial with code='${refusalCode2}' missingKey='${refusalMissing2}' message='${refusalMessage2}'. Process-level non-zero exit not observed here.`,
|
|
64
|
+
evidence: { refusalMessage: refusalMessage2, refusalCode: refusalCode2, missingKey: refusalMissing2 },
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// AC-14103-1 presence shape check for all six profiles.
|
|
68
|
+
const shape = [];
|
|
69
|
+
let allShapeOk = true;
|
|
70
|
+
for (const name of SHIPPED_NAMES) {
|
|
71
|
+
let resolved = null;
|
|
72
|
+
let err = null;
|
|
73
|
+
try { resolved = refuseIfPartial(resolveProfile(name)); } catch (e) { err = e.message; }
|
|
74
|
+
const surfaceOk = resolved && (resolved.paths || resolved.command || resolved.notify);
|
|
75
|
+
const ok = Boolean(resolved && resolved.transport && surfaceOk && resolved.responseContract && resolved.semanticModel);
|
|
76
|
+
if (!ok) allShapeOk = false;
|
|
77
|
+
shape.push({ name, transport: resolved?.transport, hasSurface: Boolean(surfaceOk), hasResponseContract: Boolean(resolved?.responseContract), hasSemanticModel: Boolean(resolved?.semanticModel), err });
|
|
78
|
+
}
|
|
79
|
+
results.push({
|
|
80
|
+
anchorAcId: null,
|
|
81
|
+
conformanceOnly: true,
|
|
82
|
+
limitation: LIM_14103_1,
|
|
83
|
+
verdict: allShapeOk ? 'pass' : 'fail',
|
|
84
|
+
detail: `observed presence-only shape check for all six shipped profiles: ${JSON.stringify(shape)}. Enum-membership per field is not observed here.`,
|
|
85
|
+
evidence: { acceptedProfile: 'all-six', resolvedTransport: 'mixed', resolvedPaths: {}, shape, shippedNames: SHIPPED_NAMES },
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// AC-14103-3 loadBalancer shape observation (not materialised).
|
|
89
|
+
const lb = resolveProfile('loadBalancer');
|
|
90
|
+
const lbOk = lb.paths?.health && !lb.paths?.liveness && !lb.paths?.readiness && lb.semanticModel === 'singleHealthSignal';
|
|
91
|
+
results.push({
|
|
92
|
+
anchorAcId: null,
|
|
93
|
+
conformanceOnly: true,
|
|
94
|
+
limitation: LIM_14103_3,
|
|
95
|
+
verdict: lbOk ? 'pass' : 'fail',
|
|
96
|
+
detail: `The loadBalancer profile resolves to a single-endpoint HTTP GET - observed resolved paths=${JSON.stringify(lb.paths)} semanticModel='${lb.semanticModel}'; expected paths.health present with no paths.liveness/paths.readiness and semanticModel==='singleHealthSignal'. Materialised handler absence not observed here.`,
|
|
97
|
+
evidence: { acceptedProfile: lb.name, resolvedTransport: lb.transport, resolvedPaths: lb.paths, semanticModel: lb.semanticModel },
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
return { results, extra: { envDeclared: ['RCF_FIXTURE_OBS_PROBE_PORT', 'RCF_FIXTURE_OBS_PROBE_SEPARATE_PORT'], shippedNames: SHIPPED_NAMES } };
|
|
101
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
export const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
|
|
7
|
+
export const FIXTURE_DIR = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/probe-pack-observability-probe-endpoints');
|
|
8
|
+
export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/observability-probe-endpoints');
|
|
9
|
+
export const DECLARED_ENV = new Set(['RCF_FIXTURE_OBS_PROBE_PORT', 'RCF_FIXTURE_OBS_PROBE_SEPARATE_PORT']);
|
|
10
|
+
|
|
11
|
+
export function aggregate(results) {
|
|
12
|
+
if (!Array.isArray(results) || results.length === 0) return 'fail';
|
|
13
|
+
if (results.some((r) => r.verdict === 'fail')) return 'fail';
|
|
14
|
+
if (results.some((r) => r.verdict === 'warn')) return 'warn';
|
|
15
|
+
return 'pass';
|
|
16
|
+
}
|
|
17
|
+
export function isSkipped(results) { return Array.isArray(results) && results.length > 0 && results.every((r) => r.accountBoundSkipped === true); }
|
|
18
|
+
export async function writeReport({ probeName, engine, results, extra }) {
|
|
19
|
+
await mkdir(REPORT_DIR, { recursive: true });
|
|
20
|
+
const normalised = (Array.isArray(results) && results.length > 0)
|
|
21
|
+
? results
|
|
22
|
+
: [{ anchorAcId: null, harnessError: true, verdict: 'fail', detail: 'no checks ran', evidence: { reason: 'no checks ran', probeName, runAt: new Date().toISOString(), engine } }];
|
|
23
|
+
const raw = aggregate(normalised);
|
|
24
|
+
const aggregateVerdict = isSkipped(normalised) ? 'pass' : raw;
|
|
25
|
+
const report = { slug: 'observability-probe-endpoints', probeName, runAt: new Date().toISOString(), engine, results: normalised, aggregateVerdict, ...(extra ?? {}) };
|
|
26
|
+
const path = resolve(REPORT_DIR, `${probeName}.json`);
|
|
27
|
+
await writeFile(path, JSON.stringify(report, null, 2) + '\n', 'utf8');
|
|
28
|
+
return { report, path };
|
|
29
|
+
}
|
|
30
|
+
export async function runShim(probeName, engine, mainFn) {
|
|
31
|
+
try {
|
|
32
|
+
const outcome = (await mainFn()) ?? { results: [] };
|
|
33
|
+
const { results, extra } = outcome;
|
|
34
|
+
const { report, path } = await writeReport({ probeName, engine, results, extra });
|
|
35
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
36
|
+
process.stdout.write(`report written to ${path}\n`);
|
|
37
|
+
if (report.aggregateVerdict === 'fail') process.exitCode = 1;
|
|
38
|
+
} catch (err) {
|
|
39
|
+
const results = [{ anchorAcId: null, harnessError: true, verdict: 'fail', detail: `probe threw: ${err?.message ?? err}`, evidence: { thrown: true, message: err?.message ?? String(err), name: err?.name ?? 'Error', probeName, runAt: new Date().toISOString(), engine } }];
|
|
40
|
+
const { report, path } = await writeReport({ probeName, engine, results });
|
|
41
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
42
|
+
process.stderr.write(`probe error: ${err?.stack ?? err}\n`);
|
|
43
|
+
process.stderr.write(`report written to ${path}\n`);
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function portFrom(v) { if (v === undefined || v === '') return 0; const n = Number(v); return Number.isInteger(n) && n >= 0 && n <= 65535 ? n : 0; }
|
|
48
|
+
export const primaryPort = () => portFrom(process.env.RCF_FIXTURE_OBS_PROBE_PORT);
|
|
49
|
+
export const separatePort = () => portFrom(process.env.RCF_FIXTURE_OBS_PROBE_SEPARATE_PORT);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Profile-boot-materialisation probe for observability-probe-endpoints.
|
|
2
|
+
//
|
|
3
|
+
// Resolves the shipped 'kubernetes' profile and materialises it on
|
|
4
|
+
// 127.0.0.1 via the fixture registry; issues real HTTP GETs to the
|
|
5
|
+
// resolved liveness and readiness paths with a probe-varied
|
|
6
|
+
// x-request-id header per request. Records the response header echo
|
|
7
|
+
// and body excerpt and asserts the resolved profile name equals
|
|
8
|
+
// 'kubernetes' and the bound listener answers on the profile's
|
|
9
|
+
// declared paths.
|
|
10
|
+
//
|
|
11
|
+
// AC-14101-1 additionally requires observation of fused/separate port
|
|
12
|
+
// topology AND absence of handlers outside the resolved path set.
|
|
13
|
+
// This row observes only bound-path behaviour; it does not check
|
|
14
|
+
// port topology or verify no additional handlers were bound. Row
|
|
15
|
+
// de-claimed (conformanceOnly, anchorAcId=null) with the limitation
|
|
16
|
+
// naming AC-14101-1.
|
|
17
|
+
|
|
18
|
+
import { randomUUID } from 'node:crypto';
|
|
19
|
+
import { materialise, resolveProfile } from '../../../../packages/rcf-lite/test/fixtures/probe-pack-observability-probe-endpoints/src/profile-registry.mjs';
|
|
20
|
+
import { primaryPort } from './probe-utils.mjs';
|
|
21
|
+
|
|
22
|
+
export const anchorAcId = 'AC-14101-1';
|
|
23
|
+
export const accountBound = false;
|
|
24
|
+
const LIM_14101_1 = `AC-14101-1: requires a process configured with probeInterface.profile: kubernetes to bind probe handlers whose paths match the resolved profile AND to observe fused/separate port topology AND absence of handlers outside the resolved path set. This row observes bound-path behaviour (liveness and readiness respond 200 with body.status='pass') but does not verify port-topology or handler-absence clauses.`;
|
|
25
|
+
|
|
26
|
+
async function get(url, rid) {
|
|
27
|
+
const res = await fetch(url, { headers: { 'x-request-id': rid } });
|
|
28
|
+
const text = await res.text();
|
|
29
|
+
let parsed = null; try { parsed = JSON.parse(text); } catch {}
|
|
30
|
+
return { status: res.status, requestId: res.headers.get('x-request-id'), contentType: res.headers.get('content-type'), body: text, parsed };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default async function runProbe() {
|
|
34
|
+
const results = [];
|
|
35
|
+
const resolved = resolveProfile('kubernetes');
|
|
36
|
+
const inst = await materialise({ profile: resolved, listenerPort: primaryPort() });
|
|
37
|
+
const suppliedLive = randomUUID();
|
|
38
|
+
const suppliedReady = randomUUID();
|
|
39
|
+
let live, ready;
|
|
40
|
+
try {
|
|
41
|
+
live = await get(`http://127.0.0.1:${inst.requestPort}${inst.profile.paths.liveness}`, suppliedLive);
|
|
42
|
+
ready = await get(`http://127.0.0.1:${inst.requestPort}${inst.profile.paths.readiness}`, suppliedReady);
|
|
43
|
+
const liveOk = live.status === 200 && live.requestId === suppliedLive && live.parsed?.status === 'pass' && live.parsed?.profile === 'kubernetes' && live.parsed?.kind === 'liveness';
|
|
44
|
+
const readyOk = ready.status === 200 && ready.requestId === suppliedReady && ready.parsed?.status === 'pass' && ready.parsed?.profile === 'kubernetes' && ready.parsed?.kind === 'readiness';
|
|
45
|
+
const nameOk = inst.profile.name === 'kubernetes';
|
|
46
|
+
const pathsOk = inst.profile.paths.liveness === '/live' && inst.profile.paths.readiness === '/ready';
|
|
47
|
+
results.push({
|
|
48
|
+
anchorAcId: null,
|
|
49
|
+
conformanceOnly: true,
|
|
50
|
+
limitation: LIM_14101_1,
|
|
51
|
+
verdict: liveOk && readyOk && nameOk && pathsOk ? 'pass' : 'fail',
|
|
52
|
+
detail: `observed resolved profile.name='${inst.profile.name}' paths=${JSON.stringify(inst.profile.paths)} on port ${inst.requestPort}; live status=${live.status} echoed rid=${live.requestId === suppliedLive} body.status='${live.parsed?.status}' body.profile='${live.parsed?.profile}'; ready status=${ready.status} echoed rid=${ready.requestId === suppliedReady} body.status='${ready.parsed?.status}' body.profile='${ready.parsed?.profile}'.`,
|
|
53
|
+
evidence: {
|
|
54
|
+
acceptedProfile: inst.profile.name,
|
|
55
|
+
resolvedTransport: inst.profile.transport,
|
|
56
|
+
resolvedPaths: inst.profile.paths,
|
|
57
|
+
port: inst.requestPort,
|
|
58
|
+
variedInputs: { liveness: suppliedLive, readiness: suppliedReady },
|
|
59
|
+
derivedLive: { status: live.status, requestId: live.requestId, contentType: live.contentType, bodyExcerpt: live.body.slice(0, 300) },
|
|
60
|
+
derivedReady: { status: ready.status, requestId: ready.requestId, contentType: ready.contentType, bodyExcerpt: ready.body.slice(0, 300) },
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
} finally { await inst.close(); }
|
|
64
|
+
return { results, extra: { envDeclared: ['RCF_FIXTURE_OBS_PROBE_PORT', 'RCF_FIXTURE_OBS_PROBE_SEPARATE_PORT'], boundPort: inst.requestPort,
|
|
65
|
+
variedInputs: { liveness: suppliedLive, readiness: suppliedReady },
|
|
66
|
+
derivedLive: live && { status: live.status, requestId: live.requestId, contentType: live.contentType, bodyExcerpt: live.body.slice(0, 300) },
|
|
67
|
+
derivedReady: ready && { status: ready.status, requestId: ready.requestId, contentType: ready.contentType, bodyExcerpt: ready.body.slice(0, 300) },
|
|
68
|
+
} };
|
|
69
|
+
}
|
|
@@ -19,7 +19,7 @@ Rules for new topics (inherited from the application-spa, application-api-rest,
|
|
|
19
19
|
|
|
20
20
|
## Id number bands (registry bootstrap)
|
|
21
21
|
|
|
22
|
-
AC ids (and therefore US numeric ids, which anchor them) are NOT namespaced by the 0.5.0 schema grammar; the band allocation IS the AC-collision enforcement mechanism. Composing blueprints take a fresh band rather than proposing namespaced AC ids. Band allocation is
|
|
22
|
+
AC ids (and therefore US numeric ids, which anchor them) are NOT namespaced by the 0.5.0 schema grammar; the band allocation IS the AC-collision enforcement mechanism. Composing blueprints take a fresh band rather than proposing namespaced AC ids. Band allocation is policy; this table is the shared registry-bootstrap replicated across every shipped and forthcoming blueprint's `docs/topics.md` until a mechanism-side central registry lands (v1.1 candidate).
|
|
23
23
|
|
|
24
24
|
This table is maintained shelf-wide across every blueprint's `docs/topics.md`. Rows are recorded at ship, never predicted.
|
|
25
25
|
|
|
@@ -64,7 +64,7 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
64
64
|
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
65
65
|
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
66
66
|
|
|
67
|
-
US 14101-14108 sit at the LOW end of the 14101-14899 band on purpose. A project-side story that mechanically derives from an observability-probe-endpoints REQ id into the number `14108` would collide against observability-probe-endpoints-US-14108 in this package; the band leaves headroom at the HIGH end (US 14181-14899) so a project's own stories anchored to observability-probe-endpoints REQs can allocate without conflict.
|
|
67
|
+
US 14101-14108 sit at the LOW end of the 14101-14899 band on purpose. A project-side story that mechanically derives from an observability-probe-endpoints REQ id into the number `14108` would collide against observability-probe-endpoints-US-14108 in this package; the band leaves headroom at the HIGH end (US 14181-14899) so a project's own stories anchored to observability-probe-endpoints REQs can allocate without conflict. Band spacing between the previous shelf-lane row (persistence-data-d1, 13101-13899, 14xx) and this one (14101-14899, 15xx) reflects the four-digit widening pattern opened by security-auth-clerk at 10xx and continued through the second shelf-lane block.
|
|
68
68
|
|
|
69
69
|
## Shared expectations for future composing blueprints
|
|
70
70
|
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.6 - 2026-09-11
|
|
4
|
+
|
|
5
|
+
facade-round-trip AC-13101-4 (missing-binding refusal) row is de-claimed to conformanceOnly (anchorAcId=null on the row; the module anchor is unchanged). The refusal is thrown by the local fixture's openFacade before any call reaches the D1 engine, so no engine-returned request id or resource identifier is available; the credential-leak-absent predicate is retained on the row. The earlier CHANGELOG description of a locally minted callTrackingId as a resource identifier is corrected: the field is dropped from the probe's evidence and the language does not appear here.
|
|
6
|
+
|
|
7
|
+
## 1.1.5 - 2026-09-11
|
|
8
|
+
|
|
9
|
+
AC-13101-4 anchor now positively asserts no-credential-leak: a sentinel account id and API token are stashed on the env passed to openFacade alongside the missing DB binding, and the row verdict requires neither sentinel appears in the refusal error message, kind, bindingName, stack or JSON serialisation (credentialLeakAbsent=true); the row records a locally minted row correlation string on the row (no engine identifier is available on the refusal path). CHANGELOG history restored (the 1.1.0/1.1.1/1.1.2 entries were unintentionally overwritten in the previous pass) and this 1.1.5 entry is added.
|
|
10
|
+
|
|
11
|
+
## 1.1.4 - 2026-09-11
|
|
12
|
+
|
|
13
|
+
Adds a contributions/probes/ pack (facade-round-trip, migrations-forward-only, real-account-d1-round-trip) with a fixture-side sqlite-backed D1 binding and a facade module under packages/rcf-lite/test/fixtures/probe-pack-persistence-data-d1/. Probes run against the fixture on Node 24 and against real Cloudflare D1 on the account-bound branch (CI_HAS_CLOUDFLARE_ACCOUNT gate + CF_ACCOUNT_ID + CF_API_TOKEN, one variable per skip row).
|
|
14
|
+
|
|
15
|
+
Anchoring: facade-round-trip anchors AC-13101-4 (missing-binding refusal) as its module anchor; the facadeReady, insert, find and delete rows de-claim (conformanceOnly, anchorAcId=null) with limitations naming AC-13101-1 or AC-13101-2 (source-tree sole-reader and facade-surface scan are not observable at runtime). migrations-forward-only anchors AC-13102-2 as its module anchor; each row de-claims with a limitation naming AC-13102-2 or AC-13102-3 (wrangler CLI not spawned; internal table name is not the configured d1_migrations). real-account-d1-round-trip anchors AC-13101-1 as its module anchor; every live row de-claims with the limitation naming AC-13101-1 (raw REST is not the source-tree sole-reader property). Live create rows record only what the create call proves; presentAfterDelete is set only on the teardown row after delete + inventory. An auth failure with credentials PRESENT is a FAIL, not an accountBoundSkipped row. Live scratch resources are named qa-e-d1-<short> and deleted with a post-run inventory check.
|
|
3
16
|
|
|
4
17
|
## 1.1.2 - 2026-09-10
|
|
5
18
|
|
|
6
|
-
|
|
19
|
+
Removed the `prepare().bind()` and `db.exec(<consumer string>)` literals from `ADR-1404.context` (the argument now names the prepared-statement discipline owned on `TAC-1401-persistence-data-d1-facade.responsibilities[2]`); added the one-line owner pointer to the facade-shape asset and the batch-usage asset naming the TAC responsibility indices they demonstrate. ADR-1404 bumped to 1.0.1.
|
|
7
20
|
|
|
8
21
|
## 1.1.1 - 2026-09-10
|
|
9
22
|
|
|
10
23
|
Dimension-d single-definition-ownership cleanup on REQ-004: REQ description now references the prepared-statement discipline owned on TAC-1401 (facade responsibilities) rather than restating the vendor prepare/bind/exec literals. `deliveredBy` re-pointed at `TAC-1401-persistence-data-d1-facade.responsibilities.prepare` so the pass-2 delivery-carried check resolves against surface text present on the TAC. Chain-consistency lint zero on pass 1 and pass 2.
|
|
11
24
|
|
|
12
25
|
## 1.1.0 - 2026-09-09
|
|
13
|
-
Adds deliveredBy on REQ-001. Adds ownerRef and disposition to every AC.
|
|
26
|
+
Adds deliveredBy on REQ-001. Adds ownerRef and disposition to every AC. ADR-1404 settles the allowed query surface: `db.exec` is refused on the facade's public verbs and on consumer code, and permitted only inside the migration runner, out of consumer reach. No new contributions.
|
|
14
27
|
|
|
15
28
|
|
|
16
29
|
|
|
17
|
-
|
|
30
|
+
Version bumped from 1.0.1 to 1.1.0 to reflect the net-added AC contributions on existing stories (migration-D1-binding failure paths added under US-13101; deploy-gate quota-exhausted added under US-13102).
|
|
18
31
|
|
|
19
32
|
Adds deliveredBy on REQ-002 through REQ-007 (six of seven mandatory REQs). Sweeps vendorCitation onto fixed ACs resting on vendor facts (AC-13103-1, AC-13104-3, AC-13105-2).
|
|
@@ -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 wrangler-owned migration discipline, the deploy-pipeline gate contract, the prepared-statement and batch atomicity boundaries, the two-path recovery model, the metadata-only 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, on top of the migration directory the project maintains; the blueprint governs the facade contract and the migration discipline, not the domain shape); an ORM or query builder above the D1 prepared-statement surface (the facade is a project-authored surface; how it internally implements its verbs above the vendor binding is not blueprint-owned, but the boundary discipline refuses raw-SQL passthrough on the public surface); a Worker deploy blueprint (a companion `deploy-cloudflare-workers` blueprint is the natural pair for the Worker deploy step the deploy-gate TAC assumes; until it ships, projects wire their own deploy step); a secrets management surface for the CI credential that runs `wrangler d1 migrations apply` and `wrangler deploy` (the credential storage and rotation posture are the concern of the `security-secrets-management` blueprint, not this one); a CI pipeline template (CI shape is the concern of the `delivery-ci-workflows` blueprint, not this one; this blueprint contributes the requirement that the migrations-apply step orders strictly before the deploy step, not the file that implements it); a replication or failover surface (D1's read-replica surface is a read-scaling primitive, not a failover primitive; a project needing failover supersedes ADR-1401 with an alternate engine); a logical schema-agnostic dump beyond the vendor's `wrangler d1 export` (out of scope; see ADR-1405's alternatives).
|
|
35
35
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"slug": "persistence-data-d1",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"category": "persistence",
|
|
5
5
|
"contributions": [
|
|
6
6
|
{
|
|
@@ -122,5 +122,6 @@
|
|
|
122
122
|
"kind": "adr",
|
|
123
123
|
"path": "adrs/adr-1405-persistence-data-d1-recovery-model.json"
|
|
124
124
|
}
|
|
125
|
-
]
|
|
125
|
+
],
|
|
126
|
+
"updatedAt": "2026-09-11"
|
|
126
127
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"status": "accepted",
|
|
7
7
|
"title": "The D1 store facade is the only module that reads the D1 binding; consumers use named domain verbs, and every statement is a parameterised prepared statement",
|
|
8
8
|
"context": "A persistence boundary that leaks (the domain code reads the D1 binding from `env` directly, or the facade exposes a general-purpose raw-SQL passthrough) is a boundary the swap-out story does not work through, the test-double story does not work through, the reasoning-about-persistence-code-paths story does not work through, and (worse for D1 than for a local-file engine) the SQL-injection story does not work through: any consumer-supplied SQL fragment that reaches the vendor surface bypasses the prepared-statement discipline owned on TAC-1401-persistence-data-d1-facade.responsibilities[2], and the discipline is only load-bearing when it holds at every call site the facade exposes.",
|
|
9
|
-
"decision": "One module (the D1 store facade, TAC-1401-persistence-data-d1-facade) reads the D1 binding from the Worker `env`. Every other module in the source tree that touches persistence imports the facade and calls its named verbs. The facade's public surface exposes named domain verbs with typed parameters; it does not export the D1 binding, and it does not expose a general-purpose query method whose parameter is a SQL string or a prepared-statement object supplied by a consumer. Every statement the facade issues follows the prepared-statement chain owned on TAC-1401-persistence-data-d1-facade.responsibilities[2]; the raw `exec` surface is never invoked with a non-literal string, and SQL is never constructed by string concatenation with consumer arguments. Multi-statement writes that require atomicity go through the batch call owned on TAC-1401-persistence-data-d1-facade.responsibilities[3]; the facade never fakes atomicity by chaining sequential independent calls under an application-side try-catch. Allowed query surface
|
|
9
|
+
"decision": "One module (the D1 store facade, TAC-1401-persistence-data-d1-facade) reads the D1 binding from the Worker `env`. Every other module in the source tree that touches persistence imports the facade and calls its named verbs. The facade's public surface exposes named domain verbs with typed parameters; it does not export the D1 binding, and it does not expose a general-purpose query method whose parameter is a SQL string or a prepared-statement object supplied by a consumer. Every statement the facade issues follows the prepared-statement chain owned on TAC-1401-persistence-data-d1-facade.responsibilities[2]; the raw `exec` surface is never invoked with a non-literal string, and SQL is never constructed by string concatenation with consumer arguments. Multi-statement writes that require atomicity go through the batch call owned on TAC-1401-persistence-data-d1-facade.responsibilities[3]; the facade never fakes atomicity by chaining sequential independent calls under an application-side try-catch. Allowed query surface: only the prepared-statement chain above; no `exec` on consumer-supplied strings; the raw `exec` surface is permitted ONLY inside the migration runner (out of consumer-code reach) for the vendor-required schema-DDL pass, never on the facade's public verbs. Consumer code that calls the raw `exec` surface on the facade's exposed handle is refused by the source-scan probe.",
|
|
10
10
|
"consequences": "The engine choice is swappable because there is exactly one place that reads the binding. Domain tests run against an in-memory double that implements the same verb surface, without any reference to D1 at any point in the test's call path. Every persistence code path is discoverable by grepping for the facade's exports. Consumer arguments never traverse the SQL parser; the vendor's parameter-binding layer is the only place values reach the engine, and SQL injection is closed by construction rather than by discipline-at-call-site. Consumers pay a small cost when they need a new query shape (a facade edit and a consumer edit, in one commit); the size of that cost is the mechanism enforcing the boundary. Composing blueprints that contribute persistence-adjacent components (a cache, an outbox, a projection) contribute their own facade modules on the same discipline; every one of them imports the D1 store facade for its persistence needs, not the D1 binding.",
|
|
11
11
|
"alternativesConsidered": [
|
|
12
12
|
{
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Facade round-trip probe for persistence-data-d1.
|
|
2
|
+
//
|
|
3
|
+
// The 'facadeReady' event count-per-open is a fixture-added observation
|
|
4
|
+
// not stated on any shipped AC; the nearest shipped AC on facade shape
|
|
5
|
+
// is AC-13101-1 (single source-tree reader of the binding). Row
|
|
6
|
+
// de-claimed (conformanceOnly, anchorAcId=null) with the limitation
|
|
7
|
+
// naming AC-13101-1.
|
|
8
|
+
//
|
|
9
|
+
// AC-13101-2 (named domain verbs; no general-purpose query method
|
|
10
|
+
// accepting raw SQL) requires an exhaustive scan of the facade's
|
|
11
|
+
// public surface to prove absence of a general-purpose query method
|
|
12
|
+
// on top of the runtime CRUD observation. This probe observes the
|
|
13
|
+
// runtime CRUD half only; rows de-claimed with the limitation naming
|
|
14
|
+
// AC-13101-2.
|
|
15
|
+
//
|
|
16
|
+
// the strict-evidence contract tightening: AC-13101-4 (missing-binding refusal with
|
|
17
|
+
// d1BindingMissing) is observed via the local fixture openFacade
|
|
18
|
+
// throwing on a missing DB binding. The refusal never reaches the D1
|
|
19
|
+
// engine, so no engine-returned request id or resource identifier is
|
|
20
|
+
// available; the row is de-claimed to conformanceOnly naming AC-13101-4.
|
|
21
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
22
|
+
import { tmpdir } from 'node:os';
|
|
23
|
+
import { join } from 'node:path';
|
|
24
|
+
import { createD1Binding } from '../../../../packages/rcf-lite/test/fixtures/probe-pack-persistence-data-d1/src/d1-binding-mock.mjs';
|
|
25
|
+
import { openFacade } from '../../../../packages/rcf-lite/test/fixtures/probe-pack-persistence-data-d1/src/facade.mjs';
|
|
26
|
+
|
|
27
|
+
// The module anchor names the AC this probe observes as a property;
|
|
28
|
+
// individual rows may still de-claim (conformanceOnly) when the
|
|
29
|
+
// evidence shape does not carry an engine-returned identifier.
|
|
30
|
+
export const anchorAcId = 'AC-13101-4';
|
|
31
|
+
export const accountBound = false;
|
|
32
|
+
const AC4 = 'Dependency not ready: D1 binding absent from the';
|
|
33
|
+
const LIM_13101_1 = `AC-13101-1: requires exactly one source-tree module to read the D1 binding from the Worker env. A fixture-added 'facadeReady' event count per open is not evidence of the import-graph sole-reader property AC-13101-1 states.`;
|
|
34
|
+
const LIM_13101_2 = `AC-13101-2: requires the facade to expose named domain verbs for every persistence operation AND not to export the raw D1 binding or a general-purpose query method accepting a raw SQL string. Runtime CRUD round-trips through the facade demonstrate the named verbs work; a probe would still need an exhaustive scan of the facade's public surface to prove absence of a general-purpose query method.`;
|
|
35
|
+
const LIM_13101_4 = `AC-13101-4: the missing-binding refusal is thrown by the local fixture's openFacade before any call reaches the D1 engine. No engine-returned request id or resource identifier is available on the refusal path; the credential-leak-absent predicate is observed, but the identifier half of the strict-evidence contract requires an id the engine or its response headers produced.`;
|
|
36
|
+
|
|
37
|
+
export default async function runProbe() {
|
|
38
|
+
const dir = await mkdtemp(join(tmpdir(), 'rcf-d1-'));
|
|
39
|
+
const path = process.env.RCF_FIXTURE_D1_SQLITE_PATH || join(dir, 'd1.sqlite');
|
|
40
|
+
const events = [];
|
|
41
|
+
const results = [];
|
|
42
|
+
const binding = createD1Binding({ path });
|
|
43
|
+
const env = { DB: binding };
|
|
44
|
+
let rowId = null;
|
|
45
|
+
try {
|
|
46
|
+
const facade = await openFacade({ env, eventSink: (e) => events.push(e) });
|
|
47
|
+
const ready = events.filter((e) => e.event === 'facadeReady');
|
|
48
|
+
results.push({
|
|
49
|
+
anchorAcId: null,
|
|
50
|
+
conformanceOnly: true,
|
|
51
|
+
limitation: LIM_13101_1,
|
|
52
|
+
verdict: ready.length === 1 && facade.bindingName === 'DB' ? 'pass' : 'fail',
|
|
53
|
+
detail: `observed facadeReady x${ready.length} on bindingName='${facade.bindingName}'; migrations=${JSON.stringify(facade.migrationsApplied)}. Fixture-added event; the import-graph sole-reader property on AC-13101-1 is not observed at runtime.`,
|
|
54
|
+
evidence: { event: ready[0], bindingName: facade.bindingName, migrationsApplied: facade.migrationsApplied, bodyExcerpt: `facadeReady=${ready.length} binding=${facade.bindingName}` },
|
|
55
|
+
});
|
|
56
|
+
const ins = await facade.insertItem({ name: 'probe-item-1', note: 'from probe' });
|
|
57
|
+
rowId = ins.rowId;
|
|
58
|
+
results.push({
|
|
59
|
+
anchorAcId: null,
|
|
60
|
+
conformanceOnly: true,
|
|
61
|
+
limitation: LIM_13101_2,
|
|
62
|
+
verdict: Number.isInteger(ins.rowId) && ins.rowId > 0 && ins.changes === 1 ? 'pass' : 'fail',
|
|
63
|
+
detail: `observed insertItem returned real rowId=${ins.rowId} changes=${ins.changes} through the facade's named insert verb (no raw SQL leaves the facade at runtime).`,
|
|
64
|
+
evidence: { rowId: ins.rowId, changes: ins.changes, bodyExcerpt: `insertItem rowId=${ins.rowId} changes=${ins.changes}` },
|
|
65
|
+
});
|
|
66
|
+
const found = await facade.findItemByName('probe-item-1');
|
|
67
|
+
results.push({
|
|
68
|
+
anchorAcId: null,
|
|
69
|
+
conformanceOnly: true,
|
|
70
|
+
limitation: LIM_13101_2,
|
|
71
|
+
verdict: found && found.name === 'probe-item-1' && found.id === ins.rowId ? 'pass' : 'fail',
|
|
72
|
+
detail: `observed findItemByName returned id=${found?.id} name=${found?.name} through the facade's named find verb.`,
|
|
73
|
+
evidence: { found, rowIdOnRead: found?.id, bodyExcerpt: `findItemByName id=${found?.id} name=${found?.name}` },
|
|
74
|
+
});
|
|
75
|
+
const del = await facade.deleteItem({ name: 'probe-item-1' });
|
|
76
|
+
const after = await facade.findItemByName('probe-item-1');
|
|
77
|
+
results.push({
|
|
78
|
+
anchorAcId: null,
|
|
79
|
+
conformanceOnly: true,
|
|
80
|
+
limitation: LIM_13101_2,
|
|
81
|
+
verdict: del.changes === 1 && after === null ? 'pass' : 'fail',
|
|
82
|
+
detail: `observed deleteItem changes=${del.changes}; find-after-delete=${after ? 'present' : 'absent'} through the facade's named delete and find verbs.`,
|
|
83
|
+
evidence: { rowIdCreatedThenDeleted: rowId, deleteChanges: del.changes, presentAfterDelete: Boolean(after), bodyExcerpt: `deleteItem changes=${del.changes} presentAfterDelete=${Boolean(after)}` },
|
|
84
|
+
});
|
|
85
|
+
binding.__closeForFixture();
|
|
86
|
+
// Sentinels stashed on the env passed alongside the missing DB
|
|
87
|
+
// binding. AC-13101-4 requires the refusal to leak neither the
|
|
88
|
+
// account id nor the API token; the probe drives a positive predicate by
|
|
89
|
+
// proving neither sentinel appears anywhere in the refusal error's
|
|
90
|
+
// message, kind, bindingName, stack or JSON serialisation. Row
|
|
91
|
+
// de-claimed to conformanceOnly (the strict-evidence contract): the refusal never
|
|
92
|
+
// reaches the D1 engine so no engine-returned identifier exists.
|
|
93
|
+
const accountIdSentinel = 'acct-sentinel-' + Math.random().toString(36).slice(2, 12);
|
|
94
|
+
const apiTokenSentinel = 'token-sentinel-' + Math.random().toString(36).slice(2, 12);
|
|
95
|
+
let refusal = null;
|
|
96
|
+
let refusalErr = null;
|
|
97
|
+
try {
|
|
98
|
+
await openFacade({
|
|
99
|
+
env: { CLOUDFLARE_ACCOUNT_ID: accountIdSentinel, CLOUDFLARE_API_TOKEN: apiTokenSentinel },
|
|
100
|
+
eventSink: (e) => events.push(e),
|
|
101
|
+
});
|
|
102
|
+
} catch (e) {
|
|
103
|
+
refusalErr = e;
|
|
104
|
+
refusal = { message: e.message, kind: e.kind, bindingName: e.bindingName };
|
|
105
|
+
}
|
|
106
|
+
const refusalString = [
|
|
107
|
+
refusalErr?.message ?? '',
|
|
108
|
+
refusalErr?.kind ?? '',
|
|
109
|
+
refusalErr?.bindingName ?? '',
|
|
110
|
+
refusalErr?.stack ?? '',
|
|
111
|
+
(() => { try { return JSON.stringify(refusalErr, Object.getOwnPropertyNames(refusalErr || {})); } catch { return ''; } })(),
|
|
112
|
+
].join(' || ');
|
|
113
|
+
const accountIdInRefusal = accountIdSentinel.length > 0 && refusalString.includes(accountIdSentinel);
|
|
114
|
+
const apiTokenInRefusal = apiTokenSentinel.length > 0 && refusalString.includes(apiTokenSentinel);
|
|
115
|
+
const credentialLeakAbsent = accountIdInRefusal === false && apiTokenInRefusal === false;
|
|
116
|
+
const readyAfterRefusal = events.filter((e) => e.event === 'facadeReady').length;
|
|
117
|
+
results.push({
|
|
118
|
+
anchorAcId: null,
|
|
119
|
+
conformanceOnly: true,
|
|
120
|
+
limitation: LIM_13101_4,
|
|
121
|
+
verdict: refusal?.kind === 'd1BindingMissing' && refusal?.bindingName === 'DB' && readyAfterRefusal === 1 && credentialLeakAbsent ? 'pass' : 'fail',
|
|
122
|
+
detail: `observed refusal kind='${refusal?.kind}' bindingName='${refusal?.bindingName}' after openFacade with env carrying sentinel account-id and api-token but no DB binding; accountIdInRefusal=${accountIdInRefusal}; apiTokenInRefusal=${apiTokenInRefusal}; credentialLeakAbsent=${credentialLeakAbsent}; facadeReady after refusal=${readyAfterRefusal} (unchanged; no extra event fired). Refusal never reaches the D1 engine; no engine-returned identifier is available.`,
|
|
123
|
+
evidence: {
|
|
124
|
+
...refusal,
|
|
125
|
+
refusalMessage: refusal?.message,
|
|
126
|
+
kind: refusal?.kind,
|
|
127
|
+
bindingName: refusal?.bindingName,
|
|
128
|
+
missingKey: refusal?.bindingName,
|
|
129
|
+
accountIdInRefusal,
|
|
130
|
+
apiTokenInRefusal,
|
|
131
|
+
credentialLeakAbsent,
|
|
132
|
+
readyAfterRefusal,
|
|
133
|
+
bodyExcerpt: `refusal kind=${refusal?.kind} bindingName=${refusal?.bindingName} credentialLeakAbsent=${credentialLeakAbsent}`,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
} finally {
|
|
137
|
+
await rm(dir, { recursive: true, force: true });
|
|
138
|
+
}
|
|
139
|
+
return { results, extra: { envDeclared: ['RCF_FIXTURE_D1_SQLITE_PATH'], rowIdCreatedThenDeleted: rowId } };
|
|
140
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Migrations-forward-only probe for persistence-data-d1.
|
|
2
|
+
//
|
|
3
|
+
// AC-13102-2 requires the wrangler `list -> apply -> list` sequence
|
|
4
|
+
// against a fresh local D1. This probe uses the fixture's openFacade
|
|
5
|
+
// (which drives a sqlite-backed D1 binding), not a wrangler CLI. Row
|
|
6
|
+
// de-claimed (conformanceOnly, anchorAcId=null) with the limitation
|
|
7
|
+
// naming AC-13102-2.
|
|
8
|
+
//
|
|
9
|
+
// AC-13102-3 requires reading the configured bookkeeping table
|
|
10
|
+
// (`migrations_table`; default `d1_migrations`). This probe queries
|
|
11
|
+
// `schema_migrations`, the fixture's internal table name, not the
|
|
12
|
+
// configured `d1_migrations`. Row de-claimed with the limitation
|
|
13
|
+
// naming AC-13102-3.
|
|
14
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
15
|
+
import { tmpdir } from 'node:os';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
import { createD1Binding } from '../../../../packages/rcf-lite/test/fixtures/probe-pack-persistence-data-d1/src/d1-binding-mock.mjs';
|
|
18
|
+
import { openFacade } from '../../../../packages/rcf-lite/test/fixtures/probe-pack-persistence-data-d1/src/facade.mjs';
|
|
19
|
+
|
|
20
|
+
export const anchorAcId = 'AC-13102-2';
|
|
21
|
+
export const accountBound = false;
|
|
22
|
+
const AC2_LIM = `AC-13102-2: requires the wrangler 'list -> apply -> list' sequence against a fresh local D1 (wrangler CLI observed). openFacade is the fixture-embedded migration runner; a wrangler CLI is not spawned.`;
|
|
23
|
+
const AC3_LIM = `AC-13102-3: requires reading the configured bookkeeping table (migrations_table; default d1_migrations). The fixture's internal table is schema_migrations, not the configured d1_migrations.`;
|
|
24
|
+
|
|
25
|
+
export default async function runProbe() {
|
|
26
|
+
const dir = await mkdtemp(join(tmpdir(), 'rcf-d1-mig-'));
|
|
27
|
+
const path = process.env.RCF_FIXTURE_D1_SQLITE_PATH || join(dir, 'd1.sqlite');
|
|
28
|
+
const results = [];
|
|
29
|
+
const binding = createD1Binding({ path });
|
|
30
|
+
try {
|
|
31
|
+
const firstOpen = await openFacade({ env: { DB: binding } });
|
|
32
|
+
results.push({
|
|
33
|
+
anchorAcId: null,
|
|
34
|
+
conformanceOnly: true,
|
|
35
|
+
limitation: AC2_LIM,
|
|
36
|
+
verdict: firstOpen.migrationsApplied.length === 2
|
|
37
|
+
&& firstOpen.migrationsApplied[0] === '0001_init.sql'
|
|
38
|
+
&& firstOpen.migrationsApplied[1] === '0002_add_notes.sql' ? 'pass' : 'fail',
|
|
39
|
+
detail: `observed first open applied migrations in order: ${JSON.stringify(firstOpen.migrationsApplied)} through the sqlite-backed D1 binding (fixture-embedded migration runner; not wrangler CLI).`,
|
|
40
|
+
evidence: { migrationsApplied: firstOpen.migrationsApplied, bodyExcerpt: `applied=${JSON.stringify(firstOpen.migrationsApplied)}` },
|
|
41
|
+
});
|
|
42
|
+
const secondOpen = await openFacade({ env: { DB: binding } });
|
|
43
|
+
results.push({
|
|
44
|
+
anchorAcId: null,
|
|
45
|
+
conformanceOnly: true,
|
|
46
|
+
limitation: AC2_LIM,
|
|
47
|
+
verdict: secondOpen.migrationsApplied.length === 0 ? 'pass' : 'fail',
|
|
48
|
+
detail: `observed second open applied migrations: ${JSON.stringify(secondOpen.migrationsApplied)} (subsequent-list-reports-zero-unapplied shape; via fixture-embedded runner, not wrangler CLI).`,
|
|
49
|
+
evidence: { migrationsAppliedOnReopen: secondOpen.migrationsApplied.length > 0 ? secondOpen.migrationsApplied : ['<none-applied-on-reopen>'], bodyExcerpt: `reopenApplied=${JSON.stringify(secondOpen.migrationsApplied)}` },
|
|
50
|
+
});
|
|
51
|
+
const rows = (await binding.prepare('SELECT id FROM schema_migrations ORDER BY id').all()).results;
|
|
52
|
+
const ids = rows.map((r) => r.id);
|
|
53
|
+
results.push({
|
|
54
|
+
anchorAcId: null,
|
|
55
|
+
conformanceOnly: true,
|
|
56
|
+
limitation: AC3_LIM,
|
|
57
|
+
verdict: ids.length === 2 && ids[0] === '0001_init.sql' && ids[1] === '0002_add_notes.sql' ? 'pass' : 'fail',
|
|
58
|
+
detail: `observed fixture schema_migrations rows=${JSON.stringify(ids)} through a bounded SELECT (fixture internal table name schema_migrations, not the configured d1_migrations).`,
|
|
59
|
+
evidence: { migrationRows: ids, bodyExcerpt: `schema_migrations=${JSON.stringify(ids)}` },
|
|
60
|
+
});
|
|
61
|
+
binding.__closeForFixture();
|
|
62
|
+
} finally {
|
|
63
|
+
await rm(dir, { recursive: true, force: true });
|
|
64
|
+
}
|
|
65
|
+
return { results, extra: { envDeclared: ['RCF_FIXTURE_D1_SQLITE_PATH'] } };
|
|
66
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
export const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
|
|
7
|
+
export const FIXTURE_DIR = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/probe-pack-persistence-data-d1');
|
|
8
|
+
export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/persistence-data-d1');
|
|
9
|
+
export const DECLARED_ENV = new Set([
|
|
10
|
+
'RCF_FIXTURE_D1_SQLITE_PATH',
|
|
11
|
+
'SIMULATE_D1_RATE_LIMIT',
|
|
12
|
+
'CI_HAS_CLOUDFLARE_ACCOUNT',
|
|
13
|
+
'CF_ACCOUNT_ID',
|
|
14
|
+
'CF_API_TOKEN',
|
|
15
|
+
]);
|
|
16
|
+
export function aggregate(results) {
|
|
17
|
+
if (!Array.isArray(results) || results.length === 0) return 'fail';
|
|
18
|
+
if (results.some((r) => r.verdict === 'fail')) return 'fail';
|
|
19
|
+
if (results.some((r) => r.verdict === 'warn')) return 'warn';
|
|
20
|
+
return 'pass';
|
|
21
|
+
}
|
|
22
|
+
export function isSkipped(results) { return Array.isArray(results) && results.length > 0 && results.every((r) => r.accountBoundSkipped === true); }
|
|
23
|
+
export async function writeReport({ probeName, engine, results, extra }) {
|
|
24
|
+
await mkdir(REPORT_DIR, { recursive: true });
|
|
25
|
+
const normalised = (Array.isArray(results) && results.length > 0)
|
|
26
|
+
? results
|
|
27
|
+
: [{ anchorAcId: null, harnessError: true, verdict: 'fail', detail: 'no checks ran', evidence: { reason: 'no checks ran', probeName, runAt: new Date().toISOString(), engine } }];
|
|
28
|
+
const raw = aggregate(normalised);
|
|
29
|
+
const aggregateVerdict = isSkipped(normalised) ? 'pass' : raw;
|
|
30
|
+
const report = { slug: 'persistence-data-d1', probeName, runAt: new Date().toISOString(), engine, results: normalised, aggregateVerdict, ...(extra ?? {}) };
|
|
31
|
+
const path = resolve(REPORT_DIR, `${probeName}.json`);
|
|
32
|
+
await writeFile(path, JSON.stringify(report, null, 2) + '\n', 'utf8');
|
|
33
|
+
return { report, path };
|
|
34
|
+
}
|
|
35
|
+
export async function runShim(probeName, engine, mainFn) {
|
|
36
|
+
try {
|
|
37
|
+
const outcome = (await mainFn()) ?? { results: [] };
|
|
38
|
+
const { results, extra } = outcome;
|
|
39
|
+
const { report, path } = await writeReport({ probeName, engine, results, extra });
|
|
40
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
41
|
+
process.stdout.write(`report written to ${path}\n`);
|
|
42
|
+
if (report.aggregateVerdict === 'fail') process.exitCode = 1;
|
|
43
|
+
} catch (err) {
|
|
44
|
+
const results = [{ anchorAcId: null, harnessError: true, verdict: 'fail', detail: `probe threw: ${err?.message ?? err}`, evidence: { thrown: true, message: err?.message ?? String(err), name: err?.name ?? 'Error', probeName, runAt: new Date().toISOString(), engine } }];
|
|
45
|
+
const { report, path } = await writeReport({ probeName, engine, results });
|
|
46
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
47
|
+
process.stderr.write(`probe error: ${err?.stack ?? err}\n`);
|
|
48
|
+
process.stderr.write(`report written to ${path}\n`);
|
|
49
|
+
process.exitCode = 1;
|
|
50
|
+
}
|
|
51
|
+
}
|