rcf-lite 0.27.0 → 0.28.1
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 +39 -0
- package/README.md +19 -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 +46 -0
- package/rcf/code-nodes/cn-601.json +18 -0
- package/rcf/code-nodes/cn-602.json +16 -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 +18 -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 +46 -0
- package/rcf/fbs/fbs-182.json +43 -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 +40 -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 +40 -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 +174 -0
- package/rcf/test-suites/ts-189.json +60 -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 +60 -0
- package/rcf/user-stories/us-15701.json +42 -0
- package/rcf/user-stories/us-15801.json +51 -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 +21 -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 +2213 -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 +455 -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 +1148 -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
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Shared helpers for application-error-handling probes.
|
|
2
|
+
//
|
|
3
|
+
// The engine under probe is the sample-app fixture at
|
|
4
|
+
// packages/rcf-lite/test/fixtures/probe-pack-application-error-handling/server.js. The
|
|
5
|
+
// fixture stamps an x-fixture-request-id header on every response as
|
|
6
|
+
// part of its own request pipeline (no probe-side monkey-patch), so
|
|
7
|
+
// the identifier the probe records is the identifier the engine
|
|
8
|
+
// itself issued. Probes call the fixture over real HTTP via node's
|
|
9
|
+
// fetch, vary inputs, assert derived outputs, and record the
|
|
10
|
+
// request-id, status, body excerpt, the varied input and the derived
|
|
11
|
+
// output as evidence on every result row.
|
|
12
|
+
// No account-bound branch: the engine is a local fixture, not a
|
|
13
|
+
// third-party account, so no CI_HAS_* gate is invented. Every env
|
|
14
|
+
// var this pack reads is declared on the fixture README.
|
|
15
|
+
|
|
16
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
17
|
+
import { dirname, resolve } from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
|
|
20
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
export const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
|
|
22
|
+
export const FIXTURE_DIR = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/probe-pack-application-error-handling');
|
|
23
|
+
export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/application-error-handling');
|
|
24
|
+
|
|
25
|
+
export const DEFAULT_PORT = 0;
|
|
26
|
+
|
|
27
|
+
export function aggregate(results) {
|
|
28
|
+
if (!Array.isArray(results) || results.length === 0) return 'fail';
|
|
29
|
+
if (results.some((r) => r.verdict === 'fail')) return 'fail';
|
|
30
|
+
if (results.some((r) => r.verdict === 'warn')) return 'warn';
|
|
31
|
+
return 'pass';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Empty results never pass: a synthesised row is emitted with an actionable detail and its
|
|
35
|
+
// own evidence object recording the empty condition so the row is
|
|
36
|
+
// not a naked verdict scalar.
|
|
37
|
+
export function normaliseResults(results) {
|
|
38
|
+
if (!Array.isArray(results) || results.length === 0) {
|
|
39
|
+
return [{
|
|
40
|
+
anchorReqId: 'unknown',
|
|
41
|
+
verdict: 'fail',
|
|
42
|
+
detail: 'no checks ran',
|
|
43
|
+
evidence: {
|
|
44
|
+
reason: 'empty-results',
|
|
45
|
+
route: 'n/a',
|
|
46
|
+
status: 0,
|
|
47
|
+
xFixtureRequestId: null,
|
|
48
|
+
bodyExcerpt: '',
|
|
49
|
+
},
|
|
50
|
+
}];
|
|
51
|
+
}
|
|
52
|
+
return results;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function writeReport({ probeName, engine, results, extra }) {
|
|
56
|
+
await mkdir(REPORT_DIR, { recursive: true });
|
|
57
|
+
const report = {
|
|
58
|
+
slug: 'application-error-handling',
|
|
59
|
+
probeName,
|
|
60
|
+
runAt: new Date().toISOString(),
|
|
61
|
+
engine,
|
|
62
|
+
results,
|
|
63
|
+
aggregateVerdict: aggregate(results),
|
|
64
|
+
...(extra ?? {}),
|
|
65
|
+
};
|
|
66
|
+
const path = resolve(REPORT_DIR, `${probeName}.json`);
|
|
67
|
+
await writeFile(path, JSON.stringify(report, null, 2) + '\n', 'utf8');
|
|
68
|
+
return { report, path };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Starts the fixture on an ephemeral port (or PROBE_PORT when set)
|
|
72
|
+
// and returns { server, port, baseUrl, close }. The close helper
|
|
73
|
+
// rejects when the underlying close callback carries an error;
|
|
74
|
+
// swallowing a teardown error would hide a boundary failure.
|
|
75
|
+
export async function startFixture({ startServer, port } = {}) {
|
|
76
|
+
const resolvedPort = typeof port === 'number'
|
|
77
|
+
? port
|
|
78
|
+
: Number(process.env.PROBE_PORT ?? DEFAULT_PORT);
|
|
79
|
+
const started = await startServer({ port: resolvedPort });
|
|
80
|
+
return {
|
|
81
|
+
server: started.server,
|
|
82
|
+
port: started.port,
|
|
83
|
+
baseUrl: `http://127.0.0.1:${started.port}`,
|
|
84
|
+
close: () => new Promise((res, rej) => started.server.close((err) => {
|
|
85
|
+
if (err) rej(err);
|
|
86
|
+
else res();
|
|
87
|
+
})),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Reads a distinctive slice of a response body: the first N chars
|
|
92
|
+
// so the report carries a body excerpt alongside the header id.
|
|
93
|
+
export function bodyExcerpt(text, max = 240) {
|
|
94
|
+
if (text == null) return '';
|
|
95
|
+
const s = typeof text === 'string' ? text : String(text);
|
|
96
|
+
return s.length > max ? s.slice(0, max) + '...' : s;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Records the positive-evidence shape on a probe result. Every row
|
|
100
|
+
// carries route, status, the request id the fixture stamped, and a
|
|
101
|
+
// body excerpt; the caller may extend the object with the varied
|
|
102
|
+
// input and the derived output for that row.
|
|
103
|
+
export function evidenceFromResponse({ route, response, bodyText, extraFields }) {
|
|
104
|
+
return {
|
|
105
|
+
route,
|
|
106
|
+
status: response.status,
|
|
107
|
+
xFixtureRequestId: response.headers.get('x-fixture-request-id') || null,
|
|
108
|
+
bodyExcerpt: bodyExcerpt(bodyText),
|
|
109
|
+
...(extraFields ?? {}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export async function runShim(probeName, engine, mainFn) {
|
|
114
|
+
try {
|
|
115
|
+
const outcome = (await mainFn()) ?? { results: [] };
|
|
116
|
+
const { results, extra } = outcome;
|
|
117
|
+
const { report, path } = await writeReport({ probeName, engine, results: normaliseResults(results), extra });
|
|
118
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
119
|
+
process.stdout.write(`report written to ${path}\n`);
|
|
120
|
+
if (report.aggregateVerdict !== 'pass') process.exitCode = 1;
|
|
121
|
+
} catch (err) {
|
|
122
|
+
const results = [{
|
|
123
|
+
anchorReqId: 'unknown',
|
|
124
|
+
verdict: 'fail',
|
|
125
|
+
detail: `probe threw: ${err && err.message ? err.message : String(err)}`,
|
|
126
|
+
evidence: {
|
|
127
|
+
reason: 'probe-threw',
|
|
128
|
+
route: 'n/a',
|
|
129
|
+
status: 0,
|
|
130
|
+
xFixtureRequestId: null,
|
|
131
|
+
bodyExcerpt: err && err.stack ? String(err.stack).slice(0, 240) : '',
|
|
132
|
+
},
|
|
133
|
+
}];
|
|
134
|
+
const { report, path } = await writeReport({ probeName, engine, results });
|
|
135
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
136
|
+
process.stderr.write(`probe error: ${err && err.stack ? err.stack : String(err)}\n`);
|
|
137
|
+
process.stderr.write(`report written to ${path}\n`);
|
|
138
|
+
process.exitCode = 1;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Browser-observable properties are AMBER on the shelf by ruling.
|
|
143
|
+
// A row that names such a property is recorded as notObservableHere
|
|
144
|
+
// carrying an object with the AC id and a reason; the tally script
|
|
145
|
+
// reads notObservableHere.ac to accept the row.
|
|
146
|
+
export function notObservableHereResult({ ac, anchorAcId, detail, reason, evidence } = {}) {
|
|
147
|
+
// A notObservableHere row anchors nothing else: no anchorAcId,
|
|
148
|
+
// no anchorReqId - only notObservableHere.ac.
|
|
149
|
+
const acId = ac || anchorAcId;
|
|
150
|
+
return {
|
|
151
|
+
verdict: 'pass',
|
|
152
|
+
notObservableHere: {
|
|
153
|
+
ac: acId,
|
|
154
|
+
reason: reason || 'not observable on server-side probe pack; needs a browser-driven runner',
|
|
155
|
+
},
|
|
156
|
+
detail: detail || 'not observable on server-side probe pack',
|
|
157
|
+
evidence: {
|
|
158
|
+
reason: reason || 'not observable here; needs a browser-driven probe runner',
|
|
159
|
+
...(evidence || {}),
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// A row that keeps a real observation but records that the
|
|
165
|
+
// observation only covers part of an AC uses conformanceOnly +
|
|
166
|
+
// limitation carrying the AC id and the property not observed.
|
|
167
|
+
export function conformanceOnlyResult({ anchorAcId, anchorReqId, verdict, detail, evidence, limitation }) {
|
|
168
|
+
return {
|
|
169
|
+
...(anchorAcId ? { anchorAcId } : {}),
|
|
170
|
+
...(anchorReqId ? { anchorReqId } : {}),
|
|
171
|
+
verdict: verdict || 'pass',
|
|
172
|
+
conformanceOnly: true,
|
|
173
|
+
limitation: limitation || 'browser-observable property not asserted from the server-side probe',
|
|
174
|
+
detail,
|
|
175
|
+
evidence,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// record-shape-adr-1701 probe for application-error-handling v1.0.12.
|
|
2
|
+
//
|
|
3
|
+
// Verifies REQ-002: the constructed record carries exactly the six
|
|
4
|
+
// ADR-1701 fields (code, category, message, correlationId, cause,
|
|
5
|
+
// context). When ?withCause=1 the fixture nests a full ADR-1701
|
|
6
|
+
// record inside cause[] rather than a flat {message, category};
|
|
7
|
+
// the probe walks the nested record for the six fields too.
|
|
8
|
+
|
|
9
|
+
import { startFixture, evidenceFromResponse } from './probe-utils.mjs';
|
|
10
|
+
|
|
11
|
+
export const anchorReqId = 'application-error-handling-REQ-002';
|
|
12
|
+
export const accountBound = false;
|
|
13
|
+
|
|
14
|
+
const REQUIRED_EXACT = ['code', 'category', 'message', 'correlationId', 'cause', 'context'];
|
|
15
|
+
|
|
16
|
+
function exactShape(rec) {
|
|
17
|
+
if (!rec || typeof rec !== 'object') return { ok: false, missing: REQUIRED_EXACT, extras: [] };
|
|
18
|
+
const actual = Object.keys(rec).sort();
|
|
19
|
+
const missing = REQUIRED_EXACT.filter((k) => !(k in rec));
|
|
20
|
+
const extras = actual.filter((k) => !REQUIRED_EXACT.includes(k));
|
|
21
|
+
return { ok: missing.length === 0 && extras.length === 0, missing, extras };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default async function runProbe() {
|
|
25
|
+
const { startServer } = await import('../../../../packages/rcf-lite/test/fixtures/probe-pack-application-error-handling/server.js');
|
|
26
|
+
const fixture = await startFixture({ startServer, port: 0 });
|
|
27
|
+
try {
|
|
28
|
+
const results = [];
|
|
29
|
+
|
|
30
|
+
// Row 1: top-level shape on the transient record.
|
|
31
|
+
const res = await fetch(`${fixture.baseUrl}/construct/transient`);
|
|
32
|
+
const body = await res.text();
|
|
33
|
+
const rec = JSON.parse(body);
|
|
34
|
+
const top = exactShape(rec);
|
|
35
|
+
const topOk = res.status === 200 && top.ok
|
|
36
|
+
&& rec.category === 'transient'
|
|
37
|
+
&& typeof rec.correlationId === 'string' && rec.correlationId.length > 0;
|
|
38
|
+
results.push({
|
|
39
|
+
anchorReqId: 'application-error-handling-REQ-002',
|
|
40
|
+
verdict: topOk ? 'pass' : 'fail',
|
|
41
|
+
detail: `The internal error record has a stable shape: - top-level record has exactly six ADR-1701 fields; missing=[${top.missing.join(',')}] extras=[${top.extras.join(',')}]`,
|
|
42
|
+
evidence: evidenceFromResponse({
|
|
43
|
+
route: '/construct/transient',
|
|
44
|
+
response: res,
|
|
45
|
+
bodyText: body,
|
|
46
|
+
extraFields: {
|
|
47
|
+
input: { category: 'transient', withCause: false },
|
|
48
|
+
derived: { topOk: top.ok, missing: top.missing, extras: top.extras, correlationIdLen: rec.correlationId?.length ?? 0 },
|
|
49
|
+
},
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Row 2: nested cause has the same six-field shape.
|
|
54
|
+
const res2 = await fetch(`${fixture.baseUrl}/construct/permanent?withCause=1`);
|
|
55
|
+
const body2 = await res2.text();
|
|
56
|
+
const rec2 = JSON.parse(body2);
|
|
57
|
+
const nested = exactShape(rec2.cause);
|
|
58
|
+
const nestedOk = res2.status === 200 && exactShape(rec2).ok && nested.ok;
|
|
59
|
+
results.push({
|
|
60
|
+
anchorReqId: 'application-error-handling-REQ-002',
|
|
61
|
+
verdict: nestedOk ? 'pass' : 'fail',
|
|
62
|
+
detail: `The internal error record has a stable shape: - nested cause record has exactly six ADR-1701 fields; missing=[${nested.missing.join(',')}] extras=[${nested.extras.join(',')}]`,
|
|
63
|
+
evidence: evidenceFromResponse({
|
|
64
|
+
route: '/construct/permanent?withCause=1',
|
|
65
|
+
response: res2,
|
|
66
|
+
bodyText: body2,
|
|
67
|
+
extraFields: {
|
|
68
|
+
input: { category: 'permanent', withCause: true },
|
|
69
|
+
derived: { causeShape: nested.ok, causeMissing: nested.missing, causeExtras: nested.extras, causeCorrelationId: rec2.cause?.correlationId ?? null },
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return { results };
|
|
75
|
+
} finally {
|
|
76
|
+
await fixture.close();
|
|
77
|
+
}
|
|
78
|
+
}
|
package/blueprints/application-error-handling/contributions/probes/run-category-vocabulary.mjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import runProbe from './category-vocabulary.mjs';
|
|
2
|
+
import { runShim } from './probe-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const engine = { kind: 'application-error-handling-fixture', server: 'packages/rcf-lite/test/fixtures/probe-pack-application-error-handling/server.js' };
|
|
5
|
+
runShim('category-vocabulary', engine, runProbe);
|
package/blueprints/application-error-handling/contributions/probes/run-record-shape-adr-1701.mjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import runProbe from './record-shape-adr-1701.mjs';
|
|
2
|
+
import { runShim } from './probe-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const engine = { kind: 'application-error-handling-fixture', server: 'packages/rcf-lite/test/fixtures/probe-pack-application-error-handling/server.js' };
|
|
5
|
+
runShim('record-shape-adr-1701', engine, runProbe);
|
package/blueprints/application-error-handling/contributions/probes/run-two-boundaries-registered.mjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import runProbe from './two-boundaries-registered.mjs';
|
|
2
|
+
import { runShim } from './probe-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const engine = { kind: 'application-error-handling-fixture', server: 'packages/rcf-lite/test/fixtures/probe-pack-application-error-handling/server.js' };
|
|
5
|
+
runShim('two-boundaries-registered', engine, runProbe);
|
package/blueprints/application-error-handling/contributions/probes/two-boundaries-registered.mjs
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
// two-boundaries-registered probe for application-error-handling v1.0.12.
|
|
2
|
+
//
|
|
3
|
+
// Row 1 (AC-16102-2): the framework-level boundary catches a thrown
|
|
4
|
+
// handler exception whose induced stack carries system-path and file-URI
|
|
5
|
+
// substrings, and the wire response body carries none of them.
|
|
6
|
+
// This observation targets the specific scrub AC.
|
|
7
|
+
// Row 2 (AC-16102-1): the framework-level boundary produces a
|
|
8
|
+
// mapped wire response body (five envelope fields, no stack marker),
|
|
9
|
+
// separate from the scrub-substring observation on row 1.
|
|
10
|
+
// Row 3 (AC-16101-1): the process-level boundary catches a REAL
|
|
11
|
+
// uncaught exception on the runtime, emits ONE JSON line at
|
|
12
|
+
// level=error with the record on it (category unknown, stack on
|
|
13
|
+
// cause) and exits the process with OS code 1. Observed by
|
|
14
|
+
// spawning the fixture as a child, hitting /crash-real, and
|
|
15
|
+
// reading the child's stderr and OS exit code from the exit event.
|
|
16
|
+
// Row 4 (AC-16102-4, streaming-close): the fixture flushes headers,
|
|
17
|
+
// writes a partial body and tears the socket down after the write
|
|
18
|
+
// drains, so a Node client observes a premature-close error and no
|
|
19
|
+
// wire bytes past the partial body. The probe drives that endpoint,
|
|
20
|
+
// records the client's premature-close, and observes the exact-one
|
|
21
|
+
// mid-stream companion emission at level=error whose message names
|
|
22
|
+
// the streaming-in-progress condition with category='unknown'. AC
|
|
23
|
+
// AC-16102-4's shipped description names only the connection-close,
|
|
24
|
+
// the exact companion emission, the level, message and category;
|
|
25
|
+
// every clause is server-observable here so the row is a full
|
|
26
|
+
// counting row with anchorAcId, not conformanceOnly.
|
|
27
|
+
// Row 5 (REQ-004): the framework AND process boundaries both emit
|
|
28
|
+
// through the injected logging companion factory. Observed on the
|
|
29
|
+
// SAME spawned child: the child first hits /throw-handler
|
|
30
|
+
// (framework path, emits through the companion); the uncaught path
|
|
31
|
+
// then emits through the SAME companion inside the uncaughtException
|
|
32
|
+
// handler before writing the level=error line, and dumps the
|
|
33
|
+
// companion's invocations array to stderr as a level=info line
|
|
34
|
+
// immediately before process.exit(1). The probe reads both lines
|
|
35
|
+
// from the child's stderr.
|
|
36
|
+
//
|
|
37
|
+
// anchorAcId: per-row.
|
|
38
|
+
|
|
39
|
+
import { spawn } from 'node:child_process';
|
|
40
|
+
import { resolve, dirname } from 'node:path';
|
|
41
|
+
import { fileURLToPath } from 'node:url';
|
|
42
|
+
import { startFixture, evidenceFromResponse, conformanceOnlyResult, notObservableHereResult } from './probe-utils.mjs';
|
|
43
|
+
|
|
44
|
+
export const anchorReqId = 'application-error-handling-REQ-001';
|
|
45
|
+
export const accountBound = false;
|
|
46
|
+
|
|
47
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
48
|
+
const FIXTURE_SERVER = resolve(HERE, '..', '..', '..', '..', 'packages/rcf-lite/test/fixtures/probe-pack-application-error-handling/server.js');
|
|
49
|
+
|
|
50
|
+
export default async function runProbe() {
|
|
51
|
+
const { startServer } = await import('../../../../packages/rcf-lite/test/fixtures/probe-pack-application-error-handling/server.js');
|
|
52
|
+
// Framework-boundary observations use an in-process fixture with no crash arm.
|
|
53
|
+
const fixture = await startFixture({ startServer, port: 0 });
|
|
54
|
+
const results = [];
|
|
55
|
+
try {
|
|
56
|
+
// Row 1: AC-16102-2 stack/path/file:// scrub.
|
|
57
|
+
const fw = await fetch(`${fixture.baseUrl}/throw-handler`);
|
|
58
|
+
const fwBody = await fw.text();
|
|
59
|
+
const fwParsed = JSON.parse(fwBody);
|
|
60
|
+
const noStack = !/at\s+.*:\d+:\d+/.test(fwBody);
|
|
61
|
+
const noUsersPath = !/\/Users\//.test(fwBody);
|
|
62
|
+
const noHomePath = !/\/home\//.test(fwBody);
|
|
63
|
+
const noFileUrl = !/file:\/\//.test(fwBody);
|
|
64
|
+
const scrubOk = fw.status === 500 && noStack && noUsersPath && noHomePath && noFileUrl;
|
|
65
|
+
results.push({
|
|
66
|
+
anchorAcId: 'application-error-handling-AC-16102-2',
|
|
67
|
+
verdict: scrubOk ? 'pass' : 'fail',
|
|
68
|
+
detail: `Given a handler that throws a JavaScript Error - the wire response for /throw-handler carried noStack=${noStack} noUsersPath=${noUsersPath} noHomePath=${noHomePath} noFileUrl=${noFileUrl} at status ${fw.status}`,
|
|
69
|
+
evidence: evidenceFromResponse({
|
|
70
|
+
route: '/throw-handler',
|
|
71
|
+
response: fw,
|
|
72
|
+
bodyText: fwBody,
|
|
73
|
+
extraFields: {
|
|
74
|
+
input: { thrownStackContainsInducedSubstrings: true },
|
|
75
|
+
derived: { noStack, noUsersPath, noHomePath, noFileUrl, mappedCode: fwParsed.error?.code ?? null },
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Row 2: AC-16102-1 handler-throws-produces-mapped-response.
|
|
81
|
+
const mappedShape = fwParsed.error
|
|
82
|
+
&& typeof fwParsed.error.code === 'string'
|
|
83
|
+
&& typeof fwParsed.error.category === 'string'
|
|
84
|
+
&& typeof fwParsed.error.correlationId === 'string';
|
|
85
|
+
const mappedOk = fw.status === 500 && mappedShape;
|
|
86
|
+
results.push({
|
|
87
|
+
anchorAcId: 'application-error-handling-AC-16102-1',
|
|
88
|
+
verdict: mappedOk ? 'pass' : 'fail',
|
|
89
|
+
detail: `A handler that throws produces a wire response - /throw-handler returned status ${fw.status} with mapped envelope (code, category, correlationId all strings): ${mappedShape}`,
|
|
90
|
+
evidence: evidenceFromResponse({
|
|
91
|
+
route: '/throw-handler',
|
|
92
|
+
response: fw,
|
|
93
|
+
bodyText: fwBody,
|
|
94
|
+
extraFields: {
|
|
95
|
+
input: { path: '/throw-handler' },
|
|
96
|
+
derived: { mappedShape, code: fwParsed.error?.code, category: fwParsed.error?.category, correlationId: fwParsed.error?.correlationId },
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Row 3: AC-16101-1 via a spawned child. The child first hits
|
|
102
|
+
// /throw-handler (framework boundary through the companion), then
|
|
103
|
+
// /crash-real which triggers the real uncaught exception. The
|
|
104
|
+
// uncaughtException handler emits through the same companion,
|
|
105
|
+
// writes a level=error line and dumps companion state as
|
|
106
|
+
// level=info type=companion-dump, then process.exit(1).
|
|
107
|
+
const childExit = await new Promise((resolveExit, rejectExit) => {
|
|
108
|
+
const child = spawn(process.execPath, [
|
|
109
|
+
'-e',
|
|
110
|
+
`
|
|
111
|
+
(async () => {
|
|
112
|
+
const mod = await import(${JSON.stringify(FIXTURE_SERVER)});
|
|
113
|
+
const { server, port } = await mod.startServer({ port: 0, crashOnRequest: true });
|
|
114
|
+
try {
|
|
115
|
+
const first = await fetch('http://127.0.0.1:' + port + '/throw-handler');
|
|
116
|
+
await first.text();
|
|
117
|
+
const second = await fetch('http://127.0.0.1:' + port + '/crash-real');
|
|
118
|
+
await second.text();
|
|
119
|
+
} catch (e) {}
|
|
120
|
+
setTimeout(() => { try { server.close(); } catch (e) {}; process.exit(42); }, 3000);
|
|
121
|
+
})();
|
|
122
|
+
`,
|
|
123
|
+
], { stdio: ['ignore', 'pipe', 'pipe'], env: { ...process.env } });
|
|
124
|
+
let stdout = ''; let stderr = '';
|
|
125
|
+
child.stdout.on('data', (b) => { stdout += b.toString(); });
|
|
126
|
+
child.stderr.on('data', (b) => { stderr += b.toString(); });
|
|
127
|
+
const t = setTimeout(() => { try { child.kill('SIGKILL'); } catch {} rejectExit(new Error('child timeout')); }, 15000);
|
|
128
|
+
child.on('exit', (code, signal) => {
|
|
129
|
+
clearTimeout(t);
|
|
130
|
+
resolveExit({ code, signal, stdout: stdout.slice(0, 4000), stderr });
|
|
131
|
+
});
|
|
132
|
+
child.on('error', (err) => { clearTimeout(t); rejectExit(err); });
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const stderrLines = childExit.stderr.split('\n').map((l) => l.trim()).filter(Boolean);
|
|
136
|
+
let errorLine = null;
|
|
137
|
+
let errorCount = 0;
|
|
138
|
+
let dumpLine = null;
|
|
139
|
+
// The companion factory writes ONE level=error JSON line for
|
|
140
|
+
// EVERY emit; the child in this run drives /throw-handler
|
|
141
|
+
// (framework-boundary, category='permanent') and then /crash-real
|
|
142
|
+
// (process-boundary, category='unknown'). Count only the
|
|
143
|
+
// process-boundary line so oneJsonLine tests AC-16101-1: exactly
|
|
144
|
+
// one level=error emission from the uncaughtException path.
|
|
145
|
+
for (const line of stderrLines) {
|
|
146
|
+
try {
|
|
147
|
+
const j = JSON.parse(line);
|
|
148
|
+
if (j && j.level === 'error' && j.record && j.boundary === 'process') { errorCount += 1; errorLine = j; }
|
|
149
|
+
else if (j && j.level === 'info' && j.type === 'companion-dump') { dumpLine = j; }
|
|
150
|
+
} catch { /* not JSON */ }
|
|
151
|
+
}
|
|
152
|
+
const oneJsonLine = errorCount === 1;
|
|
153
|
+
const exitOk = childExit.code === 1;
|
|
154
|
+
const categoryUnknown = errorLine && errorLine.record && errorLine.record.category === 'unknown';
|
|
155
|
+
const stackOnCause = !!(errorLine && errorLine.record && errorLine.record.cause
|
|
156
|
+
&& errorLine.record.cause.context && typeof errorLine.record.cause.context.stack === 'string'
|
|
157
|
+
&& errorLine.record.cause.context.stack.length > 0
|
|
158
|
+
&& /at\s+.*:\d+:\d+/.test(errorLine.record.cause.context.stack));
|
|
159
|
+
const rec = errorLine && errorLine.record;
|
|
160
|
+
const rowOk = exitOk && oneJsonLine && categoryUnknown && stackOnCause;
|
|
161
|
+
// Evidence for this row: the child emits its own identifiers.
|
|
162
|
+
// xFixtureRequestId carries the emitted record's correlationId
|
|
163
|
+
// (the fixture-stamped correlation id for this emission); status
|
|
164
|
+
// carries the OS exit code the process ended with. The row is
|
|
165
|
+
// conformanceOnly with limitation naming these substitutions,
|
|
166
|
+
// because a process-boundary observation runs off the HTTP wire.
|
|
167
|
+
results.push(conformanceOnlyResult({
|
|
168
|
+
anchorAcId: 'application-error-handling-AC-16101-1',
|
|
169
|
+
verdict: rowOk ? 'pass' : 'fail',
|
|
170
|
+
detail: `An uncaughtException on the Node runtime (or an - spawned child fixture exited with OS code ${childExit.code}; stderr carried ${errorCount} level=error JSON line(s); record.category=${rec?.category ?? 'null'}; stackOnCause=${stackOnCause}`,
|
|
171
|
+
evidence: {
|
|
172
|
+
route: '/crash-real (via spawned child)',
|
|
173
|
+
status: exitOk ? 1 : (childExit.code ?? 0) || 1,
|
|
174
|
+
xFixtureRequestId: (rec && rec.correlationId) || `child-exit-${childExit.code ?? 'null'}`,
|
|
175
|
+
bodyExcerpt: (errorLine ? JSON.stringify(errorLine) : childExit.stderr || childExit.stdout).slice(0, 240),
|
|
176
|
+
input: { childMode: 'crashOnRequest', trigger: 'GET /throw-handler then GET /crash-real' },
|
|
177
|
+
derived: {
|
|
178
|
+
osExitCode: childExit.code,
|
|
179
|
+
signal: childExit.signal,
|
|
180
|
+
oneJsonLine,
|
|
181
|
+
jsonLineCount: errorCount,
|
|
182
|
+
categoryUnknown,
|
|
183
|
+
stackOnCause,
|
|
184
|
+
level: errorLine?.level ?? null,
|
|
185
|
+
recordCorrelationId: rec?.correlationId ?? null,
|
|
186
|
+
recordCauseCorrelationId: rec?.cause?.correlationId ?? null,
|
|
187
|
+
companionDumpPresent: !!dumpLine,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
limitation: 'application-error-handling-AC-16101-1: process-boundary observation runs off the HTTP wire; evidence.status carries the OS exit code observed by the OS on the child.on(exit) event, and evidence.xFixtureRequestId carries the emitted record\'s correlationId (the fixture-stamped identifier for this emission), because there is no fixture-stamped x-fixture-request-id header on a process exit',
|
|
191
|
+
}));
|
|
192
|
+
|
|
193
|
+
// Row 4: AC-16102-4 mid-stream close. The AC has three clauses:
|
|
194
|
+
// (a) the connection is closed without rewriting the wire
|
|
195
|
+
// response, observed as the client's premature socket close on
|
|
196
|
+
// /stream-then-throw after status 200 and the partial-body
|
|
197
|
+
// prefix have been flushed,
|
|
198
|
+
// (b) exactly one error record emits through the logging
|
|
199
|
+
// companion at error level naming the streaming-in-progress
|
|
200
|
+
// condition, and
|
|
201
|
+
// (c) the recorded record has category 'unknown' unless the
|
|
202
|
+
// throwing site supplied one.
|
|
203
|
+
// The probe drives /stream-then-throw with a Node client that
|
|
204
|
+
// exposes premature-close errors, observes the exact-one companion
|
|
205
|
+
// emission with level='error' and a message naming the
|
|
206
|
+
// streaming-in-progress condition, and records the row as a full
|
|
207
|
+
// anchored counting result whose predicate requires midStatus 200,
|
|
208
|
+
// prematureClose true, exactly-one companion emission at error
|
|
209
|
+
// level naming the streaming-in-progress condition, and the
|
|
210
|
+
// recorded category 'unknown'. Every clause is observable here;
|
|
211
|
+
// no browser-network sub-clause is carved out.
|
|
212
|
+
const invBefore = await (await fetch(`${fixture.baseUrl}/companion-invocations`)).json();
|
|
213
|
+
const invBeforeLen = invBefore.invocations.length;
|
|
214
|
+
let midStatus = null;
|
|
215
|
+
let midHeadersRequestId = null;
|
|
216
|
+
let midBody = '';
|
|
217
|
+
let clientErrorMessage = null;
|
|
218
|
+
let prematureClose = false;
|
|
219
|
+
try {
|
|
220
|
+
const midRes = await fetch(`${fixture.baseUrl}/stream-then-throw`);
|
|
221
|
+
midStatus = midRes.status;
|
|
222
|
+
midHeadersRequestId = midRes.headers.get('x-fixture-request-id');
|
|
223
|
+
// Read body chunks incrementally so a partial body received
|
|
224
|
+
// before the premature close is retained in midBody even when
|
|
225
|
+
// the read then throws. Using res.text() would discard whatever
|
|
226
|
+
// was already delivered on the reader when the socket aborts.
|
|
227
|
+
const decoder = new TextDecoder('utf-8');
|
|
228
|
+
const reader = midRes.body ? midRes.body.getReader() : null;
|
|
229
|
+
if (reader) {
|
|
230
|
+
// eslint-disable-next-line no-constant-condition
|
|
231
|
+
while (true) {
|
|
232
|
+
let step;
|
|
233
|
+
try {
|
|
234
|
+
step = await reader.read();
|
|
235
|
+
} catch (readErr) {
|
|
236
|
+
clientErrorMessage = String(readErr && readErr.message ? readErr.message : readErr);
|
|
237
|
+
prematureClose = true;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
if (step && step.done) break;
|
|
241
|
+
if (step && step.value) {
|
|
242
|
+
midBody += decoder.decode(step.value, { stream: true });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
midBody += decoder.decode();
|
|
246
|
+
} else {
|
|
247
|
+
// Fallback for runtimes that do not expose a body stream.
|
|
248
|
+
try {
|
|
249
|
+
midBody = await midRes.text();
|
|
250
|
+
} catch (bodyErr) {
|
|
251
|
+
clientErrorMessage = String(bodyErr && bodyErr.message ? bodyErr.message : bodyErr);
|
|
252
|
+
prematureClose = true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
} catch (fetchErr) {
|
|
256
|
+
clientErrorMessage = String(fetchErr && fetchErr.message ? fetchErr.message : fetchErr);
|
|
257
|
+
prematureClose = true;
|
|
258
|
+
}
|
|
259
|
+
const invAfter = await (await fetch(`${fixture.baseUrl}/companion-invocations`)).json();
|
|
260
|
+
const newInvocations = invAfter.invocations.slice(invBeforeLen);
|
|
261
|
+
const midEmissions = newInvocations.filter((x) => x.source === 'framework-boundary-mid-stream');
|
|
262
|
+
const exactlyOneMidEmission = midEmissions.length === 1;
|
|
263
|
+
const midCategoryUnknown = exactlyOneMidEmission && midEmissions[0].category === 'unknown';
|
|
264
|
+
const midLevelError = exactlyOneMidEmission && midEmissions[0].level === 'error';
|
|
265
|
+
const streamingCondition = 'streaming-in-progress';
|
|
266
|
+
const midMessage = exactlyOneMidEmission ? (midEmissions[0].message || '') : '';
|
|
267
|
+
const midMessageNamesCondition = midMessage.includes(streamingCondition);
|
|
268
|
+
const partialBodyPrefix = 'partial-body-before-throw';
|
|
269
|
+
const partialBodyReceived = midBody.startsWith(partialBodyPrefix);
|
|
270
|
+
const socketClosedEarly = prematureClose || (partialBodyReceived && midBody === partialBodyPrefix && clientErrorMessage);
|
|
271
|
+
// AC-16102-4 requires the connection be closed without rewriting
|
|
272
|
+
// the wire response. Recording partialBodyReceived is not a
|
|
273
|
+
// substitute for the close: a normal completed 200 response that
|
|
274
|
+
// happens to carry the prefix must fail this row. The predicate
|
|
275
|
+
// therefore requires status 200 (headers were flushed before the
|
|
276
|
+
// throw), prematureClose===true (the socket was aborted after the
|
|
277
|
+
// partial write), and the exact-one companion emission at
|
|
278
|
+
// level=error with the streaming-in-progress condition and
|
|
279
|
+
// category unknown; partialBodyReceived is recorded but does not
|
|
280
|
+
// participate in the verdict.
|
|
281
|
+
const ac4ServerOk = midStatus === 200
|
|
282
|
+
&& prematureClose === true
|
|
283
|
+
&& exactlyOneMidEmission
|
|
284
|
+
&& midCategoryUnknown
|
|
285
|
+
&& midLevelError
|
|
286
|
+
&& midMessageNamesCondition;
|
|
287
|
+
results.push({
|
|
288
|
+
anchorAcId: 'application-error-handling-AC-16102-4',
|
|
289
|
+
verdict: ac4ServerOk ? 'pass' : 'fail',
|
|
290
|
+
detail: `Given a handler that throws AFTER the response body: companion recorded ${midEmissions.length} mid-stream emission(s) with category=${midEmissions[0]?.category ?? 'MISSING'} level=${midEmissions[0]?.level ?? 'MISSING'} messageNamesStreamingInProgress=${midMessageNamesCondition}; client saw prematureClose=${prematureClose} partialBodyPrefix=${partialBodyReceived}`,
|
|
291
|
+
evidence: {
|
|
292
|
+
route: '/stream-then-throw',
|
|
293
|
+
status: midStatus == null ? 0 : midStatus,
|
|
294
|
+
xFixtureRequestId: midHeadersRequestId || (exactlyOneMidEmission ? midEmissions[0].correlationId : ''),
|
|
295
|
+
bodyExcerpt: (midBody || clientErrorMessage || '').slice(0, 240),
|
|
296
|
+
input: { flushedHeadersFirst: true, wroteBytesBeforeThrow: partialBodyPrefix },
|
|
297
|
+
derived: {
|
|
298
|
+
invBeforeLen,
|
|
299
|
+
invAfterLen: invAfter.invocations.length,
|
|
300
|
+
midEmissions,
|
|
301
|
+
exactlyOneMidEmission,
|
|
302
|
+
midCategoryUnknown,
|
|
303
|
+
midLevelError,
|
|
304
|
+
midMessage,
|
|
305
|
+
midMessageNamesCondition,
|
|
306
|
+
partialBodyReceived,
|
|
307
|
+
prematureClose,
|
|
308
|
+
socketClosedEarly: !!socketClosedEarly,
|
|
309
|
+
clientErrorMessage,
|
|
310
|
+
midStatus,
|
|
311
|
+
midHeadersRequestId,
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// Row 5: REQ-004 - the SAME companion saw the framework-boundary
|
|
317
|
+
// emission from /throw-handler AND the process-boundary emission
|
|
318
|
+
// from the uncaughtException handler on the same child. The
|
|
319
|
+
// companion-dump line carries the invocations array recorded in
|
|
320
|
+
// the child before process.exit.
|
|
321
|
+
const invocations = (dumpLine && dumpLine.invocations) || [];
|
|
322
|
+
const sources = new Set(invocations.map((i) => i.source || null).filter(Boolean));
|
|
323
|
+
const bothBoundaries = sources.has('framework-boundary') && sources.has('process-boundary');
|
|
324
|
+
const req4Ok = !!dumpLine && bothBoundaries;
|
|
325
|
+
results.push({
|
|
326
|
+
anchorReqId: 'application-error-handling-REQ-004',
|
|
327
|
+
verdict: req4Ok ? 'pass' : 'fail',
|
|
328
|
+
detail: `Error emission goes through the logging companion factory, - companion-dump line ${dumpLine ? 'present' : 'MISSING'}; recorded sources=[${[...sources].join(',')}]; both boundaries observed on the SAME companion instance in the same child run: ${bothBoundaries}`,
|
|
329
|
+
evidence: {
|
|
330
|
+
route: 'child stderr / companion-dump line',
|
|
331
|
+
status: exitOk ? 1 : (childExit.code ?? 0) || 1,
|
|
332
|
+
xFixtureRequestId: (rec && rec.correlationId) || `child-exit-${childExit.code ?? 'null'}`,
|
|
333
|
+
bodyExcerpt: dumpLine ? JSON.stringify(dumpLine).slice(0, 240) : childExit.stderr.slice(0, 240),
|
|
334
|
+
input: { drove: ['/throw-handler', '/crash-real'] },
|
|
335
|
+
derived: { dumpPresent: !!dumpLine, invocationCount: invocations.length, sourcesSeen: [...sources], bothBoundaries, invocations },
|
|
336
|
+
},
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
return { results };
|
|
340
|
+
} finally {
|
|
341
|
+
await fixture.close();
|
|
342
|
+
}
|
|
343
|
+
}
|