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
|
@@ -1,69 +1,221 @@
|
|
|
1
|
-
// Probe: manifest schema validate.
|
|
1
|
+
// Probe: manifest schema validate (v1.1.8).
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
3
|
+
// This is an offline schema validator: it reads the shipped fixture
|
|
4
|
+
// manifests and checks them against `hetzner-server.schema.json`.
|
|
5
|
+
// It has no engine-minted identifier - the sha256 of a manifest is
|
|
6
|
+
// computed by this probe with Node's `createHash` and therefore
|
|
7
|
+
// does not satisfy the semantic anatomy identifier rule; the
|
|
8
|
+
// manifest name and JSON path are the probe's own choices.
|
|
9
|
+
// Every result row is a `conformanceOnly` de-claim naming the
|
|
10
|
+
// shipped AC clause the offline check does not observe:
|
|
5
11
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// on ajv or similar. See validate() at the bottom.
|
|
12
|
+
// - AC-37102-1 general nine-required-fields schema shape,
|
|
13
|
+
// - AC-37106-1 firewall rule shape (ssh restricted, 80/443 open,
|
|
14
|
+
// no other inbound),
|
|
15
|
+
// - AC-37107-1 snapshotCadence enum {weekly, daily, off}.
|
|
11
16
|
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
// section 3.4 lesson 4. (2026-09-08).
|
|
17
|
+
// A single manifest emits ONE row per property, each carrying its
|
|
18
|
+
// own `evidence` object. The hash of the manifest bytes and the
|
|
19
|
+
// validator output stay on the row as derived context.
|
|
20
|
+
//
|
|
21
|
+
// Purity: no process.env.SIMULATE_ switch is read. Fixture-side
|
|
22
|
+
// mutations live in the fixture-side run-manifest-schema-validate.mjs
|
|
23
|
+
// shim; the probe reads only the schema and manifest tree.
|
|
20
24
|
|
|
21
25
|
import { readFile } from 'node:fs/promises';
|
|
26
|
+
import { createHash } from 'node:crypto';
|
|
22
27
|
import { readManifestFiles, SCHEMA_PATH } from './probe-utils.mjs';
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
function sha256(text) {
|
|
30
|
+
return createHash('sha256').update(text, 'utf8').digest('hex');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const anchorAcId = null;
|
|
25
34
|
export const accountBound = false;
|
|
26
35
|
|
|
36
|
+
const NINE_REQUIRED = [
|
|
37
|
+
'name', 'serverType', 'location', 'image', 'sshKeyIds',
|
|
38
|
+
'firewallId', 'cloudInitPath', 'labels', 'firewallRules', 'snapshotCadence',
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const LIMIT_37102 = 'AC-37102-1: manifest schema shape is validated offline against the shipped hetzner-server.schema.json; the live observation (a real-account apply that consumes the same manifest) is carried by real-account-throwaway-server-provision.';
|
|
42
|
+
const LIMIT_37106 = 'AC-37106-1: firewall rule shape is validated offline against the shipped schema and the TAC-3804 binding; the live-account observation (a `hcloud firewall describe` on the applied firewall) would live on a real-account firewall probe.';
|
|
43
|
+
const LIMIT_37107 = 'AC-37107-1: snapshotCadence enum is validated offline against the shipped schema enum; the live observation (a real-account server label matching the manifest cadence) lives on real-account-snapshot-on-demand.';
|
|
44
|
+
|
|
27
45
|
export default async function runProbe() {
|
|
28
46
|
const schema = JSON.parse(await readFile(SCHEMA_PATH, 'utf8'));
|
|
29
47
|
const { present, files } = await readManifestFiles();
|
|
30
48
|
if (!present) {
|
|
31
49
|
return {
|
|
32
50
|
results: [{
|
|
33
|
-
anchorAcId,
|
|
51
|
+
anchorAcId: null,
|
|
52
|
+
conformanceOnly: true,
|
|
53
|
+
limitation: LIMIT_37102,
|
|
34
54
|
verdict: 'fail',
|
|
35
|
-
detail: 'fixture hetzner/servers/ holds zero JSON files; ship at least ci-throwaway.json.',
|
|
55
|
+
detail: 'offline manifest scan: fixture hetzner/servers/ holds zero JSON files; ship at least ci-throwaway.json.',
|
|
56
|
+
evidence: { manifestCount: 0 },
|
|
36
57
|
}],
|
|
37
58
|
};
|
|
38
59
|
}
|
|
39
60
|
const results = [];
|
|
40
61
|
for (const f of files) {
|
|
62
|
+
const manifestSha256 = sha256(f.text);
|
|
41
63
|
let doc;
|
|
42
64
|
try {
|
|
43
65
|
doc = JSON.parse(f.text);
|
|
44
66
|
} catch (err) {
|
|
45
67
|
results.push({
|
|
46
|
-
anchorAcId,
|
|
68
|
+
anchorAcId: null,
|
|
69
|
+
conformanceOnly: true,
|
|
70
|
+
limitation: LIMIT_37102,
|
|
47
71
|
verdict: 'fail',
|
|
48
|
-
detail: `manifest ${f.name} does not parse: ${err.message}`,
|
|
72
|
+
detail: `offline manifest scan: manifest ${f.name} does not parse: ${err.message}`,
|
|
73
|
+
evidence: { manifestSha256, manifestName: f.name, parseError: err.message },
|
|
49
74
|
});
|
|
50
75
|
continue;
|
|
51
76
|
}
|
|
52
77
|
const errors = validate(schema, doc, `#/${f.name}`);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
78
|
+
// General schema errors that are neither firewall- nor snapshot-
|
|
79
|
+
// scoped anchor to AC-37102-1 (as their limitation).
|
|
80
|
+
const generalErrors = errors.filter((e) => (
|
|
81
|
+
e.field !== 'firewallRules' && !(e.path || '').includes('firewallRules')
|
|
82
|
+
&& e.field !== 'snapshotCadence' && !(e.path || '').includes('snapshotCadence')
|
|
83
|
+
));
|
|
84
|
+
if (generalErrors.length > 0) {
|
|
85
|
+
for (const e of generalErrors) {
|
|
56
86
|
results.push({
|
|
57
|
-
anchorAcId:
|
|
87
|
+
anchorAcId: null,
|
|
88
|
+
conformanceOnly: true,
|
|
89
|
+
limitation: LIMIT_37102,
|
|
58
90
|
verdict: 'fail',
|
|
59
|
-
detail: `manifest ${f.name} schema violation at ${e.path}: ${e.message}`,
|
|
91
|
+
detail: `offline manifest scan: manifest ${f.name} schema violation at ${e.path}: ${e.message}`,
|
|
92
|
+
evidence: { manifestSha256, manifestName: f.name, jsonPath: e.path, message: e.message, field: e.field || null },
|
|
60
93
|
});
|
|
61
94
|
}
|
|
62
95
|
} else {
|
|
96
|
+
const observedKeys = Object.keys(doc).sort();
|
|
63
97
|
results.push({
|
|
64
|
-
anchorAcId,
|
|
98
|
+
anchorAcId: null,
|
|
99
|
+
conformanceOnly: true,
|
|
100
|
+
limitation: LIMIT_37102,
|
|
65
101
|
verdict: 'pass',
|
|
66
|
-
detail: `manifest ${f.name}
|
|
102
|
+
detail: `offline manifest scan: manifest ${f.name} carries the nine required fields per hetzner-server.schema.json.`,
|
|
103
|
+
evidence: {
|
|
104
|
+
manifestSha256,
|
|
105
|
+
manifestName: f.name,
|
|
106
|
+
requiredFields: NINE_REQUIRED,
|
|
107
|
+
observedKeys,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const firewallErrors = errors.filter((e) => e.field === 'firewallRules' || (e.path || '').includes('firewallRules'));
|
|
112
|
+
if (firewallErrors.length > 0) {
|
|
113
|
+
for (const e of firewallErrors) {
|
|
114
|
+
results.push({
|
|
115
|
+
anchorAcId: null,
|
|
116
|
+
conformanceOnly: true,
|
|
117
|
+
limitation: LIMIT_37106,
|
|
118
|
+
verdict: 'fail',
|
|
119
|
+
detail: `offline firewall shape scan: manifest ${f.name} firewall rule shape violation at ${e.path}: ${e.message}`,
|
|
120
|
+
evidence: { manifestSha256, manifestName: f.name, jsonPath: e.path, message: e.message },
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
} else if (Array.isArray(doc.firewallRules)) {
|
|
124
|
+
const rules = doc.firewallRules;
|
|
125
|
+
const REQUIRED_BINDING = {
|
|
126
|
+
ssh: { protocol: 'tcp', direction: 'in', port: 22, sourceMustOpen: false },
|
|
127
|
+
http: { protocol: 'tcp', direction: 'in', port: 80, sourceMustOpen: true },
|
|
128
|
+
https: { protocol: 'tcp', direction: 'in', port: 443, sourceMustOpen: true },
|
|
129
|
+
};
|
|
130
|
+
const nameCounts = {};
|
|
131
|
+
for (const r of rules) if (r && typeof r.name === 'string') nameCounts[r.name] = (nameCounts[r.name] || 0) + 1;
|
|
132
|
+
const duplicates = Object.entries(nameCounts).filter(([, n]) => n > 1).map(([n]) => n);
|
|
133
|
+
const bindingErrors = [];
|
|
134
|
+
const bindingEvidence = {};
|
|
135
|
+
for (const [name, want] of Object.entries(REQUIRED_BINDING)) {
|
|
136
|
+
const rule = rules.find((r) => r && r.name === name);
|
|
137
|
+
if (!rule) {
|
|
138
|
+
bindingErrors.push(`missing required rule '${name}'`);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const observed = {
|
|
142
|
+
name, protocol: rule.protocol, direction: rule.direction,
|
|
143
|
+
port: rule.port, sourceIps: Array.isArray(rule.sourceIps) ? rule.sourceIps : [],
|
|
144
|
+
};
|
|
145
|
+
bindingEvidence[name] = observed;
|
|
146
|
+
if (rule.protocol !== want.protocol) bindingErrors.push(`'${name}' protocol '${rule.protocol}' != required '${want.protocol}'`);
|
|
147
|
+
if (rule.direction !== want.direction) bindingErrors.push(`'${name}' direction '${rule.direction}' != required '${want.direction}'`);
|
|
148
|
+
if (rule.port !== want.port) bindingErrors.push(`'${name}' port ${rule.port} != required ${want.port}`);
|
|
149
|
+
if (!Array.isArray(rule.sourceIps) || rule.sourceIps.length === 0) {
|
|
150
|
+
bindingErrors.push(`'${name}' sourceIps empty or not array`);
|
|
151
|
+
} else if (want.sourceMustOpen) {
|
|
152
|
+
const hasOpen = rule.sourceIps.includes('0.0.0.0/0');
|
|
153
|
+
if (!hasOpen) bindingErrors.push(`'${name}' must include '0.0.0.0/0' per open-service contract`);
|
|
154
|
+
} else if (name === 'ssh') {
|
|
155
|
+
const openLeak = rule.sourceIps.filter((s) => s === '0.0.0.0/0' || s === '::/0');
|
|
156
|
+
if (openLeak.length > 0) bindingErrors.push(`'ssh' sourceIps must not include ${openLeak.join(', ')}; use operator-nominated set per TAC-3804`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (duplicates.length > 0) bindingErrors.push(`duplicate rule names: ${duplicates.join(', ')}`);
|
|
160
|
+
if (bindingErrors.length > 0) {
|
|
161
|
+
results.push({
|
|
162
|
+
anchorAcId: null,
|
|
163
|
+
conformanceOnly: true,
|
|
164
|
+
limitation: LIMIT_37106,
|
|
165
|
+
verdict: 'fail',
|
|
166
|
+
detail: `offline firewall shape scan: manifest ${f.name} firewall rule shape violation: ${bindingErrors.join('; ')}.`,
|
|
167
|
+
evidence: {
|
|
168
|
+
manifestSha256,
|
|
169
|
+
manifestName: f.name,
|
|
170
|
+
ruleNames: rules.map((r) => r && r.name).filter(Boolean),
|
|
171
|
+
observedBinding: bindingEvidence,
|
|
172
|
+
duplicates,
|
|
173
|
+
errors: bindingErrors,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
} else {
|
|
177
|
+
const ssh = rules.find((r) => r && r.name === 'ssh');
|
|
178
|
+
results.push({
|
|
179
|
+
anchorAcId: null,
|
|
180
|
+
conformanceOnly: true,
|
|
181
|
+
limitation: LIMIT_37106,
|
|
182
|
+
verdict: 'pass',
|
|
183
|
+
detail: `offline firewall shape scan: manifest ${f.name} firewall rule shape valid: ssh (tcp/in/22, restricted to ${(ssh && ssh.sourceIps || []).join(', ')}, no 0.0.0.0/0), http (tcp/in/80, open), https (tcp/in/443, open); no duplicates.`,
|
|
184
|
+
evidence: {
|
|
185
|
+
manifestSha256,
|
|
186
|
+
manifestName: f.name,
|
|
187
|
+
ruleNames: rules.map((r) => r && r.name).filter(Boolean),
|
|
188
|
+
observedBinding: bindingEvidence,
|
|
189
|
+
duplicates: [],
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const snapshotErrors = errors.filter((e) => e.field === 'snapshotCadence' || (e.path || '').includes('snapshotCadence'));
|
|
195
|
+
if (snapshotErrors.length > 0) {
|
|
196
|
+
for (const e of snapshotErrors) {
|
|
197
|
+
results.push({
|
|
198
|
+
anchorAcId: null,
|
|
199
|
+
conformanceOnly: true,
|
|
200
|
+
limitation: LIMIT_37107,
|
|
201
|
+
verdict: 'fail',
|
|
202
|
+
detail: `offline snapshotCadence scan: manifest ${f.name} snapshotCadence violation at ${e.path}: ${e.message}`,
|
|
203
|
+
evidence: { manifestSha256, manifestName: f.name, jsonPath: e.path, message: e.message },
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
} else if (typeof doc.snapshotCadence === 'string') {
|
|
207
|
+
results.push({
|
|
208
|
+
anchorAcId: null,
|
|
209
|
+
conformanceOnly: true,
|
|
210
|
+
limitation: LIMIT_37107,
|
|
211
|
+
verdict: 'pass',
|
|
212
|
+
detail: `offline snapshotCadence scan: manifest ${f.name} snapshotCadence "${doc.snapshotCadence}" is in the shipped enum {weekly, daily, off}.`,
|
|
213
|
+
evidence: {
|
|
214
|
+
manifestSha256,
|
|
215
|
+
manifestName: f.name,
|
|
216
|
+
snapshotCadence: doc.snapshotCadence,
|
|
217
|
+
shippedEnum: ['weekly', 'daily', 'off'],
|
|
218
|
+
},
|
|
67
219
|
});
|
|
68
220
|
}
|
|
69
221
|
}
|
|
@@ -76,20 +228,8 @@ export default async function runProbe() {
|
|
|
76
228
|
};
|
|
77
229
|
}
|
|
78
230
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return 'AC-37106-1';
|
|
82
|
-
}
|
|
83
|
-
if (err.field === 'snapshotCadence' || (err.path || '').includes('snapshotCadence')) {
|
|
84
|
-
return 'AC-37107-1';
|
|
85
|
-
}
|
|
86
|
-
return 'AC-37102-1';
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Draft-07 subset validator: required, type, enum, minLength, minItems,
|
|
90
|
-
// additionalProperties, items, properties, required-on-array-items.
|
|
91
|
-
// Extra rule: on firewallRules the ssh rule sourceIps must NOT include
|
|
92
|
-
// 0.0.0.0/0 (per TAC-3804); handled after schema validation.
|
|
231
|
+
// Draft-07 subset validator (unchanged from v1.1.3 apart from the
|
|
232
|
+
// caller splitting per-property).
|
|
93
233
|
export function validate(schema, doc, pathPrefix = '#') {
|
|
94
234
|
const errors = [];
|
|
95
235
|
walk(schema, doc, pathPrefix, errors);
|
|
@@ -112,6 +252,35 @@ export function validate(schema, doc, pathPrefix = '#') {
|
|
|
112
252
|
});
|
|
113
253
|
}
|
|
114
254
|
}
|
|
255
|
+
// Reject duplicate rule names (defect: firewall
|
|
256
|
+
// validation must prohibit duplicates).
|
|
257
|
+
const counts = {};
|
|
258
|
+
for (const r of doc.firewallRules) if (r && typeof r.name === 'string') counts[r.name] = (counts[r.name] || 0) + 1;
|
|
259
|
+
for (const [name, n] of Object.entries(counts)) {
|
|
260
|
+
if (n > 1) {
|
|
261
|
+
errors.push({
|
|
262
|
+
path: `${pathPrefix}/firewallRules`,
|
|
263
|
+
field: 'firewallRules',
|
|
264
|
+
message: `firewallRules contains a duplicate rule named '${name}' (${n} occurrences); each of {ssh, http, https} must appear exactly once.`,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
// Bind each required rule name to protocol/direction/port
|
|
269
|
+
// (defect).
|
|
270
|
+
const bindings = { ssh: { protocol: 'tcp', direction: 'in', port: 22 }, http: { protocol: 'tcp', direction: 'in', port: 80 }, https: { protocol: 'tcp', direction: 'in', port: 443 } };
|
|
271
|
+
for (const [name, want] of Object.entries(bindings)) {
|
|
272
|
+
const rule = doc.firewallRules.find((r) => r && r.name === name);
|
|
273
|
+
if (!rule) continue;
|
|
274
|
+
for (const k of ['protocol', 'direction', 'port']) {
|
|
275
|
+
if (rule[k] !== want[k]) {
|
|
276
|
+
errors.push({
|
|
277
|
+
path: `${pathPrefix}/firewallRules/${name}/${k}`,
|
|
278
|
+
field: 'firewallRules',
|
|
279
|
+
message: `firewallRules '${name}' ${k} '${rule[k]}' does not match required '${want[k]}' per TAC-3804.`,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
115
284
|
}
|
|
116
285
|
return errors;
|
|
117
286
|
}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
// Shared helpers for deploy-hetzner-server probes.
|
|
1
|
+
// Shared helpers for deploy-hetzner-server probes (v1.1.4, criterion e
|
|
2
|
+
// v1.1.5, 2026-09-11).
|
|
3
|
+
//
|
|
4
|
+
// Every result row a probe returns MUST carry either an `evidence`
|
|
5
|
+
// object naming the observed artefact (server id, inventory-diff,
|
|
6
|
+
// response body excerpt, deploy record) OR `accountBoundSkipped: true`
|
|
7
|
+
// with a `reason` field naming exactly one unset variable. Empty or
|
|
8
|
+
// null probe outcomes FAIL with detail exactly `no checks ran` per
|
|
9
|
+
// binding rule 3 of the criterion e .
|
|
2
10
|
//
|
|
3
11
|
// Runtime-dependency posture:
|
|
4
12
|
// - cloud-init-render-lint, manifest-schema-validate and
|
|
@@ -7,9 +15,10 @@
|
|
|
7
15
|
// server/. No real API call fires; hcloud is mocked via
|
|
8
16
|
// src/hcloud-mock.mjs so the shim never crosses the process boundary.
|
|
9
17
|
// - real-account-* probes call the fixture's provision.mjs / destroy.mjs
|
|
10
|
-
// / snapshot verbs. Without CI_HAS_HETZNER_ACCOUNT
|
|
11
|
-
//
|
|
12
|
-
//
|
|
18
|
+
// / snapshot verbs. Without CI_HAS_HETZNER_ACCOUNT set to exactly the
|
|
19
|
+
// string "true", each probe records accountBoundSkipped: true and a
|
|
20
|
+
// reason naming CI_HAS_HETZNER_ACCOUNT (set-but-not-true is reported
|
|
21
|
+
// as such, distinguished from unset).
|
|
13
22
|
|
|
14
23
|
import { mkdir, writeFile, readFile, readdir } from 'node:fs/promises';
|
|
15
24
|
import { dirname, resolve, join } from 'node:path';
|
|
@@ -21,39 +30,83 @@ export const FIXTURE_DIR = resolve(
|
|
|
21
30
|
PROJECT_ROOT,
|
|
22
31
|
'packages/rcf-lite/test/fixtures/hetzner-throwaway-server',
|
|
23
32
|
);
|
|
24
|
-
// Config override, not a mutation switch: the fixture-side shim for
|
|
25
|
-
// manifest-schema-validate may write a mutated copy to a scratch dir
|
|
26
|
-
// and point MANIFEST_DIR at it via RCF_FIXTURE_MANIFEST_DIR so the
|
|
27
|
-
// probe stays SIMULATE-free (mutation-purity gate row, 2026-09-08).
|
|
28
33
|
export const MANIFEST_DIR = process.env.RCF_FIXTURE_MANIFEST_DIR
|
|
29
34
|
? resolve(process.env.RCF_FIXTURE_MANIFEST_DIR)
|
|
30
35
|
: resolve(FIXTURE_DIR, 'hetzner/servers');
|
|
31
36
|
export const SCHEMA_PATH = resolve(HERE, '..', 'schemas', 'hetzner-server.schema.json');
|
|
32
|
-
export const REPORT_DIR =
|
|
33
|
-
|
|
34
|
-
'.rcf/reports/blueprints/deploy-hetzner-server'
|
|
35
|
-
);
|
|
37
|
+
export const REPORT_DIR = process.env.RCF_REPORT_DIR_OVERRIDE
|
|
38
|
+
? resolve(process.env.RCF_REPORT_DIR_OVERRIDE, 'blueprints/deploy-hetzner-server')
|
|
39
|
+
: resolve(PROJECT_ROOT, '.rcf/reports/blueprints/deploy-hetzner-server');
|
|
40
|
+
export const BLUEPRINT_JSON_PATH = resolve(HERE, '..', '..', 'blueprint.json');
|
|
36
41
|
|
|
42
|
+
// The report's `version` field is read from the blueprint's own
|
|
43
|
+
// blueprint.json at write time; every regenerated record therefore
|
|
44
|
+
// carries the version the shipped code was at when the record was
|
|
45
|
+
// written. The strict walker compares each record's `version` to
|
|
46
|
+
// blueprint.json's `version` and FAILS on any mismatch (a record
|
|
47
|
+
// at an older version fails the walk). The read is deliberately
|
|
48
|
+
// per-call so a version bump between two writes in one process is
|
|
49
|
+
// picked up honestly.
|
|
50
|
+
async function readBlueprintVersion() {
|
|
51
|
+
const raw = await readFile(BLUEPRINT_JSON_PATH, 'utf8');
|
|
52
|
+
const doc = JSON.parse(raw);
|
|
53
|
+
if (typeof doc.version !== 'string' || doc.version.length === 0) {
|
|
54
|
+
throw new Error(`blueprint.json at ${BLUEPRINT_JSON_PATH} carries no string version`);
|
|
55
|
+
}
|
|
56
|
+
return doc.version;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Aggregation rule (the shape rule): an empty results array is never
|
|
60
|
+
// pass; it is a fail with detail `no checks ran`. Callers hand the
|
|
61
|
+
// empty case a synthesised fail row via `emptyResultsFail()` before
|
|
62
|
+
// aggregating so the report body itself carries the row.
|
|
37
63
|
export function aggregate(results) {
|
|
64
|
+
if (!Array.isArray(results) || results.length === 0) return 'fail';
|
|
38
65
|
if (results.some((r) => r.verdict === 'fail')) return 'fail';
|
|
39
66
|
if (results.some((r) => r.verdict === 'warn')) return 'warn';
|
|
40
67
|
return 'pass';
|
|
41
68
|
}
|
|
42
69
|
|
|
70
|
+
// An empty results array is an honest failure of the probe: no anchor
|
|
71
|
+
// can be manufactured. Callers that KNOW the anchor may pass it in;
|
|
72
|
+
// otherwise the row carries anchorAcId: null so downstream tallies do
|
|
73
|
+
// not see an invented AC id.
|
|
74
|
+
export function emptyResultsFail(anchorAcId = null) {
|
|
75
|
+
return {
|
|
76
|
+
anchorAcId: anchorAcId ?? null,
|
|
77
|
+
verdict: 'fail',
|
|
78
|
+
detail: 'no checks ran',
|
|
79
|
+
evidence: { reason: 'the probe returned zero result rows', probeName: '(unknown at empty-fail construction)' },
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
43
83
|
export function isSkipped(results) {
|
|
44
|
-
return results.length > 0 && results.every((r) => r.accountBoundSkipped === true);
|
|
84
|
+
return Array.isArray(results) && results.length > 0 && results.every((r) => r.accountBoundSkipped === true);
|
|
45
85
|
}
|
|
46
86
|
|
|
47
87
|
export async function writeReport({ probeName, engine, results, extra }) {
|
|
48
88
|
await mkdir(REPORT_DIR, { recursive: true });
|
|
49
|
-
const
|
|
50
|
-
|
|
89
|
+
const rows = Array.isArray(results) && results.length > 0 ? results : [emptyResultsFail()];
|
|
90
|
+
// the anchor-prefix rule: every row's detail starts with the first eight
|
|
91
|
+
// words of the anchored AC text. The prepend is idempotent so a
|
|
92
|
+
// caller that already wrapped its detail via `anchored()` does not
|
|
93
|
+
// double up.
|
|
94
|
+
for (const r of rows) {
|
|
95
|
+
const prefix = r && r.anchorAcId && AC_ANCHOR_PREFIX[r.anchorAcId];
|
|
96
|
+
if (prefix && typeof r.detail === 'string' && !r.detail.startsWith(prefix)) {
|
|
97
|
+
r.detail = `${prefix}. ${r.detail}`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const rawVerdict = aggregate(rows);
|
|
101
|
+
const aggregateVerdict = isSkipped(rows) ? 'pass' : rawVerdict;
|
|
102
|
+
const version = await readBlueprintVersion();
|
|
51
103
|
const report = {
|
|
52
104
|
slug: 'deploy-hetzner-server',
|
|
53
105
|
probeName,
|
|
106
|
+
version,
|
|
54
107
|
runAt: new Date().toISOString(),
|
|
55
108
|
engine,
|
|
56
|
-
results,
|
|
109
|
+
results: rows,
|
|
57
110
|
aggregateVerdict,
|
|
58
111
|
...(extra ?? {}),
|
|
59
112
|
};
|
|
@@ -64,17 +117,27 @@ export async function writeReport({ probeName, engine, results, extra }) {
|
|
|
64
117
|
|
|
65
118
|
export async function runShim(probeName, engine, mainFn) {
|
|
66
119
|
try {
|
|
67
|
-
const outcome =
|
|
68
|
-
const
|
|
69
|
-
const
|
|
120
|
+
const outcome = await mainFn();
|
|
121
|
+
const results = (outcome && Array.isArray(outcome.results)) ? outcome.results : null;
|
|
122
|
+
const extra = outcome && outcome.extra;
|
|
123
|
+
const rows = results && results.length > 0 ? results : [emptyResultsFail()];
|
|
124
|
+
const { report, path } = await writeReport({ probeName, engine, results: rows, extra });
|
|
70
125
|
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
71
126
|
process.stdout.write(`report written to ${path}\n`);
|
|
72
127
|
if (report.aggregateVerdict === 'fail') process.exitCode = 1;
|
|
73
128
|
} catch (err) {
|
|
129
|
+
// A probe that throws has no known anchor at this layer; use null
|
|
130
|
+
// rather than the invented "unknown" fallback (defect).
|
|
131
|
+
// The runShim caller carries the probeName so evidence names it.
|
|
74
132
|
const results = [{
|
|
75
|
-
anchorAcId:
|
|
133
|
+
anchorAcId: null,
|
|
76
134
|
verdict: 'fail',
|
|
77
135
|
detail: `probe threw: ${err && err.message ? err.message : String(err)}`,
|
|
136
|
+
evidence: {
|
|
137
|
+
probeName,
|
|
138
|
+
errorMessage: err && err.message ? err.message : String(err),
|
|
139
|
+
errorStack: (err && err.stack ? err.stack : String(err)).slice(0, 800),
|
|
140
|
+
},
|
|
78
141
|
}];
|
|
79
142
|
const { report, path } = await writeReport({ probeName, engine, results });
|
|
80
143
|
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
@@ -102,11 +165,66 @@ export async function readManifestFiles(dir = MANIFEST_DIR) {
|
|
|
102
165
|
return { present: entries.length > 0, entries, files };
|
|
103
166
|
}
|
|
104
167
|
|
|
105
|
-
|
|
168
|
+
// Skip helper (the shape rule): the reason field names exactly one
|
|
169
|
+
// unset variable. A gate variable set to a value other than 'true'
|
|
170
|
+
// is reported as `set-but-not-true` with the observed value, not as
|
|
171
|
+
// `unset`. Callers hand the exact variable name and a short note.
|
|
172
|
+
export function firstTierGateSkipResult(anchorAcId, varName = 'CI_HAS_HETZNER_ACCOUNT', note = '') {
|
|
173
|
+
const observed = process.env[varName];
|
|
174
|
+
const state = observed === undefined
|
|
175
|
+
? `unset`
|
|
176
|
+
: `set-but-not-true (observed value ${JSON.stringify(observed)})`;
|
|
106
177
|
return {
|
|
107
178
|
anchorAcId,
|
|
108
179
|
verdict: 'skipped',
|
|
109
180
|
accountBoundSkipped: true,
|
|
110
|
-
|
|
181
|
+
reason: varName,
|
|
182
|
+
gateState: state,
|
|
183
|
+
detail: `accountBoundSkipped: gate variable ${varName} ${state}; ${note || 'run with CI_HAS_HETZNER_ACCOUNT=true to exercise the account-bound branch.'}`,
|
|
111
184
|
};
|
|
112
185
|
}
|
|
186
|
+
|
|
187
|
+
// Second-tier skip helper (the shape rule): the account-bound branch
|
|
188
|
+
// requires HCLOUD_TOKEN once the first-tier gate is true. When only the
|
|
189
|
+
// second-tier is missing, the skip row names HCLOUD_TOKEN in `reason`,
|
|
190
|
+
// carries accountBoundSkipped: true, and the aggregate still flips to
|
|
191
|
+
// pass. Missing configuration is a skip, not a failure.
|
|
192
|
+
export function secondTierMissingSkipResult(anchorAcId, varName, note = '') {
|
|
193
|
+
return {
|
|
194
|
+
anchorAcId,
|
|
195
|
+
verdict: 'skipped',
|
|
196
|
+
accountBoundSkipped: true,
|
|
197
|
+
reason: varName,
|
|
198
|
+
gateState: 'unset',
|
|
199
|
+
detail: `accountBoundSkipped: second-tier variable ${varName} unset while CI_HAS_HETZNER_ACCOUNT=true; ${note || 'the probe cannot open the vendor client.'}`,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Legacy shim (kept during the update cutover for callers not yet
|
|
204
|
+
// updated). Prefer firstTierGateSkipResult / secondTierMissingSkipResult.
|
|
205
|
+
export function accountBoundSkippedResult(anchorAcId, note) {
|
|
206
|
+
return firstTierGateSkipResult(anchorAcId, 'CI_HAS_HETZNER_ACCOUNT', note);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// the anchor-prefix rule: every result row's detail starts with the first
|
|
210
|
+
// eight words of the anchored AC text. This map holds those prefixes
|
|
211
|
+
// for the deploy-hetzner-server ACs and the shared AC-14501-1 chain
|
|
212
|
+
// artefact (used elsewhere in the estate); callers wrap their detail
|
|
213
|
+
// via `anchored(anchorAcId, detail)`.
|
|
214
|
+
export const AC_ANCHOR_PREFIX = {
|
|
215
|
+
'AC-37101-1': 'On process boot the provisioner facade opens against',
|
|
216
|
+
'AC-37102-1': 'manifest-schema-validate.mjs asserts every hetzner/servers/*.json under the shared throwaway-server',
|
|
217
|
+
'AC-37103-1': 'The real-account-throwaway-server-provision probe (accountBound: true, skipped without CI_HAS_HETZNER_ACCOUNT)',
|
|
218
|
+
'AC-37104-1': 'cloud-init-render-lint.mjs renders the template with the fixture manifest',
|
|
219
|
+
'AC-37105-1': 'real-account-cloud-init-hardened.mjs (accountBound: true, skipped without CI_HAS_HETZNER_ACCOUNT) waits for',
|
|
220
|
+
'AC-37106-1': 'manifest-schema-validate.mjs asserts every fixture manifest carries a firewallRules',
|
|
221
|
+
'AC-37107-1': 'manifest-schema-validate.mjs asserts every fixture manifest carries snapshotCadence with',
|
|
222
|
+
'AC-37108-1': 'real-account-snapshot-on-demand.mjs (accountBound: true, skipped without CI_HAS_HETZNER_ACCOUNT) fires the',
|
|
223
|
+
'AC-37109-1': 'hcloud-dry-run-mock.mjs drives every lifecycle event through the facade',
|
|
224
|
+
'AC-37109-3': 'Event fires once per lifecycle moment (repeat-run idempotency).',
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export function anchored(anchorAcId, body) {
|
|
228
|
+
const prefix = AC_ANCHOR_PREFIX[anchorAcId];
|
|
229
|
+
return prefix ? `${prefix}. ${body}` : body;
|
|
230
|
+
}
|