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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"slug": "application-spa",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.11",
|
|
4
4
|
"category": "application",
|
|
5
5
|
"contributions": [
|
|
6
6
|
{
|
|
@@ -415,5 +415,6 @@
|
|
|
415
415
|
"role": "errorHandling",
|
|
416
416
|
"reason": "The browser-facing error boundary constructs the internal record from a client-side exception and hands it to the applied transport writer; an error-handling companion supplies the boundary and the record factory the SPA composes on."
|
|
417
417
|
}
|
|
418
|
-
]
|
|
418
|
+
],
|
|
419
|
+
"updatedAt": "2026-09-11T16:04:17Z"
|
|
419
420
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"version": "1.1.1",
|
|
6
6
|
"status": "accepted",
|
|
7
7
|
"title": "Semantic design tokens as CSS custom properties with a root-level theme switch",
|
|
8
|
-
"context": "Dark and light parity is a
|
|
8
|
+
"context": "Dark and light parity is a shipped requirement (application-spa-REQ-005). Parity is only checkable when every colour decision routes through a named token that exists in both palettes. How theming is realised is a whole-project decision: two theming mechanisms cannot coexist without drift. A declared discipline is not the same as a compelled one: raw palette values can sit in component stylesheets across passing build cycles. The token-adherence gate enforces token parity so a violation refuses ship at gate time.",
|
|
9
9
|
"decision": "The token layer in assets/tokens/design-tokens.json is the single source of colour, spacing, radius, typography, elevation, and motion values. Tokens are realised as CSS custom properties on the document root (assets/tokens/theme.css); the active theme is a data-theme attribute swap. Components consume semantic tokens only; raw palette values in component styles are a defect.",
|
|
10
10
|
"consequences": "Theme parity and contrast become data checks over one JSON file. Re-skinning is a token edit. The indirection cost is one layer of naming; the working agent extends tokens by adding pairs, never by inlining values. The v1.1 token-adherence probe (TAC-207-application-spa-token-adherence-probe) is the runtime-observable handle the ship gate exercises: the probe scans the built stylesheet output for raw colour literals outside the token-realisation file and diffs the light and dark token key sets, and exits non-zero on any violation. When the probe is wired as a delivery-ci-workflows gate (TAC-701), a violation refuses ship through the ordinary gate-failure path.",
|
|
11
11
|
"alternativesConsidered": [
|
package/blueprints/application-spa/contributions/adrs/adr-206-application-spa-iconography.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"version": "1.1.1",
|
|
6
6
|
"status": "accepted",
|
|
7
7
|
"title": "One icon set behind semantic aliases",
|
|
8
|
-
"context": "application-spa-REQ-011 requires a single icon set. Which construction (stroke width, grid) and how components reference icons needs one recorded answer inside the SPA.
|
|
8
|
+
"context": "application-spa-REQ-011 requires a single icon set. Which construction (stroke width, grid) and how components reference icons needs one recorded answer inside the SPA. A recorded discipline is not the same as a compelled one: raw inline SVG can sit outside the registry across passing build cycles. The icon-adherence gate enforces registry use so a violation refuses ship at gate time.",
|
|
9
9
|
"decision": "The project selects exactly one icon set (consistent stroke and grid across all glyphs) and components reference icons only through semantic aliases (icon.close, icon.danger, icon.search, and peers) declared in one registry. Bespoke per-component artwork requires extending the registry, not inlining SVG.",
|
|
10
10
|
"consequences": "Swapping icon sets is a registry edit. Decorative versus meaningful icon semantics get one enforcement point for the application-spa-REQ-019 naming rules. The v1.1 icon-adherence probe (TAC-208-application-spa-icon-adherence-probe) is the runtime-observable handle the ship gate exercises: the probe scans the component source for inline SVG outside the registry and for icon references naming aliases the registry does not declare, and exits non-zero on any violation. When the probe is wired as a delivery-ci-workflows gate (TAC-701), a violation refuses ship through the ordinary gate-failure path.",
|
|
11
11
|
"createdAt": "2026-08-19T09:00:00Z",
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// designed-empty-state probe for application-spa v1.5.11.
|
|
2
|
+
//
|
|
3
|
+
// Verifies AC-1117-1: every data-bearing route renders a designed
|
|
4
|
+
// loading, empty, error and success state (not a generic frame).
|
|
5
|
+
// The probe drives every data-bearing route through each of the
|
|
6
|
+
// four state values via ?state= and asserts the state-specific
|
|
7
|
+
// region markers.
|
|
8
|
+
//
|
|
9
|
+
// anchorAcId: application-spa-AC-1117-1.
|
|
10
|
+
|
|
11
|
+
import { startFixture, evidenceFromResponse } from './probe-utils.mjs';
|
|
12
|
+
|
|
13
|
+
export const anchorReqId = 'application-spa-REQ-010';
|
|
14
|
+
export const accountBound = false;
|
|
15
|
+
|
|
16
|
+
const STATES = ['loading', 'empty', 'error', 'success'];
|
|
17
|
+
|
|
18
|
+
function stateMarkers(state) {
|
|
19
|
+
if (state === 'loading') return { attr: /data-route-state="loading"/, region: /aria-busy="true"/ };
|
|
20
|
+
if (state === 'empty') return { attr: /data-route-state="empty"/, region: /data-empty-state=/ };
|
|
21
|
+
if (state === 'error') return { attr: /data-route-state="error"/, region: /data-state="error"/ };
|
|
22
|
+
return { attr: /data-route-state="success"/, region: /data-state="success"/ };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default async function runProbe() {
|
|
26
|
+
const { startServer } = await import('../../../../packages/rcf-lite/test/fixtures/probe-pack-application-spa/server.js');
|
|
27
|
+
const fixture = await startFixture({ startServer, port: 0 });
|
|
28
|
+
try {
|
|
29
|
+
const results = [];
|
|
30
|
+
|
|
31
|
+
const routesRes = await fetch(`${fixture.baseUrl}/__routes`);
|
|
32
|
+
const routesJson = JSON.parse(await routesRes.text());
|
|
33
|
+
const dataBearing = (routesJson.routes || []).filter((r) => r.dataBearing);
|
|
34
|
+
|
|
35
|
+
const matrix = {};
|
|
36
|
+
let allPass = true;
|
|
37
|
+
let lastRes = null, lastBody = null, lastRoute = null;
|
|
38
|
+
for (const r of dataBearing) {
|
|
39
|
+
matrix[r.path] = {};
|
|
40
|
+
for (const state of STATES) {
|
|
41
|
+
const res = await fetch(`${fixture.baseUrl}${r.path}?state=${state}`);
|
|
42
|
+
const body = await res.text();
|
|
43
|
+
lastRes = res; lastBody = body; lastRoute = `${r.path}?state=${state}`;
|
|
44
|
+
const markers = stateMarkers(state);
|
|
45
|
+
const attrOk = markers.attr.test(body);
|
|
46
|
+
const regionOk = markers.region.test(body);
|
|
47
|
+
const pass = res.status === 200 && attrOk && regionOk;
|
|
48
|
+
matrix[r.path][state] = { status: res.status, attrOk, regionOk, pass };
|
|
49
|
+
if (!pass) allPass = false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const overallPass = allPass && dataBearing.length > 0;
|
|
53
|
+
results.push({
|
|
54
|
+
anchorAcId: 'application-spa-AC-1117-1',
|
|
55
|
+
anchorReqId: 'application-spa-REQ-010',
|
|
56
|
+
verdict: overallPass ? 'pass' : 'fail',
|
|
57
|
+
detail: `Every data-bearing route renders designed loading, empty, error, - drove ${dataBearing.length} data-bearing routes through 4 states each (${dataBearing.length * 4} observations); all state markers present: ${allPass}`,
|
|
58
|
+
evidence: evidenceFromResponse({
|
|
59
|
+
route: lastRoute || '/reports?state=empty',
|
|
60
|
+
response: lastRes,
|
|
61
|
+
bodyText: lastBody,
|
|
62
|
+
extraFields: {
|
|
63
|
+
input: { dataBearingPaths: dataBearing.map((r) => r.path), states: STATES },
|
|
64
|
+
derived: { matrix, allPass },
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
return { results };
|
|
69
|
+
} finally {
|
|
70
|
+
await fixture.close();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Shared helpers for application-spa probes.
|
|
2
|
+
//
|
|
3
|
+
// The engine under probe is the sample-app fixture at
|
|
4
|
+
// packages/rcf-lite/test/fixtures/probe-pack-application-spa/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-spa');
|
|
23
|
+
export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/application-spa');
|
|
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-spa',
|
|
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,185 @@
|
|
|
1
|
+
// route-inventory-published probe for application-spa v1.5.11.
|
|
2
|
+
//
|
|
3
|
+
// Verifies AC-1101-1: the project maintains a declared route
|
|
4
|
+
// inventory naming every route AND no navigable surface exists
|
|
5
|
+
// outside it. To rule out fixture self-agreement the probe drives
|
|
6
|
+
// two independent inputs it controls:
|
|
7
|
+
//
|
|
8
|
+
// Run A: routes = [/, /alpha, /beta]
|
|
9
|
+
// Run B: routes = [/, /gamma, /delta, /epsilon]
|
|
10
|
+
//
|
|
11
|
+
// For each run the probe reads /__routes and /__mounted and
|
|
12
|
+
// checks both endpoints reflect the injected input verbatim,
|
|
13
|
+
// then crawls every declared path (expects 200) and every path
|
|
14
|
+
// from the OTHER run's set that is NOT in the current set (expects
|
|
15
|
+
// 404). If /__routes or /__mounted diverged from the injected
|
|
16
|
+
// input, or if a path outside the input responded 200, the row
|
|
17
|
+
// fails. The two runs together establish input-driven variation.
|
|
18
|
+
//
|
|
19
|
+
// anchorAcId: application-spa-AC-1101-1.
|
|
20
|
+
|
|
21
|
+
import { startFixture, evidenceFromResponse, conformanceOnlyResult } from './probe-utils.mjs';
|
|
22
|
+
|
|
23
|
+
export const anchorReqId = 'application-spa-REQ-001';
|
|
24
|
+
export const accountBound = false;
|
|
25
|
+
|
|
26
|
+
const RUN_A_ROUTES = [
|
|
27
|
+
{ path: '/', name: 'landing', state: 'populated', dataBearing: false },
|
|
28
|
+
{ path: '/alpha', name: 'alpha', state: 'populated', dataBearing: true },
|
|
29
|
+
{ path: '/beta', name: 'beta', state: 'populated', dataBearing: false },
|
|
30
|
+
];
|
|
31
|
+
const RUN_B_ROUTES = [
|
|
32
|
+
{ path: '/', name: 'landing', state: 'populated', dataBearing: false },
|
|
33
|
+
{ path: '/gamma', name: 'gamma', state: 'populated', dataBearing: true },
|
|
34
|
+
{ path: '/delta', name: 'delta', state: 'populated', dataBearing: false },
|
|
35
|
+
{ path: '/epsilon', name: 'epsilon', state: 'empty', dataBearing: true },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
async function runOne(routeSet, otherSet) {
|
|
39
|
+
const { startServer } = await import('../../../../packages/rcf-lite/test/fixtures/probe-pack-application-spa/server.js');
|
|
40
|
+
const fixture = await startFixture({ startServer: (opts) => startServer({ ...opts, routes: routeSet }), port: 0 });
|
|
41
|
+
try {
|
|
42
|
+
const declaredPaths = routeSet.map((r) => r.path);
|
|
43
|
+
const routesRes = await fetch(`${fixture.baseUrl}/__routes`);
|
|
44
|
+
const routesBody = await routesRes.text();
|
|
45
|
+
const routesJson = JSON.parse(routesBody);
|
|
46
|
+
const routesPaths = (routesJson.routes || []).map((r) => r.path);
|
|
47
|
+
|
|
48
|
+
const mountedRes = await fetch(`${fixture.baseUrl}/__mounted`);
|
|
49
|
+
const mountedBody = await mountedRes.text();
|
|
50
|
+
const mountedJson = JSON.parse(mountedBody);
|
|
51
|
+
const mountedPaths = mountedJson.paths || [];
|
|
52
|
+
|
|
53
|
+
const perPath = {};
|
|
54
|
+
for (const p of declaredPaths) {
|
|
55
|
+
const r = await fetch(`${fixture.baseUrl}${p}`);
|
|
56
|
+
const body = await r.text();
|
|
57
|
+
perPath[p] = { status: r.status, ok: r.status === 200 && /<main[^>]+data-route=/.test(body) };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Paths NOT in the injected inventory must 404. We take them
|
|
61
|
+
// from the OTHER run's set (minus paths shared with this run).
|
|
62
|
+
const shared = new Set(declaredPaths);
|
|
63
|
+
const outsidePaths = otherSet.map((r) => r.path).filter((p) => !shared.has(p));
|
|
64
|
+
const perOutside = {};
|
|
65
|
+
for (const p of outsidePaths) {
|
|
66
|
+
const r = await fetch(`${fixture.baseUrl}${p}`);
|
|
67
|
+
await r.text();
|
|
68
|
+
perOutside[p] = { status: r.status, ok: r.status === 404 };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const routesMatchInput = declaredPaths.length === routesPaths.length && declaredPaths.every((p) => routesPaths.includes(p));
|
|
72
|
+
const mountedMatchInput = declaredPaths.length === mountedPaths.length && declaredPaths.every((p) => mountedPaths.includes(p));
|
|
73
|
+
const declaredAll200 = Object.values(perPath).every((v) => v.ok);
|
|
74
|
+
const outsideAll404 = Object.values(perOutside).every((v) => v.ok);
|
|
75
|
+
return {
|
|
76
|
+
routesRes,
|
|
77
|
+
routesBody,
|
|
78
|
+
mountedRes,
|
|
79
|
+
mountedBody,
|
|
80
|
+
declaredPaths,
|
|
81
|
+
routesPaths,
|
|
82
|
+
mountedPaths,
|
|
83
|
+
outsidePaths,
|
|
84
|
+
perPath,
|
|
85
|
+
perOutside,
|
|
86
|
+
routesMatchInput,
|
|
87
|
+
mountedMatchInput,
|
|
88
|
+
declaredAll200,
|
|
89
|
+
outsideAll404,
|
|
90
|
+
};
|
|
91
|
+
} finally {
|
|
92
|
+
await fixture.close();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default async function runProbe() {
|
|
97
|
+
const results = [];
|
|
98
|
+
const runA = await runOne(RUN_A_ROUTES, RUN_B_ROUTES);
|
|
99
|
+
const runB = await runOne(RUN_B_ROUTES, RUN_A_ROUTES);
|
|
100
|
+
|
|
101
|
+
const bothMatchInput = runA.routesMatchInput && runA.mountedMatchInput && runB.routesMatchInput && runB.mountedMatchInput;
|
|
102
|
+
const bothDeclared200 = runA.declaredAll200 && runB.declaredAll200;
|
|
103
|
+
const bothOutside404 = runA.outsideAll404 && runB.outsideAll404;
|
|
104
|
+
const pass = bothMatchInput && bothDeclared200 && bothOutside404;
|
|
105
|
+
|
|
106
|
+
results.push({
|
|
107
|
+
anchorAcId: 'application-spa-AC-1101-1',
|
|
108
|
+
anchorReqId: 'application-spa-REQ-001',
|
|
109
|
+
verdict: pass ? 'pass' : 'fail',
|
|
110
|
+
detail: `The project maintains a declared route inventory naming every route; no navigable surface exists outside it - runA(${runA.declaredPaths.join(',')}) routes=${runA.routesMatchInput} mounted=${runA.mountedMatchInput} declared200=${runA.declaredAll200} outside404=${runA.outsideAll404}; runB(${runB.declaredPaths.join(',')}) routes=${runB.routesMatchInput} mounted=${runB.mountedMatchInput} declared200=${runB.declaredAll200} outside404=${runB.outsideAll404}`,
|
|
111
|
+
evidence: evidenceFromResponse({
|
|
112
|
+
route: '/__routes (runA)',
|
|
113
|
+
response: runA.routesRes,
|
|
114
|
+
bodyText: runA.routesBody,
|
|
115
|
+
extraFields: {
|
|
116
|
+
input: {
|
|
117
|
+
runARoutes: RUN_A_ROUTES.map((r) => r.path),
|
|
118
|
+
runBRoutes: RUN_B_ROUTES.map((r) => r.path),
|
|
119
|
+
},
|
|
120
|
+
derived: {
|
|
121
|
+
runA: {
|
|
122
|
+
routesPaths: runA.routesPaths,
|
|
123
|
+
mountedPaths: runA.mountedPaths,
|
|
124
|
+
routesMatchInput: runA.routesMatchInput,
|
|
125
|
+
mountedMatchInput: runA.mountedMatchInput,
|
|
126
|
+
perPath: runA.perPath,
|
|
127
|
+
outsidePaths: runA.outsidePaths,
|
|
128
|
+
perOutside: runA.perOutside,
|
|
129
|
+
},
|
|
130
|
+
runB: {
|
|
131
|
+
routesPaths: runB.routesPaths,
|
|
132
|
+
mountedPaths: runB.mountedPaths,
|
|
133
|
+
routesMatchInput: runB.routesMatchInput,
|
|
134
|
+
mountedMatchInput: runB.mountedMatchInput,
|
|
135
|
+
perPath: runB.perPath,
|
|
136
|
+
outsidePaths: runB.outsidePaths,
|
|
137
|
+
perOutside: runB.perOutside,
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
altBodyExcerpt: runB.routesBody.slice(0, 240),
|
|
141
|
+
},
|
|
142
|
+
}),
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Second row: shell <meta name="route-inventory"> agrees with
|
|
146
|
+
// /__routes and /__mounted under run A. This observation covers
|
|
147
|
+
// only a same-run agreement slice of AC-1101-1 (route-inventory
|
|
148
|
+
// completeness across the app) and is emitted as conformanceOnly
|
|
149
|
+
// anchored on AC-1101-1 with a limitation naming the property the
|
|
150
|
+
// slice does not observe. The first row already carries the full
|
|
151
|
+
// positive AC-1101-1 observation across two injected sets.
|
|
152
|
+
const { startServer } = await import('../../../../packages/rcf-lite/test/fixtures/probe-pack-application-spa/server.js');
|
|
153
|
+
const fixture = await startFixture({ startServer: (opts) => startServer({ ...opts, routes: RUN_A_ROUTES }), port: 0 });
|
|
154
|
+
let shellRes; let shellBody; let shellPaths = []; let shellAgreesJson = false; let shellAgreesMounted = false;
|
|
155
|
+
try {
|
|
156
|
+
shellRes = await fetch(`${fixture.baseUrl}/`);
|
|
157
|
+
shellBody = await shellRes.text();
|
|
158
|
+
const metaMatch = shellBody.match(/<meta name="route-inventory" content="([^"]+)"/);
|
|
159
|
+
shellPaths = metaMatch ? metaMatch[1].split(',') : [];
|
|
160
|
+
const declaredSet = new Set(RUN_A_ROUTES.map((r) => r.path));
|
|
161
|
+
shellAgreesJson = shellPaths.length === RUN_A_ROUTES.length && shellPaths.every((p) => declaredSet.has(p));
|
|
162
|
+
shellAgreesMounted = shellPaths.every((p) => runA.mountedPaths.includes(p));
|
|
163
|
+
} finally {
|
|
164
|
+
await fixture.close();
|
|
165
|
+
}
|
|
166
|
+
const agreeAll = shellAgreesJson && shellAgreesMounted;
|
|
167
|
+
results.push(conformanceOnlyResult({
|
|
168
|
+
anchorAcId: 'application-spa-AC-1101-1',
|
|
169
|
+
anchorReqId: 'application-spa-REQ-001',
|
|
170
|
+
verdict: agreeAll ? 'pass' : 'fail',
|
|
171
|
+
detail: `The project maintains a declared route inventory naming every route - same-run agreement slice: shell <meta name="route-inventory"> ${shellPaths.join(',')} agrees with /__routes JSON: ${shellAgreesJson} and /__mounted: ${shellAgreesMounted}`,
|
|
172
|
+
evidence: evidenceFromResponse({
|
|
173
|
+
route: '/',
|
|
174
|
+
response: shellRes,
|
|
175
|
+
bodyText: shellBody,
|
|
176
|
+
extraFields: {
|
|
177
|
+
input: { shellMetaPaths: shellPaths, injectedRoutes: RUN_A_ROUTES.map((r) => r.path) },
|
|
178
|
+
derived: { shellAgreesJson, shellAgreesMounted, agreeAll },
|
|
179
|
+
},
|
|
180
|
+
}),
|
|
181
|
+
limitation: 'application-spa-AC-1101-1: this row observes only same-run agreement between the shell meta, /__routes and /__mounted for one injected set; the AC also requires that no navigable surface exists outside the declared inventory, which the first AC-1101-1 row observes by injecting two independent route sets and confirming outsiders return 404',
|
|
182
|
+
}));
|
|
183
|
+
|
|
184
|
+
return { results };
|
|
185
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import runProbe from './designed-empty-state.mjs';
|
|
2
|
+
import { runShim } from './probe-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const engine = { kind: 'application-spa-fixture', server: 'packages/rcf-lite/test/fixtures/probe-pack-application-spa/server.js' };
|
|
5
|
+
runShim('designed-empty-state', engine, runProbe);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import runProbe from './route-inventory-published.mjs';
|
|
2
|
+
import { runShim } from './probe-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const engine = { kind: 'application-spa-fixture', server: 'packages/rcf-lite/test/fixtures/probe-pack-application-spa/server.js' };
|
|
5
|
+
runShim('route-inventory-published', engine, runProbe);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import runProbe from './shell-nav-present.mjs';
|
|
2
|
+
import { runShim } from './probe-utils.mjs';
|
|
3
|
+
|
|
4
|
+
const engine = { kind: 'application-spa-fixture', server: 'packages/rcf-lite/test/fixtures/probe-pack-application-spa/server.js' };
|
|
5
|
+
runShim('shell-nav-present', engine, runProbe);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// shell-nav-present probe for application-spa v1.5.11.
|
|
2
|
+
//
|
|
3
|
+
// Verifies AC-1102-1: navigation renders on every route (not only
|
|
4
|
+
// the shell root). The probe crawls every declared inventory path,
|
|
5
|
+
// GETs each, and asserts the primary <nav> block appears in every
|
|
6
|
+
// rendered page with one link per inventory entry.
|
|
7
|
+
//
|
|
8
|
+
// anchorAcId: application-spa-AC-1102-1.
|
|
9
|
+
|
|
10
|
+
import { startFixture, evidenceFromResponse } from './probe-utils.mjs';
|
|
11
|
+
|
|
12
|
+
export const anchorReqId = 'application-spa-REQ-002';
|
|
13
|
+
export const accountBound = false;
|
|
14
|
+
|
|
15
|
+
export default async function runProbe() {
|
|
16
|
+
const { startServer } = await import('../../../../packages/rcf-lite/test/fixtures/probe-pack-application-spa/server.js');
|
|
17
|
+
const fixture = await startFixture({ startServer, port: 0 });
|
|
18
|
+
try {
|
|
19
|
+
const results = [];
|
|
20
|
+
|
|
21
|
+
const routesRes = await fetch(`${fixture.baseUrl}/__routes`);
|
|
22
|
+
const routesJson = JSON.parse(await routesRes.text());
|
|
23
|
+
const inventory = routesJson.routes || [];
|
|
24
|
+
const inventoryNames = inventory.map((r) => r.name);
|
|
25
|
+
|
|
26
|
+
const perRoute = {};
|
|
27
|
+
let allPerRoutePass = true;
|
|
28
|
+
let firstFailBody = '';
|
|
29
|
+
let lastRoute = null;
|
|
30
|
+
let lastBody = null;
|
|
31
|
+
let lastRes = null;
|
|
32
|
+
|
|
33
|
+
for (const r of inventory) {
|
|
34
|
+
const shellRes = await fetch(`${fixture.baseUrl}${r.path}`);
|
|
35
|
+
const body = await shellRes.text();
|
|
36
|
+
lastRes = shellRes; lastBody = body; lastRoute = r.path;
|
|
37
|
+
const navMatch = body.match(/<nav[^>]+aria-label="Primary"[^>]+data-region="primary-nav"[^>]*>([\s\S]*?)<\/nav>/);
|
|
38
|
+
const hasNav = !!navMatch;
|
|
39
|
+
const linksInNav = hasNav
|
|
40
|
+
? Array.from(navMatch[1].matchAll(/data-route-name="([^"]+)"/g)).map((m) => m[1])
|
|
41
|
+
: [];
|
|
42
|
+
const linksParity = linksInNav.length === inventoryNames.length
|
|
43
|
+
&& inventoryNames.every((n) => linksInNav.includes(n));
|
|
44
|
+
const routePass = shellRes.status === 200 && hasNav && linksParity;
|
|
45
|
+
perRoute[r.path] = { status: shellRes.status, hasNav, linksInNav, routePass };
|
|
46
|
+
if (!routePass) { allPerRoutePass = false; if (!firstFailBody) firstFailBody = body.slice(0, 240); }
|
|
47
|
+
}
|
|
48
|
+
const pass = allPerRoutePass && inventory.length > 0;
|
|
49
|
+
|
|
50
|
+
results.push({
|
|
51
|
+
anchorAcId: 'application-spa-AC-1102-1',
|
|
52
|
+
anchorReqId: 'application-spa-REQ-002',
|
|
53
|
+
verdict: pass ? 'pass' : 'fail',
|
|
54
|
+
detail: `Top navigation renders on every route from the - primary <nav aria-label="Primary"> renders on all ${Object.keys(perRoute).length} routes; every route carries links [${inventoryNames.join(',')}]`,
|
|
55
|
+
evidence: evidenceFromResponse({
|
|
56
|
+
route: lastRoute || '/',
|
|
57
|
+
response: lastRes,
|
|
58
|
+
bodyText: lastBody,
|
|
59
|
+
extraFields: {
|
|
60
|
+
input: { inventoryPaths: inventory.map((r) => r.path), inventoryNames },
|
|
61
|
+
derived: { perRoute, allRoutesRenderNav: allPerRoutePass, firstFailBody },
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
return { results };
|
|
66
|
+
} finally {
|
|
67
|
+
await fixture.close();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"version": "1.0.1",
|
|
6
6
|
"status": "approved",
|
|
7
7
|
"name": "Token adherence probe",
|
|
8
|
-
"purpose": "The runtime-observable enforcement handle for the ADR-202 theming discipline. The blueprint declares that component styles consume semantic tokens only, that raw palette values are a defect, and that every light token has a declared dark counterpart (application-spa-REQ-005, US-1106).
|
|
8
|
+
"purpose": "The runtime-observable enforcement handle for the ADR-202 theming discipline. The blueprint declares that component styles consume semantic tokens only, that raw palette values are a defect, and that every light token has a declared dark counterpart (application-spa-REQ-005, US-1106). This TAC is the project-realised probe that inspects the built stylesheet output plus the design-tokens JSON, refuses at non-zero exit on any raw palette literal outside the token-realisation file or any missing light/dark counterpart, and writes a stable JSON report the delivery-ci-workflows aggregate report can name.",
|
|
9
9
|
"responsibilities": [
|
|
10
10
|
"Expose a Node entry point (a single `.js` or `.mjs` file) invocable as `node <path>` with no shell glue; the entry point path is stable and recorded on the aggregate report's `runner.entryPoint` field when this probe is wired as a delivery-ci-workflows gate (AC-1129-1, AC-1129-4).",
|
|
11
11
|
"Read the design tokens source at a configured path (default `assets/tokens/design-tokens.json` per ADR-202) and enumerate the semantic token key sets for both themes (AC-1129-2).",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"version": "1.0.1",
|
|
6
6
|
"status": "approved",
|
|
7
7
|
"name": "Icon adherence probe",
|
|
8
|
-
"purpose": "The runtime-observable enforcement handle for the ADR-206 iconography discipline. The blueprint declares that components reference icons only through the semantic alias registry and that bespoke per-component artwork is an extension to the registry rather than inline SVG (application-spa-REQ-011, US-1118).
|
|
8
|
+
"purpose": "The runtime-observable enforcement handle for the ADR-206 iconography discipline. The blueprint declares that components reference icons only through the semantic alias registry and that bespoke per-component artwork is an extension to the registry rather than inline SVG (application-spa-REQ-011, US-1118). This TAC is the project-realised probe that inspects the shipped component source (or built bundle), refuses at non-zero exit on any inline SVG outside the registry or any icon reference naming an alias the registry does not declare, and writes a stable JSON report the delivery-ci-workflows aggregate report can name.",
|
|
9
9
|
"responsibilities": [
|
|
10
10
|
"Expose a Node entry point (a single `.js` or `.mjs` file) invocable as `node <path>` with no shell glue; the entry point path is stable and recorded on the aggregate report's `runner.entryPoint` field when this probe is wired as a delivery-ci-workflows gate (AC-1130-1, AC-1130-4).",
|
|
11
11
|
"Read the icon alias registry at a configured path (default `assets/icons/aliases.json` or the project-declared equivalent per ADR-206) and enumerate the declared alias names (AC-1130-2).",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"description": "When this probe is wired as a delivery-ci-workflows gate, the runner invokes it as a child process, captures the exit code, and delegates the per-gate report write to TAC-702. The probe writes its own detailed report; the gate report writer records the exit-code envelope."
|
|
51
51
|
}
|
|
52
52
|
],
|
|
53
|
-
"tradeoffs": "Scanning source for inline SVG accepts that a project may sometimes ship a genuinely single-use bespoke glyph; the discipline says such a glyph joins the registry rather than living inline, and the probe surfaces the choice at the ship gate rather than at design
|
|
53
|
+
"tradeoffs": "Scanning source for inline SVG accepts that a project may sometimes ship a genuinely single-use bespoke glyph; the discipline says such a glyph joins the registry rather than living inline, and the probe surfaces the choice at the ship gate rather than at the design gate. The alias-reference scanner needs a project-declared reference-shape pattern (JSX prop, function call, or template literal); the probe ships a small pattern library and the project selects the shape it uses. The cost is one line of configuration; the buy is a runtime-observable enforcement that closes the mechanism-reach gap this probe cures.",
|
|
54
54
|
"createdAt": "2026-08-24T00:00:00Z",
|
|
55
55
|
"updatedAt": "2026-08-24T00:00:00Z"
|
|
56
56
|
}
|
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
"version": "1.0.2",
|
|
6
6
|
"status": "approved",
|
|
7
7
|
"name": "Styled-under-shipped-CSP adherence probe",
|
|
8
|
-
"purpose": "The runtime-observable enforcement handle for application-spa-REQ-018 (SPA security baselines: CSP, sanitised dynamic HTML, hardened cookies, secret-free bundle).
|
|
8
|
+
"purpose": "The runtime-observable enforcement handle for application-spa-REQ-018 (SPA security baselines: CSP, sanitised dynamic HTML, hardened cookies, secret-free bundle). This TAC is the project-realised probe that (a) refuses any inline <style> block in the rendered HTML surface, (b) refuses a CSP that relaxes style-src to unsafe-inline, and (c) drives a real browser at the same server instance that stamps the production headers to prove the shipped stylesheet actually reaches the runtime surface. Writes a stable JSON report the delivery-ci-workflows aggregate report can name.",
|
|
9
9
|
"responsibilities": [
|
|
10
10
|
"Expose a Node entry point (a single `.js` or `.mjs` file) invocable as `node <path>` with no shell glue; the entry point path is stable and recorded on the aggregate report's `runner.entryPoint` field when this probe is wired as a delivery-ci-workflows gate (AC-1131-5, AC-1131-6).",
|
|
11
11
|
"Accept configuration naming (i) how to boot the target server (a Node module or command that starts the same server instance the production entry point starts, with the same route registration), (ii) the enumerated set of UI-bearing routes to probe, and (iii) the stylesheet URL every rendered document is expected to link (AC-1131-3, AC-1131-4).",
|
|
12
12
|
"For every enumerated route: navigate a real headless browser to the served URL, capture the response `content-security-policy` header, capture the response body, read the browser's final URL after any redirect chain resolves, run getComputedStyle on document.body, and record the results (AC-1131-1, AC-1131-2, AC-1131-3).",
|
|
13
13
|
"Refuse the run when any captured CSP declares 'unsafe-inline' or 'unsafe-eval' on style-src, when style-src is absent, or when style-src is served as a wildcard (AC-1131-1).",
|
|
14
14
|
"Refuse the run when any captured response body contains a `<style` substring (case-insensitive), including <style> injected by templating helpers (AC-1131-2).",
|
|
15
|
-
"Refuse the run when the browser's final URL path for any enumerated route does NOT equal the requested route path (a `pathMismatch` refusal class); a headless browser follows redirects by default, so a session-broken authenticated route silently 302'ing to a styled /login would otherwise cause every downstream styled-body assertion below to pass against the redirect target rather than the requested surface. The refusal names both the requested and the landed path (AC-1131-3,
|
|
15
|
+
"Refuse the run when the browser's final URL path for any enumerated route does NOT equal the requested route path (a `pathMismatch` refusal class); a headless browser follows redirects by default, so a session-broken authenticated route silently 302'ing to a styled /login would otherwise cause every downstream styled-body assertion below to pass against the redirect target rather than the requested surface. The refusal names both the requested and the landed path (AC-1131-3, `pathMismatch`).",
|
|
16
16
|
"Refuse the run when the computed body backgroundColor for any route is the browser default (`rgba(0, 0, 0, 0)` / `transparent`) or when the computed body fontFamily resolves to an empty value; both indicate the shipped stylesheet did NOT reach the runtime surface under the production headers (AC-1131-3).",
|
|
17
17
|
"Issue a same-origin GET against the linked stylesheet URL through the same server instance and refuse when the response is not 200 with content-type `text/css` (AC-1131-4).",
|
|
18
18
|
"Write a JSON report at a stable relative path (`reports/csp-styled-adherence.json` under the configured report directory, matching the delivery-ci-workflows per-gate report shape of TAC-702) naming: every route probed, the CSP header captured, whether an inline <style> was detected, the computed background and fontFamily values, the stylesheet GET verdict, and an ok / fail verdict (AC-1131-5).",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"description": "When this probe is wired as a delivery-ci-workflows gate, the runner invokes it as a child process, captures the exit code, and delegates the per-gate report write to TAC-702 in the ordinary way. The probe writes its own detailed report; the gate report writer records the exit-code envelope."
|
|
56
56
|
}
|
|
57
57
|
],
|
|
58
|
-
"tradeoffs": "The probe requires a real browser and a running server for every delivery-ci-workflows invocation. That cost buys
|
|
58
|
+
"tradeoffs": "The probe requires a real browser and a running server for every delivery-ci-workflows invocation. That cost buys runtime-observable enforcement of the production header path: driving the shipped construction (not a bespoke harness) is the load-bearing choice, and refusing app.inject() satisfaction is deliberate because a probe that stamps its own headers cannot refuse a CSP defect. The landed-path refusal is necessary because Playwright's `page.goto` follows redirects by default and returns the FINAL response, so without a final-path check a session-broken authenticated route that silently 302's to a styled /login would leave every downstream styled-body assertion validating the login page instead of the requested surface. Comparing `new URL(page.url()).pathname` to the enumerated route path is the cheapest structural refusal that closes that gap without coupling the probe to session-lane internals.",
|
|
59
59
|
"createdAt": "2026-08-24T10:30:00Z",
|
|
60
60
|
"updatedAt": "2026-08-31T11:15:00Z"
|
|
61
61
|
}
|