rcf-lite 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +10 -0
- package/bin/rcf.js +2 -0
- package/blueprints/application-account-settings/CHANGELOG.md +35 -6
- package/blueprints/application-account-settings/README.md +1 -1
- package/blueprints/application-account-settings/blueprint.json +4 -2
- package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +1 -1
- package/blueprints/application-account-settings/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-account-settings/contributions/probes/profile-form-autocomplete.mjs +67 -0
- package/blueprints/application-account-settings/contributions/probes/run-profile-form-autocomplete.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-adapter-uniform.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-surface-shape.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-shell-tablist-per-capability.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-theme-radiogroup.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-adapter-uniform.mjs +130 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-surface-shape.mjs +70 -0
- package/blueprints/application-account-settings/contributions/probes/shell-tablist-per-capability.mjs +60 -0
- package/blueprints/application-account-settings/contributions/probes/theme-radiogroup.mjs +126 -0
- package/blueprints/application-admin-console/CHANGELOG.md +32 -6
- package/blueprints/application-admin-console/README.md +1 -1
- package/blueprints/application-admin-console/blueprint.json +4 -2
- package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +1 -1
- package/blueprints/application-admin-console/contributions/probes/audit-log-surface.mjs +79 -0
- package/blueprints/application-admin-console/contributions/probes/org-switcher-surface.mjs +83 -0
- package/blueprints/application-admin-console/contributions/probes/permission-matrix-grid.mjs +67 -0
- package/blueprints/application-admin-console/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-admin-console/contributions/probes/run-audit-log-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-org-switcher-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-permission-matrix-grid.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-sign-in-access-gated-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-users-directory-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/sign-in-access-gated-surface.mjs +117 -0
- package/blueprints/application-admin-console/contributions/probes/users-directory-surface.mjs +145 -0
- package/blueprints/application-api-rest/CHANGELOG.md +16 -8
- package/blueprints/application-api-rest/README.md +3 -3
- package/blueprints/application-api-rest/blueprint.json +3 -2
- package/blueprints/application-api-rest/contributions/adrs/adr-302-application-api-rest-auth-model.json +1 -1
- package/blueprints/application-api-rest/contributions/probes/cursor-pagination-round-trip.mjs +154 -0
- package/blueprints/application-api-rest/contributions/probes/health-probes-distinct.mjs +124 -0
- package/blueprints/application-api-rest/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-api-rest/contributions/probes/problem-details-on-error.mjs +77 -0
- package/blueprints/application-api-rest/contributions/probes/request-id-echoed.mjs +76 -0
- package/blueprints/application-api-rest/contributions/probes/run-cursor-pagination-round-trip.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-health-probes-distinct.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-problem-details-on-error.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-request-id-echoed.mjs +5 -0
- package/blueprints/application-api-rest/docs/topics.md +1 -1
- package/blueprints/application-charts/CHANGELOG.md +35 -9
- package/blueprints/application-charts/README.md +6 -6
- package/blueprints/application-charts/blueprint.json +5 -3
- package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +1 -1
- package/blueprints/application-charts/contributions/probes/keyboard-traversal.mjs +151 -0
- package/blueprints/application-charts/contributions/probes/non-colour-distinction.mjs +67 -0
- package/blueprints/application-charts/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-charts/contributions/probes/run-keyboard-traversal.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-non-colour-distinction.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-text-alternative-table.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/text-alternative-table.mjs +139 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +1 -1
- package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +1 -1
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +5 -5
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +1 -1
- package/blueprints/application-charts/guide/application-charts.md +1 -1
- package/blueprints/application-dashboard/CHANGELOG.md +20 -10
- package/blueprints/application-dashboard/README.md +6 -6
- package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +2 -2
- package/blueprints/application-dashboard/blueprint.json +3 -2
- package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +1 -1
- package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +1 -1
- package/blueprints/application-dashboard/contributions/probes/export-handle-formats.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/four-tile-states.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/primary-kpi-top-left.mjs +58 -0
- package/blueprints/application-dashboard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-dashboard/contributions/probes/run-export-handle-formats.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-four-tile-states.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-primary-kpi-top-left.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-shell-five-regions.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/shell-five-regions.mjs +93 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +1 -1
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +5 -5
- package/blueprints/application-dashboard/docs/topics.md +2 -2
- package/blueprints/application-dashboard/guide/application-dashboard.md +2 -2
- package/blueprints/application-datatable/CHANGELOG.md +19 -9
- package/blueprints/application-datatable/README.md +2 -2
- package/blueprints/application-datatable/blueprint.json +3 -2
- package/blueprints/application-datatable/contributions/probes/apg-table-shape.mjs +57 -0
- package/blueprints/application-datatable/contributions/probes/four-states-regions.mjs +80 -0
- package/blueprints/application-datatable/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-datatable/contributions/probes/run-apg-table-shape.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-four-states-regions.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-search-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-sort-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/search-adapter-round-trip.mjs +58 -0
- package/blueprints/application-datatable/contributions/probes/sort-adapter-round-trip.mjs +60 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +1 -1
- package/blueprints/application-datatable/docs/topics.md +1 -1
- package/blueprints/application-empty-error-states/CHANGELOG.md +33 -3
- package/blueprints/application-empty-error-states/blueprint.json +4 -2
- package/blueprints/application-empty-error-states/contributions/probes/empty-list-and-no-search.mjs +66 -0
- package/blueprints/application-empty-error-states/contributions/probes/error-boundary-alert.mjs +65 -0
- package/blueprints/application-empty-error-states/contributions/probes/forbidden-and-server-error.mjs +167 -0
- package/blueprints/application-empty-error-states/contributions/probes/not-found-and-recovery.mjs +61 -0
- package/blueprints/application-empty-error-states/contributions/probes/permission-denied-and-offline.mjs +155 -0
- package/blueprints/application-empty-error-states/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-empty-list-and-no-search.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-error-boundary-alert.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-forbidden-and-server-error.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-not-found-and-recovery.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-permission-denied-and-offline.mjs +5 -0
- package/blueprints/application-error-handling/CHANGELOG.md +45 -6
- package/blueprints/application-error-handling/blueprint.json +3 -2
- package/blueprints/application-error-handling/contributions/probes/category-vocabulary.mjs +90 -0
- package/blueprints/application-error-handling/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-error-handling/contributions/probes/record-shape-adr-1701.mjs +78 -0
- package/blueprints/application-error-handling/contributions/probes/run-category-vocabulary.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-record-shape-adr-1701.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-two-boundaries-registered.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/two-boundaries-registered.mjs +343 -0
- package/blueprints/application-file-upload/CHANGELOG.md +28 -6
- package/blueprints/application-file-upload/README.md +1 -1
- package/blueprints/application-file-upload/blueprint.json +3 -2
- package/blueprints/application-file-upload/contributions/probes/assertive-completion-slot.mjs +78 -0
- package/blueprints/application-file-upload/contributions/probes/chunked-transport-endpoints.mjs +173 -0
- package/blueprints/application-file-upload/contributions/probes/per-file-progressbar.mjs +124 -0
- package/blueprints/application-file-upload/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-file-upload/contributions/probes/run-assertive-completion-slot.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-chunked-transport-endpoints.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-per-file-progressbar.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-upload-surface-shape.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/upload-surface-shape.mjs +55 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +1 -1
- package/blueprints/application-file-upload/probe-packs/application-file-upload.pack.mjs +1 -1
- package/blueprints/application-forms-wizard/CHANGELOG.md +20 -6
- package/blueprints/application-forms-wizard/README.md +2 -2
- package/blueprints/application-forms-wizard/blueprint.json +3 -2
- package/blueprints/application-forms-wizard/contributions/probes/draft-persistence-round-trip.mjs +110 -0
- package/blueprints/application-forms-wizard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-draft-persistence-round-trip.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-step-page-shape.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-task-list-surface.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/step-page-shape.mjs +61 -0
- package/blueprints/application-forms-wizard/contributions/probes/task-list-surface.mjs +109 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +1 -1
- package/blueprints/application-forms-wizard/probe-packs/application-forms-wizard.pack.mjs +1 -1
- package/blueprints/application-notifications-in-app/CHANGELOG.md +38 -5
- package/blueprints/application-notifications-in-app/README.md +4 -4
- package/blueprints/application-notifications-in-app/blueprint.json +4 -2
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/probes/centre-acknowledge-round-trip.mjs +210 -0
- package/blueprints/application-notifications-in-app/contributions/probes/live-region-preseeding.mjs +93 -0
- package/blueprints/application-notifications-in-app/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-centre-acknowledge-round-trip.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-live-region-preseeding.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-toast-contract.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/toast-contract.mjs +92 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +3 -3
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +1 -1
- package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +3 -3
- package/blueprints/application-onboarding-tour/CHANGELOG.md +31 -5
- package/blueprints/application-onboarding-tour/README.md +1 -1
- package/blueprints/application-onboarding-tour/blueprint.json +5 -3
- package/blueprints/application-onboarding-tour/contributions/probes/checklist-anchor-open.mjs +81 -0
- package/blueprints/application-onboarding-tour/contributions/probes/completion-persistence.mjs +159 -0
- package/blueprints/application-onboarding-tour/contributions/probes/first-run-detection.mjs +67 -0
- package/blueprints/application-onboarding-tour/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-checklist-anchor-open.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-completion-persistence.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-first-run-detection.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-stepper-role-dialog.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/stepper-role-dialog.mjs +45 -0
- package/blueprints/application-spa/CHANGELOG.md +20 -11
- package/blueprints/application-spa/README.md +9 -10
- package/blueprints/application-spa/blueprint.json +3 -2
- package/blueprints/application-spa/contributions/adrs/adr-202-application-spa-theming.json +1 -1
- package/blueprints/application-spa/contributions/adrs/adr-206-application-spa-iconography.json +1 -1
- package/blueprints/application-spa/contributions/probes/designed-empty-state.mjs +72 -0
- package/blueprints/application-spa/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-spa/contributions/probes/route-inventory-published.mjs +185 -0
- package/blueprints/application-spa/contributions/probes/run-designed-empty-state.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-route-inventory-published.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-shell-nav-present.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/shell-nav-present.mjs +69 -0
- package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +1 -1
- package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +3 -3
- package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +2 -2
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +1 -1
- package/blueprints/application-spa/docs/topics.md +1 -1
- package/blueprints/delivery-ci-workflows/CHANGELOG.md +31 -11
- package/blueprints/delivery-ci-workflows/README.md +3 -3
- package/blueprints/delivery-ci-workflows/blueprint.json +3 -2
- package/blueprints/delivery-ci-workflows/contributions/adrs/adr-702-delivery-ci-workflows-strict-coverage-gate.json +2 -2
- package/blueprints/delivery-ci-workflows/contributions/probes/node-gate-entrypoint.mjs +76 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/probe-utils.mjs +56 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/real-account-github-actions-run-record.mjs +139 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-node-gate-entrypoint.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-real-account-github-actions-run-record.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-workflow-template-shape.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/workflow-template-shape.mjs +94 -0
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-004.json +1 -1
- package/blueprints/delivery-ci-workflows/docs/topics.md +2 -3
- package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +4 -4
- package/blueprints/deploy-cloudflare-workers/README.md +3 -3
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +2 -2
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +2 -2
- package/blueprints/deploy-hetzner-server/CHANGELOG.md +98 -7
- package/blueprints/deploy-hetzner-server/blueprint.json +7 -6
- package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +46 -21
- package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +344 -83
- package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +211 -42
- package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +140 -22
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +111 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +158 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +154 -32
- package/blueprints/edge-cloudflare-access/CHANGELOG.md +6 -5
- package/blueprints/edge-cloudflare-access/blueprint.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +9 -1
- package/blueprints/edge-cloudflare-access/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +4 -7
- package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +4 -6
- package/blueprints/edge-cloudflare-tunnel/README.md +1 -2
- package/blueprints/edge-cloudflare-tunnel/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +2 -3
- package/blueprints/edge-cloudflare-turnstile/docs/topics.md +1 -1
- package/blueprints/email-smtp-resend/CHANGELOG.md +24 -8
- package/blueprints/email-smtp-resend/README.md +2 -2
- package/blueprints/email-smtp-resend/blueprint.json +3 -2
- package/blueprints/email-smtp-resend/contributions/probes/probe-utils.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/real-account-resend-send.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-real-account-resend-send.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-smtp-round-trip.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-unverified-sender-refusal.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/smtp-round-trip.mjs +43 -0
- package/blueprints/email-smtp-resend/contributions/probes/unverified-sender-refusal.mjs +99 -0
- package/blueprints/email-smtp-resend/docs/topics.md +2 -3
- package/blueprints/jobs-background/CHANGELOG.md +66 -5
- package/blueprints/jobs-background/README.md +2 -2
- package/blueprints/jobs-background/blueprint.json +3 -2
- package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +38 -10
- package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +28 -6
- package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +16 -2
- package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +102 -21
- package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +10 -2
- package/blueprints/jobs-background/contributions/probes/retry-and-fail-real-account.mjs +355 -0
- package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +33 -2
- package/blueprints/jobs-background/contributions/probes/run-retry-and-fail-real-account.mjs +12 -0
- package/blueprints/jobs-background/docs/topics.md +1 -1
- package/blueprints/jobs-background/guide/jobs-background.md +1 -1
- package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +25 -19
- package/blueprints/messaging-queue-cloudflare/README.md +12 -12
- package/blueprints/messaging-queue-cloudflare/blueprint.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +2 -2
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +180 -12
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +1 -1
- package/blueprints/messaging-queue-cloudflare/docs/topics.md +2 -2
- package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +2 -2
- package/blueprints/object-storage-s3/CHANGELOG.md +75 -4
- package/blueprints/object-storage-s3/blueprint.json +3 -2
- package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +73 -12
- package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +55 -7
- package/blueprints/object-storage-s3/contributions/probes/hetzner-object-storage-round-trip.mjs +102 -18
- package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +105 -36
- package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +104 -55
- package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +129 -7
- package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +80 -18
- package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +291 -37
- package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +5 -5
- package/blueprints/object-storage-s3/contributions/probes/run-hetzner-object-storage-round-trip.mjs +8 -5
- package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +6 -3
- package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +10 -2
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +1 -1
- package/blueprints/object-storage-s3/docs/topics.md +1 -1
- package/blueprints/object-storage-s3/guide/object-storage-s3.md +1 -1
- package/blueprints/observability-essentials/CHANGELOG.md +23 -7
- package/blueprints/observability-essentials/README.md +2 -2
- package/blueprints/observability-essentials/assets/probe-samples/probe-response-baseline.v2.json +1 -1
- package/blueprints/observability-essentials/blueprint.json +3 -2
- package/blueprints/observability-essentials/contributions/probes/liveness-probe.mjs +84 -0
- package/blueprints/observability-essentials/contributions/probes/metrics-endpoint.mjs +96 -0
- package/blueprints/observability-essentials/contributions/probes/probe-utils.mjs +52 -0
- package/blueprints/observability-essentials/contributions/probes/readiness-probe.mjs +171 -0
- package/blueprints/observability-essentials/contributions/probes/run-liveness-probe.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-metrics-endpoint.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-readiness-probe.mjs +3 -0
- package/blueprints/observability-essentials/docs/topics.md +2 -3
- package/blueprints/observability-logging/CHANGELOG.md +29 -4
- package/blueprints/observability-logging/README.md +2 -2
- package/blueprints/observability-logging/blueprint.json +3 -2
- package/blueprints/observability-logging/contributions/probes/correlation-id-flow.mjs +173 -0
- package/blueprints/observability-logging/contributions/probes/line-shape-and-fields.mjs +82 -0
- package/blueprints/observability-logging/contributions/probes/probe-utils.mjs +47 -0
- package/blueprints/observability-logging/contributions/probes/redaction-boundary.mjs +130 -0
- package/blueprints/observability-logging/contributions/probes/run-correlation-id-flow.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-line-shape-and-fields.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-redaction-boundary.mjs +3 -0
- package/blueprints/observability-probe-endpoints/CHANGELOG.md +23 -8
- package/blueprints/observability-probe-endpoints/README.md +3 -3
- package/blueprints/observability-probe-endpoints/blueprint.json +3 -2
- package/blueprints/observability-probe-endpoints/contributions/probes/kubernetes-startup-enabled.mjs +80 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/partial-profile-refusal.mjs +101 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/probe-utils.mjs +49 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/profile-boot-materialisation.mjs +69 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-kubernetes-startup-enabled.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-partial-profile-refusal.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-profile-boot-materialisation.mjs +3 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +2 -2
- package/blueprints/persistence-data-d1/CHANGELOG.md +16 -3
- package/blueprints/persistence-data-d1/README.md +2 -2
- package/blueprints/persistence-data-d1/blueprint.json +3 -2
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1404-persistence-data-d1-store-boundary.json +1 -1
- package/blueprints/persistence-data-d1/contributions/probes/facade-round-trip.mjs +140 -0
- package/blueprints/persistence-data-d1/contributions/probes/migrations-forward-only.mjs +66 -0
- package/blueprints/persistence-data-d1/contributions/probes/probe-utils.mjs +51 -0
- package/blueprints/persistence-data-d1/contributions/probes/real-account-d1-round-trip.mjs +133 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-facade-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-migrations-forward-only.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-real-account-d1-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/docs/topics.md +2 -3
- package/blueprints/persistence-data-postgres/CHANGELOG.md +84 -4
- package/blueprints/persistence-data-postgres/README.md +2 -2
- package/blueprints/persistence-data-postgres/blueprint.json +3 -2
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +87 -12
- package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +245 -19
- package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +109 -26
- package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +151 -38
- package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +24 -6
- package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +261 -48
- package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +76 -20
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +1 -1
- package/blueprints/persistence-data-postgres/docs/topics.md +1 -1
- package/blueprints/persistence-data-sqlite/CHANGELOG.md +16 -2
- package/blueprints/persistence-data-sqlite/README.md +2 -2
- package/blueprints/persistence-data-sqlite/blueprint.json +3 -2
- package/blueprints/persistence-data-sqlite/contributions/probes/boot-open-migrate.mjs +90 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/facade-round-trip.mjs +82 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/probe-utils.mjs +83 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-boot-open-migrate.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-facade-round-trip.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-wal-checkpoint.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/wal-checkpoint.mjs +137 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +5 -5
- package/blueprints/platform-cloudflare-cron-triggers/README.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +6 -10
- package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-kv/CHANGELOG.md +16 -12
- package/blueprints/platform-cloudflare-kv/README.md +2 -4
- package/blueprints/platform-cloudflare-kv/blueprint.json +2 -2
- package/blueprints/platform-cloudflare-kv/docs/topics.md +1 -1
- package/blueprints/platform-docker-compose-host/CHANGELOG.md +92 -5
- package/blueprints/platform-docker-compose-host/blueprint.json +2 -2
- package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +116 -29
- package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +181 -109
- package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +146 -26
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +238 -24
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +207 -21
- package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +246 -42
- package/blueprints/platform-docker-compose-host/docs/topics.md +1 -1
- package/blueprints/security-auth-clerk/CHANGELOG.md +18 -6
- package/blueprints/security-auth-clerk/README.md +3 -3
- package/blueprints/security-auth-clerk/assets/wiring/workers-wrangler-toml-shape.md +1 -1
- package/blueprints/security-auth-clerk/blueprint.json +3 -2
- package/blueprints/security-auth-clerk/contributions/probes/hosted-identity-ui-config.mjs +61 -0
- package/blueprints/security-auth-clerk/contributions/probes/probe-utils.mjs +188 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-principal-directory-round-trip.mjs +216 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-session-inventory.mjs +260 -0
- package/blueprints/security-auth-clerk/contributions/probes/role-model-adapter.mjs +53 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-hosted-identity-ui-config.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-principal-directory-round-trip.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-session-inventory.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-role-model-adapter.mjs +4 -0
- package/blueprints/security-auth-clerk/docs/topics.md +2 -3
- package/blueprints/security-auth-keycloak/CHANGELOG.md +18 -7
- package/blueprints/security-auth-keycloak/README.md +2 -2
- package/blueprints/security-auth-keycloak/blueprint.json +3 -2
- package/blueprints/security-auth-keycloak/contributions/probes/discovery-shape.mjs +68 -0
- package/blueprints/security-auth-keycloak/contributions/probes/introspection-shape.mjs +88 -0
- package/blueprints/security-auth-keycloak/contributions/probes/jwt-verifier-shape.mjs +86 -0
- package/blueprints/security-auth-keycloak/contributions/probes/probe-utils.mjs +180 -0
- package/blueprints/security-auth-keycloak/contributions/probes/real-account-realm-round-trip.mjs +91 -0
- package/blueprints/security-auth-keycloak/contributions/probes/role-adapter-shape.mjs +69 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-discovery-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-introspection-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-jwt-verifier-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-real-account-realm-round-trip.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-role-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/docs/topics.md +1 -2
- package/blueprints/security-auth-magic-link/CHANGELOG.md +15 -4
- package/blueprints/security-auth-magic-link/README.md +2 -2
- package/blueprints/security-auth-magic-link/assets/principal-registry-samples/single-address.md +1 -1
- package/blueprints/security-auth-magic-link/blueprint.json +3 -2
- package/blueprints/security-auth-magic-link/contributions/probes/probe-utils.mjs +174 -0
- package/blueprints/security-auth-magic-link/contributions/probes/real-account-magic-link-send.mjs +139 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-real-account-magic-link-send.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-entropy-shape.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-issue-verify.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-entropy-shape.mjs +60 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-issue-verify.mjs +90 -0
- package/blueprints/security-auth-magic-link/docs/topics.md +1 -1
- package/blueprints/security-auth-oauth2/CHANGELOG.md +16 -5
- package/blueprints/security-auth-oauth2/README.md +2 -2
- package/blueprints/security-auth-oauth2/blueprint.json +3 -2
- package/blueprints/security-auth-oauth2/contributions/probes/authorisation-code-flow-shape.mjs +259 -0
- package/blueprints/security-auth-oauth2/contributions/probes/pkce-challenge-shape.mjs +58 -0
- package/blueprints/security-auth-oauth2/contributions/probes/probe-utils.mjs +190 -0
- package/blueprints/security-auth-oauth2/contributions/probes/provider-adapter-shape.mjs +64 -0
- package/blueprints/security-auth-oauth2/contributions/probes/real-account-authorisation-code-flow.mjs +93 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-authorisation-code-flow-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-pkce-challenge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-provider-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-real-account-authorisation-code-flow.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-session-bridge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/session-bridge-shape.mjs +78 -0
- package/blueprints/security-auth-oauth2/docs/topics.md +1 -2
- package/blueprints/security-secrets-management/CHANGELOG.md +15 -4
- package/blueprints/security-secrets-management/README.md +2 -2
- package/blueprints/security-secrets-management/blueprint.json +3 -2
- package/blueprints/security-secrets-management/contributions/probes/add-recipient-rotation.mjs +107 -0
- package/blueprints/security-secrets-management/contributions/probes/encrypt-decrypt-round-trip.mjs +122 -0
- package/blueprints/security-secrets-management/contributions/probes/key-rotation.mjs +93 -0
- package/blueprints/security-secrets-management/contributions/probes/mismatched-key-refusal.mjs +74 -0
- package/blueprints/security-secrets-management/contributions/probes/probe-utils.mjs +214 -0
- package/blueprints/security-secrets-management/contributions/probes/run-add-recipient-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-encrypt-decrypt-round-trip.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-key-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-mismatched-key-refusal.mjs +4 -0
- package/blueprints/security-secrets-management/docs/topics.md +2 -3
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/harness-template.md +25 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +25 -0
- package/package.json +2 -2
- package/rcf/adrs/adr-4101-feedback-store-gitignored.json +20 -0
- package/rcf/adrs/adr-4102-fingerprint-and-labels.json +25 -0
- package/rcf/adrs/adr-4103-redaction-rule-based.json +20 -0
- package/rcf/adrs/adr-4104-destination-on-library.json +25 -0
- package/rcf/adrs/adr-4105-gh-ambient-auth.json +20 -0
- package/rcf/adrs/adr-4106-bundled-entries-terminal.json +20 -0
- package/rcf/adrs/adr-4107-stop-is-ask-event.json +30 -0
- package/rcf/adrs/adr-4108-hooks-in-committed-config.json +25 -0
- package/rcf/adrs/adr-4109-referee-validate-adr-crosslinks.json +25 -0
- package/rcf/adrs/adr-4110-referee-coverage-strict-by-default.json +25 -0
- package/rcf/adrs/adr-4111-referee-finalise-refusals.json +20 -0
- package/rcf/adrs/adr-4112-referee-finalise-verified-invariant.json +30 -0
- package/rcf/code-nodes/cn-600.json +45 -0
- package/rcf/code-nodes/cn-601.json +18 -0
- package/rcf/code-nodes/cn-602.json +15 -0
- package/rcf/code-nodes/cn-603.json +12 -0
- package/rcf/code-nodes/cn-604.json +14 -0
- package/rcf/code-nodes/cn-605.json +17 -0
- package/rcf/code-nodes/cn-606.json +12 -0
- package/rcf/code-nodes/cn-607.json +12 -0
- package/rcf/code-nodes/cn-608.json +14 -0
- package/rcf/code-nodes/cn-609.json +17 -0
- package/rcf/code-nodes/cn-620.json +18 -0
- package/rcf/code-nodes/cn-621.json +14 -0
- package/rcf/code-nodes/cn-622.json +15 -0
- package/rcf/code-nodes/cn-623.json +16 -0
- package/rcf/code-nodes/cn-624.json +14 -0
- package/rcf/code-nodes/cn-625.json +15 -0
- package/rcf/code-nodes/cn-626.json +13 -0
- package/rcf/code-nodes/cn-627.json +13 -0
- package/rcf/code-nodes/cn-628.json +14 -0
- package/rcf/code-nodes/cn-629.json +12 -0
- package/rcf/code-nodes/cn-630.json +12 -0
- package/rcf/code-nodes/cn-631.json +13 -0
- package/rcf/code-nodes/cn-632.json +13 -0
- package/rcf/fbs/fbs-180.json +45 -0
- package/rcf/fbs/fbs-181.json +45 -0
- package/rcf/fbs/fbs-182.json +42 -0
- package/rcf/fbs/fbs-183.json +50 -0
- package/rcf/fbs/fbs-184.json +49 -0
- package/rcf/fbs/fbs-185.json +34 -0
- package/rcf/fbs/fbs-186.json +16 -0
- package/rcf/fbs/fbs-187.json +17 -0
- package/rcf/fbs/fbs-188.json +17 -0
- package/rcf/fbs/fbs-189.json +17 -0
- package/rcf/requirements/req-155.json +13 -0
- package/rcf/requirements/req-156.json +13 -0
- package/rcf/requirements/req-157.json +13 -0
- package/rcf/requirements/req-158.json +13 -0
- package/rcf/requirements/req-159.json +13 -0
- package/rcf/requirements/req-160.json +13 -0
- package/rcf/requirements/req-161.json +13 -0
- package/rcf/requirements/req-162.json +13 -0
- package/rcf/requirements/req-163.json +13 -0
- package/rcf/requirements/req-164.json +13 -0
- package/rcf/requirements/req-165.json +13 -0
- package/rcf/tacs/tac-4101-feedback-cli.json +77 -0
- package/rcf/tacs/tac-4102-feedback-store.json +50 -0
- package/rcf/tacs/tac-4103-feedback-redact.json +39 -0
- package/rcf/tacs/tac-4104-feedback-fingerprint.json +33 -0
- package/rcf/tacs/tac-4105-feedback-render.json +45 -0
- package/rcf/tacs/tac-4106-feedback-destination.json +39 -0
- package/rcf/tacs/tac-4107-feedback-gh.json +43 -0
- package/rcf/tacs/tac-4108-feedback-hook.json +46 -0
- package/rcf/tacs/tac-4109-referee-validate-adr-crosslinks.json +20 -0
- package/rcf/tacs/tac-4110-referee-coverage-mode-selector.json +21 -0
- package/rcf/tacs/tac-4111-referee-finalise-per-ac-refusals.json +21 -0
- package/rcf/tacs/tac-4112-referee-finalise-verified-invariant.json +22 -0
- package/rcf/test-suites/ts-140.json +9 -9
- package/rcf/test-suites/ts-150.json +9 -9
- package/rcf/test-suites/ts-185.json +54 -0
- package/rcf/test-suites/ts-186.json +58 -0
- package/rcf/test-suites/ts-187.json +44 -0
- package/rcf/test-suites/ts-188.json +166 -0
- package/rcf/test-suites/ts-189.json +38 -0
- package/rcf/test-suites/ts-190.json +30 -0
- package/rcf/test-suites/ts-191.json +51 -0
- package/rcf/test-suites/ts-192.json +37 -0
- package/rcf/test-suites/ts-193.json +60 -0
- package/rcf/test-suites/ts-194.json +67 -0
- package/rcf/test-suites/ts-195.json +52 -0
- package/rcf/test-suites/ts-196.json +58 -0
- package/rcf/test-suites/ts-197.json +66 -0
- package/rcf/test-suites/ts-198.json +87 -0
- package/rcf/test-suites/ts-199.json +51 -0
- package/rcf/test-suites/ts-200.json +30 -0
- package/rcf/test-suites/ts-201.json +38 -0
- package/rcf/test-suites/ts-202.json +38 -0
- package/rcf/test-suites/ts-203.json +38 -0
- package/rcf/user-stories/us-15501.json +60 -0
- package/rcf/user-stories/us-15502.json +33 -0
- package/rcf/user-stories/us-15503.json +33 -0
- package/rcf/user-stories/us-15601.json +51 -0
- package/rcf/user-stories/us-15701.json +42 -0
- package/rcf/user-stories/us-15801.json +42 -0
- package/rcf/user-stories/us-15802.json +33 -0
- package/rcf/user-stories/us-15901.json +33 -0
- package/rcf/user-stories/us-15902.json +51 -0
- package/rcf/user-stories/us-16001.json +51 -0
- package/rcf/user-stories/us-16101.json +42 -0
- package/rcf/user-stories/us-16102.json +33 -0
- package/rcf/user-stories/us-16103.json +42 -0
- package/rcf/user-stories/us-16104.json +42 -0
- package/rcf/user-stories/us-16201.json +33 -0
- package/rcf/user-stories/us-16301.json +36 -0
- package/rcf/user-stories/us-16401.json +45 -0
- package/rcf/user-stories/us-16501.json +45 -0
- package/rcf/user-stories/us-16502.json +45 -0
- package/releases/releases.yaml +11 -1
- package/src/blueprint/library-loader.js +48 -0
- package/src/blueprint/library-registry.js +13 -0
- package/src/browser-verify/pack-runner.js +7 -12
- package/src/build/mark.js +1 -1
- package/src/cli/blueprint-library.js +149 -0
- package/src/cli/coverage.js +49 -24
- package/src/cli/doctor.js +195 -7
- package/src/cli/feedback.js +2204 -0
- package/src/cli/finalise.js +158 -1
- package/src/cli/help.js +6 -0
- package/src/cli/init.js +63 -0
- package/src/cli/update.js +21 -1
- package/src/core/store/walker.js +33 -0
- package/src/core/store/writer.js +23 -0
- package/src/feedback/destination.js +361 -0
- package/src/feedback/fingerprint.js +132 -0
- package/src/feedback/gh.js +376 -0
- package/src/feedback/hook.js +183 -0
- package/src/feedback/labels.js +87 -0
- package/src/feedback/redact-allowlist.json +14 -0
- package/src/feedback/redact.js +1108 -0
- package/src/feedback/render.js +267 -0
- package/src/feedback/store.js +604 -0
- package/src/finalise/index.js +4 -0
- package/src/finalise/ingest.js +61 -0
- package/src/finalise/ship-without-eval.js +19 -7
- package/src/mcp/tools.js +8 -2
- package/src/setup/feedback-hooks.js +397 -0
- package/src/setup/managed-gitignore.js +3 -0
- package/src/view/html-page.js +5 -5
- package/src/view/style.css +2 -2
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// Shared helpers for security-auth-clerk probes.
|
|
2
|
+
//
|
|
3
|
+
// Runtime-dependency posture:
|
|
4
|
+
// - Local probes drive shipped-shape checks against the fixture at
|
|
5
|
+
// packages/rcf-lite/test/fixtures/security-auth-clerk/ without
|
|
6
|
+
// contacting Clerk.
|
|
7
|
+
// - real-account-* probes call the Clerk Backend API (base URL
|
|
8
|
+
// https://api.clerk.com/v1, docs verifiedOn 2026-09-11
|
|
9
|
+
// https://clerk.com/docs/reference/backend-api) via fetch. The
|
|
10
|
+
// probe records real request ids (Clerk stamps X-Request-ID and
|
|
11
|
+
// returns object ids like user_..., ses_...) and cleans up the
|
|
12
|
+
// scratch principal in a finally block. Without
|
|
13
|
+
// CI_HAS_CLERK_ACCOUNT the probe records accountBoundSkipped: true
|
|
14
|
+
// naming the missing var per rule 7d.
|
|
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 SLUG = 'security-auth-clerk';
|
|
23
|
+
export const FIXTURE_DIR = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/security-auth-clerk');
|
|
24
|
+
export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/security-auth-clerk');
|
|
25
|
+
|
|
26
|
+
// Declared env vars (mirror the fixture README table).
|
|
27
|
+
export const DECLARED_ENV = Object.freeze([
|
|
28
|
+
'CI_HAS_CLERK_ACCOUNT',
|
|
29
|
+
'CLERK_SECRET_KEY',
|
|
30
|
+
'CLERK_PUBLISHABLE_KEY',
|
|
31
|
+
'CLERK_API_BASE_URL',
|
|
32
|
+
'GITHUB_RUN_ID',
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
export const SCRATCH_PRINCIPAL_PREFIX = 'pxe-clerk-';
|
|
36
|
+
|
|
37
|
+
// First-8-words-of-anchor helper. Each result row's `detail` starts
|
|
38
|
+
// with the first eight words of the anchored AC's or REQ's
|
|
39
|
+
// description text. Anchor lookup walks contributions/user-stories/
|
|
40
|
+
// and contributions/requirements/ under the blueprint root and
|
|
41
|
+
// caches the map on first call. Null / unknown / missing anchors
|
|
42
|
+
// yield an empty prefix.
|
|
43
|
+
import { readFileSync as _rf } from 'node:fs';
|
|
44
|
+
import { readdirSync as _rd } from 'node:fs';
|
|
45
|
+
let _anchorMap = null;
|
|
46
|
+
function _loadAnchorMap() {
|
|
47
|
+
const map = new Map();
|
|
48
|
+
const dirs = [
|
|
49
|
+
{ dir: resolve(PROJECT_ROOT, 'blueprints', SLUG, 'contributions', 'user-stories'), kind: 'ac' },
|
|
50
|
+
{ dir: resolve(PROJECT_ROOT, 'blueprints', SLUG, 'contributions', 'requirements'), kind: 'req' },
|
|
51
|
+
];
|
|
52
|
+
for (const { dir, kind } of dirs) {
|
|
53
|
+
let entries;
|
|
54
|
+
try { entries = _rd(dir); } catch { continue; }
|
|
55
|
+
for (const name of entries) {
|
|
56
|
+
if (!name.endsWith('.json')) continue;
|
|
57
|
+
let j;
|
|
58
|
+
try { j = JSON.parse(_rf(resolve(dir, name), 'utf8')); } catch { continue; }
|
|
59
|
+
if (kind === 'ac') {
|
|
60
|
+
const usId = j.usId;
|
|
61
|
+
for (const ac of (j.acceptanceCriteria || [])) {
|
|
62
|
+
// AC id in the shipped JSON is like "AC-9101-1"; the
|
|
63
|
+
// anchor form used by probes is "<slug>-AC-9101-1".
|
|
64
|
+
const key = `${SLUG}-${ac.id}`;
|
|
65
|
+
map.set(key, ac.description || '');
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
const key = j.reqId; // already "<slug>-REQ-###"
|
|
69
|
+
if (key) map.set(key, j.description || j.title || '');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return map;
|
|
74
|
+
}
|
|
75
|
+
export function first8Words(anchor) {
|
|
76
|
+
if (!anchor) return '';
|
|
77
|
+
if (!_anchorMap) _anchorMap = _loadAnchorMap();
|
|
78
|
+
const txt = _anchorMap.get(anchor) || '';
|
|
79
|
+
if (!txt) return '';
|
|
80
|
+
const words = txt.split(/\s+/).filter(Boolean).slice(0, 8).join(' ');
|
|
81
|
+
return words;
|
|
82
|
+
}
|
|
83
|
+
export function withAnchorPrefix(row) {
|
|
84
|
+
const prefix = first8Words(row.anchorAcId);
|
|
85
|
+
if (!prefix) return row;
|
|
86
|
+
const already = typeof row.detail === 'string' && row.detail.startsWith(prefix);
|
|
87
|
+
if (already) return row;
|
|
88
|
+
const oldDetail = row.detail || '';
|
|
89
|
+
return { ...row, detail: `${prefix} :: ${oldDetail}` };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function aggregate(results) {
|
|
93
|
+
if (!Array.isArray(results) || results.length === 0) return 'fail';
|
|
94
|
+
if (results.some((r) => r.verdict === 'fail')) return 'fail';
|
|
95
|
+
if (results.some((r) => r.verdict === 'warn')) return 'warn';
|
|
96
|
+
return 'pass';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function isSkipped(results) {
|
|
100
|
+
return results.length > 0 && results.every((r) => r.accountBoundSkipped === true);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function writeReport({ probeName, engine, results, extra }) {
|
|
104
|
+
await mkdir(REPORT_DIR, { recursive: true });
|
|
105
|
+
// Prefix every row's detail with the first eight words of its
|
|
106
|
+
// anchored AC or REQ description; unanchored rows are left alone.
|
|
107
|
+
const prefixedResults = (results || []).map(withAnchorPrefix);
|
|
108
|
+
const raw = aggregate(prefixedResults);
|
|
109
|
+
const aggregateVerdict = isSkipped(prefixedResults) ? 'pass' : raw;
|
|
110
|
+
const report = {
|
|
111
|
+
slug: 'security-auth-clerk',
|
|
112
|
+
probeName,
|
|
113
|
+
runAt: new Date().toISOString(),
|
|
114
|
+
engine,
|
|
115
|
+
results: prefixedResults,
|
|
116
|
+
aggregateVerdict,
|
|
117
|
+
...(extra ?? {}),
|
|
118
|
+
};
|
|
119
|
+
const path = resolve(REPORT_DIR, `${probeName}.json`);
|
|
120
|
+
await writeFile(path, JSON.stringify(report, null, 2) + '\n', 'utf8');
|
|
121
|
+
return { report, path };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function runShim(probeName, engine, mainFn) {
|
|
125
|
+
try {
|
|
126
|
+
const outcome = await mainFn();
|
|
127
|
+
if (!outcome || !Array.isArray(outcome.results) || outcome.results.length === 0) {
|
|
128
|
+
const results = [{
|
|
129
|
+
anchorAcId: 'unknown',
|
|
130
|
+
verdict: 'fail',
|
|
131
|
+
detail: 'no checks ran',
|
|
132
|
+
}];
|
|
133
|
+
const { report, path } = await writeReport({ probeName, engine, results });
|
|
134
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
135
|
+
process.stderr.write(`no-checks-ran fail written to ${path}\n`);
|
|
136
|
+
process.exitCode = 1;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const { results, extra } = outcome;
|
|
140
|
+
const { report, path } = await writeReport({ probeName, engine, results, extra });
|
|
141
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
142
|
+
process.stdout.write(`report written to ${path}\n`);
|
|
143
|
+
if (report.aggregateVerdict === 'fail') process.exitCode = 1;
|
|
144
|
+
} catch (err) {
|
|
145
|
+
const results = [{
|
|
146
|
+
anchorAcId: 'unknown',
|
|
147
|
+
verdict: 'fail',
|
|
148
|
+
detail: `probe threw: ${err && err.message ? err.message : String(err)}`,
|
|
149
|
+
}];
|
|
150
|
+
const { report, path } = await writeReport({ probeName, engine, results });
|
|
151
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
152
|
+
process.stderr.write(`probe error: ${err && err.stack ? err.stack : String(err)}\n`);
|
|
153
|
+
process.stderr.write(`report written to ${path}\n`);
|
|
154
|
+
process.exitCode = 1;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// De-claim helper. When the shipped AC does not observe what the probe observes, the row keeps its
|
|
159
|
+
// verdict, evidence and engine as they are, but the anchor drops to null and the
|
|
160
|
+
// row carries conformanceOnly:true plus a limitation string naming the AC that
|
|
161
|
+
// this probe does NOT observe and why. The integration-harness follow-up (the auth integration harness follow-up)
|
|
162
|
+
// is the surface where those AC-level properties become observable.
|
|
163
|
+
export function deClaim(row, { ac, limitation }) {
|
|
164
|
+
const acId = ac || 'unknown-AC';
|
|
165
|
+
const limText = (limitation || '').trim();
|
|
166
|
+
const finalLim = /^(security-[a-z0-9-]+-)?(AC|REQ)-/.test(limText) ? limText : (limText ? `${acId}: ${limText}` : `${acId}: not observable at this probe surface; needs the integration harness (the auth integration harness follow-up)`);
|
|
167
|
+
const out = { ...row };
|
|
168
|
+
out.anchorAcId = null;
|
|
169
|
+
if ('anchorReqId' in out) delete out.anchorReqId;
|
|
170
|
+
out.conformanceOnly = true;
|
|
171
|
+
out.limitation = finalLim;
|
|
172
|
+
const tag = ` :: conformance-only (${finalLim})`;
|
|
173
|
+
if (typeof out.detail === 'string' && !out.detail.includes('conformance-only')) {
|
|
174
|
+
out.detail = out.detail + tag;
|
|
175
|
+
}
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function accountBoundSkippedResult(anchorAcId, capability, reason) {
|
|
180
|
+
return {
|
|
181
|
+
anchorAcId,
|
|
182
|
+
capability,
|
|
183
|
+
verdict: 'pass',
|
|
184
|
+
accountBoundSkipped: true,
|
|
185
|
+
reason,
|
|
186
|
+
detail: `accountBoundSkipped: ${reason} unset; probe did not execute against a real Clerk account. Set the missing var and re-run.`,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// Real-account principal-directory smoke for security-auth-clerk.
|
|
2
|
+
//
|
|
3
|
+
// Conformance-only. This probe drives the Clerk Backend API
|
|
4
|
+
// principal-directory (users) surface end to end (create + read +
|
|
5
|
+
// list + delete + list-diff) and records what the Backend API
|
|
6
|
+
// returned. The blueprint's shipped principal-directory acceptance
|
|
7
|
+
// criteria bind runtime sign-in and session semantics on the
|
|
8
|
+
// project's own middleware; a Backend API smoke against
|
|
9
|
+
// api.clerk.com does not observe those runtime properties, so the
|
|
10
|
+
// row is emitted with `anchorAcId: null` and a limitation naming
|
|
11
|
+
// the nearest shipped AC whose property the probe does not
|
|
12
|
+
// observe. Positive evidence per rule 7d is preserved on the row:
|
|
13
|
+
// the Clerk-assigned user_ id, the created-then-deleted resource id
|
|
14
|
+
// in the pre-diff / post-diff inventory pair, and the HTTP status
|
|
15
|
+
// codes. The probe reads the X-Request-Id header from each response
|
|
16
|
+
// and records it on every call, but Clerk's Backend API did not
|
|
17
|
+
// return that header on the instance these records were captured
|
|
18
|
+
// from, so every request-id field is null; the evidence rests on
|
|
19
|
+
// the created id, the inventory-diff pair and the response
|
|
20
|
+
// statuses rather than on request-id capture.
|
|
21
|
+
//
|
|
22
|
+
// Teardown is fail-safe: a mid-run crash leaves the user address
|
|
23
|
+
// deterministic; the finally block always issues DELETE. A
|
|
24
|
+
// teardown failure flips the verdict to FAIL regardless of
|
|
25
|
+
// upstream success.
|
|
26
|
+
//
|
|
27
|
+
// Base URL is https://api.clerk.com/v1 by default; CLERK_API_BASE_URL
|
|
28
|
+
// (declared, optional) may override for local mock testing.
|
|
29
|
+
//
|
|
30
|
+
// Docs: Clerk Backend API https://clerk.com/docs/reference/backend-api
|
|
31
|
+
// verifiedOn 2026-09-11.
|
|
32
|
+
//
|
|
33
|
+
// capability: principalDirectory.
|
|
34
|
+
// accountBound: true.
|
|
35
|
+
|
|
36
|
+
import { DECLARED_ENV, SCRATCH_PRINCIPAL_PREFIX, accountBoundSkippedResult } from './probe-utils.mjs';
|
|
37
|
+
|
|
38
|
+
export const anchorAcId = null;
|
|
39
|
+
export const capability = 'principalDirectory';
|
|
40
|
+
export const accountBound = true;
|
|
41
|
+
// AC-9110-1 states the project runtime does not create, update, or
|
|
42
|
+
// delete users on Clerk. This probe drives the Backend API from a
|
|
43
|
+
// probe process, not the project runtime, so it cannot observe the
|
|
44
|
+
// runtime property AC-9110-1 states; the row records that limit
|
|
45
|
+
// alongside the raw Backend API evidence it did capture.
|
|
46
|
+
const DECLAIM_LIMITATION = 'security-auth-clerk-AC-9110-1: probe drives the Clerk Backend API users surface from a probe process; the AC states the project runtime does not create, update or delete users on Clerk, which requires observing the deployed runtime through the integration harness follow-up.';
|
|
47
|
+
|
|
48
|
+
const BASE_URL_DEFAULT = 'https://api.clerk.com/v1';
|
|
49
|
+
|
|
50
|
+
function shortRandom() {
|
|
51
|
+
return Math.random().toString(36).slice(2, 10);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function pickRequestId(headers) {
|
|
55
|
+
return (
|
|
56
|
+
headers.get('x-request-id') ||
|
|
57
|
+
headers.get('cf-request-id') ||
|
|
58
|
+
headers.get('x-clerk-request-id') ||
|
|
59
|
+
null
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function clerkFetch({ baseUrl, path, method, body, token }) {
|
|
64
|
+
const url = `${baseUrl}${path}`;
|
|
65
|
+
const init = {
|
|
66
|
+
method,
|
|
67
|
+
headers: {
|
|
68
|
+
Authorization: `Bearer ${token}`,
|
|
69
|
+
Accept: 'application/json',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
if (body !== undefined) {
|
|
73
|
+
init.headers['Content-Type'] = 'application/json';
|
|
74
|
+
init.body = JSON.stringify(body);
|
|
75
|
+
}
|
|
76
|
+
const res = await fetch(url, init);
|
|
77
|
+
const requestId = pickRequestId(res.headers);
|
|
78
|
+
let payload = null;
|
|
79
|
+
const text = await res.text();
|
|
80
|
+
if (text.length > 0) {
|
|
81
|
+
try { payload = JSON.parse(text); } catch { payload = { rawText: text.slice(0, 200) }; }
|
|
82
|
+
}
|
|
83
|
+
return { status: res.status, ok: res.ok, requestId, payload };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function gateResult(varName, value) {
|
|
87
|
+
if (value === undefined || value === '') return { kind: 'unset', reason: varName };
|
|
88
|
+
if (value !== 'true') return { kind: 'set-not-true', reason: `${varName}_SET_NOT_TRUE`, observedValue: value };
|
|
89
|
+
return { kind: 'true' };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export default async function runProbe() {
|
|
93
|
+
const gate = gateResult('CI_HAS_CLERK_ACCOUNT', process.env.CI_HAS_CLERK_ACCOUNT);
|
|
94
|
+
if (gate.kind === 'unset') {
|
|
95
|
+
return {
|
|
96
|
+
results: [accountBoundSkippedResult(null, capability, 'CI_HAS_CLERK_ACCOUNT')],
|
|
97
|
+
extra: { accountBoundSkipped: true, reason: 'CI_HAS_CLERK_ACCOUNT', envDeclared: [...DECLARED_ENV] },
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (gate.kind === 'set-not-true') {
|
|
101
|
+
return {
|
|
102
|
+
results: [{
|
|
103
|
+
anchorAcId: null, capability, verdict: 'fail',
|
|
104
|
+
conformanceOnly: true, limitation: DECLAIM_LIMITATION,
|
|
105
|
+
detail: `conformance-only: CI_HAS_CLERK_ACCOUNT is set to "${gate.observedValue}" (not the string "true"). Gate refuses this shape; set the variable to the exact string "true" to run the live branch.`,
|
|
106
|
+
evidence: { gate: 'CI_HAS_CLERK_ACCOUNT', observedValue: gate.observedValue, expected: 'true' },
|
|
107
|
+
}],
|
|
108
|
+
extra: { gateMisconfigured: true, gate: 'CI_HAS_CLERK_ACCOUNT', envDeclared: [...DECLARED_ENV] },
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (!process.env.CLERK_SECRET_KEY) {
|
|
112
|
+
return {
|
|
113
|
+
results: [accountBoundSkippedResult(null, capability, 'CLERK_SECRET_KEY')],
|
|
114
|
+
extra: { accountBoundSkipped: true, reason: 'CLERK_SECRET_KEY', envDeclared: [...DECLARED_ENV] },
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const baseUrl = process.env.CLERK_API_BASE_URL || BASE_URL_DEFAULT;
|
|
119
|
+
const token = process.env.CLERK_SECRET_KEY;
|
|
120
|
+
const runId = process.env.GITHUB_RUN_ID || `local-${Date.now()}`;
|
|
121
|
+
const short = shortRandom();
|
|
122
|
+
const emailAddress = `${SCRATCH_PRINCIPAL_PREFIX}${short}+clerk_test@example.com`;
|
|
123
|
+
|
|
124
|
+
const evidence = {
|
|
125
|
+
envDeclared: [...DECLARED_ENV],
|
|
126
|
+
baseUrl,
|
|
127
|
+
scratchEmailAddress: emailAddress,
|
|
128
|
+
runId,
|
|
129
|
+
calls: [],
|
|
130
|
+
};
|
|
131
|
+
const resultRow = { anchorAcId: null, conformanceOnly: true, limitation: DECLAIM_LIMITATION, capability, verdict: 'fail', detail: '', evidence: {} };
|
|
132
|
+
let createdUserId = null;
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const created = await clerkFetch({
|
|
136
|
+
baseUrl,
|
|
137
|
+
path: '/users',
|
|
138
|
+
method: 'POST',
|
|
139
|
+
token,
|
|
140
|
+
body: {
|
|
141
|
+
email_address: [emailAddress],
|
|
142
|
+
first_name: 'ProbeUser',
|
|
143
|
+
last_name: short,
|
|
144
|
+
username: `probe_clerk_${short}`,
|
|
145
|
+
skip_password_requirement: true,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
evidence.calls.push({ verb: 'POST /users', status: created.status, requestId: created.requestId, resourceId: created.payload && created.payload.id });
|
|
149
|
+
if (!created.ok || !(created.payload && created.payload.id)) {
|
|
150
|
+
resultRow.detail = `POST /v1/users failed: status=${created.status} requestId=${created.requestId} payloadKeys=${JSON.stringify(Object.keys(created.payload || {}))} bodyExcerpt=${JSON.stringify(created.payload).slice(0, 200)}`;
|
|
151
|
+
return { results: [resultRow], extra: evidence };
|
|
152
|
+
}
|
|
153
|
+
createdUserId = created.payload.id;
|
|
154
|
+
evidence.createdUserId = createdUserId;
|
|
155
|
+
|
|
156
|
+
const readBack = await clerkFetch({ baseUrl, path: `/users/${createdUserId}`, method: 'GET', token });
|
|
157
|
+
evidence.calls.push({ verb: `GET /users/${createdUserId}`, status: readBack.status, requestId: readBack.requestId, resourceId: readBack.payload && readBack.payload.id });
|
|
158
|
+
const readOk = readBack.ok && readBack.payload && readBack.payload.id === createdUserId;
|
|
159
|
+
|
|
160
|
+
const listPre = await clerkFetch({ baseUrl, path: `/users?limit=200&order_by=-created_at`, method: 'GET', token });
|
|
161
|
+
const listedIdsPre = Array.isArray(listPre.payload) ? listPre.payload.map((u) => u.id) : [];
|
|
162
|
+
evidence.calls.push({ verb: 'GET /users?limit=200 (pre-delete)', status: listPre.status, requestId: listPre.requestId, listedCount: listedIdsPre.length, foundScratch: listedIdsPre.includes(createdUserId) });
|
|
163
|
+
const listPreOk = listPre.ok && listedIdsPre.includes(createdUserId);
|
|
164
|
+
|
|
165
|
+
const deleted = await clerkFetch({ baseUrl, path: `/users/${createdUserId}`, method: 'DELETE', token });
|
|
166
|
+
evidence.calls.push({ verb: `DELETE /users/${createdUserId}`, status: deleted.status, requestId: deleted.requestId });
|
|
167
|
+
const deleteOk = deleted.ok;
|
|
168
|
+
|
|
169
|
+
const listPost = await clerkFetch({ baseUrl, path: `/users?limit=200&order_by=-created_at`, method: 'GET', token });
|
|
170
|
+
const listedIdsPost = Array.isArray(listPost.payload) ? listPost.payload.map((u) => u.id) : [];
|
|
171
|
+
evidence.calls.push({ verb: 'GET /users?limit=200 (post-delete)', status: listPost.status, requestId: listPost.requestId, listedCount: listedIdsPost.length, foundScratch: listedIdsPost.includes(createdUserId) });
|
|
172
|
+
const listPostOk = listPost.ok && !listedIdsPost.includes(createdUserId);
|
|
173
|
+
|
|
174
|
+
if (readOk && listPreOk && deleteOk && listPostOk) {
|
|
175
|
+
resultRow.verdict = 'pass';
|
|
176
|
+
resultRow.detail =
|
|
177
|
+
`Clerk Backend API users surface observation: created ${createdUserId} (POST status ${created.status}, requestId ${created.requestId}); ` +
|
|
178
|
+
`readBack GET ${readBack.status} (requestId ${readBack.requestId}); listPre observed ${listedIdsPre.length} users, created id present; ` +
|
|
179
|
+
`DELETE ${deleted.status} (requestId ${deleted.requestId}); listPost observed ${listedIdsPost.length} users, created id absent.`;
|
|
180
|
+
resultRow.evidence = {
|
|
181
|
+
createdUserId,
|
|
182
|
+
createStatus: created.status, createRequestId: created.requestId,
|
|
183
|
+
readBackStatus: readBack.status, readBackRequestId: readBack.requestId,
|
|
184
|
+
listPreCount: listedIdsPre.length, listPreContainsCreated: listPreOk,
|
|
185
|
+
deleteStatus: deleted.status, deleteRequestId: deleted.requestId,
|
|
186
|
+
listPostCount: listedIdsPost.length, listPostAbsence: listPostOk,
|
|
187
|
+
};
|
|
188
|
+
createdUserId = null;
|
|
189
|
+
} else {
|
|
190
|
+
resultRow.evidence = { calls: evidence.calls }; resultRow.detail = `one or more Backend API calls failed: readOk=${readOk} listPreOk=${listPreOk} deleteOk=${deleteOk} listPostOk=${listPostOk}; calls=${JSON.stringify(evidence.calls)}`;
|
|
191
|
+
}
|
|
192
|
+
} catch (err) {
|
|
193
|
+
resultRow.detail = `probe threw: ${err && err.message ? err.message : String(err)}`;
|
|
194
|
+
resultRow.evidence = { threw: err && err.message ? err.message : String(err) };
|
|
195
|
+
evidence.threw = err && err.message ? err.message : String(err);
|
|
196
|
+
} finally {
|
|
197
|
+
if (createdUserId) {
|
|
198
|
+
try {
|
|
199
|
+
const teardown = await clerkFetch({ baseUrl, path: `/users/${createdUserId}`, method: 'DELETE', token });
|
|
200
|
+
evidence.teardownDelete = { status: teardown.status, requestId: teardown.requestId };
|
|
201
|
+
if (!teardown.ok) {
|
|
202
|
+
resultRow.verdict = 'fail';
|
|
203
|
+
resultRow.detail = (resultRow.detail ? resultRow.detail + ' ' : '') +
|
|
204
|
+
`TEARDOWN FAILED leaving orphan user ${createdUserId}: DELETE status=${teardown.status} requestId=${teardown.requestId}. This run is FAIL-WITH-ORPHAN.`;
|
|
205
|
+
evidence.orphanUserId = createdUserId;
|
|
206
|
+
}
|
|
207
|
+
} catch (err) {
|
|
208
|
+
resultRow.verdict = 'fail';
|
|
209
|
+
resultRow.detail = (resultRow.detail ? resultRow.detail + ' ' : '') +
|
|
210
|
+
`TEARDOWN THREW: ${err && err.message ? err.message : String(err)} leaving orphan user ${createdUserId}.`;
|
|
211
|
+
evidence.orphanUserId = createdUserId;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return { results: [resultRow], extra: evidence };
|
|
216
|
+
}
|
package/blueprints/security-auth-clerk/contributions/probes/real-account-session-inventory.mjs
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
// Real-account sign-in-token surface smoke for security-auth-clerk.
|
|
2
|
+
//
|
|
3
|
+
// Scope of observation. The blueprint's session-inventory ACs bind
|
|
4
|
+
// authenticated browser sessions and inventory operations that
|
|
5
|
+
// Clerk's Backend API cannot author from the server side (Sessions
|
|
6
|
+
// are created by Clerk's Frontend API in a browser flow; the
|
|
7
|
+
// Backend API exposes only list/get/revoke/refresh/verify). This
|
|
8
|
+
// probe therefore does not observe the session-inventory
|
|
9
|
+
// properties AC-9112-1, AC-9112-3, AC-9112-4 or AC-9112-5 name;
|
|
10
|
+
// each row is emitted with `anchorAcId: null` and a limitation
|
|
11
|
+
// citing the nearest shipped session-inventory AC whose runtime
|
|
12
|
+
// property the probe does not observe.
|
|
13
|
+
//
|
|
14
|
+
// What THIS probe drives at the Backend API surface. Create a
|
|
15
|
+
// scratch user; mint a sign-in token for that user with
|
|
16
|
+
// `POST /v1/sign_in_tokens`; capture the returned token id; revoke
|
|
17
|
+
// it with `POST /v1/sign_in_tokens/{id}/revoke`; re-fetch the
|
|
18
|
+
// token to observe the `revoked` status flip (or 404). Delete the
|
|
19
|
+
// user in the finally block. Positive evidence per rule 7d is
|
|
20
|
+
// preserved: the Clerk-assigned token id (created-then-revoked
|
|
21
|
+
// resource id in the token's lifecycle state, shape 3), and the
|
|
22
|
+
// HTTP statuses. The probe reads the X-Request-Id header from each
|
|
23
|
+
// response and records it on every call, but Clerk's Backend API
|
|
24
|
+
// did not return that header on the instance these records were
|
|
25
|
+
// captured from, so every request-id field is null; the evidence
|
|
26
|
+
// rests on the token lifecycle transitions and response statuses
|
|
27
|
+
// rather than on request-id capture.
|
|
28
|
+
//
|
|
29
|
+
// engine: clerk-backend-api (live) or skip:CI_HAS_CLERK_ACCOUNT.
|
|
30
|
+
// accountBound: true.
|
|
31
|
+
|
|
32
|
+
import { DECLARED_ENV, SCRATCH_PRINCIPAL_PREFIX, accountBoundSkippedResult } from './probe-utils.mjs';
|
|
33
|
+
|
|
34
|
+
export const anchorAcId = null;
|
|
35
|
+
export const capability = 'sessionInventory';
|
|
36
|
+
export const accountBound = true;
|
|
37
|
+
const LIM_MINT = 'security-auth-clerk-AC-9112-3: probe drives the Backend API sign-in-token mint from a probe process; the AC binds revokeAllExceptCurrent semantics on the project session-inventory interface, which requires a browser-driven runner (the integration harness follow-up).';
|
|
38
|
+
const LIM_REVOKE = 'security-auth-clerk-AC-9112-4: probe drives the Backend API sign-in-token revoke from a probe process; the AC binds SESSION_INVENTORY_UNAUTHENTICATED refusal at the project inventory operations, which requires a browser-driven runner (the integration harness follow-up).';
|
|
39
|
+
const LIM_NOT_OBS_1 = 'security-auth-clerk-AC-9112-1: two shaped active sessions cannot be authored server-side against the Clerk Backend API; the AC needs a browser-driven runner (the integration harness follow-up).';
|
|
40
|
+
const LIM_NOT_OBS_5 = 'security-auth-clerk-AC-9112-5: revoke against an unowned or already-revoked session id cannot be authored server-side against the Backend API; the AC needs a browser-driven runner (the integration harness follow-up).';
|
|
41
|
+
|
|
42
|
+
const BASE_URL_DEFAULT = 'https://api.clerk.com/v1';
|
|
43
|
+
|
|
44
|
+
function shortRandom() {
|
|
45
|
+
return Math.random().toString(36).slice(2, 10);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function pickRequestId(headers) {
|
|
49
|
+
return (
|
|
50
|
+
headers.get('x-request-id') ||
|
|
51
|
+
headers.get('cf-request-id') ||
|
|
52
|
+
headers.get('x-clerk-request-id') ||
|
|
53
|
+
null
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function clerkFetch({ baseUrl, path, method, body, form, token }) {
|
|
58
|
+
const url = `${baseUrl}${path}`;
|
|
59
|
+
const init = {
|
|
60
|
+
method,
|
|
61
|
+
headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
|
|
62
|
+
};
|
|
63
|
+
if (body !== undefined) {
|
|
64
|
+
init.headers['Content-Type'] = 'application/json';
|
|
65
|
+
init.body = JSON.stringify(body);
|
|
66
|
+
} else if (form !== undefined) {
|
|
67
|
+
init.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
68
|
+
init.body = form.toString();
|
|
69
|
+
}
|
|
70
|
+
const res = await fetch(url, init);
|
|
71
|
+
const requestId = pickRequestId(res.headers);
|
|
72
|
+
let payload = null;
|
|
73
|
+
const text = await res.text();
|
|
74
|
+
if (text.length > 0) {
|
|
75
|
+
try { payload = JSON.parse(text); } catch { payload = { rawText: text.slice(0, 200) }; }
|
|
76
|
+
}
|
|
77
|
+
return { status: res.status, ok: res.ok, requestId, payload };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function gateResult(varName, value) {
|
|
81
|
+
if (value === undefined || value === '') return { kind: 'unset', reason: varName };
|
|
82
|
+
if (value !== 'true') return { kind: 'set-not-true', reason: `${varName}_SET_NOT_TRUE`, observedValue: value };
|
|
83
|
+
return { kind: 'true' };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default async function runProbe() {
|
|
87
|
+
const gate = gateResult('CI_HAS_CLERK_ACCOUNT', process.env.CI_HAS_CLERK_ACCOUNT);
|
|
88
|
+
if (gate.kind === 'unset') {
|
|
89
|
+
return {
|
|
90
|
+
results: [accountBoundSkippedResult(null, capability, 'CI_HAS_CLERK_ACCOUNT')],
|
|
91
|
+
extra: { accountBoundSkipped: true, reason: 'CI_HAS_CLERK_ACCOUNT', envDeclared: [...DECLARED_ENV] },
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
if (gate.kind === 'set-not-true') {
|
|
95
|
+
return {
|
|
96
|
+
results: [{
|
|
97
|
+
anchorAcId: null, capability, verdict: 'fail',
|
|
98
|
+
conformanceOnly: true, limitation: LIM_MINT,
|
|
99
|
+
detail: `conformance-only: CI_HAS_CLERK_ACCOUNT is set to "${gate.observedValue}" (not the string "true"). Gate refuses this shape; set the variable to the exact string "true" to run the live branch.`,
|
|
100
|
+
evidence: { gate: 'CI_HAS_CLERK_ACCOUNT', observedValue: gate.observedValue, expected: 'true' },
|
|
101
|
+
}],
|
|
102
|
+
extra: { gateMisconfigured: true, gate: 'CI_HAS_CLERK_ACCOUNT', envDeclared: [...DECLARED_ENV] },
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (!process.env.CLERK_SECRET_KEY) {
|
|
106
|
+
return {
|
|
107
|
+
results: [accountBoundSkippedResult(null, capability, 'CLERK_SECRET_KEY')],
|
|
108
|
+
extra: { accountBoundSkipped: true, reason: 'CLERK_SECRET_KEY', envDeclared: [...DECLARED_ENV] },
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const baseUrl = process.env.CLERK_API_BASE_URL || BASE_URL_DEFAULT;
|
|
113
|
+
const token = process.env.CLERK_SECRET_KEY;
|
|
114
|
+
const short = shortRandom();
|
|
115
|
+
const emailAddress = `${SCRATCH_PRINCIPAL_PREFIX}sess-${short}+clerk_test@example.com`;
|
|
116
|
+
|
|
117
|
+
const evidence = { envDeclared: [...DECLARED_ENV], baseUrl, scratchEmailAddress: emailAddress, calls: [] };
|
|
118
|
+
const results = [];
|
|
119
|
+
const rowSignIn = { anchorAcId: null, conformanceOnly: true, limitation: LIM_MINT, capability, verdict: 'fail', detail: '' };
|
|
120
|
+
const rowRevoke = { anchorAcId: null, conformanceOnly: true, limitation: LIM_REVOKE, capability, verdict: 'fail', detail: '' };
|
|
121
|
+
const rowNotObservable1 = {
|
|
122
|
+
anchorAcId: null,
|
|
123
|
+
conformanceOnly: true,
|
|
124
|
+
limitation: LIM_NOT_OBS_1,
|
|
125
|
+
capability,
|
|
126
|
+
verdict: 'pass',
|
|
127
|
+
detail:
|
|
128
|
+
'AC-9112-1 (two shaped active sessions per Backend API list()) is not observable at the Backend API surface: Clerk creates authenticated sessions via the Frontend API in a browser flow, and the Backend API exposes only list/get/revoke/refresh/verify on Sessions (no server-side session-create). Full AC-9112-1 observation requires a shelf-level browser-driven auth harness, tracked as a separate follow-up.',
|
|
129
|
+
evidence: {
|
|
130
|
+
notObservableACs: ['security-auth-clerk-AC-9112-1'],
|
|
131
|
+
notObservableReason: 'Clerk Backend API cannot create authenticated browser sessions from the server side; observation requires a Frontend-API-driven browser flow.',
|
|
132
|
+
docsUrl: 'https://clerk.com/docs/reference/backend-api',
|
|
133
|
+
docsVerifiedOn: '2026-09-11',
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
const rowNotObservable5 = {
|
|
137
|
+
anchorAcId: null,
|
|
138
|
+
conformanceOnly: true,
|
|
139
|
+
limitation: LIM_NOT_OBS_5,
|
|
140
|
+
capability,
|
|
141
|
+
verdict: 'pass',
|
|
142
|
+
detail:
|
|
143
|
+
'AC-9112-5 (revoke against an unowned or already-revoked session id refuses with SESSION_INVENTORY_UNKNOWN_SESSION and audit event) is not observable at the Backend API surface: the AC is bound to the project session-inventory interface driven from an authenticated caller, and the Backend API cannot create such an authenticated caller server-side. Full AC-9112-5 observation requires a shelf-level browser-driven auth harness, tracked as a separate follow-up.',
|
|
144
|
+
evidence: {
|
|
145
|
+
notObservableACs: ['security-auth-clerk-AC-9112-5'],
|
|
146
|
+
notObservableReason: 'AC-9112-5 binds a project session-inventory refusal that requires an authenticated project caller; the Backend API cannot create one server-side.',
|
|
147
|
+
docsUrl: 'https://clerk.com/docs/reference/backend-api',
|
|
148
|
+
docsVerifiedOn: '2026-09-11',
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
let createdUserId = null;
|
|
152
|
+
let createdTokenId = null;
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const created = await clerkFetch({
|
|
156
|
+
baseUrl, path: '/users', method: 'POST', token,
|
|
157
|
+
body: {
|
|
158
|
+
email_address: [emailAddress],
|
|
159
|
+
first_name: 'ProbeUser', last_name: short,
|
|
160
|
+
username: `probe_clerk_${short}`,
|
|
161
|
+
skip_password_requirement: true,
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
evidence.calls.push({ verb: 'POST /users', status: created.status, requestId: created.requestId, resourceId: created.payload && created.payload.id });
|
|
165
|
+
if (!created.ok || !(created.payload && created.payload.id)) {
|
|
166
|
+
rowSignIn.detail = `precondition POST /v1/users failed status=${created.status} requestId=${created.requestId} bodyExcerpt=${JSON.stringify(created.payload).slice(0, 200)}`;
|
|
167
|
+
rowSignIn.evidence = { call: evidence.calls[evidence.calls.length - 1] };
|
|
168
|
+
rowRevoke.detail = 'skipped: precondition POST /users failed';
|
|
169
|
+
rowRevoke.evidence = { skipped: 'precondition failed' };
|
|
170
|
+
results.push(rowSignIn, rowRevoke, rowNotObservable1, rowNotObservable5);
|
|
171
|
+
return { results, extra: evidence };
|
|
172
|
+
}
|
|
173
|
+
createdUserId = created.payload.id;
|
|
174
|
+
evidence.createdUserId = createdUserId;
|
|
175
|
+
|
|
176
|
+
const mint = await clerkFetch({
|
|
177
|
+
baseUrl, path: '/sign_in_tokens', method: 'POST', token,
|
|
178
|
+
body: { user_id: createdUserId, expires_in_seconds: 300 },
|
|
179
|
+
});
|
|
180
|
+
evidence.calls.push({
|
|
181
|
+
verb: 'POST /sign_in_tokens', status: mint.status, requestId: mint.requestId,
|
|
182
|
+
resourceId: mint.payload && mint.payload.id, status_flag: mint.payload && mint.payload.status,
|
|
183
|
+
});
|
|
184
|
+
const mintOk = mint.ok && mint.payload && typeof mint.payload.id === 'string' && mint.payload.status === 'pending';
|
|
185
|
+
createdTokenId = (mint.payload && mint.payload.id) || null;
|
|
186
|
+
rowSignIn.verdict = mintOk ? 'pass' : 'fail';
|
|
187
|
+
rowSignIn.detail = mintOk
|
|
188
|
+
? `Clerk Backend API sign-in-token mint observed: POST /v1/sign_in_tokens user_id=${createdUserId} status=${mint.status} requestId=${mint.requestId} tokenId=${createdTokenId} tokenStatus=pending.`
|
|
189
|
+
: `Clerk Backend API sign-in-token mint failed: status=${mint.status} requestId=${mint.requestId} bodyExcerpt=${JSON.stringify(mint.payload).slice(0, 200)}`;
|
|
190
|
+
rowSignIn.evidence = {
|
|
191
|
+
requestId: mint.requestId,
|
|
192
|
+
status: mint.status,
|
|
193
|
+
tokenId: createdTokenId,
|
|
194
|
+
tokenStatus: mint.payload && mint.payload.status,
|
|
195
|
+
createdUserId,
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
if (!createdTokenId) {
|
|
199
|
+
rowRevoke.detail = 'skipped: mint did not return a token id';
|
|
200
|
+
rowRevoke.evidence = { skipped: 'no tokenId' };
|
|
201
|
+
results.push(rowSignIn, rowRevoke, rowNotObservable1, rowNotObservable5);
|
|
202
|
+
return { results, extra: evidence };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const revoked = await clerkFetch({
|
|
206
|
+
baseUrl, path: `/sign_in_tokens/${createdTokenId}/revoke`, method: 'POST', token,
|
|
207
|
+
});
|
|
208
|
+
evidence.calls.push({
|
|
209
|
+
verb: `POST /sign_in_tokens/${createdTokenId}/revoke`, status: revoked.status, requestId: revoked.requestId,
|
|
210
|
+
status_flag: revoked.payload && revoked.payload.status,
|
|
211
|
+
});
|
|
212
|
+
const readBack = await clerkFetch({
|
|
213
|
+
baseUrl, path: `/sign_in_tokens/${createdTokenId}`, method: 'GET', token,
|
|
214
|
+
});
|
|
215
|
+
evidence.calls.push({
|
|
216
|
+
verb: `GET /sign_in_tokens/${createdTokenId}`, status: readBack.status, requestId: readBack.requestId,
|
|
217
|
+
status_flag: readBack.payload && readBack.payload.status,
|
|
218
|
+
});
|
|
219
|
+
const revokedFlag = readBack.payload && (readBack.payload.status === 'revoked' || readBack.payload.revoked === true);
|
|
220
|
+
const goneAfterRevoke = revokedFlag || readBack.status === 404 || readBack.status === 410;
|
|
221
|
+
const revokeOk = revoked.ok && goneAfterRevoke;
|
|
222
|
+
rowRevoke.verdict = revokeOk ? 'pass' : 'fail';
|
|
223
|
+
rowRevoke.detail = revokeOk
|
|
224
|
+
? `Clerk Backend API sign-in-token revoke observed: revoke POST status=${revoked.status} requestId=${revoked.requestId}; re-fetch status=${readBack.status} tokenStatus=${readBack.payload && readBack.payload.status || (readBack.status === 404 ? 'gone-404' : 'unknown')}; the created-then-revoked tokenId (${createdTokenId}) records the Backend API lifecycle transition (404 after revoke means the resource no longer resolves).`
|
|
225
|
+
: `Clerk Backend API sign-in-token revoke failed: revokeStatus=${revoked.status} readBackStatus=${readBack.status} readBackStatusFlag=${readBack.payload && readBack.payload.status}`;
|
|
226
|
+
rowRevoke.evidence = {
|
|
227
|
+
revokeStatus: revoked.status,
|
|
228
|
+
revokeRequestId: revoked.requestId,
|
|
229
|
+
readBackStatus: readBack.status,
|
|
230
|
+
readBackRequestId: readBack.requestId,
|
|
231
|
+
readBackTokenStatus: readBack.payload && readBack.payload.status,
|
|
232
|
+
tokenId: createdTokenId,
|
|
233
|
+
createdThenRevokedTokenId: createdTokenId,
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
results.push(rowSignIn, rowRevoke, rowNotObservable1, rowNotObservable5);
|
|
237
|
+
} catch (err) {
|
|
238
|
+
rowSignIn.detail = `probe threw: ${err && err.message ? err.message : String(err)}`;
|
|
239
|
+
rowSignIn.evidence = { threw: err && err.message ? err.message : String(err) };
|
|
240
|
+
rowRevoke.detail = 'skipped: probe threw before completing';
|
|
241
|
+
rowRevoke.evidence = { skipped: 'threw' };
|
|
242
|
+
results.push(rowSignIn, rowRevoke, rowNotObservable1, rowNotObservable5);
|
|
243
|
+
evidence.threw = err && err.message ? err.message : String(err);
|
|
244
|
+
} finally {
|
|
245
|
+
if (createdUserId) {
|
|
246
|
+
try {
|
|
247
|
+
const teardown = await clerkFetch({ baseUrl, path: `/users/${createdUserId}`, method: 'DELETE', token });
|
|
248
|
+
evidence.teardownDelete = { status: teardown.status, requestId: teardown.requestId };
|
|
249
|
+
if (!teardown.ok) {
|
|
250
|
+
for (const r of results) { r.verdict = 'fail'; r.detail = (r.detail || '') + ` TEARDOWN FAILED leaving orphan user ${createdUserId}: status=${teardown.status} requestId=${teardown.requestId}.`; }
|
|
251
|
+
evidence.orphanUserId = createdUserId;
|
|
252
|
+
}
|
|
253
|
+
} catch (err) {
|
|
254
|
+
for (const r of results) { r.verdict = 'fail'; r.detail = (r.detail || '') + ` TEARDOWN THREW: ${err && err.message ? err.message : String(err)} leaving orphan user ${createdUserId}.`; }
|
|
255
|
+
evidence.orphanUserId = createdUserId;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return { results, extra: evidence };
|
|
260
|
+
}
|