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/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs
CHANGED
|
@@ -1,28 +1,72 @@
|
|
|
1
|
-
// Probe: real-account cloud-init hardened.
|
|
1
|
+
// Probe: real-account cloud-init hardened (v1.1.5).
|
|
2
2
|
//
|
|
3
3
|
// anchorAcId: AC-37105-1. accountBound: true.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// -
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
5
|
+
// Contract:
|
|
6
|
+
// - First-tier gate CI_HAS_HETZNER_ACCOUNT must equal exactly the
|
|
7
|
+
// string "true"; anything else records an honest skip row.
|
|
8
|
+
// - Second-tier HCLOUD_TOKEN missing carries its own honest skip row.
|
|
9
|
+
// - The pass row carries an `evidence` object with the created
|
|
10
|
+
// server id, the ssh readiness result, the cloud-init status exit
|
|
11
|
+
// code and every baseline block's stdout excerpt (bounded).
|
|
12
|
+
// - A non-zero exit from `cloud-init status --wait` FAILS the
|
|
13
|
+
// verdict; the six baseline checks that follow are diagnostic in
|
|
14
|
+
// that case rather than the verdict.
|
|
15
|
+
// - Teardown lives in a finally block and its failure FAILS the
|
|
16
|
+
// verdict (the shape rule).
|
|
15
17
|
|
|
16
|
-
import {
|
|
18
|
+
import { spawn } from 'node:child_process';
|
|
17
19
|
import { resolve } from 'node:path';
|
|
20
|
+
import {
|
|
21
|
+
firstTierGateSkipResult, secondTierMissingSkipResult, FIXTURE_DIR,
|
|
22
|
+
} from './probe-utils.mjs';
|
|
18
23
|
|
|
19
24
|
export const anchorAcId = 'AC-37105-1';
|
|
20
25
|
export const accountBound = true;
|
|
21
26
|
|
|
27
|
+
function hcloudJson(argv, { timeoutMs = 60_000 } = {}) {
|
|
28
|
+
return new Promise((resolvePromise, reject) => {
|
|
29
|
+
const p = spawn('hcloud', argv, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
30
|
+
let stdout = '';
|
|
31
|
+
let stderr = '';
|
|
32
|
+
const timer = setTimeout(() => { try { p.kill('SIGKILL'); } catch (_) {} reject(new Error(`hcloud ${argv.join(' ')} timed out after ${timeoutMs}ms`)); }, timeoutMs);
|
|
33
|
+
p.stdout.on('data', (d) => { stdout += d.toString(); });
|
|
34
|
+
p.stderr.on('data', (d) => { stderr += d.toString(); });
|
|
35
|
+
p.on('error', (err) => { clearTimeout(timer); reject(err); });
|
|
36
|
+
p.on('close', (code) => {
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
if (code !== 0) return reject(new Error(`hcloud ${argv.join(' ')} exited ${code}: ${stderr}`));
|
|
39
|
+
const trimmed = stdout.trim();
|
|
40
|
+
if (trimmed.length === 0) return resolvePromise([]);
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(trimmed);
|
|
43
|
+
resolvePromise(Array.isArray(parsed) ? parsed : (parsed.servers || []));
|
|
44
|
+
} catch (err) {
|
|
45
|
+
reject(new Error(`hcloud stdout not JSON: ${err.message}`));
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
22
51
|
export default async function runProbe() {
|
|
23
52
|
if (process.env.CI_HAS_HETZNER_ACCOUNT !== 'true') {
|
|
24
53
|
return {
|
|
25
|
-
results: [
|
|
54
|
+
results: [firstTierGateSkipResult(
|
|
55
|
+
anchorAcId,
|
|
56
|
+
'CI_HAS_HETZNER_ACCOUNT',
|
|
57
|
+
'real-account cloud-init hardened check skipped; run with CI_HAS_HETZNER_ACCOUNT=true to exercise the six ssh baseline checks against a throwaway cx23.',
|
|
58
|
+
)],
|
|
59
|
+
extra: { skipped: true, missingEnv: ['CI_HAS_HETZNER_ACCOUNT'] },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (!process.env.HCLOUD_TOKEN) {
|
|
63
|
+
return {
|
|
64
|
+
results: [secondTierMissingSkipResult(
|
|
65
|
+
anchorAcId,
|
|
66
|
+
'HCLOUD_TOKEN',
|
|
67
|
+
'the throwaway server cannot be provisioned without HCLOUD_TOKEN.',
|
|
68
|
+
)],
|
|
69
|
+
extra: { skipped: true, missingEnv: ['HCLOUD_TOKEN'] },
|
|
26
70
|
};
|
|
27
71
|
}
|
|
28
72
|
const provisionPath = resolve(FIXTURE_DIR, 'provision.mjs');
|
|
@@ -31,34 +75,71 @@ export default async function runProbe() {
|
|
|
31
75
|
const { provisionThrowawayServer } = await import(provisionPath);
|
|
32
76
|
const { destroyThrowawayServer } = await import(destroyPath);
|
|
33
77
|
const { runSshBaselineChecks } = await import(sshCheckPath);
|
|
78
|
+
|
|
79
|
+
const evidence = {};
|
|
80
|
+
const resultRow = { anchorAcId, verdict: 'fail', detail: '', evidence };
|
|
34
81
|
let provisioned;
|
|
35
82
|
try {
|
|
36
83
|
provisioned = await provisionThrowawayServer({ runId: process.env.GITHUB_RUN_ID ?? 'local' });
|
|
84
|
+
evidence.serverId = provisioned.id;
|
|
85
|
+
evidence.serverName = provisioned.name;
|
|
86
|
+
evidence.primaryIpv4 = provisioned.primaryIpv4;
|
|
37
87
|
const report = await runSshBaselineChecks(provisioned);
|
|
88
|
+
evidence.sshReadiness = report.readiness;
|
|
89
|
+
evidence.cloudInit = report.cloudInit;
|
|
90
|
+
evidence.baselineChecks = report.checks.map((c) => ({
|
|
91
|
+
id: c.id,
|
|
92
|
+
verdict: c.verdict,
|
|
93
|
+
stdoutExcerpt: (c.detail || '').slice(0, 200),
|
|
94
|
+
}));
|
|
95
|
+
// Rule 6 of the fix list: cloud-init non-zero FAILS the verdict.
|
|
96
|
+
if (!report.cloudInit || report.cloudInit.code !== 0) {
|
|
97
|
+
resultRow.verdict = 'fail';
|
|
98
|
+
resultRow.detail = `cloud-init status --wait exited ${report.cloudInit ? report.cloudInit.code : 'null'} on server ${provisioned.id}; the ssh baseline checks are diagnostic and do not carry the verdict when cloud-init did not reach a terminal success state. stderr: ${(report.cloudInit && report.cloudInit.stderr) || ''}`;
|
|
99
|
+
return { results: [resultRow], extra: evidence };
|
|
100
|
+
}
|
|
38
101
|
const failed = report.checks.filter((c) => c.verdict === 'fail');
|
|
39
102
|
if (failed.length > 0) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
};
|
|
103
|
+
// Fail with per-block detail on the FIRST failing block so the
|
|
104
|
+
// result row carries a specific failure locus; the full check
|
|
105
|
+
// list is in evidence.baselineChecks.
|
|
106
|
+
const first = failed[0];
|
|
107
|
+
resultRow.verdict = 'fail';
|
|
108
|
+
resultRow.detail = `cloud-init baseline block "${first.label}" failed on server ${provisioned.id}: ${first.detail}`;
|
|
109
|
+
return { results: [resultRow], extra: evidence };
|
|
47
110
|
}
|
|
48
111
|
const blocks = report.checks.filter((c) => c.verdict === 'pass').map((c) => c.id);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
anchorAcId,
|
|
52
|
-
verdict: 'pass',
|
|
53
|
-
detail: `cloud-init reached terminal state on server ${provisioned.id} (cloud-init status --wait exit ${report.cloudInit ? report.cloudInit.code : 'skipped'}); six baseline hardening blocks observed: ${blocks.join(', ')}.`,
|
|
54
|
-
}],
|
|
55
|
-
extra: report,
|
|
56
|
-
};
|
|
112
|
+
resultRow.verdict = 'pass';
|
|
113
|
+
resultRow.detail = `cloud-init reached terminal state on server ${provisioned.id} (cloud-init status --wait exit 0); six baseline hardening blocks observed: ${blocks.join(', ')}.`;
|
|
57
114
|
} catch (err) {
|
|
58
|
-
|
|
115
|
+
resultRow.verdict = 'fail';
|
|
116
|
+
resultRow.detail = `check failed: ${err.message}`;
|
|
117
|
+
evidence.checkError = err.message;
|
|
118
|
+
return { results: [resultRow], extra: evidence };
|
|
59
119
|
} finally {
|
|
60
120
|
if (provisioned && provisioned.id) {
|
|
61
|
-
try {
|
|
121
|
+
try {
|
|
122
|
+
await destroyThrowawayServer(provisioned);
|
|
123
|
+
evidence.teardown = { destroyed: provisioned.id };
|
|
124
|
+
try {
|
|
125
|
+
const finalList = await hcloudJson(['server', 'list', '--output', 'json']);
|
|
126
|
+
evidence.postTeardownServerIds = finalList.map((s) => s.id);
|
|
127
|
+
if (finalList.some((s) => s.id === provisioned.id)) {
|
|
128
|
+
resultRow.verdict = 'fail';
|
|
129
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN INCOMPLETE: server ${provisioned.id} still present in hcloud server list.`;
|
|
130
|
+
}
|
|
131
|
+
} catch (err) {
|
|
132
|
+
evidence.postTeardownListError = err.message;
|
|
133
|
+
resultRow.verdict = 'fail';
|
|
134
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN CONFIRMATION FAILED: post-teardown hcloud server list threw (${err.message}); cannot confirm server ${provisioned.id} was removed.`;
|
|
135
|
+
}
|
|
136
|
+
} catch (err) {
|
|
137
|
+
resultRow.verdict = 'fail';
|
|
138
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN FAILED for server ${provisioned.id}: ${err.message}.`;
|
|
139
|
+
evidence.teardownError = err.message;
|
|
140
|
+
evidence.orphanServerId = provisioned.id;
|
|
141
|
+
}
|
|
62
142
|
}
|
|
63
143
|
}
|
|
144
|
+
return { results: [resultRow], extra: evidence };
|
|
64
145
|
}
|
package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs
CHANGED
|
@@ -1,30 +1,72 @@
|
|
|
1
|
-
// Probe: real-account snapshot on demand.
|
|
1
|
+
// Probe: real-account snapshot on demand (v1.1.5).
|
|
2
2
|
//
|
|
3
3
|
// anchorAcId: AC-37108-1. accountBound: true.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// -
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// -
|
|
15
|
-
//
|
|
16
|
-
//
|
|
5
|
+
// Contract:
|
|
6
|
+
// - First-tier gate CI_HAS_HETZNER_ACCOUNT must equal exactly the
|
|
7
|
+
// string "true"; anything else records an honest skip row.
|
|
8
|
+
// - Second-tier HCLOUD_TOKEN missing carries its own honest skip row.
|
|
9
|
+
// - The pass row carries an `evidence` object with the created
|
|
10
|
+
// server id, the pre- and post-snapshot inventory (proving the
|
|
11
|
+
// snapshot id was created then deleted), the snapshot id, the
|
|
12
|
+
// hetznerSnapshotTaken event shape (serverName, snapshotId, ts),
|
|
13
|
+
// and the label-match evidence.
|
|
14
|
+
// - Teardown failure FAILS the verdict (the shape rule); the
|
|
15
|
+
// evidence tree carries the orphan snapshot id and server id when
|
|
16
|
+
// the destroy leaks.
|
|
17
17
|
|
|
18
|
-
import {
|
|
18
|
+
import { spawn } from 'node:child_process';
|
|
19
19
|
import { resolve } from 'node:path';
|
|
20
|
+
import {
|
|
21
|
+
firstTierGateSkipResult, secondTierMissingSkipResult, FIXTURE_DIR,
|
|
22
|
+
} from './probe-utils.mjs';
|
|
20
23
|
|
|
21
24
|
export const anchorAcId = 'AC-37108-1';
|
|
22
25
|
export const accountBound = true;
|
|
23
26
|
|
|
27
|
+
function hcloudJson(argv, { timeoutMs = 60_000 } = {}) {
|
|
28
|
+
return new Promise((resolvePromise, reject) => {
|
|
29
|
+
const p = spawn('hcloud', argv, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
30
|
+
let stdout = '';
|
|
31
|
+
let stderr = '';
|
|
32
|
+
const timer = setTimeout(() => { try { p.kill('SIGKILL'); } catch (_) {} reject(new Error(`hcloud ${argv.join(' ')} timed out after ${timeoutMs}ms`)); }, timeoutMs);
|
|
33
|
+
p.stdout.on('data', (d) => { stdout += d.toString(); });
|
|
34
|
+
p.stderr.on('data', (d) => { stderr += d.toString(); });
|
|
35
|
+
p.on('error', (err) => { clearTimeout(timer); reject(err); });
|
|
36
|
+
p.on('close', (code) => {
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
if (code !== 0) return reject(new Error(`hcloud ${argv.join(' ')} exited ${code}: ${stderr}`));
|
|
39
|
+
const trimmed = stdout.trim();
|
|
40
|
+
if (trimmed.length === 0) return resolvePromise([]);
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(trimmed);
|
|
43
|
+
resolvePromise(Array.isArray(parsed) ? parsed : (parsed.images || parsed.servers || []));
|
|
44
|
+
} catch (err) {
|
|
45
|
+
reject(new Error(`hcloud stdout not JSON: ${err.message}`));
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
24
51
|
export default async function runProbe() {
|
|
25
52
|
if (process.env.CI_HAS_HETZNER_ACCOUNT !== 'true') {
|
|
26
53
|
return {
|
|
27
|
-
results: [
|
|
54
|
+
results: [firstTierGateSkipResult(
|
|
55
|
+
anchorAcId,
|
|
56
|
+
'CI_HAS_HETZNER_ACCOUNT',
|
|
57
|
+
'real-account snapshot on-demand skipped; run with CI_HAS_HETZNER_ACCOUNT=true to exercise the hcloud server create-image path.',
|
|
58
|
+
)],
|
|
59
|
+
extra: { skipped: true, missingEnv: ['CI_HAS_HETZNER_ACCOUNT'] },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (!process.env.HCLOUD_TOKEN) {
|
|
63
|
+
return {
|
|
64
|
+
results: [secondTierMissingSkipResult(
|
|
65
|
+
anchorAcId,
|
|
66
|
+
'HCLOUD_TOKEN',
|
|
67
|
+
'the snapshot verb cannot be issued without HCLOUD_TOKEN.',
|
|
68
|
+
)],
|
|
69
|
+
extra: { skipped: true, missingEnv: ['HCLOUD_TOKEN'] },
|
|
28
70
|
};
|
|
29
71
|
}
|
|
30
72
|
const provisionPath = resolve(FIXTURE_DIR, 'provision.mjs');
|
|
@@ -33,28 +75,114 @@ export default async function runProbe() {
|
|
|
33
75
|
const { provisionThrowawayServer } = await import(provisionPath);
|
|
34
76
|
const { destroyThrowawayServer } = await import(destroyPath);
|
|
35
77
|
const { takeAndVerifySnapshot } = await import(snapshotPath);
|
|
78
|
+
|
|
79
|
+
const evidence = {};
|
|
80
|
+
const resultRow = { anchorAcId, verdict: 'fail', detail: '', evidence };
|
|
36
81
|
let provisioned;
|
|
82
|
+
// Observed events on injected sinks (defect): the snapshot
|
|
83
|
+
// verb emits hetznerSnapshotTaken; the provision emits
|
|
84
|
+
// hetznerServerProvisioned. Both are OBSERVED, not constructed here.
|
|
85
|
+
const observedEvents = [];
|
|
86
|
+
const eventSink = (body) => observedEvents.push(body);
|
|
37
87
|
try {
|
|
38
|
-
|
|
39
|
-
|
|
88
|
+
// Pre-snapshot inventory: capture the snapshot ids present before
|
|
89
|
+
// the run so the inventory-diff evidence shape is honest.
|
|
90
|
+
try {
|
|
91
|
+
const baseline = await hcloudJson(['image', 'list', '--type=snapshot', '--output', 'json']);
|
|
92
|
+
evidence.baselineSnapshotIds = baseline.map((s) => s.id);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
evidence.baselineListError = err.message;
|
|
95
|
+
}
|
|
96
|
+
provisioned = await provisionThrowawayServer({
|
|
97
|
+
runId: process.env.GITHUB_RUN_ID ?? 'local',
|
|
98
|
+
eventSink,
|
|
99
|
+
});
|
|
100
|
+
evidence.serverId = provisioned.id;
|
|
101
|
+
evidence.serverName = provisioned.name;
|
|
102
|
+
const outcome = await takeAndVerifySnapshot(provisioned, { eventSink });
|
|
103
|
+
evidence.snapshotId = outcome.snapshotId;
|
|
104
|
+
evidence.wallClockTime = outcome.wallClockTime;
|
|
105
|
+
evidence.labelMatch = outcome.match ? {
|
|
106
|
+
id: outcome.match.id,
|
|
107
|
+
serverNameLabel: (outcome.match.labels || {}).serverName,
|
|
108
|
+
} : null;
|
|
109
|
+
// OBSERVE the hetznerSnapshotTaken event from the sink. The event
|
|
110
|
+
// body is derived by snapshot-verb.mjs after the vendor list call
|
|
111
|
+
// confirmed the id landed (defect: was constructed here
|
|
112
|
+
// in v1.1.4; now observed from the sink emit).
|
|
113
|
+
evidence.observedEvents = observedEvents.map((e) => ({ event: e.event, keys: Object.keys(e).sort() }));
|
|
114
|
+
const snapshotEvent = observedEvents.find((e) => e && e.event === 'hetznerSnapshotTaken');
|
|
115
|
+
if (outcome.snapshotId && !snapshotEvent) {
|
|
116
|
+
resultRow.verdict = 'fail';
|
|
117
|
+
resultRow.detail = `snapshot verb returned snapshotId ${outcome.snapshotId} but no hetznerSnapshotTaken event was observed on the injected sink; AC-37108-3 event-shape observation is missing.`;
|
|
118
|
+
evidence.eventName = 'hetznerSnapshotTaken';
|
|
119
|
+
evidence.eventObserved = false;
|
|
120
|
+
return { results: [resultRow], extra: evidence };
|
|
121
|
+
}
|
|
122
|
+
evidence.hetznerSnapshotTakenEvent = snapshotEvent ?? null;
|
|
123
|
+
// Post-create inventory: prove the id appears in the vendor
|
|
124
|
+
// snapshot list so the AC's inventory-diff evidence is real.
|
|
125
|
+
try {
|
|
126
|
+
const afterCreate = await hcloudJson(['image', 'list', '--type=snapshot', '--output', 'json']);
|
|
127
|
+
evidence.postCreateSnapshotIds = afterCreate.map((s) => s.id);
|
|
128
|
+
evidence.postCreateSnapshotCarriedId = !!(outcome.snapshotId && afterCreate.some((s) => s.id === outcome.snapshotId));
|
|
129
|
+
} catch (err) {
|
|
130
|
+
evidence.postCreateListError = err.message;
|
|
131
|
+
}
|
|
40
132
|
if (!outcome.snapshotId) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
};
|
|
133
|
+
resultRow.verdict = 'fail';
|
|
134
|
+
resultRow.detail = `snapshot verb ran but no matching snapshot appeared in hcloud image list; the AC's inventory-diff evidence is missing.`;
|
|
135
|
+
return { results: [resultRow], extra: evidence };
|
|
44
136
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
anchorAcId,
|
|
48
|
-
verdict: 'pass',
|
|
49
|
-
detail: `snapshot ${outcome.snapshotId} tagged with server name ${provisioned.name} and time ${outcome.wallClockTime} on server ${provisioned.id}.`,
|
|
50
|
-
}],
|
|
51
|
-
extra: outcome,
|
|
52
|
-
};
|
|
137
|
+
resultRow.verdict = 'pass';
|
|
138
|
+
resultRow.detail = `snapshot ${outcome.snapshotId} created against server ${provisioned.id} (${provisioned.name}); hcloud image list --type=snapshot carries the id; hetznerSnapshotTaken event shape {serverName, snapshotId, ts} confirmed.`;
|
|
53
139
|
} catch (err) {
|
|
54
|
-
|
|
140
|
+
resultRow.verdict = 'fail';
|
|
141
|
+
resultRow.detail = `snapshot verb threw: ${err.message}`;
|
|
142
|
+
evidence.snapshotError = err.message;
|
|
143
|
+
return { results: [resultRow], extra: evidence };
|
|
55
144
|
} finally {
|
|
56
145
|
if (provisioned && provisioned.id) {
|
|
57
|
-
try {
|
|
146
|
+
try {
|
|
147
|
+
await destroyThrowawayServer(provisioned);
|
|
148
|
+
evidence.teardown = { destroyed: provisioned.id };
|
|
149
|
+
// Confirm the snapshot AND the server were both removed;
|
|
150
|
+
// destroy.mjs sweeps snapshots that carry the server-name
|
|
151
|
+
// label in the same call, so the post-teardown snapshot list
|
|
152
|
+
// must NOT carry the id.
|
|
153
|
+
try {
|
|
154
|
+
const finalSnaps = await hcloudJson(['image', 'list', '--type=snapshot', '--output', 'json']);
|
|
155
|
+
evidence.postTeardownSnapshotIds = finalSnaps.map((s) => s.id);
|
|
156
|
+
if (evidence.snapshotId && finalSnaps.some((s) => s.id === evidence.snapshotId)) {
|
|
157
|
+
resultRow.verdict = 'fail';
|
|
158
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN INCOMPLETE: snapshot ${evidence.snapshotId} still present.`;
|
|
159
|
+
evidence.orphanSnapshotId = evidence.snapshotId;
|
|
160
|
+
}
|
|
161
|
+
} catch (err) {
|
|
162
|
+
evidence.postTeardownListError = err.message;
|
|
163
|
+
resultRow.verdict = 'fail';
|
|
164
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN CONFIRMATION FAILED: post-teardown snapshot list threw (${err.message}); cannot confirm snapshot ${evidence.snapshotId || 'n/a'} was deleted.`;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const finalServers = await hcloudJson(['server', 'list', '--output', 'json']);
|
|
168
|
+
evidence.postTeardownServerIds = finalServers.map((s) => s.id);
|
|
169
|
+
if (finalServers.some((s) => s.id === provisioned.id)) {
|
|
170
|
+
resultRow.verdict = 'fail';
|
|
171
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN INCOMPLETE: server ${provisioned.id} still present.`;
|
|
172
|
+
}
|
|
173
|
+
} catch (err) {
|
|
174
|
+
evidence.postTeardownServerListError = err.message;
|
|
175
|
+
resultRow.verdict = 'fail';
|
|
176
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN CONFIRMATION FAILED: post-teardown server list threw (${err.message}); cannot confirm server ${provisioned.id} was removed.`;
|
|
177
|
+
}
|
|
178
|
+
} catch (err) {
|
|
179
|
+
resultRow.verdict = 'fail';
|
|
180
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN FAILED for server ${provisioned.id}: ${err.message}.`;
|
|
181
|
+
evidence.teardownError = err.message;
|
|
182
|
+
evidence.orphanServerId = provisioned.id;
|
|
183
|
+
if (evidence.snapshotId) evidence.orphanSnapshotId = evidence.snapshotId;
|
|
184
|
+
}
|
|
58
185
|
}
|
|
59
186
|
}
|
|
187
|
+
return { results: [resultRow], extra: evidence };
|
|
60
188
|
}
|
|
@@ -1,58 +1,180 @@
|
|
|
1
|
-
// Probe: real-account throwaway-server provision.
|
|
1
|
+
// Probe: real-account throwaway-server provision (v1.1.5).
|
|
2
2
|
//
|
|
3
3
|
// anchorAcId: AC-37103-1. accountBound: true.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// -
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
5
|
+
// Contract:
|
|
6
|
+
// - First-tier gate CI_HAS_HETZNER_ACCOUNT must equal exactly the
|
|
7
|
+
// string "true"; anything else records an honest skip row naming
|
|
8
|
+
// the variable (set-but-not-true distinguished from unset).
|
|
9
|
+
// - Second-tier HCLOUD_TOKEN must be set once past the first-tier
|
|
10
|
+
// gate; missing carries its own honest skip row naming HCLOUD_TOKEN.
|
|
11
|
+
// - The pass row carries an `evidence` object with the created
|
|
12
|
+
// server id, the pre-provision inventory count, the post-provision
|
|
13
|
+
// inventory entry proving the id landed, the primaryIpv4, location
|
|
14
|
+
// and serverType observed on the vendor payload, plus the emitted
|
|
15
|
+
// `hetznerServerProvisioned` event shape (event names only, no
|
|
16
|
+
// token bytes).
|
|
17
|
+
// - Teardown lives in a finally block and its failure FAILS the
|
|
18
|
+
// verdict; the evidence carries the surviving orphan id so a
|
|
19
|
+
// later sweep-orphans run can find it.
|
|
17
20
|
|
|
18
|
-
import {
|
|
21
|
+
import { spawn } from 'node:child_process';
|
|
19
22
|
import { resolve } from 'node:path';
|
|
23
|
+
import {
|
|
24
|
+
firstTierGateSkipResult, secondTierMissingSkipResult, FIXTURE_DIR,
|
|
25
|
+
} from './probe-utils.mjs';
|
|
20
26
|
|
|
21
27
|
export const anchorAcId = 'AC-37103-1';
|
|
22
28
|
export const accountBound = true;
|
|
23
29
|
|
|
30
|
+
function hcloudJson(argv, { timeoutMs = 60_000 } = {}) {
|
|
31
|
+
return new Promise((resolvePromise, reject) => {
|
|
32
|
+
const p = spawn('hcloud', argv, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
33
|
+
let stdout = '';
|
|
34
|
+
let stderr = '';
|
|
35
|
+
const timer = setTimeout(() => { try { p.kill('SIGKILL'); } catch (_) {} reject(new Error(`hcloud ${argv.join(' ')} timed out after ${timeoutMs}ms`)); }, timeoutMs);
|
|
36
|
+
p.stdout.on('data', (d) => { stdout += d.toString(); });
|
|
37
|
+
p.stderr.on('data', (d) => { stderr += d.toString(); });
|
|
38
|
+
p.on('error', (err) => { clearTimeout(timer); reject(err); });
|
|
39
|
+
p.on('close', (code) => {
|
|
40
|
+
clearTimeout(timer);
|
|
41
|
+
if (code !== 0) return reject(new Error(`hcloud ${argv.join(' ')} exited ${code}: ${stderr}`));
|
|
42
|
+
const trimmed = stdout.trim();
|
|
43
|
+
if (trimmed.length === 0) return resolvePromise([]);
|
|
44
|
+
try {
|
|
45
|
+
const parsed = JSON.parse(trimmed);
|
|
46
|
+
resolvePromise(Array.isArray(parsed) ? parsed : (parsed.servers || []));
|
|
47
|
+
} catch (err) {
|
|
48
|
+
reject(new Error(`hcloud stdout not JSON: ${err.message}`));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
24
54
|
export default async function runProbe() {
|
|
25
55
|
if (process.env.CI_HAS_HETZNER_ACCOUNT !== 'true') {
|
|
26
56
|
return {
|
|
27
|
-
results: [
|
|
57
|
+
results: [firstTierGateSkipResult(
|
|
58
|
+
anchorAcId,
|
|
59
|
+
'CI_HAS_HETZNER_ACCOUNT',
|
|
60
|
+
'real-account throwaway-server provision skipped; run with CI_HAS_HETZNER_ACCOUNT=true to exercise.',
|
|
61
|
+
)],
|
|
62
|
+
extra: { skipped: true, missingEnv: ['CI_HAS_HETZNER_ACCOUNT'] },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (!process.env.HCLOUD_TOKEN) {
|
|
66
|
+
return {
|
|
67
|
+
results: [secondTierMissingSkipResult(
|
|
68
|
+
anchorAcId,
|
|
69
|
+
'HCLOUD_TOKEN',
|
|
70
|
+
'the shared hetzner-throwaway-server provisioner cannot open without HCLOUD_TOKEN.',
|
|
71
|
+
)],
|
|
72
|
+
extra: { skipped: true, missingEnv: ['HCLOUD_TOKEN'] },
|
|
28
73
|
};
|
|
29
74
|
}
|
|
30
75
|
const provisionPath = resolve(FIXTURE_DIR, 'provision.mjs');
|
|
31
76
|
const destroyPath = resolve(FIXTURE_DIR, 'destroy.mjs');
|
|
32
77
|
const { provisionThrowawayServer } = await import(provisionPath);
|
|
33
78
|
const { destroyThrowawayServer } = await import(destroyPath);
|
|
79
|
+
|
|
80
|
+
const evidence = {};
|
|
34
81
|
let provisioned;
|
|
82
|
+
const resultRow = { anchorAcId, verdict: 'fail', detail: '', evidence };
|
|
83
|
+
// Observed event sink (defect). We OBSERVE the emitted
|
|
84
|
+
// hetznerServerProvisioned event rather than constructing one from
|
|
85
|
+
// the return value.
|
|
86
|
+
const observedEvents = [];
|
|
87
|
+
const eventSink = (body) => observedEvents.push(body);
|
|
35
88
|
try {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
89
|
+
let baselineList = [];
|
|
90
|
+
try {
|
|
91
|
+
baselineList = await hcloudJson(['server', 'list', '--output', 'json']);
|
|
92
|
+
evidence.baselineServerIds = baselineList.map((s) => s.id);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
// Baseline list is diagnostic; capture error but do not fail.
|
|
95
|
+
evidence.baselineListError = err.message;
|
|
96
|
+
}
|
|
97
|
+
provisioned = await provisionThrowawayServer({
|
|
98
|
+
runId: process.env.GITHUB_RUN_ID ?? 'local',
|
|
99
|
+
eventSink,
|
|
100
|
+
});
|
|
101
|
+
evidence.serverId = provisioned.id;
|
|
102
|
+
evidence.serverName = provisioned.name;
|
|
103
|
+
evidence.primaryIpv4 = provisioned.primaryIpv4;
|
|
104
|
+
evidence.location = provisioned.location;
|
|
105
|
+
evidence.serverType = provisioned.serverType;
|
|
106
|
+
// OBSERVE the emitted event from the sink; do not manufacture it.
|
|
107
|
+
const provisionedEvent = observedEvents.find((e) => e && e.event === 'hetznerServerProvisioned');
|
|
108
|
+
evidence.observedEvents = observedEvents.map((e) => ({ event: e.event, keys: Object.keys(e).sort() }));
|
|
109
|
+
if (!provisionedEvent) {
|
|
110
|
+
resultRow.verdict = 'fail';
|
|
111
|
+
resultRow.detail = `hetznerServerProvisioned event was not observed on the injected sink after provisionThrowawayServer returned id ${provisioned.id}.`;
|
|
112
|
+
evidence.eventName = 'hetznerServerProvisioned';
|
|
113
|
+
evidence.eventObserved = false;
|
|
114
|
+
return { results: [resultRow], extra: evidence };
|
|
115
|
+
}
|
|
116
|
+
evidence.hetznerServerProvisionedEvent = provisionedEvent;
|
|
117
|
+
// Observe the server-list AFTER provision to prove the id landed.
|
|
118
|
+
// A list failure at this step FAILS the row (defect:
|
|
119
|
+
// the new list failure is no longer allowed to continue to pass).
|
|
120
|
+
let postListError = null;
|
|
121
|
+
try {
|
|
122
|
+
const postList = await hcloudJson(['server', 'list', '--output', 'json']);
|
|
123
|
+
evidence.postProvisionServerIds = postList.map((s) => s.id);
|
|
124
|
+
const match = postList.find((s) => s.id === provisioned.id);
|
|
125
|
+
evidence.postProvisionMatch = match ? { id: match.id, name: match.name, status: match.status } : null;
|
|
126
|
+
if (!match) {
|
|
127
|
+
resultRow.verdict = 'fail';
|
|
128
|
+
resultRow.detail = `provisionThrowawayServer returned id ${provisioned.id} but the post-provision hcloud server list did not carry it; the AC's inventory-diff evidence is missing.`;
|
|
129
|
+
return { results: [resultRow], extra: evidence };
|
|
130
|
+
}
|
|
131
|
+
} catch (err) {
|
|
132
|
+
postListError = err.message;
|
|
133
|
+
evidence.postProvisionListError = postListError;
|
|
134
|
+
resultRow.verdict = 'fail';
|
|
135
|
+
resultRow.detail = `hcloud server list after provision failed (${postListError}); AC-37103-1 requires the live inventory-diff evidence, which could not be observed.`;
|
|
136
|
+
return { results: [resultRow], extra: evidence };
|
|
137
|
+
}
|
|
138
|
+
if (!provisioned.primaryIpv4 || provisioned.location !== 'fsn1' || provisioned.serverType !== 'cx23') {
|
|
139
|
+
resultRow.verdict = 'fail';
|
|
140
|
+
resultRow.detail = `hetznerServerProvisioned payload malformed: expected primaryIpv4, location=fsn1, serverType=cx23; observed ${JSON.stringify(evidence.hetznerServerProvisionedEvent)}.`;
|
|
141
|
+
return { results: [resultRow], extra: evidence };
|
|
142
|
+
}
|
|
143
|
+
resultRow.verdict = 'pass';
|
|
144
|
+
resultRow.detail = `throwaway server ${provisioned.id} provisioned in fsn1; hetznerServerProvisioned event OBSERVED on the injected sink (id ${provisioned.id}, primaryIpv4 ${provisioned.primaryIpv4}, serverType cx23); post-provision hcloud server list carries the id.`;
|
|
45
145
|
} catch (err) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
detail: `provision failed: ${err.message}`,
|
|
51
|
-
}],
|
|
52
|
-
};
|
|
146
|
+
resultRow.verdict = 'fail';
|
|
147
|
+
resultRow.detail = `provision failed: ${err.message}`;
|
|
148
|
+
evidence.provisionError = err.message;
|
|
149
|
+
return { results: [resultRow], extra: evidence };
|
|
53
150
|
} finally {
|
|
54
151
|
if (provisioned && provisioned.id) {
|
|
55
|
-
try {
|
|
152
|
+
try {
|
|
153
|
+
await destroyThrowawayServer(provisioned);
|
|
154
|
+
evidence.teardown = { destroyed: provisioned.id };
|
|
155
|
+
// Confirm absence by re-listing. Failure to confirm FAILS the
|
|
156
|
+
// row ( Item on partly-fixed teardown: post-teardown
|
|
157
|
+
// inventory failures were being swallowed).
|
|
158
|
+
try {
|
|
159
|
+
const finalList = await hcloudJson(['server', 'list', '--output', 'json']);
|
|
160
|
+
evidence.postTeardownServerIds = finalList.map((s) => s.id);
|
|
161
|
+
if (finalList.some((s) => s.id === provisioned.id)) {
|
|
162
|
+
resultRow.verdict = 'fail';
|
|
163
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN INCOMPLETE: server ${provisioned.id} still present in hcloud server list; sweep-orphans must collect.`;
|
|
164
|
+
}
|
|
165
|
+
} catch (err) {
|
|
166
|
+
evidence.postTeardownListError = err.message;
|
|
167
|
+
resultRow.verdict = 'fail';
|
|
168
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN CONFIRMATION FAILED: post-teardown hcloud server list threw (${err.message}); cannot confirm server ${provisioned.id} was removed.`;
|
|
169
|
+
}
|
|
170
|
+
} catch (err) {
|
|
171
|
+
// Teardown failure fails the verdict (the shape rule).
|
|
172
|
+
resultRow.verdict = 'fail';
|
|
173
|
+
resultRow.detail = `${resultRow.detail} TEARDOWN FAILED for server ${provisioned.id}: ${err.message}. Orphan surfaced through sweep-orphans on next run.`;
|
|
174
|
+
evidence.teardownError = err.message;
|
|
175
|
+
evidence.orphanServerId = provisioned.id;
|
|
176
|
+
}
|
|
56
177
|
}
|
|
57
178
|
}
|
|
179
|
+
return { results: [resultRow], extra: evidence };
|
|
58
180
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.4 - 2026-09-12
|
|
4
|
+
|
|
5
|
+
- The application-admin-console fixture now refuses unauthenticated requests on gated sign-in paths (AC-21815-2), so the admin-console-gate-surface probe supplies a fixture Authorization header when the applied capability set includes zeroTrustGate; the fallback (non-gated) request is unchanged.
|
|
6
|
+
|
|
3
7
|
## 1.1.3 - 2026-09-10
|
|
4
8
|
|
|
5
9
|
Positive-evidence rule alignment on the probe pack skip path (authoring standard section 7d); register tidy in shipped prose (no capability change).
|
|
6
10
|
|
|
7
11
|
- Probes and fixture: the account-bound skip return on `contributions/probes/real-account-gated-url.mjs` now carries a `reason` field naming the exact env var(s) that were unset; the same fixture README (`packages/rcf-lite/test/fixtures/cf-edge/README.md`) gains a "Declared env vars" section covering the access-side env-var surface, per authoring standard section 7d. Skip-path probe reports regenerated so the shipped shape carries the new field.
|
|
8
|
-
- Closes F-8: README compose bullet and consumer note stripped of internal pattern label.
|
|
9
|
-
- Closes F-9: REQ-006 description stripped of internal mechanism label.
|
|
10
12
|
|
|
11
13
|
## 1.1.2 - 2026-09-10
|
|
12
14
|
|
|
@@ -21,8 +23,7 @@ Single-mechanism story legality notes; owner reference for the audit-record shap
|
|
|
21
23
|
|
|
22
24
|
## 1.1.0 - 2026-09-09
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
Adds REQ-007 with its US-34110 binding, and adds failure-path ACs to US-34102, US-34104 and US-34107.
|
|
26
27
|
- Added REQ-007 and US-34110: the shipped guide names, per policy-shape option, the required dashboard-owned inputs (email domain, group name, identity provider, application-vs-path scope) and every shipped elicit alongside its runtime effect (closes F-1).
|
|
27
28
|
- Added failure-path ACs to US-34102 (AC-34102-2..5 close F-2: wrong audience, malformed JWT, unknown kid after refresh, JWKS-unavailable fail-closed); US-34104 (AC-34104-2..3 close F-3: neither and both application identifiers refuse apply); US-34107 (AC-34107-2..5 close F-4: break-glass disabled, wrong id, wrong secret via constant-time compare, and partial-pair fall-through).
|
|
28
29
|
- Every REQ now carries `deliveredBy`; every AC carries `disposition`; ACs referencing owner-owned literals carry `ownerRef`.
|
|
@@ -31,7 +32,7 @@ hardening pass edge (criterion a REQ-layer backing; criterion b AC-set sufficien
|
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
All notable changes to `edge-cloudflare-access` are recorded here. The shape follows Keep a Changelog and Semantic Versioning per the blueprint authoring standard.
|
|
34
|
-
-
|
|
35
|
+
- split US-34103 into canonical-pass and SIMULATE_NON_VALIDATOR_HEADER-fail ACs, each with a concrete oracle (probe verdict + named field) and an `ownerRef` into TAC-3501. Re-marked ACs per section 7b: mechanism-invariant refusal reasons (`aud-mismatch`, `jwt-malformed`, `kid-unknown`, `jwks-unavailable`, `bypass-id-mismatch`, `bypass-secret-mismatch`, `jwt-missing`), audit-record shapes, guide-section presence assertions and the JWT validator happy path stay `fixed`; US-34104 AC-34104-1 (elicit shape recording), US-34107 AC-34107-1/-3/-4/-5 (bypass id/secret pair) and US-34109 AC-34109-1 (CF_ACCESS_HOST) re-marked `template` naming the values the applying agent sets (access-application-host or access-selfhosted-app-id, access-audience, access-jwks-url, access-policy-shape enum, access-bypass-service-auth-id + paired secret, CF_ACCESS_HOST). Vendor citations added on US-34101 (Cf-Access-Jwt-Assertion header), US-34105 (Zero Trust dashboard docs), US-34107 AC-34107-1 (service-tokens docs) and US-34109 (Access policies docs). Genuinely single-mechanism stories (US-34101, US-34105, US-34106, US-34108, US-34109, US-34110) carry the section-7a note inside the story `description` field, not in a schema-illegal new field.
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
## 1.0.0 (2026-09-07)
|