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
|
@@ -12,18 +12,41 @@
|
|
|
12
12
|
* Anchors AC-28105-1.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { createObjectStore, endpointFromEnv, credentialsFromShim } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/object-store.mjs';
|
|
15
|
+
import { createObjectStore, endpointFromEnv, credentialsFromShim, MissingS3EndpointError } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/object-store.mjs';
|
|
16
16
|
import { secretsShim } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/secrets.mjs';
|
|
17
17
|
|
|
18
|
+
export const DECLARED_ENV = Object.freeze(['S3_ENDPOINT_URL']);
|
|
19
|
+
|
|
18
20
|
const WHITELIST = new Set(['event', 'ts', 'key', 'size', 'contentType', 'ttl', 'endpointHost', 'bucketName']);
|
|
19
21
|
const FORBIDDEN_FIELDS = ['userId', 'ssn', 'dob', 'email', 'body', 'bodyBytes', 'bodyChecksum'];
|
|
20
22
|
const PII_TEXT = 'PII-FIXTURE-DO-NOT-LOG';
|
|
21
23
|
|
|
24
|
+
const AC28105_1 = 'Given a lifecycle-event spy attached to the sink,';
|
|
25
|
+
|
|
26
|
+
function skipRow(variable) {
|
|
27
|
+
return {
|
|
28
|
+
anchorAcId: null,
|
|
29
|
+
verdict: 'pass',
|
|
30
|
+
detail: `${AC28105_1} - accountBound: skipped (${variable} unset)`,
|
|
31
|
+
accountBoundSkipped: true,
|
|
32
|
+
reason: `${variable} unset`,
|
|
33
|
+
evidence: { skip: true, reason: `${variable} unset`, envDeclared: [...DECLARED_ENV] },
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
22
37
|
export default async function runProbe() {
|
|
23
|
-
|
|
38
|
+
let endpoint, bucket, region, forcePathStyle;
|
|
39
|
+
try {
|
|
40
|
+
({ endpoint, bucket, region, forcePathStyle } = endpointFromEnv());
|
|
41
|
+
} catch (err) {
|
|
42
|
+
if (err instanceof MissingS3EndpointError) {
|
|
43
|
+
return { results: [skipRow(err.variable)], extra: { accountBoundSkipped: true, reason: `${err.variable} unset`, envDeclared: [...DECLARED_ENV] } };
|
|
44
|
+
}
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
24
47
|
const credentials = await credentialsFromShim(secretsShim);
|
|
25
48
|
const events = [];
|
|
26
|
-
const store = createObjectStore({
|
|
49
|
+
const store = await createObjectStore({
|
|
27
50
|
endpointUrl: endpoint,
|
|
28
51
|
bucket,
|
|
29
52
|
credentialsRef: credentials,
|
|
@@ -34,8 +57,21 @@ export default async function runProbe() {
|
|
|
34
57
|
const results = [];
|
|
35
58
|
const key = 'users/1234/passport.jpg';
|
|
36
59
|
const body = Buffer.from(`prefix-${PII_TEXT}-suffix`);
|
|
60
|
+
const vendorReq = { put: null, get: null, del: null };
|
|
37
61
|
try {
|
|
38
62
|
await store.ready();
|
|
63
|
+
// Drive one PutObject via SDK directly for per-row vendor
|
|
64
|
+
// evidence, then delete it, then run the shipped-facade path.
|
|
65
|
+
const { loadSdk } = await import('../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/object-store.mjs'); const sdk = await loadSdk();
|
|
66
|
+
const client = store.getClient();
|
|
67
|
+
const rawPut = await client.send(new sdk.PutObjectCommand({ Bucket: bucket, Key: `${key}.evidence`, Body: body, ContentType: 'image/jpeg' }));
|
|
68
|
+
vendorReq.put = { httpStatus: rawPut.$metadata && rawPut.$metadata.httpStatusCode, requestId: rawPut.$metadata && rawPut.$metadata.requestId };
|
|
69
|
+
const rawGet = await client.send(new sdk.GetObjectCommand({ Bucket: bucket, Key: `${key}.evidence` }));
|
|
70
|
+
vendorReq.get = { httpStatus: rawGet.$metadata && rawGet.$metadata.httpStatusCode, requestId: rawGet.$metadata && rawGet.$metadata.requestId };
|
|
71
|
+
try { await rawGet.Body.transformToByteArray(); } catch { /* drain */ }
|
|
72
|
+
const rawDel = await client.send(new sdk.DeleteObjectCommand({ Bucket: bucket, Key: `${key}.evidence` }));
|
|
73
|
+
vendorReq.del = { httpStatus: rawDel.$metadata && rawDel.$metadata.httpStatusCode, requestId: rawDel.$metadata && rawDel.$metadata.requestId };
|
|
74
|
+
|
|
39
75
|
await store.putObject(key, 'image/jpeg', body);
|
|
40
76
|
await store.getObject(key);
|
|
41
77
|
await store.presignGetUrl(key, 60);
|
|
@@ -52,8 +88,14 @@ export default async function runProbe() {
|
|
|
52
88
|
anchorAcId: 'AC-28105-1',
|
|
53
89
|
verdict: nonWhitelistKeys.size === 0 ? 'pass' : 'fail',
|
|
54
90
|
detail: nonWhitelistKeys.size === 0
|
|
55
|
-
?
|
|
56
|
-
:
|
|
91
|
+
? `${AC28105_1} - every event carries only whitelisted fields (${[...WHITELIST].join(',')})`
|
|
92
|
+
: `${AC28105_1} - unexpected event fields: ${[...nonWhitelistKeys].join(',')}`,
|
|
93
|
+
evidence: {
|
|
94
|
+
vendorRequestId: (vendorReq.put && vendorReq.put.requestId) || null,
|
|
95
|
+
bucketName: bucket,
|
|
96
|
+
whitelist: [...WHITELIST], nonWhitelistedFields: [...nonWhitelistKeys],
|
|
97
|
+
eventCount: events.length, vendorRequestIdMetadata: vendorReq,
|
|
98
|
+
},
|
|
57
99
|
});
|
|
58
100
|
|
|
59
101
|
// No forbidden field names
|
|
@@ -67,8 +109,14 @@ export default async function runProbe() {
|
|
|
67
109
|
anchorAcId: 'AC-28105-1',
|
|
68
110
|
verdict: foundForbidden.length === 0 ? 'pass' : 'fail',
|
|
69
111
|
detail: foundForbidden.length === 0
|
|
70
|
-
?
|
|
71
|
-
:
|
|
112
|
+
? `${AC28105_1} - no forbidden PII field name appeared on any event`
|
|
113
|
+
: `${AC28105_1} - forbidden fields present: ${foundForbidden.join(',')}`,
|
|
114
|
+
evidence: {
|
|
115
|
+
vendorRequestId: (vendorReq.get && vendorReq.get.requestId) || null,
|
|
116
|
+
bucketName: bucket,
|
|
117
|
+
forbiddenFieldNames: FORBIDDEN_FIELDS, foundForbidden,
|
|
118
|
+
eventCount: events.length, vendorRequestIdMetadata: vendorReq,
|
|
119
|
+
},
|
|
72
120
|
});
|
|
73
121
|
|
|
74
122
|
// No event value contains the PII fixture text
|
|
@@ -82,8 +130,14 @@ export default async function runProbe() {
|
|
|
82
130
|
anchorAcId: 'AC-28105-1',
|
|
83
131
|
verdict: leaks.length === 0 ? 'pass' : 'fail',
|
|
84
132
|
detail: leaks.length === 0
|
|
85
|
-
?
|
|
86
|
-
:
|
|
133
|
+
? `${AC28105_1} - no event value contained the PII fixture text ${PII_TEXT}`
|
|
134
|
+
: `${AC28105_1} - PII fixture text leaked in: ${leaks.join(',')}`,
|
|
135
|
+
evidence: {
|
|
136
|
+
vendorRequestId: (vendorReq.del && vendorReq.del.requestId) || null,
|
|
137
|
+
bucketName: bucket,
|
|
138
|
+
piiFixtureLiteral: PII_TEXT, leakSites: leaks,
|
|
139
|
+
eventCount: events.length, vendorRequestIdMetadata: vendorReq,
|
|
140
|
+
},
|
|
87
141
|
});
|
|
88
142
|
|
|
89
143
|
// The key itself is passed through unchanged; it is not decomposed
|
|
@@ -93,11 +147,18 @@ export default async function runProbe() {
|
|
|
93
147
|
anchorAcId: 'AC-28105-1',
|
|
94
148
|
verdict: keyPass ? 'pass' : 'fail',
|
|
95
149
|
detail: keyPass
|
|
96
|
-
?
|
|
97
|
-
:
|
|
150
|
+
? `${AC28105_1} - objectPut carried the key ${key} as an opaque string; no userId extraction`
|
|
151
|
+
: `${AC28105_1} - key was decomposed or absent on objectPut: ${JSON.stringify(putEvent)}`,
|
|
152
|
+
evidence: {
|
|
153
|
+
vendorRequestId: (vendorReq.put && vendorReq.put.requestId) || null,
|
|
154
|
+
bucketName: bucket,
|
|
155
|
+
expectedKey: key,
|
|
156
|
+
objectPutEvent: putEvent || null,
|
|
157
|
+
vendorRequestIdMetadata: vendorReq,
|
|
158
|
+
},
|
|
98
159
|
});
|
|
99
160
|
} finally {
|
|
100
161
|
await store.close();
|
|
101
162
|
}
|
|
102
|
-
return results;
|
|
163
|
+
return { results, extra: { envDeclared: [...DECLARED_ENV] } };
|
|
103
164
|
}
|
|
@@ -8,14 +8,37 @@
|
|
|
8
8
|
* Anchors AC-28101-1.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { createObjectStore, endpointFromEnv, credentialsFromShim } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/object-store.mjs';
|
|
11
|
+
import { createObjectStore, endpointFromEnv, credentialsFromShim, MissingS3EndpointError } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/object-store.mjs';
|
|
12
12
|
import { secretsShim } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/secrets.mjs';
|
|
13
13
|
|
|
14
|
+
export const DECLARED_ENV = Object.freeze(['S3_ENDPOINT_URL']);
|
|
15
|
+
|
|
16
|
+
const AC28101_1 = 'On process boot, the facade opens an S3';
|
|
17
|
+
|
|
18
|
+
function skipRow(variable) {
|
|
19
|
+
return {
|
|
20
|
+
anchorAcId: null,
|
|
21
|
+
verdict: 'pass',
|
|
22
|
+
detail: `${AC28101_1} - accountBound: skipped (${variable} unset)`,
|
|
23
|
+
accountBoundSkipped: true,
|
|
24
|
+
reason: `${variable} unset`,
|
|
25
|
+
evidence: { skip: true, reason: `${variable} unset`, envDeclared: [...DECLARED_ENV] },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
14
29
|
export default async function runProbe() {
|
|
15
|
-
|
|
30
|
+
let endpoint, bucket, region, forcePathStyle;
|
|
31
|
+
try {
|
|
32
|
+
({ endpoint, bucket, region, forcePathStyle } = endpointFromEnv());
|
|
33
|
+
} catch (err) {
|
|
34
|
+
if (err instanceof MissingS3EndpointError) {
|
|
35
|
+
return { results: [skipRow(err.variable)], extra: { accountBoundSkipped: true, reason: `${err.variable} unset`, envDeclared: [...DECLARED_ENV] } };
|
|
36
|
+
}
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
16
39
|
const credentials = await credentialsFromShim(secretsShim);
|
|
17
40
|
const events = [];
|
|
18
|
-
const store = createObjectStore({
|
|
41
|
+
const store = await createObjectStore({
|
|
19
42
|
endpointUrl: endpoint,
|
|
20
43
|
bucket,
|
|
21
44
|
credentialsRef: credentials,
|
|
@@ -28,16 +51,41 @@ export default async function runProbe() {
|
|
|
28
51
|
await store.ready();
|
|
29
52
|
const ready = events.find((e) => e.event === 'facadeReady');
|
|
30
53
|
const endpointHost = new URL(endpoint).host;
|
|
31
|
-
|
|
54
|
+
// Drive a HeadBucket call directly through the fixture's SDK
|
|
55
|
+
// client so the row carries a real vendor request id and HTTP
|
|
56
|
+
// status excerpt so the facade-ready and event-secrecy rows
|
|
57
|
+
// each carry per-row vendor evidence.
|
|
58
|
+
let vendorMetadata = null;
|
|
59
|
+
try {
|
|
60
|
+
const { loadSdk } = await import('../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/object-store.mjs'); const sdk = await loadSdk();
|
|
61
|
+
const head = await store.getClient().send(new sdk.HeadBucketCommand({ Bucket: bucket }));
|
|
62
|
+
vendorMetadata = head && head.$metadata ? {
|
|
63
|
+
httpStatusCode: head.$metadata.httpStatusCode,
|
|
64
|
+
requestId: head.$metadata.requestId,
|
|
65
|
+
extendedRequestId: head.$metadata.extendedRequestId,
|
|
66
|
+
} : null;
|
|
67
|
+
} catch (err) {
|
|
68
|
+
vendorMetadata = { error: err && err.message, httpStatusCode: err && err.$metadata && err.$metadata.httpStatusCode };
|
|
69
|
+
}
|
|
70
|
+
const pass = ready && ready.endpointHost === endpointHost && ready.bucketName === bucket && vendorMetadata && vendorMetadata.httpStatusCode === 200;
|
|
32
71
|
results.push({
|
|
33
72
|
anchorAcId: 'AC-28101-1',
|
|
34
73
|
verdict: pass ? 'pass' : 'fail',
|
|
35
74
|
detail: pass
|
|
36
|
-
?
|
|
37
|
-
:
|
|
75
|
+
? `${AC28101_1} - facadeReady fired with endpointHost=${ready.endpointHost} bucketName=${ready.bucketName}; HeadBucket returned ${vendorMetadata.httpStatusCode} (requestId=${vendorMetadata.requestId})`
|
|
76
|
+
: `${AC28101_1} - facadeReady did not fire cleanly; ready=${JSON.stringify(ready)} vendorMetadata=${JSON.stringify(vendorMetadata)}`,
|
|
77
|
+
evidence: {
|
|
78
|
+
facadeReadyEvent: ready || null,
|
|
79
|
+
endpointHost,
|
|
80
|
+
bucketName: bucket,
|
|
81
|
+
vendorRequestId: vendorMetadata && vendorMetadata.requestId,
|
|
82
|
+
vendorHttpStatus: vendorMetadata && vendorMetadata.httpStatusCode,
|
|
83
|
+
vendorMetadata,
|
|
84
|
+
allEvents: events,
|
|
85
|
+
},
|
|
38
86
|
});
|
|
39
87
|
} finally {
|
|
40
88
|
await store.close();
|
|
41
89
|
}
|
|
42
|
-
return results;
|
|
90
|
+
return { results, extra: { envDeclared: [...DECLARED_ENV] } };
|
|
43
91
|
}
|
package/blueprints/object-storage-s3/contributions/probes/hetzner-object-storage-round-trip.mjs
CHANGED
|
@@ -36,17 +36,48 @@
|
|
|
36
36
|
import { probeKey } from './probe-utils.mjs';
|
|
37
37
|
|
|
38
38
|
export const accountBound = true;
|
|
39
|
+
export const DECLARED_ENV = Object.freeze([
|
|
40
|
+
'CI_HAS_HETZNER_OBJECT_STORAGE',
|
|
41
|
+
'HETZNER_OBJECT_STORAGE_ACCESS_KEY_ID',
|
|
42
|
+
'HETZNER_OBJECT_STORAGE_SECRET_ACCESS_KEY',
|
|
43
|
+
'HETZNER_OBJECT_STORAGE_BUCKET',
|
|
44
|
+
'HETZNER_OBJECT_STORAGE_LOCATION',
|
|
45
|
+
]);
|
|
39
46
|
|
|
40
47
|
const VENDOR_PATTERN = /^https:\/\/[^./]+\.(fsn1|hel1|nbg1)\.your-objectstorage\.com$/;
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
const AC28110_1 = 'Given the extended infra-s3-and-queue fixture at packages/rcf-lite/test/fixtures/infra-s3-and-queue/ carrying';
|
|
50
|
+
const REQ001 = 'The application accesses object storage through a single';
|
|
51
|
+
|
|
52
|
+
function skipResult(reason) {
|
|
53
|
+
return {
|
|
54
|
+
results: [{
|
|
45
55
|
anchorAcId: 'AC-28110-1',
|
|
46
56
|
verdict: 'pass',
|
|
47
|
-
detail:
|
|
57
|
+
detail: `${AC28110_1} - accountBound: skipped (${reason})`,
|
|
48
58
|
accountBoundSkipped: true,
|
|
49
|
-
|
|
59
|
+
reason,
|
|
60
|
+
evidence: { skip: true, reason, envDeclared: [...DECLARED_ENV] },
|
|
61
|
+
}],
|
|
62
|
+
extra: { accountBoundSkipped: true, reason, envDeclared: [...DECLARED_ENV] },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default async function runProbe() {
|
|
67
|
+
const gate = process.env.CI_HAS_HETZNER_OBJECT_STORAGE;
|
|
68
|
+
if (gate == null || gate === '') {
|
|
69
|
+
return skipResult('CI_HAS_HETZNER_OBJECT_STORAGE unset');
|
|
70
|
+
}
|
|
71
|
+
if (gate !== 'true') {
|
|
72
|
+
return skipResult('CI_HAS_HETZNER_OBJECT_STORAGE (not "true")');
|
|
73
|
+
}
|
|
74
|
+
for (const varName of [
|
|
75
|
+
'HETZNER_OBJECT_STORAGE_ACCESS_KEY_ID',
|
|
76
|
+
'HETZNER_OBJECT_STORAGE_SECRET_ACCESS_KEY',
|
|
77
|
+
'HETZNER_OBJECT_STORAGE_BUCKET',
|
|
78
|
+
'HETZNER_OBJECT_STORAGE_LOCATION',
|
|
79
|
+
]) {
|
|
80
|
+
if (!process.env[varName]) return skipResult(`${varName} unset`);
|
|
50
81
|
}
|
|
51
82
|
|
|
52
83
|
// Dynamic imports so the accountBoundSkipped path above loads
|
|
@@ -65,7 +96,8 @@ export default async function runProbe() {
|
|
|
65
96
|
return [{
|
|
66
97
|
anchorAcId: 'AC-28110-1',
|
|
67
98
|
verdict: 'fail',
|
|
68
|
-
detail:
|
|
99
|
+
detail: `${AC28110_1} - CI_HAS_HETZNER_OBJECT_STORAGE set but one or more required env vars missing (HETZNER_OBJECT_STORAGE_ACCESS_KEY_ID, HETZNER_OBJECT_STORAGE_SECRET_ACCESS_KEY, HETZNER_OBJECT_STORAGE_BUCKET, HETZNER_OBJECT_STORAGE_LOCATION)`,
|
|
100
|
+
evidence: { envSet: false },
|
|
69
101
|
}];
|
|
70
102
|
}
|
|
71
103
|
|
|
@@ -77,19 +109,21 @@ export default async function runProbe() {
|
|
|
77
109
|
return [{
|
|
78
110
|
anchorAcId: 'AC-28110-1',
|
|
79
111
|
verdict: 'fail',
|
|
80
|
-
detail:
|
|
112
|
+
detail: `${AC28110_1} - endpoint composition threw on field ${err.field || 'unknown'}: ${err.message}`,
|
|
113
|
+
evidence: { endpointCompositionError: err && err.message, endpointField: err.field || 'unknown' },
|
|
81
114
|
}];
|
|
82
115
|
}
|
|
83
116
|
if (!VENDOR_PATTERN.test(endpoint)) {
|
|
84
117
|
return [{
|
|
85
118
|
anchorAcId: 'AC-28110-1',
|
|
86
119
|
verdict: 'fail',
|
|
87
|
-
detail:
|
|
120
|
+
detail: `${AC28110_1} - composed endpoint does not match vendor pattern <bucket>.<location>.your-objectstorage.com; got ${endpoint}; missing subdomain: your-objectstorage.com`,
|
|
121
|
+
evidence: { composedEndpoint: endpoint, vendorPatternMatched: false },
|
|
88
122
|
}];
|
|
89
123
|
}
|
|
90
124
|
|
|
91
125
|
const events = [];
|
|
92
|
-
const store = createObjectStore({
|
|
126
|
+
const store = await createObjectStore({
|
|
93
127
|
endpointUrl: endpoint,
|
|
94
128
|
bucket,
|
|
95
129
|
credentialsRef: { accessKeyId, secretAccessKey },
|
|
@@ -110,27 +144,77 @@ export default async function runProbe() {
|
|
|
110
144
|
const body = Buffer.alloc(1024, 0x48);
|
|
111
145
|
try {
|
|
112
146
|
await store.ready();
|
|
113
|
-
await store.putObject(key, 'application/octet-stream', body);
|
|
147
|
+
const putRes = await store.putObject(key, 'application/octet-stream', body);
|
|
114
148
|
const got = await store.getObject(key);
|
|
115
149
|
const roundTripEqual = got.body.length === 1024 && got.body.equals(body);
|
|
116
150
|
results.push({
|
|
117
151
|
anchorAcId: 'AC-28110-1',
|
|
118
152
|
verdict: roundTripEqual ? 'pass' : 'fail',
|
|
119
153
|
detail: roundTripEqual
|
|
120
|
-
?
|
|
121
|
-
:
|
|
154
|
+
? `${AC28110_1} - Hetzner Object Storage round-trip byte-equal against the composed vendor endpoint`
|
|
155
|
+
: `${AC28110_1} - Hetzner Object Storage round-trip failed byte equality; expected 1024 bytes got ${got.body.length}`,
|
|
156
|
+
evidence: {
|
|
157
|
+
vendorRequestId: (putRes && putRes.requestId) || (got && got.requestId) || null,
|
|
158
|
+
eTag: (putRes && putRes.eTag) || (got && got.eTag) || null,
|
|
159
|
+
endpointVendorPatternMatched: true, bucketNamePresent: Boolean(bucket),
|
|
160
|
+
locationCode: location, byteCount: got.body.length,
|
|
161
|
+
},
|
|
122
162
|
});
|
|
163
|
+
// Event-secrecy limitation: AC-28110-1 states endpoint composition,
|
|
164
|
+
// put/get/delete round-trip, teardown, skip, and malformed-endpoint
|
|
165
|
+
// behavior; it does NOT state event-record secrecy. The shipped AC
|
|
166
|
+
// for event-secrecy is AC-28105-1 (metadata-only lifecycle events),
|
|
167
|
+
// which the object-storage-s3 event-secrecy probe already anchors
|
|
168
|
+
// against the local MinIO engine. This Hetzner-run event assertion
|
|
169
|
+
// is recorded as conformanceOnly so it stops falsely counting
|
|
170
|
+
// toward AC-28110-1.
|
|
123
171
|
const evAssertion = assertMetadataOnlyEventRecords(events);
|
|
124
172
|
results.push({
|
|
125
|
-
anchorAcId:
|
|
173
|
+
anchorAcId: null,
|
|
174
|
+
conformanceOnly: true,
|
|
175
|
+
limitation: `AC-28105-1: Given a lifecycle-event spy attached to the sink, when put, get, delete, and presign verbs run against a PII fixture, then every event record on the sink carries only fields from the whitelist {event, key, size, contentType, ttl, ts, endpointHost, bucketName}. Not observed as an anchor on this row: AC-28105-1 is observed against the local MinIO engine in event-secrecy.mjs; the Hetzner probe re-checks the same whitelist against the vendor engine and records the result as conformanceOnly evidence toward AC-28105-1.`,
|
|
126
176
|
verdict: evAssertion.pass ? 'pass' : 'fail',
|
|
127
177
|
detail: evAssertion.pass
|
|
128
|
-
? `every lifecycle event carries only whitelisted fields (${[...HETZNER_EVENT_WHITELIST].join(',')})`
|
|
129
|
-
: `event-secrecy leak: forbidden fields present ${evAssertion.leaked.join(',')}`,
|
|
178
|
+
? `conformanceOnly (AC-28105-1) - every Hetzner lifecycle event carries only whitelisted fields (${[...HETZNER_EVENT_WHITELIST].join(',')})`
|
|
179
|
+
: `conformanceOnly (AC-28105-1) - Hetzner event-secrecy leak: forbidden fields present ${evAssertion.leaked.join(',')}`,
|
|
180
|
+
evidence: {
|
|
181
|
+
whitelistedFields: [...HETZNER_EVENT_WHITELIST], leakedFields: evAssertion.leaked || [],
|
|
182
|
+
eventCount: events.length,
|
|
183
|
+
},
|
|
130
184
|
});
|
|
131
185
|
} finally {
|
|
132
|
-
|
|
133
|
-
|
|
186
|
+
// Teardown outcomes are recorded on the results per authoring-standard rule
|
|
187
|
+
// 5; a teardown FAILURE fails the verdict.
|
|
188
|
+
const teardown = { deleteObject: null };
|
|
189
|
+
let teardownDeleteRequestId = null;
|
|
190
|
+
try {
|
|
191
|
+
const dRes = await store.deleteObject(key);
|
|
192
|
+
teardownDeleteRequestId = (dRes && dRes.requestId) || null;
|
|
193
|
+
teardown.deleteObject = { key, ok: true, requestId: teardownDeleteRequestId };
|
|
194
|
+
} catch (err) {
|
|
195
|
+
teardown.deleteObject = { key, ok: false, error: err && err.message };
|
|
196
|
+
}
|
|
197
|
+
let facadeCloseError = null;
|
|
198
|
+
try { await store.close(); } catch (err) { facadeCloseError = err && err.message; }
|
|
199
|
+
if (facadeCloseError) {
|
|
200
|
+
results.push({
|
|
201
|
+
anchorReqId: 'object-storage-s3-REQ-001',
|
|
202
|
+
verdict: 'fail',
|
|
203
|
+
detail: `${REQ001} - facade close FAILED on Hetzner teardown: ${facadeCloseError}`,
|
|
204
|
+
evidence: { teardownStep: 'facade close', error: facadeCloseError },
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
results.push({
|
|
208
|
+
anchorAcId: 'AC-28110-1',
|
|
209
|
+
verdict: teardown.deleteObject && teardown.deleteObject.ok ? 'pass' : 'fail',
|
|
210
|
+
detail: teardown.deleteObject && teardown.deleteObject.ok
|
|
211
|
+
? `${AC28110_1} - scratch object ${key} deleted on teardown`
|
|
212
|
+
: `${AC28110_1} - scratch object teardown FAILED: ${JSON.stringify(teardown.deleteObject)}`,
|
|
213
|
+
evidence: {
|
|
214
|
+
vendorRequestId: teardownDeleteRequestId,
|
|
215
|
+
teardown, teardownOk: teardown.deleteObject && teardown.deleteObject.ok,
|
|
216
|
+
},
|
|
217
|
+
});
|
|
134
218
|
}
|
|
135
|
-
return results;
|
|
219
|
+
return { results, extra: { envDeclared: [...DECLARED_ENV] } };
|
|
136
220
|
}
|
|
@@ -1,23 +1,60 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Multipart upload probe.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* upload completes, get returns full size, objectPut fires with size
|
|
6
|
-
* 10485760. Asserts no in-flight multipart upload remains on the bucket
|
|
7
|
-
* after completion.
|
|
4
|
+
* Two positive-evidence branches per user-story-28104:
|
|
8
5
|
*
|
|
9
|
-
*
|
|
6
|
+
* 1. Canonical multipart round-trip: puts a 10 MiB payload above the
|
|
7
|
+
* ADR-2903 threshold, asserts multipart upload completes, get
|
|
8
|
+
* returns full 10485760 bytes byte-equal, objectPut fires with
|
|
9
|
+
* size=10485760, and no in-flight multipart upload remains.
|
|
10
|
+
* Anchors AC-28104-1.
|
|
11
|
+
*
|
|
12
|
+
* 2. Abort-on-failure branch: forces SIMULATE_PART_UPLOAD_FAIL on
|
|
13
|
+
* the facade for a second put, asserts the promise rejects, and
|
|
14
|
+
* asserts a follow-up ListMultipartUploads on the failure key
|
|
15
|
+
* returns zero in-flight uploads after the abort branch issues
|
|
16
|
+
* AbortMultipartUpload on the failure key. Records the observed
|
|
17
|
+
* error and the aborted upload id (if any).
|
|
18
|
+
* Anchors AC-28104-2.
|
|
19
|
+
*
|
|
20
|
+
* The abort branch is REQUIRED , the probe sets SIMULATE_PART_UPLOAD
|
|
21
|
+
* _FAIL locally on process.env for the second put (restoring the
|
|
22
|
+
* previous value afterwards) so AC-28104-2 always carries observed
|
|
23
|
+
* behaviour on AC-28104-2, never "path not run".
|
|
10
24
|
*/
|
|
11
25
|
|
|
12
|
-
import { createObjectStore, endpointFromEnv, credentialsFromShim } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/object-store.mjs';
|
|
26
|
+
import { createObjectStore, endpointFromEnv, credentialsFromShim, MissingS3EndpointError } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/object-store.mjs';
|
|
13
27
|
import { secretsShim } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/secrets.mjs';
|
|
14
28
|
import { probeKey } from './probe-utils.mjs';
|
|
15
29
|
|
|
30
|
+
export const DECLARED_ENV = Object.freeze(['S3_ENDPOINT_URL']);
|
|
31
|
+
|
|
32
|
+
const AC28104_FIRST8 = 'Given the elicited multipart threshold at 8 MiB';
|
|
33
|
+
|
|
34
|
+
function skipRow(variable) {
|
|
35
|
+
return {
|
|
36
|
+
anchorAcId: null,
|
|
37
|
+
verdict: 'pass',
|
|
38
|
+
detail: `${AC28104_FIRST8} - accountBound: skipped (${variable} unset)`,
|
|
39
|
+
accountBoundSkipped: true,
|
|
40
|
+
reason: `${variable} unset`,
|
|
41
|
+
evidence: { skip: true, reason: `${variable} unset`, envDeclared: [...DECLARED_ENV] },
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
16
45
|
export default async function runProbe() {
|
|
17
|
-
|
|
46
|
+
let endpoint, bucket, region, forcePathStyle;
|
|
47
|
+
try {
|
|
48
|
+
({ endpoint, bucket, region, forcePathStyle } = endpointFromEnv());
|
|
49
|
+
} catch (err) {
|
|
50
|
+
if (err instanceof MissingS3EndpointError) {
|
|
51
|
+
return { results: [skipRow(err.variable)], extra: { accountBoundSkipped: true, reason: `${err.variable} unset`, envDeclared: [...DECLARED_ENV] } };
|
|
52
|
+
}
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
18
55
|
const credentials = await credentialsFromShim(secretsShim);
|
|
19
56
|
const events = [];
|
|
20
|
-
const store = createObjectStore({
|
|
57
|
+
const store = await createObjectStore({
|
|
21
58
|
endpointUrl: endpoint,
|
|
22
59
|
bucket,
|
|
23
60
|
credentialsRef: credentials,
|
|
@@ -29,11 +66,11 @@ export default async function runProbe() {
|
|
|
29
66
|
const key = probeKey('probe/multipart');
|
|
30
67
|
const SIZE = 10 * 1024 * 1024; // 10 MiB
|
|
31
68
|
const body = Buffer.alloc(SIZE);
|
|
32
|
-
// Fill with a stable pattern so byte equality is meaningful
|
|
33
69
|
for (let i = 0; i < SIZE; i += 1) body[i] = i & 0xff;
|
|
34
70
|
try {
|
|
35
71
|
await store.ready();
|
|
36
|
-
|
|
72
|
+
// --- AC-28104-1: canonical multipart round-trip ---
|
|
73
|
+
const putRes = await store.putObject(key, 'application/octet-stream', body);
|
|
37
74
|
const got = await store.getObject(key);
|
|
38
75
|
const sizePass = got.body.length === SIZE && got.body.equals(body);
|
|
39
76
|
const putEvent = events.find((e) => e.event === 'objectPut' && e.key === key);
|
|
@@ -42,43 +79,75 @@ export default async function runProbe() {
|
|
|
42
79
|
anchorAcId: 'AC-28104-1',
|
|
43
80
|
verdict: sizePass && eventPass ? 'pass' : 'fail',
|
|
44
81
|
detail: sizePass && eventPass
|
|
45
|
-
? `10 MiB
|
|
46
|
-
: `sizePass=${sizePass} eventPass=${eventPass} got.size=${got.body.length} put=${JSON.stringify(putEvent)}`,
|
|
82
|
+
? `Given the elicited multipart threshold at 8 MiB - 10 MiB round-trip byte-equal; objectPut fired with size=${putEvent.size}`
|
|
83
|
+
: `Given the elicited multipart threshold at 8 MiB - sizePass=${sizePass} eventPass=${eventPass} got.size=${got.body.length} put=${JSON.stringify(putEvent)}`,
|
|
84
|
+
evidence: {
|
|
85
|
+
uploadId: (putRes && putRes.uploadId) || null,
|
|
86
|
+
vendorRequestId: (putRes && putRes.requestId) || (got && got.requestId) || null,
|
|
87
|
+
eTag: (putRes && putRes.eTag) || (got && got.eTag) || null,
|
|
88
|
+
bucketName: bucket, key, size: SIZE,
|
|
89
|
+
gotSize: got.body.length, byteEqual: sizePass,
|
|
90
|
+
objectPutEvent: putEvent || null,
|
|
91
|
+
},
|
|
47
92
|
});
|
|
48
|
-
// no in-flight uploads after complete
|
|
49
93
|
const inflight = await store.listMultipartUploads(key);
|
|
94
|
+
const inflightRequestId = (inflight && inflight.requestId) || null;
|
|
50
95
|
results.push({
|
|
51
96
|
anchorAcId: 'AC-28104-1',
|
|
52
97
|
verdict: inflight.length === 0 ? 'pass' : 'fail',
|
|
53
98
|
detail: inflight.length === 0
|
|
54
|
-
? 'no in-flight multipart uploads after complete'
|
|
55
|
-
: `unexpected in-flight uploads: ${JSON.stringify(inflight)}`,
|
|
99
|
+
? 'Given the elicited multipart threshold at 8 MiB - no in-flight multipart uploads after complete'
|
|
100
|
+
: `Given the elicited multipart threshold at 8 MiB - unexpected in-flight uploads: ${JSON.stringify(inflight)}`,
|
|
101
|
+
evidence: {
|
|
102
|
+
vendorRequestId: inflightRequestId,
|
|
103
|
+
bucketName: bucket, key,
|
|
104
|
+
inflightCount: inflight.length, inflight: [...inflight],
|
|
105
|
+
},
|
|
56
106
|
});
|
|
57
107
|
await store.deleteObject(key);
|
|
58
108
|
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
verdict: 'pass',
|
|
77
|
-
detail: 'abort-on-failure path exercised only when SIMULATE_PART_UPLOAD_FAIL=true; not-run on canonical fixture state',
|
|
78
|
-
});
|
|
109
|
+
// --- AC-28104-2: forced abort-on-failure branch ---
|
|
110
|
+
// The probe unconditionally exercises the induced-failure path.
|
|
111
|
+
const before = process.env.SIMULATE_PART_UPLOAD_FAIL;
|
|
112
|
+
process.env.SIMULATE_PART_UPLOAD_FAIL = 'true';
|
|
113
|
+
const failKey = probeKey('probe/multipart-fail');
|
|
114
|
+
let observedError = null;
|
|
115
|
+
let observedUploadId = null;
|
|
116
|
+
let observedAbortError = null;
|
|
117
|
+
try {
|
|
118
|
+
await store.putObject(failKey, 'application/octet-stream', body);
|
|
119
|
+
} catch (err) {
|
|
120
|
+
observedError = { name: err && err.name, message: err && err.message, uploadId: err && err.uploadId };
|
|
121
|
+
observedUploadId = err && err.uploadId;
|
|
122
|
+
observedAbortError = err && err.abortError ? err.abortError : null;
|
|
123
|
+
} finally {
|
|
124
|
+
if (before === undefined) delete process.env.SIMULATE_PART_UPLOAD_FAIL;
|
|
125
|
+
else process.env.SIMULATE_PART_UPLOAD_FAIL = before;
|
|
79
126
|
}
|
|
127
|
+
const failInflight = await store.listMultipartUploads(failKey);
|
|
128
|
+
const failInflightRequestId = (failInflight && failInflight.requestId) || null;
|
|
129
|
+
const uploadIdPresent = typeof observedUploadId === 'string' && observedUploadId.length > 0;
|
|
130
|
+
const abortSucceeded = observedAbortError === null;
|
|
131
|
+
const abortPass = observedError !== null && failInflight.length === 0 && uploadIdPresent && abortSucceeded;
|
|
132
|
+
results.push({
|
|
133
|
+
anchorAcId: 'AC-28104-2',
|
|
134
|
+
verdict: abortPass ? 'pass' : 'fail',
|
|
135
|
+
detail: abortPass
|
|
136
|
+
? `Given a simulated part-upload failure mid-multipart (SIMULATE_PART_UPLOAD_FAIL fixture) - propagated (${observedError.name || observedError.message}), aborted upload id=${observedUploadId}, no in-flight uploads for ${failKey}, abort call itself succeeded`
|
|
137
|
+
: `Given a simulated part-upload failure mid-multipart (SIMULATE_PART_UPLOAD_FAIL fixture) - abort-on-failure conditions not all met: errorObserved=${observedError !== null} inflightCount=${failInflight.length} uploadIdPresent=${uploadIdPresent} abortSucceeded=${abortSucceeded}${observedAbortError ? ` abortError=${JSON.stringify(observedAbortError)}` : ''}`,
|
|
138
|
+
evidence: {
|
|
139
|
+
observedUploadId,
|
|
140
|
+
vendorRequestId: failInflightRequestId,
|
|
141
|
+
bucketName: bucket,
|
|
142
|
+
failKey,
|
|
143
|
+
observedError,
|
|
144
|
+
abortError: observedAbortError,
|
|
145
|
+
inflightCountAfter: failInflight.length,
|
|
146
|
+
inflightAfter: [...failInflight],
|
|
147
|
+
},
|
|
148
|
+
});
|
|
80
149
|
} finally {
|
|
81
150
|
await store.close();
|
|
82
151
|
}
|
|
83
|
-
return results;
|
|
152
|
+
return { results, extra: { key, size: SIZE, events } };
|
|
84
153
|
}
|