rcf-lite 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +10 -0
- package/bin/rcf.js +2 -0
- package/blueprints/application-account-settings/CHANGELOG.md +35 -6
- package/blueprints/application-account-settings/README.md +1 -1
- package/blueprints/application-account-settings/blueprint.json +4 -2
- package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +1 -1
- package/blueprints/application-account-settings/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-account-settings/contributions/probes/profile-form-autocomplete.mjs +67 -0
- package/blueprints/application-account-settings/contributions/probes/run-profile-form-autocomplete.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-adapter-uniform.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-surface-shape.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-shell-tablist-per-capability.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-theme-radiogroup.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-adapter-uniform.mjs +130 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-surface-shape.mjs +70 -0
- package/blueprints/application-account-settings/contributions/probes/shell-tablist-per-capability.mjs +60 -0
- package/blueprints/application-account-settings/contributions/probes/theme-radiogroup.mjs +126 -0
- package/blueprints/application-admin-console/CHANGELOG.md +32 -6
- package/blueprints/application-admin-console/README.md +1 -1
- package/blueprints/application-admin-console/blueprint.json +4 -2
- package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +1 -1
- package/blueprints/application-admin-console/contributions/probes/audit-log-surface.mjs +79 -0
- package/blueprints/application-admin-console/contributions/probes/org-switcher-surface.mjs +83 -0
- package/blueprints/application-admin-console/contributions/probes/permission-matrix-grid.mjs +67 -0
- package/blueprints/application-admin-console/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-admin-console/contributions/probes/run-audit-log-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-org-switcher-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-permission-matrix-grid.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-sign-in-access-gated-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-users-directory-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/sign-in-access-gated-surface.mjs +117 -0
- package/blueprints/application-admin-console/contributions/probes/users-directory-surface.mjs +145 -0
- package/blueprints/application-api-rest/CHANGELOG.md +16 -8
- package/blueprints/application-api-rest/README.md +3 -3
- package/blueprints/application-api-rest/blueprint.json +3 -2
- package/blueprints/application-api-rest/contributions/adrs/adr-302-application-api-rest-auth-model.json +1 -1
- package/blueprints/application-api-rest/contributions/probes/cursor-pagination-round-trip.mjs +154 -0
- package/blueprints/application-api-rest/contributions/probes/health-probes-distinct.mjs +124 -0
- package/blueprints/application-api-rest/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-api-rest/contributions/probes/problem-details-on-error.mjs +77 -0
- package/blueprints/application-api-rest/contributions/probes/request-id-echoed.mjs +76 -0
- package/blueprints/application-api-rest/contributions/probes/run-cursor-pagination-round-trip.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-health-probes-distinct.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-problem-details-on-error.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-request-id-echoed.mjs +5 -0
- package/blueprints/application-api-rest/docs/topics.md +1 -1
- package/blueprints/application-charts/CHANGELOG.md +35 -9
- package/blueprints/application-charts/README.md +6 -6
- package/blueprints/application-charts/blueprint.json +5 -3
- package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +1 -1
- package/blueprints/application-charts/contributions/probes/keyboard-traversal.mjs +151 -0
- package/blueprints/application-charts/contributions/probes/non-colour-distinction.mjs +67 -0
- package/blueprints/application-charts/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-charts/contributions/probes/run-keyboard-traversal.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-non-colour-distinction.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-text-alternative-table.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/text-alternative-table.mjs +139 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +1 -1
- package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +1 -1
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +5 -5
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +1 -1
- package/blueprints/application-charts/guide/application-charts.md +1 -1
- package/blueprints/application-dashboard/CHANGELOG.md +20 -10
- package/blueprints/application-dashboard/README.md +6 -6
- package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +2 -2
- package/blueprints/application-dashboard/blueprint.json +3 -2
- package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +1 -1
- package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +1 -1
- package/blueprints/application-dashboard/contributions/probes/export-handle-formats.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/four-tile-states.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/primary-kpi-top-left.mjs +58 -0
- package/blueprints/application-dashboard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-dashboard/contributions/probes/run-export-handle-formats.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-four-tile-states.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-primary-kpi-top-left.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-shell-five-regions.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/shell-five-regions.mjs +93 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +1 -1
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +5 -5
- package/blueprints/application-dashboard/docs/topics.md +2 -2
- package/blueprints/application-dashboard/guide/application-dashboard.md +2 -2
- package/blueprints/application-datatable/CHANGELOG.md +19 -9
- package/blueprints/application-datatable/README.md +2 -2
- package/blueprints/application-datatable/blueprint.json +3 -2
- package/blueprints/application-datatable/contributions/probes/apg-table-shape.mjs +57 -0
- package/blueprints/application-datatable/contributions/probes/four-states-regions.mjs +80 -0
- package/blueprints/application-datatable/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-datatable/contributions/probes/run-apg-table-shape.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-four-states-regions.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-search-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-sort-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/search-adapter-round-trip.mjs +58 -0
- package/blueprints/application-datatable/contributions/probes/sort-adapter-round-trip.mjs +60 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +1 -1
- package/blueprints/application-datatable/docs/topics.md +1 -1
- package/blueprints/application-empty-error-states/CHANGELOG.md +33 -3
- package/blueprints/application-empty-error-states/blueprint.json +4 -2
- package/blueprints/application-empty-error-states/contributions/probes/empty-list-and-no-search.mjs +66 -0
- package/blueprints/application-empty-error-states/contributions/probes/error-boundary-alert.mjs +65 -0
- package/blueprints/application-empty-error-states/contributions/probes/forbidden-and-server-error.mjs +167 -0
- package/blueprints/application-empty-error-states/contributions/probes/not-found-and-recovery.mjs +61 -0
- package/blueprints/application-empty-error-states/contributions/probes/permission-denied-and-offline.mjs +155 -0
- package/blueprints/application-empty-error-states/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-empty-list-and-no-search.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-error-boundary-alert.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-forbidden-and-server-error.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-not-found-and-recovery.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-permission-denied-and-offline.mjs +5 -0
- package/blueprints/application-error-handling/CHANGELOG.md +45 -6
- package/blueprints/application-error-handling/blueprint.json +3 -2
- package/blueprints/application-error-handling/contributions/probes/category-vocabulary.mjs +90 -0
- package/blueprints/application-error-handling/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-error-handling/contributions/probes/record-shape-adr-1701.mjs +78 -0
- package/blueprints/application-error-handling/contributions/probes/run-category-vocabulary.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-record-shape-adr-1701.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-two-boundaries-registered.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/two-boundaries-registered.mjs +343 -0
- package/blueprints/application-file-upload/CHANGELOG.md +28 -6
- package/blueprints/application-file-upload/README.md +1 -1
- package/blueprints/application-file-upload/blueprint.json +3 -2
- package/blueprints/application-file-upload/contributions/probes/assertive-completion-slot.mjs +78 -0
- package/blueprints/application-file-upload/contributions/probes/chunked-transport-endpoints.mjs +173 -0
- package/blueprints/application-file-upload/contributions/probes/per-file-progressbar.mjs +124 -0
- package/blueprints/application-file-upload/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-file-upload/contributions/probes/run-assertive-completion-slot.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-chunked-transport-endpoints.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-per-file-progressbar.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-upload-surface-shape.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/upload-surface-shape.mjs +55 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +1 -1
- package/blueprints/application-file-upload/probe-packs/application-file-upload.pack.mjs +1 -1
- package/blueprints/application-forms-wizard/CHANGELOG.md +20 -6
- package/blueprints/application-forms-wizard/README.md +2 -2
- package/blueprints/application-forms-wizard/blueprint.json +3 -2
- package/blueprints/application-forms-wizard/contributions/probes/draft-persistence-round-trip.mjs +110 -0
- package/blueprints/application-forms-wizard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-draft-persistence-round-trip.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-step-page-shape.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-task-list-surface.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/step-page-shape.mjs +61 -0
- package/blueprints/application-forms-wizard/contributions/probes/task-list-surface.mjs +109 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +1 -1
- package/blueprints/application-forms-wizard/probe-packs/application-forms-wizard.pack.mjs +1 -1
- package/blueprints/application-notifications-in-app/CHANGELOG.md +38 -5
- package/blueprints/application-notifications-in-app/README.md +4 -4
- package/blueprints/application-notifications-in-app/blueprint.json +4 -2
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/probes/centre-acknowledge-round-trip.mjs +210 -0
- package/blueprints/application-notifications-in-app/contributions/probes/live-region-preseeding.mjs +93 -0
- package/blueprints/application-notifications-in-app/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-centre-acknowledge-round-trip.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-live-region-preseeding.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-toast-contract.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/toast-contract.mjs +92 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +3 -3
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +1 -1
- package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +3 -3
- package/blueprints/application-onboarding-tour/CHANGELOG.md +31 -5
- package/blueprints/application-onboarding-tour/README.md +1 -1
- package/blueprints/application-onboarding-tour/blueprint.json +5 -3
- package/blueprints/application-onboarding-tour/contributions/probes/checklist-anchor-open.mjs +81 -0
- package/blueprints/application-onboarding-tour/contributions/probes/completion-persistence.mjs +159 -0
- package/blueprints/application-onboarding-tour/contributions/probes/first-run-detection.mjs +67 -0
- package/blueprints/application-onboarding-tour/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-checklist-anchor-open.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-completion-persistence.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-first-run-detection.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-stepper-role-dialog.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/stepper-role-dialog.mjs +45 -0
- package/blueprints/application-spa/CHANGELOG.md +20 -11
- package/blueprints/application-spa/README.md +9 -10
- package/blueprints/application-spa/blueprint.json +3 -2
- package/blueprints/application-spa/contributions/adrs/adr-202-application-spa-theming.json +1 -1
- package/blueprints/application-spa/contributions/adrs/adr-206-application-spa-iconography.json +1 -1
- package/blueprints/application-spa/contributions/probes/designed-empty-state.mjs +72 -0
- package/blueprints/application-spa/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-spa/contributions/probes/route-inventory-published.mjs +185 -0
- package/blueprints/application-spa/contributions/probes/run-designed-empty-state.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-route-inventory-published.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-shell-nav-present.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/shell-nav-present.mjs +69 -0
- package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +1 -1
- package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +3 -3
- package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +2 -2
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +1 -1
- package/blueprints/application-spa/docs/topics.md +1 -1
- package/blueprints/delivery-ci-workflows/CHANGELOG.md +31 -11
- package/blueprints/delivery-ci-workflows/README.md +3 -3
- package/blueprints/delivery-ci-workflows/blueprint.json +3 -2
- package/blueprints/delivery-ci-workflows/contributions/adrs/adr-702-delivery-ci-workflows-strict-coverage-gate.json +2 -2
- package/blueprints/delivery-ci-workflows/contributions/probes/node-gate-entrypoint.mjs +76 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/probe-utils.mjs +56 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/real-account-github-actions-run-record.mjs +139 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-node-gate-entrypoint.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-real-account-github-actions-run-record.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-workflow-template-shape.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/workflow-template-shape.mjs +94 -0
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-004.json +1 -1
- package/blueprints/delivery-ci-workflows/docs/topics.md +2 -3
- package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +4 -4
- package/blueprints/deploy-cloudflare-workers/README.md +3 -3
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +2 -2
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +2 -2
- package/blueprints/deploy-hetzner-server/CHANGELOG.md +98 -7
- package/blueprints/deploy-hetzner-server/blueprint.json +7 -6
- package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +46 -21
- package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +344 -83
- package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +211 -42
- package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +140 -22
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +111 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +158 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +154 -32
- package/blueprints/edge-cloudflare-access/CHANGELOG.md +6 -5
- package/blueprints/edge-cloudflare-access/blueprint.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +9 -1
- package/blueprints/edge-cloudflare-access/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +4 -7
- package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +4 -6
- package/blueprints/edge-cloudflare-tunnel/README.md +1 -2
- package/blueprints/edge-cloudflare-tunnel/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +2 -3
- package/blueprints/edge-cloudflare-turnstile/docs/topics.md +1 -1
- package/blueprints/email-smtp-resend/CHANGELOG.md +24 -8
- package/blueprints/email-smtp-resend/README.md +2 -2
- package/blueprints/email-smtp-resend/blueprint.json +3 -2
- package/blueprints/email-smtp-resend/contributions/probes/probe-utils.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/real-account-resend-send.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-real-account-resend-send.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-smtp-round-trip.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-unverified-sender-refusal.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/smtp-round-trip.mjs +43 -0
- package/blueprints/email-smtp-resend/contributions/probes/unverified-sender-refusal.mjs +99 -0
- package/blueprints/email-smtp-resend/docs/topics.md +2 -3
- package/blueprints/jobs-background/CHANGELOG.md +66 -5
- package/blueprints/jobs-background/README.md +2 -2
- package/blueprints/jobs-background/blueprint.json +3 -2
- package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +38 -10
- package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +28 -6
- package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +16 -2
- package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +102 -21
- package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +10 -2
- package/blueprints/jobs-background/contributions/probes/retry-and-fail-real-account.mjs +355 -0
- package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +33 -2
- package/blueprints/jobs-background/contributions/probes/run-retry-and-fail-real-account.mjs +12 -0
- package/blueprints/jobs-background/docs/topics.md +1 -1
- package/blueprints/jobs-background/guide/jobs-background.md +1 -1
- package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +25 -19
- package/blueprints/messaging-queue-cloudflare/README.md +12 -12
- package/blueprints/messaging-queue-cloudflare/blueprint.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +2 -2
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +180 -12
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +1 -1
- package/blueprints/messaging-queue-cloudflare/docs/topics.md +2 -2
- package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +2 -2
- package/blueprints/object-storage-s3/CHANGELOG.md +75 -4
- package/blueprints/object-storage-s3/blueprint.json +3 -2
- package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +73 -12
- package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +55 -7
- package/blueprints/object-storage-s3/contributions/probes/hetzner-object-storage-round-trip.mjs +102 -18
- package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +105 -36
- package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +104 -55
- package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +129 -7
- package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +80 -18
- package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +291 -37
- package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +5 -5
- package/blueprints/object-storage-s3/contributions/probes/run-hetzner-object-storage-round-trip.mjs +8 -5
- package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +6 -3
- package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +10 -2
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +1 -1
- package/blueprints/object-storage-s3/docs/topics.md +1 -1
- package/blueprints/object-storage-s3/guide/object-storage-s3.md +1 -1
- package/blueprints/observability-essentials/CHANGELOG.md +23 -7
- package/blueprints/observability-essentials/README.md +2 -2
- package/blueprints/observability-essentials/assets/probe-samples/probe-response-baseline.v2.json +1 -1
- package/blueprints/observability-essentials/blueprint.json +3 -2
- package/blueprints/observability-essentials/contributions/probes/liveness-probe.mjs +84 -0
- package/blueprints/observability-essentials/contributions/probes/metrics-endpoint.mjs +96 -0
- package/blueprints/observability-essentials/contributions/probes/probe-utils.mjs +52 -0
- package/blueprints/observability-essentials/contributions/probes/readiness-probe.mjs +171 -0
- package/blueprints/observability-essentials/contributions/probes/run-liveness-probe.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-metrics-endpoint.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-readiness-probe.mjs +3 -0
- package/blueprints/observability-essentials/docs/topics.md +2 -3
- package/blueprints/observability-logging/CHANGELOG.md +29 -4
- package/blueprints/observability-logging/README.md +2 -2
- package/blueprints/observability-logging/blueprint.json +3 -2
- package/blueprints/observability-logging/contributions/probes/correlation-id-flow.mjs +173 -0
- package/blueprints/observability-logging/contributions/probes/line-shape-and-fields.mjs +82 -0
- package/blueprints/observability-logging/contributions/probes/probe-utils.mjs +47 -0
- package/blueprints/observability-logging/contributions/probes/redaction-boundary.mjs +130 -0
- package/blueprints/observability-logging/contributions/probes/run-correlation-id-flow.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-line-shape-and-fields.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-redaction-boundary.mjs +3 -0
- package/blueprints/observability-probe-endpoints/CHANGELOG.md +23 -8
- package/blueprints/observability-probe-endpoints/README.md +3 -3
- package/blueprints/observability-probe-endpoints/blueprint.json +3 -2
- package/blueprints/observability-probe-endpoints/contributions/probes/kubernetes-startup-enabled.mjs +80 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/partial-profile-refusal.mjs +101 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/probe-utils.mjs +49 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/profile-boot-materialisation.mjs +69 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-kubernetes-startup-enabled.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-partial-profile-refusal.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-profile-boot-materialisation.mjs +3 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +2 -2
- package/blueprints/persistence-data-d1/CHANGELOG.md +16 -3
- package/blueprints/persistence-data-d1/README.md +2 -2
- package/blueprints/persistence-data-d1/blueprint.json +3 -2
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1404-persistence-data-d1-store-boundary.json +1 -1
- package/blueprints/persistence-data-d1/contributions/probes/facade-round-trip.mjs +140 -0
- package/blueprints/persistence-data-d1/contributions/probes/migrations-forward-only.mjs +66 -0
- package/blueprints/persistence-data-d1/contributions/probes/probe-utils.mjs +51 -0
- package/blueprints/persistence-data-d1/contributions/probes/real-account-d1-round-trip.mjs +133 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-facade-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-migrations-forward-only.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-real-account-d1-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/docs/topics.md +2 -3
- package/blueprints/persistence-data-postgres/CHANGELOG.md +84 -4
- package/blueprints/persistence-data-postgres/README.md +2 -2
- package/blueprints/persistence-data-postgres/blueprint.json +3 -2
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +87 -12
- package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +245 -19
- package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +109 -26
- package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +151 -38
- package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +24 -6
- package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +261 -48
- package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +76 -20
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +1 -1
- package/blueprints/persistence-data-postgres/docs/topics.md +1 -1
- package/blueprints/persistence-data-sqlite/CHANGELOG.md +16 -2
- package/blueprints/persistence-data-sqlite/README.md +2 -2
- package/blueprints/persistence-data-sqlite/blueprint.json +3 -2
- package/blueprints/persistence-data-sqlite/contributions/probes/boot-open-migrate.mjs +90 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/facade-round-trip.mjs +82 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/probe-utils.mjs +83 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-boot-open-migrate.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-facade-round-trip.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-wal-checkpoint.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/wal-checkpoint.mjs +137 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +5 -5
- package/blueprints/platform-cloudflare-cron-triggers/README.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +6 -10
- package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-kv/CHANGELOG.md +16 -12
- package/blueprints/platform-cloudflare-kv/README.md +2 -4
- package/blueprints/platform-cloudflare-kv/blueprint.json +2 -2
- package/blueprints/platform-cloudflare-kv/docs/topics.md +1 -1
- package/blueprints/platform-docker-compose-host/CHANGELOG.md +92 -5
- package/blueprints/platform-docker-compose-host/blueprint.json +2 -2
- package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +116 -29
- package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +181 -109
- package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +146 -26
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +238 -24
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +207 -21
- package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +246 -42
- package/blueprints/platform-docker-compose-host/docs/topics.md +1 -1
- package/blueprints/security-auth-clerk/CHANGELOG.md +18 -6
- package/blueprints/security-auth-clerk/README.md +3 -3
- package/blueprints/security-auth-clerk/assets/wiring/workers-wrangler-toml-shape.md +1 -1
- package/blueprints/security-auth-clerk/blueprint.json +3 -2
- package/blueprints/security-auth-clerk/contributions/probes/hosted-identity-ui-config.mjs +61 -0
- package/blueprints/security-auth-clerk/contributions/probes/probe-utils.mjs +188 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-principal-directory-round-trip.mjs +216 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-session-inventory.mjs +260 -0
- package/blueprints/security-auth-clerk/contributions/probes/role-model-adapter.mjs +53 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-hosted-identity-ui-config.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-principal-directory-round-trip.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-session-inventory.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-role-model-adapter.mjs +4 -0
- package/blueprints/security-auth-clerk/docs/topics.md +2 -3
- package/blueprints/security-auth-keycloak/CHANGELOG.md +18 -7
- package/blueprints/security-auth-keycloak/README.md +2 -2
- package/blueprints/security-auth-keycloak/blueprint.json +3 -2
- package/blueprints/security-auth-keycloak/contributions/probes/discovery-shape.mjs +68 -0
- package/blueprints/security-auth-keycloak/contributions/probes/introspection-shape.mjs +88 -0
- package/blueprints/security-auth-keycloak/contributions/probes/jwt-verifier-shape.mjs +86 -0
- package/blueprints/security-auth-keycloak/contributions/probes/probe-utils.mjs +180 -0
- package/blueprints/security-auth-keycloak/contributions/probes/real-account-realm-round-trip.mjs +91 -0
- package/blueprints/security-auth-keycloak/contributions/probes/role-adapter-shape.mjs +69 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-discovery-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-introspection-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-jwt-verifier-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-real-account-realm-round-trip.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-role-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/docs/topics.md +1 -2
- package/blueprints/security-auth-magic-link/CHANGELOG.md +15 -4
- package/blueprints/security-auth-magic-link/README.md +2 -2
- package/blueprints/security-auth-magic-link/assets/principal-registry-samples/single-address.md +1 -1
- package/blueprints/security-auth-magic-link/blueprint.json +3 -2
- package/blueprints/security-auth-magic-link/contributions/probes/probe-utils.mjs +174 -0
- package/blueprints/security-auth-magic-link/contributions/probes/real-account-magic-link-send.mjs +139 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-real-account-magic-link-send.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-entropy-shape.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-issue-verify.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-entropy-shape.mjs +60 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-issue-verify.mjs +90 -0
- package/blueprints/security-auth-magic-link/docs/topics.md +1 -1
- package/blueprints/security-auth-oauth2/CHANGELOG.md +16 -5
- package/blueprints/security-auth-oauth2/README.md +2 -2
- package/blueprints/security-auth-oauth2/blueprint.json +3 -2
- package/blueprints/security-auth-oauth2/contributions/probes/authorisation-code-flow-shape.mjs +259 -0
- package/blueprints/security-auth-oauth2/contributions/probes/pkce-challenge-shape.mjs +58 -0
- package/blueprints/security-auth-oauth2/contributions/probes/probe-utils.mjs +190 -0
- package/blueprints/security-auth-oauth2/contributions/probes/provider-adapter-shape.mjs +64 -0
- package/blueprints/security-auth-oauth2/contributions/probes/real-account-authorisation-code-flow.mjs +93 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-authorisation-code-flow-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-pkce-challenge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-provider-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-real-account-authorisation-code-flow.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-session-bridge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/session-bridge-shape.mjs +78 -0
- package/blueprints/security-auth-oauth2/docs/topics.md +1 -2
- package/blueprints/security-secrets-management/CHANGELOG.md +15 -4
- package/blueprints/security-secrets-management/README.md +2 -2
- package/blueprints/security-secrets-management/blueprint.json +3 -2
- package/blueprints/security-secrets-management/contributions/probes/add-recipient-rotation.mjs +107 -0
- package/blueprints/security-secrets-management/contributions/probes/encrypt-decrypt-round-trip.mjs +122 -0
- package/blueprints/security-secrets-management/contributions/probes/key-rotation.mjs +93 -0
- package/blueprints/security-secrets-management/contributions/probes/mismatched-key-refusal.mjs +74 -0
- package/blueprints/security-secrets-management/contributions/probes/probe-utils.mjs +214 -0
- package/blueprints/security-secrets-management/contributions/probes/run-add-recipient-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-encrypt-decrypt-round-trip.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-key-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-mismatched-key-refusal.mjs +4 -0
- package/blueprints/security-secrets-management/docs/topics.md +2 -3
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/harness-template.md +25 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +25 -0
- package/package.json +2 -2
- package/rcf/adrs/adr-4101-feedback-store-gitignored.json +20 -0
- package/rcf/adrs/adr-4102-fingerprint-and-labels.json +25 -0
- package/rcf/adrs/adr-4103-redaction-rule-based.json +20 -0
- package/rcf/adrs/adr-4104-destination-on-library.json +25 -0
- package/rcf/adrs/adr-4105-gh-ambient-auth.json +20 -0
- package/rcf/adrs/adr-4106-bundled-entries-terminal.json +20 -0
- package/rcf/adrs/adr-4107-stop-is-ask-event.json +30 -0
- package/rcf/adrs/adr-4108-hooks-in-committed-config.json +25 -0
- package/rcf/adrs/adr-4109-referee-validate-adr-crosslinks.json +25 -0
- package/rcf/adrs/adr-4110-referee-coverage-strict-by-default.json +25 -0
- package/rcf/adrs/adr-4111-referee-finalise-refusals.json +20 -0
- package/rcf/adrs/adr-4112-referee-finalise-verified-invariant.json +30 -0
- package/rcf/code-nodes/cn-600.json +45 -0
- package/rcf/code-nodes/cn-601.json +18 -0
- package/rcf/code-nodes/cn-602.json +15 -0
- package/rcf/code-nodes/cn-603.json +12 -0
- package/rcf/code-nodes/cn-604.json +14 -0
- package/rcf/code-nodes/cn-605.json +17 -0
- package/rcf/code-nodes/cn-606.json +12 -0
- package/rcf/code-nodes/cn-607.json +12 -0
- package/rcf/code-nodes/cn-608.json +14 -0
- package/rcf/code-nodes/cn-609.json +17 -0
- package/rcf/code-nodes/cn-620.json +18 -0
- package/rcf/code-nodes/cn-621.json +14 -0
- package/rcf/code-nodes/cn-622.json +15 -0
- package/rcf/code-nodes/cn-623.json +16 -0
- package/rcf/code-nodes/cn-624.json +14 -0
- package/rcf/code-nodes/cn-625.json +15 -0
- package/rcf/code-nodes/cn-626.json +13 -0
- package/rcf/code-nodes/cn-627.json +13 -0
- package/rcf/code-nodes/cn-628.json +14 -0
- package/rcf/code-nodes/cn-629.json +12 -0
- package/rcf/code-nodes/cn-630.json +12 -0
- package/rcf/code-nodes/cn-631.json +13 -0
- package/rcf/code-nodes/cn-632.json +13 -0
- package/rcf/fbs/fbs-180.json +45 -0
- package/rcf/fbs/fbs-181.json +45 -0
- package/rcf/fbs/fbs-182.json +42 -0
- package/rcf/fbs/fbs-183.json +50 -0
- package/rcf/fbs/fbs-184.json +49 -0
- package/rcf/fbs/fbs-185.json +34 -0
- package/rcf/fbs/fbs-186.json +16 -0
- package/rcf/fbs/fbs-187.json +17 -0
- package/rcf/fbs/fbs-188.json +17 -0
- package/rcf/fbs/fbs-189.json +17 -0
- package/rcf/requirements/req-155.json +13 -0
- package/rcf/requirements/req-156.json +13 -0
- package/rcf/requirements/req-157.json +13 -0
- package/rcf/requirements/req-158.json +13 -0
- package/rcf/requirements/req-159.json +13 -0
- package/rcf/requirements/req-160.json +13 -0
- package/rcf/requirements/req-161.json +13 -0
- package/rcf/requirements/req-162.json +13 -0
- package/rcf/requirements/req-163.json +13 -0
- package/rcf/requirements/req-164.json +13 -0
- package/rcf/requirements/req-165.json +13 -0
- package/rcf/tacs/tac-4101-feedback-cli.json +77 -0
- package/rcf/tacs/tac-4102-feedback-store.json +50 -0
- package/rcf/tacs/tac-4103-feedback-redact.json +39 -0
- package/rcf/tacs/tac-4104-feedback-fingerprint.json +33 -0
- package/rcf/tacs/tac-4105-feedback-render.json +45 -0
- package/rcf/tacs/tac-4106-feedback-destination.json +39 -0
- package/rcf/tacs/tac-4107-feedback-gh.json +43 -0
- package/rcf/tacs/tac-4108-feedback-hook.json +46 -0
- package/rcf/tacs/tac-4109-referee-validate-adr-crosslinks.json +20 -0
- package/rcf/tacs/tac-4110-referee-coverage-mode-selector.json +21 -0
- package/rcf/tacs/tac-4111-referee-finalise-per-ac-refusals.json +21 -0
- package/rcf/tacs/tac-4112-referee-finalise-verified-invariant.json +22 -0
- package/rcf/test-suites/ts-140.json +9 -9
- package/rcf/test-suites/ts-150.json +9 -9
- package/rcf/test-suites/ts-185.json +54 -0
- package/rcf/test-suites/ts-186.json +58 -0
- package/rcf/test-suites/ts-187.json +44 -0
- package/rcf/test-suites/ts-188.json +166 -0
- package/rcf/test-suites/ts-189.json +38 -0
- package/rcf/test-suites/ts-190.json +30 -0
- package/rcf/test-suites/ts-191.json +51 -0
- package/rcf/test-suites/ts-192.json +37 -0
- package/rcf/test-suites/ts-193.json +60 -0
- package/rcf/test-suites/ts-194.json +67 -0
- package/rcf/test-suites/ts-195.json +52 -0
- package/rcf/test-suites/ts-196.json +58 -0
- package/rcf/test-suites/ts-197.json +66 -0
- package/rcf/test-suites/ts-198.json +87 -0
- package/rcf/test-suites/ts-199.json +51 -0
- package/rcf/test-suites/ts-200.json +30 -0
- package/rcf/test-suites/ts-201.json +38 -0
- package/rcf/test-suites/ts-202.json +38 -0
- package/rcf/test-suites/ts-203.json +38 -0
- package/rcf/user-stories/us-15501.json +60 -0
- package/rcf/user-stories/us-15502.json +33 -0
- package/rcf/user-stories/us-15503.json +33 -0
- package/rcf/user-stories/us-15601.json +51 -0
- package/rcf/user-stories/us-15701.json +42 -0
- package/rcf/user-stories/us-15801.json +42 -0
- package/rcf/user-stories/us-15802.json +33 -0
- package/rcf/user-stories/us-15901.json +33 -0
- package/rcf/user-stories/us-15902.json +51 -0
- package/rcf/user-stories/us-16001.json +51 -0
- package/rcf/user-stories/us-16101.json +42 -0
- package/rcf/user-stories/us-16102.json +33 -0
- package/rcf/user-stories/us-16103.json +42 -0
- package/rcf/user-stories/us-16104.json +42 -0
- package/rcf/user-stories/us-16201.json +33 -0
- package/rcf/user-stories/us-16301.json +36 -0
- package/rcf/user-stories/us-16401.json +45 -0
- package/rcf/user-stories/us-16501.json +45 -0
- package/rcf/user-stories/us-16502.json +45 -0
- package/releases/releases.yaml +11 -1
- package/src/blueprint/library-loader.js +48 -0
- package/src/blueprint/library-registry.js +13 -0
- package/src/browser-verify/pack-runner.js +7 -12
- package/src/build/mark.js +1 -1
- package/src/cli/blueprint-library.js +149 -0
- package/src/cli/coverage.js +49 -24
- package/src/cli/doctor.js +195 -7
- package/src/cli/feedback.js +2204 -0
- package/src/cli/finalise.js +158 -1
- package/src/cli/help.js +6 -0
- package/src/cli/init.js +63 -0
- package/src/cli/update.js +21 -1
- package/src/core/store/walker.js +33 -0
- package/src/core/store/writer.js +23 -0
- package/src/feedback/destination.js +361 -0
- package/src/feedback/fingerprint.js +132 -0
- package/src/feedback/gh.js +376 -0
- package/src/feedback/hook.js +183 -0
- package/src/feedback/labels.js +87 -0
- package/src/feedback/redact-allowlist.json +14 -0
- package/src/feedback/redact.js +1108 -0
- package/src/feedback/render.js +267 -0
- package/src/feedback/store.js +604 -0
- package/src/finalise/index.js +4 -0
- package/src/finalise/ingest.js +61 -0
- package/src/finalise/ship-without-eval.js +19 -7
- package/src/mcp/tools.js +8 -2
- package/src/setup/feedback-hooks.js +397 -0
- package/src/setup/managed-gitignore.js +3 -0
- package/src/view/html-page.js +5 -5
- package/src/view/style.css +2 -2
package/blueprints/application-account-settings/contributions/probes/sessions-surface-shape.mjs
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// application-account-settings probe: sessions surface renders under
|
|
2
|
+
// sessionInventory with data-session-id rows and required columns
|
|
3
|
+
// (AC-25105-1). Varies input: with vs without sessionInventory.
|
|
4
|
+
|
|
5
|
+
import { fixtureFetch, startFixture, excerpt } from './probe-utils.mjs';
|
|
6
|
+
|
|
7
|
+
export const anchorAcId = 'application-account-settings-AC-25105-1';
|
|
8
|
+
export const accountBound = false;
|
|
9
|
+
|
|
10
|
+
const FIRST_EIGHT = 'When sessionInventory is in the applied capability set,';
|
|
11
|
+
|
|
12
|
+
export default async function runProbe() {
|
|
13
|
+
const results = [];
|
|
14
|
+
const withCap = await startFixture({ env: { ACCOUNT_SETTINGS_CAPS: 'principalDirectory,sessionInventory' } });
|
|
15
|
+
try {
|
|
16
|
+
const r = await fixtureFetch(withCap.url, '/account/sessions');
|
|
17
|
+
const surface = /<div data-surface="sessions"/.test(r.body);
|
|
18
|
+
const rowIds = [...new Set([...r.body.matchAll(/data-session-id="([^"]+)"/g)].map((m) => m[1]))];
|
|
19
|
+
const deviceCells = (r.body.match(/data-column="device"/g) || []).length;
|
|
20
|
+
const lastActiveCells = (r.body.match(/data-column="lastActive"/g) || []).length;
|
|
21
|
+
const pass = r.status === 200 && !!r.requestId
|
|
22
|
+
&& surface
|
|
23
|
+
&& rowIds.length > 0
|
|
24
|
+
&& deviceCells === rowIds.length
|
|
25
|
+
&& lastActiveCells === rowIds.length;
|
|
26
|
+
results.push({
|
|
27
|
+
anchorAcId: null,
|
|
28
|
+
conformanceOnly: true,
|
|
29
|
+
limitation: 'application-account-settings-AC-25105-1: per-row terminate control wired to a session-termination API and its activation cycle (the AC clauses beyond the DOM shape) are not present in this fixture and not observed by this Node HTTP probe; the sessions-surface row + device + lastActive walk under sessionInventory is a partial observation of AC-25105-1',
|
|
30
|
+
verdict: pass ? 'warn' : 'fail',
|
|
31
|
+
detail: pass
|
|
32
|
+
? `${FIRST_EIGHT} GET /account/sessions returned 200 with data-surface="sessions" rendered; derived rows=${rowIds.length}, [data-column="device"] cells=${deviceCells}, [data-column="lastActive"] cells=${lastActiveCells} equal to row count (terminate control per row); x-fixture-request-id=${r.requestId}`
|
|
33
|
+
: `${FIRST_EIGHT} evidence gap: status=${r.status} rid=${r.requestId} surface=${surface} rows=${rowIds.length} device=${deviceCells} lastActive=${lastActiveCells}`,
|
|
34
|
+
evidence: {
|
|
35
|
+
requestId: r.requestId,
|
|
36
|
+
responseStatus: r.status,
|
|
37
|
+
bodyExcerpt: excerpt((r.body.match(/<div data-surface="sessions"[^]{0,240}/) || [''])[0]),
|
|
38
|
+
derived: { rowCount: rowIds.length, deviceCells, lastActiveCells },
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
} finally {
|
|
42
|
+
await withCap.kill();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const noCap = await startFixture({ env: { ACCOUNT_SETTINGS_CAPS: 'principalDirectory' } });
|
|
46
|
+
try {
|
|
47
|
+
const r = await fixtureFetch(noCap.url, '/account/sessions');
|
|
48
|
+
const surface = /<div data-surface="sessions"/.test(r.body);
|
|
49
|
+
const rowCount = (r.body.match(/data-session-id="[^"]+"/g) || []).length;
|
|
50
|
+
const pass = r.status === 200 && !!r.requestId && !surface && rowCount === 0;
|
|
51
|
+
results.push({
|
|
52
|
+
anchorAcId: null,
|
|
53
|
+
conformanceOnly: true,
|
|
54
|
+
limitation: 'application-account-settings-AC-25105-1: per-row terminate control wired to a session-termination API (the positive-branch contract the AC also carries) is not present in this fixture and not observed by this Node HTTP probe; the sessions-absence walk when sessionInventory is not applied is a partial observation of AC-25105-1',
|
|
55
|
+
verdict: pass ? 'warn' : 'fail',
|
|
56
|
+
detail: pass
|
|
57
|
+
? `${FIRST_EIGHT} absence branch: with sessionInventory not applied, AC-25105-1's stated "Absent when sessionInventory is not applied" clause is observed - no data-surface="sessions" subtree and no data-session-id rows render; x-fixture-request-id=${r.requestId}`
|
|
58
|
+
: `${FIRST_EIGHT} absence gap: status=${r.status} rid=${r.requestId} surface=${surface} rows=${rowCount}`,
|
|
59
|
+
evidence: {
|
|
60
|
+
requestId: r.requestId,
|
|
61
|
+
responseStatus: r.status,
|
|
62
|
+
bodyExcerpt: excerpt(r.body.slice(0, 240)),
|
|
63
|
+
derived: { surface, rowCount },
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
} finally {
|
|
67
|
+
await noCap.kill();
|
|
68
|
+
}
|
|
69
|
+
return { results };
|
|
70
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// application-account-settings probe: tabs shell renders one
|
|
2
|
+
// role="tab" per applied capability plus the always-on profile tab
|
|
3
|
+
// (AC-25101-1).
|
|
4
|
+
//
|
|
5
|
+
// Varied inputs: three caps configurations produce three different
|
|
6
|
+
// derived tab counts. The probe asserts the derived tab count on the
|
|
7
|
+
// rendered nav matches the sum of the always-on tab + the enabled
|
|
8
|
+
// capability tabs.
|
|
9
|
+
|
|
10
|
+
import { fixtureFetch, startFixture, excerpt } from './probe-utils.mjs';
|
|
11
|
+
|
|
12
|
+
export const anchorAcId = 'application-account-settings-AC-25101-1';
|
|
13
|
+
export const accountBound = false;
|
|
14
|
+
|
|
15
|
+
const FIRST_EIGHT = 'Given an authenticated principal AND an applied auth';
|
|
16
|
+
|
|
17
|
+
function countTabs(body) {
|
|
18
|
+
return (body.match(/<a role="tab"[^>]*>/g) || []).length;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function tabsFor(fixture, caps, apps) {
|
|
22
|
+
const q = new URLSearchParams({ caps: caps.join(','), apps: apps.join(',') });
|
|
23
|
+
const r = await fixtureFetch(fixture.url, `/account?${q.toString()}`);
|
|
24
|
+
return { r, count: countTabs(r.body) };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default async function runProbe() {
|
|
28
|
+
const fixture = await startFixture();
|
|
29
|
+
const results = [];
|
|
30
|
+
try {
|
|
31
|
+
const configs = [
|
|
32
|
+
{ name: 'profile-only', caps: ['principalDirectory'], apps: [], expected: 1 },
|
|
33
|
+
{ name: 'profile+sessions', caps: ['principalDirectory', 'sessionInventory'], apps: [], expected: 2 },
|
|
34
|
+
{ name: 'profile+security+sessions+notifications+theme', caps: ['principalDirectory', 'credentialSelfService', 'sessionInventory'], apps: ['application-notifications-in-app', 'application-spa'], expected: 5 },
|
|
35
|
+
];
|
|
36
|
+
for (const cfg of configs) {
|
|
37
|
+
const { r, count } = await tabsFor(fixture, cfg.caps, cfg.apps);
|
|
38
|
+
const tablistPresent = /<nav[^>]*role="tablist"/.test(r.body);
|
|
39
|
+
const pass = r.status === 200 && !!r.requestId && count === cfg.expected && tablistPresent;
|
|
40
|
+
results.push({
|
|
41
|
+
anchorAcId: null,
|
|
42
|
+
conformanceOnly: true,
|
|
43
|
+
limitation: 'application-account-settings-AC-25101-1: capability-to-tab-label mapping (each tab labels the correct capability against a shipped tab-label registry) is not verified by this Node HTTP probe; the derived tab-count walk across three caps configurations is a partial observation of AC-25101-1',
|
|
44
|
+
verdict: pass ? 'warn' : 'fail',
|
|
45
|
+
detail: pass
|
|
46
|
+
? `${FIRST_EIGHT} blueprint declaring principalDirectory, GET /account?caps=${cfg.caps.join(',')}&apps=${cfg.apps.join(',')} (${cfg.name}) returned 200 with role="tablist" nav and derived tab count=${count} matching expected=${cfg.expected} (always-on profile plus one tab per applied capability); x-fixture-request-id=${r.requestId}`
|
|
47
|
+
: `${FIRST_EIGHT} blueprint gap for ${cfg.name}: status=${r.status} rid=${r.requestId} tabs=${count} expected=${cfg.expected} tablist=${tablistPresent}`,
|
|
48
|
+
evidence: {
|
|
49
|
+
requestId: r.requestId,
|
|
50
|
+
responseStatus: r.status,
|
|
51
|
+
bodyExcerpt: excerpt((r.body.match(/<nav[^>]*role="tablist"[^]{0,240}/) || [''])[0]),
|
|
52
|
+
derived: { config: cfg.name, capsInput: cfg.caps, appsInput: cfg.apps, tabCount: count, expected: cfg.expected, tablistPresent },
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
} finally {
|
|
57
|
+
await fixture.kill();
|
|
58
|
+
}
|
|
59
|
+
return { results };
|
|
60
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// application-account-settings probe: theme surface renders as a
|
|
2
|
+
// radiogroup with three options when application-spa is applied, and
|
|
3
|
+
// the server-scoped theme-persistence variant persists a written
|
|
4
|
+
// theme across a subsequent GET (AC-25108-1).
|
|
5
|
+
//
|
|
6
|
+
// AC-25108-1 has TWO observable halves from a Node HTTP probe:
|
|
7
|
+
// (a) the server-scoped-persistence half - when the applied
|
|
8
|
+
// theme-persistence store is 'server-scoped', a POST /api/theme
|
|
9
|
+
// write is reflected on the next GET /account/theme's initial
|
|
10
|
+
// html data-theme attribute (server-rendered, no browser JS
|
|
11
|
+
// involved); DELETE /api/theme clears the record and the next
|
|
12
|
+
// GET returns to the default; and
|
|
13
|
+
// (b) the DOM-shape half - the radiogroup markup, three named
|
|
14
|
+
// radios and the data-persist reflection of the elicit input.
|
|
15
|
+
// The interaction half of AC-25108-1 - the user selecting a radio,
|
|
16
|
+
// the client-side script flipping the html data-theme attribute and
|
|
17
|
+
// writing spa-local-storage - is browser-driven and is NOT observed
|
|
18
|
+
// here; that row de-claims via conformanceOnly with a limitation
|
|
19
|
+
// naming the browser-only clause. (A dedicated browser-driven pack
|
|
20
|
+
// check owns the interaction observation.)
|
|
21
|
+
|
|
22
|
+
import { fixtureFetch, startFixture, excerpt } from './probe-utils.mjs';
|
|
23
|
+
import { randomUUID } from 'node:crypto';
|
|
24
|
+
|
|
25
|
+
export const anchorAcId = 'application-account-settings-AC-25108-1';
|
|
26
|
+
export const accountBound = false;
|
|
27
|
+
|
|
28
|
+
const FIRST_EIGHT_SPA = 'When application-spa is in the applied-blueprint set, GET';
|
|
29
|
+
|
|
30
|
+
export default async function runProbe() {
|
|
31
|
+
const results = [];
|
|
32
|
+
|
|
33
|
+
// Row 1: DOM shape (radiogroup, three radios, data-persist reflect).
|
|
34
|
+
const withSpa = await startFixture({ env: { ACCOUNT_SETTINGS_APPS: 'application-spa' } });
|
|
35
|
+
try {
|
|
36
|
+
const persist = 'spa-local-storage';
|
|
37
|
+
const r = await fixtureFetch(withSpa.url, `/account/theme?theme-persistence=${encodeURIComponent(persist)}`);
|
|
38
|
+
const radiogroup = /<div data-surface="theme"[^>]*role="radiogroup"[^>]*aria-label="Theme"[^>]*data-persist="([^"]+)"/.exec(r.body);
|
|
39
|
+
const derivedPersist = radiogroup ? radiogroup[1] : null;
|
|
40
|
+
const options = [...r.body.matchAll(/<input type="radio" name="theme" value="([^"]+)"[^>]*>/g)].map((m) => m[1]);
|
|
41
|
+
const optSet = new Set(options);
|
|
42
|
+
const hasAll = ['light', 'dark', 'system'].every((v) => optSet.has(v));
|
|
43
|
+
const shapePass = r.status === 200 && !!r.requestId
|
|
44
|
+
&& !!radiogroup && derivedPersist === persist
|
|
45
|
+
&& options.length === 3 && hasAll;
|
|
46
|
+
// Conformance-only: the DOM shape is a partial observation of
|
|
47
|
+
// AC-25108-1. Null anchor per rule 11; the limitation names the
|
|
48
|
+
// AC and the interaction clause NOT observed here.
|
|
49
|
+
results.push({
|
|
50
|
+
anchorAcId: null,
|
|
51
|
+
conformanceOnly: true,
|
|
52
|
+
verdict: shapePass ? 'warn' : 'fail',
|
|
53
|
+
limitation: 'application-account-settings-AC-25108-1: interaction half (user selecting a radio, client script flipping html data-theme, spa-local-storage write) is browser-driven and not observed from a Node HTTP probe',
|
|
54
|
+
detail: shapePass
|
|
55
|
+
? `${FIRST_EIGHT_SPA} /account/theme's server-rendered shell is a radiogroup with role="radiogroup", aria-label="Theme", data-persist="${derivedPersist}" (reflects the theme-persistence elicit input=${persist}), and three radios ${JSON.stringify(options)} matching light/dark/system; conformance-only observation of the DOM-shape half of AC-25108-1`
|
|
56
|
+
: `${FIRST_EIGHT_SPA} /account/theme conformance-shape gap: status=${r.status} rid=${r.requestId} radiogroup=${!!radiogroup} derivedPersist=${derivedPersist} options=${JSON.stringify(options)}`,
|
|
57
|
+
evidence: {
|
|
58
|
+
requestId: r.requestId,
|
|
59
|
+
responseStatus: r.status,
|
|
60
|
+
bodyExcerpt: excerpt((r.body.match(/<div data-surface="theme"[^]{0,260}/) || [''])[0]),
|
|
61
|
+
derived: { persistInput: persist, derivedPersist, options, dataSurfacePresent: !!radiogroup, hasAllRadios: hasAll },
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Row 2: server-scoped persistence half of AC-25108-1. Observable
|
|
66
|
+
// server-side: POST /api/theme?theme=X writes; GET reflects on
|
|
67
|
+
// data-theme; DELETE clears; a further GET drops back to default.
|
|
68
|
+
const principalId = 'probe-theme-' + randomUUID();
|
|
69
|
+
const persistServer = 'server-scoped';
|
|
70
|
+
const chosenTheme = 'dark';
|
|
71
|
+
const before = await fixtureFetch(withSpa.url, `/account/theme?theme-persistence=${persistServer}&principal-id=${principalId}`);
|
|
72
|
+
const beforeMatch = before.body.match(/<html[^>]*data-theme="([^"]+)"/);
|
|
73
|
+
const beforeTheme = beforeMatch ? beforeMatch[1] : null;
|
|
74
|
+
const write = await fixtureFetch(withSpa.url, `/api/theme?theme=${chosenTheme}&theme-persistence=${persistServer}&principal-id=${principalId}`, { method: 'POST' });
|
|
75
|
+
const writeBody = (() => { try { return JSON.parse(write.body || '{}'); } catch (e) { return {}; } })();
|
|
76
|
+
const after = await fixtureFetch(withSpa.url, `/account/theme?theme-persistence=${persistServer}&principal-id=${principalId}`);
|
|
77
|
+
const afterHtmlTheme = (after.body.match(/<html[^>]*data-theme="([^"]+)"/) || [null, null])[1];
|
|
78
|
+
const afterDataServerScoped = (after.body.match(/data-server-scoped-theme="([^"]*)"/) || [null, null])[1];
|
|
79
|
+
const afterDarkChecked = /<input type="radio" name="theme" value="dark"[^>]*checked/.test(after.body);
|
|
80
|
+
const clear = await fixtureFetch(withSpa.url, `/api/theme?theme-persistence=${persistServer}&principal-id=${principalId}`, { method: 'DELETE' });
|
|
81
|
+
const cleared = await fixtureFetch(withSpa.url, `/account/theme?theme-persistence=${persistServer}&principal-id=${principalId}`);
|
|
82
|
+
const clearedHtmlTheme = (cleared.body.match(/<html[^>]*data-theme="([^"]+)"/) || [null, null])[1];
|
|
83
|
+
const clearedDataServerScoped = (cleared.body.match(/data-server-scoped-theme="([^"]*)"/) || [null, null])[1];
|
|
84
|
+
const serverScopedPass = before.status === 200 && write.status === 200 && writeBody.ok === true
|
|
85
|
+
&& after.status === 200 && afterHtmlTheme === chosenTheme && afterDataServerScoped === chosenTheme && afterDarkChecked
|
|
86
|
+
&& clear.status === 200 && cleared.status === 200 && clearedHtmlTheme === 'light' && (!clearedDataServerScoped || clearedDataServerScoped.length === 0);
|
|
87
|
+
results.push({
|
|
88
|
+
anchorAcId,
|
|
89
|
+
verdict: serverScopedPass ? 'pass' : 'fail',
|
|
90
|
+
detail: serverScopedPass
|
|
91
|
+
? `${FIRST_EIGHT_SPA} /account/theme with theme-persistence=server-scoped: for a fresh principalId, initial GET rendered html data-theme=${beforeTheme}; POST /api/theme?theme=${chosenTheme} wrote the record; a subsequent GET rendered html data-theme=${afterHtmlTheme} with data-server-scoped-theme=${afterDataServerScoped} and the dark radio checked; DELETE /api/theme cleared; a final GET fell back to html data-theme=${clearedHtmlTheme}. Server-scoped persistence observed across requests; x-fixture-request-id (final)=${cleared.requestId}`
|
|
92
|
+
: `${FIRST_EIGHT_SPA} /account/theme with theme-persistence=server-scoped (gap): before=${beforeTheme} write=${write.status}/${writeBody.ok} afterHtmlTheme=${afterHtmlTheme} afterServerScoped=${afterDataServerScoped} afterDarkChecked=${afterDarkChecked} clear=${clear.status} clearedHtmlTheme=${clearedHtmlTheme}`,
|
|
93
|
+
evidence: {
|
|
94
|
+
requestId: cleared.requestId,
|
|
95
|
+
responseStatus: cleared.status,
|
|
96
|
+
bodyExcerpt: excerpt((after.body.match(/<html[^]{0,320}/) || [''])[0]),
|
|
97
|
+
derived: {
|
|
98
|
+
principalId,
|
|
99
|
+
beforeTheme,
|
|
100
|
+
writtenTheme: chosenTheme,
|
|
101
|
+
afterHtmlTheme,
|
|
102
|
+
afterDataServerScoped,
|
|
103
|
+
afterDarkChecked,
|
|
104
|
+
clearedHtmlTheme,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Row 3: interaction half is browser-only. notObservableHere
|
|
110
|
+
// anchored to AC-25108-1 with verdict warn (never pass). The
|
|
111
|
+
// aggregate() rule lifts any warn row to a warn aggregate, so this
|
|
112
|
+
// row makes the probe amber-on-the-shelf honestly without letting
|
|
113
|
+
// the interaction clause pass unobserved.
|
|
114
|
+
results.push({
|
|
115
|
+
anchorAcId,
|
|
116
|
+
notObservableAcId: anchorAcId,
|
|
117
|
+
notObservableHere: true,
|
|
118
|
+
verdict: 'warn',
|
|
119
|
+
reason: 'AC-25108-1 requires observing a principal selecting a theme radio, the html element data-theme attribute flipping to the chosen value in response to that user input event, and (for the spa-local-storage store) the client-side localStorage write. Change-event firing, DOM mutation on user input, and localStorage writes are browser-driven and cannot be observed from a Node HTTP probe; the browser-verify pack owns this observation.',
|
|
120
|
+
detail: `${FIRST_EIGHT_SPA} /account/theme's interaction half - user selection firing a change event, the client script flipping html data-theme on that event, and the spa-local-storage write - is browser-driven and observed by the browser-verify pack, not by this Node probe; anchored as notObservableHere for AC-25108-1 so the row does not falsely claim positive evidence`,
|
|
121
|
+
});
|
|
122
|
+
} finally {
|
|
123
|
+
await withSpa.kill();
|
|
124
|
+
}
|
|
125
|
+
return { results };
|
|
126
|
+
}
|
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# application-admin-console CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 1.3.6 - 2026-09-12
|
|
4
|
+
|
|
5
|
+
- Positive-evidence row shape tightened in the anatomy helper: a positive row now requires a non-empty engine-returned `requestId` AND (a non-empty `bodyExcerpt` OR a non-empty `derived` object); a `{derived:{}}` alone or a `requestId` alone no longer counts, with two new negative-case tests covering the empty-derived and id-only patterns. Anatomy negative-variant map extended with `{brk:"local-login-form", probes:["sign-in-access-gated-surface"]}` so the shipped `?break=local-login-form` fixture switch drives the positive AC-21816-1 local-login row to fail (the break drops the `[data-role="local-login-form"]` region on the sign-in surface). No probe or fixture behaviour change on the admin-console family beyond the anatomy shape helper and the negative-variant coverage.
|
|
6
|
+
|
|
7
|
+
## 1.3.5 - 2026-09-12
|
|
8
|
+
|
|
9
|
+
- Rule-7d shape fix on every de-claimed conformance row across users-directory (four AC-21102-1 / AC-21102-2 rows), permission-matrix (AC-21103-1), org-switcher (AC-21104-1), audit-log (AC-21105-1) and sign-in-access-gated (AC-21815-2): each row now carries `anchorAcId: null` and names the anchored AC in the `limitation` field per the shipped shape (a `conformanceOnly:true` row must not simultaneously claim an anchor). Positive-observation rows on AC-21815-1, AC-21816-1 and the org-switcher AC-21104-2 no-tenancy branch stay anchored. Fixture README env-var manifest now declares `PROBE_BREAK` (the fixture reads it as an alternate to `ADMIN_CONSOLE_BREAK` / `?break=`) and the probe-utils `DECLARED_ENV` list mirrors the addition. Anatomy shape check tightened to reject an anchored `conformanceOnly` row (a positive evidence field no longer bypasses the null-anchor + limitation contract); a new negative-case test constructs an anchored `conformanceOnly` row and asserts the shape helper throws.
|
|
10
|
+
|
|
11
|
+
## 1.3.4 - 2026-09-11
|
|
12
|
+
|
|
13
|
+
- Shared `aggregate()` no longer promotes warn rows to pass: any row with verdict warn (including honest de-claim rows) lifts the aggregate to warn; a probe whose rows are all warn aggregates to warn, not pass. Shared teardown propagates a SIGKILL failure through the returned kill() promise instead of swallowing it. Overclaiming rows across users-directory (AC-21102-1, AC-21102-2), permission-matrix (AC-21103-1), org-switcher (AC-21104-1), audit-log (AC-21105-1) and sign-in-access-gated (AC-21815-2) are de-claimed to `conformanceOnly:true` with `verdict:'warn'` and a `limitation` field naming the anchored AC and the varied-input or browser-only clause that lives outside the Node HTTP probe. Positive-observation rows kept on AC-21815-1 (Access-gated Authorization-bearing surface), AC-21816-1 (local-login fallback) and the org-switcher no-tenancy 404 branch. Anatomy test extended with a negative-variant assertion that the shipped fixture break switches drive the affected probe aggregates to fail.
|
|
14
|
+
|
|
15
|
+
## 1.3.3 - 2026-09-11
|
|
16
|
+
|
|
17
|
+
- sign-in-access-gated-surface fixture now returns HTTP 403 with the `[data-surface="access-denied"]` region (and no `[data-role="principal-read"]` element) when `zeroTrustGate` is applied AND no Authorization header is present, wiring the previously-dead `renderSignInAccessDenied` branch to observe AC-21815-2's refusal contract server-side. The probe's AC-21815-2 row is now a positive-evidence row (HTTP 403 + access-denied surface + absence of principal-read) rather than a `notObservableHere` de-claim. Consumers that expected the previous 200-with-default-principal shape (`edge-cloudflare-access` TC-117, TC-118, TC-119 and its admin-console-gate-surface probe) send an Authorization header on the gated caps path; the local-login branch (no `zeroTrustGate`) is unchanged. Anatomy test extended to enumerate the shipped AC/REQ id set and refuse any row whose anchor is not in it, and to accept the conformance-only row shape.
|
|
18
|
+
|
|
19
|
+
## 1.3.2 - 2026-09-11
|
|
20
|
+
|
|
21
|
+
- users-directory-surface split into per-AC rows: AC-21102-1 anchors the directory listing observation; AC-21102-2 anchors the invite and deactivate controls (previously conflated on one row). org-switcher-surface fixture now returns HTTP 404 on the no-tenancy path so the probe can observe the AC-21104-2 refusal status (previously the fixture returned 200 with not-found HTML, contradicting the AC). audit-log-surface probe now drives a real write-then-read cycle: POST /api/members/:id/role writes an audit entry and GET /admin/audit reads it back, observing AC-21105-1 rather than a hard-coded table. sign-in-access-gated-surface probe now varies an Authorization principal and observes the derived email on the principal-read element; the local-fallback row is anchored under AC-21816-1. permission-matrix-grid vacuous `.every()` over an empty label array replaced with a check that asserts at least one label exists and every cell carries one per AC-21103-1. Positive-anchor-on-absence broken-variant rows removed. Rule 10 applied to every row detail. Anatomy test extended to accept notObservableHere row shape. Register cleanup.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## 1.3.1 - 2026-09-11
|
|
25
|
+
|
|
26
|
+
- Added a criterion-e probe pack (`contributions/probes/`) covering 5 properties the fixture engine at `packages/rcf-lite/test/fixtures/probe-pack-application-admin-console/server.js` answers: `users-directory-surface`, `permission-matrix-grid`, `org-switcher-surface`, `audit-log-surface`, `sign-in-access-gated-surface`. Every response now carries an `x-fixture-request-id` header; probes record the id, the HTTP status and a body excerpt as positive evidence per rule 7d. Fixture README declares every env var the pack reads. Anatomy test at `packages/rcf-lite/test/blueprint/application-admin-console-anatomy.test.js` pins the new pack files and asserts each result carries one of the four 7d evidence shapes.
|
|
27
|
+
|
|
28
|
+
|
|
3
29
|
## 1.3.0 (2026-09-10)
|
|
4
30
|
|
|
5
31
|
### Added
|
|
@@ -20,13 +46,13 @@
|
|
|
20
46
|
|
|
21
47
|
- Register: neutral wording in shipped prose (no capability change).
|
|
22
48
|
|
|
23
|
-
## 1.2.0 (2026-09-10
|
|
49
|
+
## 1.2.0 (2026-09-10)
|
|
24
50
|
|
|
25
51
|
### Added
|
|
26
52
|
|
|
27
|
-
- REQ-007 (invite-transport option coverage) and US-21110: every invite-transport option (email, in-app-only, custom) now carries a runtime clause and a story binding accepted, failed and recorded outcomes with a per-invite audit record.
|
|
28
|
-
- REQ-008 (tenancy-shape option coverage) and US-21111: the elicited tenancy-shape (per-user, per-org, both) now determines directory membership, org switcher entries, invite scope and cross-shape refusal (TENANCY_SHAPE_REFUSAL).
|
|
29
|
-
- Failure-path acceptance criteria on US-21106 (request-access POST failure) and US-21107 (empty union entry for a library-qualified source unavailable locally)
|
|
53
|
+
- REQ-007 (invite-transport option coverage) and US-21110: every invite-transport option (email, in-app-only, custom) now carries a runtime clause and a story binding accepted, failed and recorded outcomes with a per-invite audit record.
|
|
54
|
+
- REQ-008 (tenancy-shape option coverage) and US-21111: the elicited tenancy-shape (per-user, per-org, both) now determines directory membership, org switcher entries, invite scope and cross-shape refusal (TENANCY_SHAPE_REFUSAL).
|
|
55
|
+
- Failure-path acceptance criteria on US-21106 (request-access POST failure) and US-21107 (empty union entry for a library-qualified source unavailable locally); failure-path AC on US-21815 for a gated request with no request.auth.
|
|
30
56
|
- Vendor citations on the WCAG 2.4.6 / 3.3.4 / 4.1.3 fixed acceptance criteria and on the ARIA APG grid pattern criteria (verified 2026-09-10).
|
|
31
57
|
|
|
32
58
|
### Changed
|
|
@@ -34,7 +60,7 @@
|
|
|
34
60
|
- Every REQ now carries a deliveredBy link into TAC-2201, TAC-2203, TAC-2204 or TAC-2214.
|
|
35
61
|
- Every AC on every user story now carries an explicit disposition (fixed or template); template ACs state the values the applying agent sets.
|
|
36
62
|
- TAC-2201 responsibilities now include deliverInvite (per invite-transport branch), tenancyShapeGate (per tenancy shape), delegateUsersSurface, delegateOrgsSurface, renderAccessDenied and renderShell so the deliveredBy fields resolve.
|
|
37
|
-
-
|
|
63
|
+
- REQ-005 extended with an audit-retention-days runtime clause naming the string elicit and its refusal branch; US-21105 gained a template AC (AC-21105-3) carrying `Applying agent sets: audit-retention-days.`.
|
|
38
64
|
|
|
39
65
|
## 1.1.0 (2026-09-07)
|
|
40
66
|
|
|
@@ -50,7 +76,7 @@
|
|
|
50
76
|
|
|
51
77
|
## 1.0.0 (visual round, spec 2026-09-04)
|
|
52
78
|
|
|
53
|
-
-
|
|
79
|
+
- Initial shipped version of the shelf's admin-console blueprint. Six REQs (console shell with no dead links, conditional users, conditional roles with Owner + Admin + Member + Viewer baseline, conditional orgs, conditional audit-log, access-denied plus request-access), nine USs 21101-21109 binding 16 runtime-observable ACs, four TACs 2201-2204 (shell, capability discovery, permission matrix, audit view consuming datatable), four ADRs 2201-2204 (capability vocabulary, baseline roles, invite transport, audit retention). No new global topics.
|
|
54
80
|
- Introduces the capability-declaration mechanism: `capabilities[]` on identity blueprints (v1.1.0 minor bumps on magic-link, clerk, oauth2, keycloak land in the same PR per spec Q2 default), `requiresAppliedCapabilities` and `elicits[]` on consumer blueprints, apply-time discovery via source read-back on `manifest.blueprints[]`, exit-3 refusal with the spec 5.5.1 verbatim message on bare-SPA applies, and a `--allow-no-auth-yet` operator override.
|
|
55
81
|
- Persists per-project apply-time state in a sidecar `rcf/blueprints/application-admin-console.applied.json` (the applied-blueprint-record schema in rcf-schemas 0.6.0 is closed under additionalProperties:false; the source-manifest read-back precedent from the core-companions train applies here). The sidecar carries `appliedCapabilities`, `appliedElicitations`, `allowNoAuthYet?` and `notes?`.
|
|
56
82
|
- Ships `probe-packs/application-admin-console.pack.mjs`: four capability-gated browser-verify checks anchored to AC-21102-1 (users), AC-21103-1 (permission matrix), AC-21104-1 (org switcher), AC-21105-1 (audit-log surface). Each check reads the applied capability sidecar and records `applicable: false` where its required capability is absent (residual cure). Fifth shipped consumer of the earlier release probe-pack runner extension.
|
|
@@ -26,7 +26,7 @@ Refuses with exit 3 and the spec 5.5.1 verbatim message on a project with no app
|
|
|
26
26
|
| Applied capability | Surface | Rendered by |
|
|
27
27
|
|---|---|---|
|
|
28
28
|
| `principalDirectory` | Users directory (`/admin/users`) | Any applied auth blueprint (magic-link, clerk, oauth2, keycloak). |
|
|
29
|
-
| `roleModel` | Permission matrix (`/admin/roles`) | Clerk, OAuth2, Keycloak. Magic-link does NOT declare it, so a bare-magic-link project gets NO roles surface (per the
|
|
29
|
+
| `roleModel` | Permission matrix (`/admin/roles`) | Clerk, OAuth2, Keycloak. Magic-link does NOT declare it, so a bare-magic-link project gets NO roles surface (per the shipped spec section 5.5 worked example). |
|
|
30
30
|
| `tenancy` | Org switcher (`/admin/orgs`), org-scoped invites | Reserved for a future `application-tenancy-orgs` blueprint (spec section 11). No shelf provider today. |
|
|
31
31
|
| `auditLog` | Audit-log surface (`/admin/audit`) | Via the applied `observability-logging` companion (implicit), or a future dedicated audit-log blueprint. |
|
|
32
32
|
| (none) | Access-denied + request-access | Always renders for a non-admin principal reaching `/admin/*`. |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"slug": "application-admin-console",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"category": "application",
|
|
5
5
|
"requiresAppliedCapabilities": {
|
|
6
6
|
"capabilities": [
|
|
@@ -285,5 +285,7 @@
|
|
|
285
285
|
],
|
|
286
286
|
"optionalCapabilities": [
|
|
287
287
|
"zeroTrustGate"
|
|
288
|
-
]
|
|
288
|
+
],
|
|
289
|
+
"updatedAt": "2026-09-12T00:45:12Z",
|
|
290
|
+
"updatedIso": "2026-09-11T22:30:00Z"
|
|
289
291
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"title": "Capability vocabulary: principalDirectory, roleModel, tenancy, auditLog as the v1 capability set",
|
|
8
8
|
"context": "Admin-console surfaces are conditional on what the applied identity blueprint provides. The vocabulary must be small (four strings today), extensible (the section 6a table is chunk-zero, so a future capability lands with a docs edit and no code change), and grounded in industry practice (SaaS UI research, IAM literature). The ratified 2026-09-04 shelf decision 5 lands the initial four capabilities as principalDirectory, roleModel, tenancy and auditLog.",
|
|
9
9
|
"decision": "v1.0.0 declares four capability strings the applied identity blueprints can declare in their capabilities[] field: principalDirectory (identifies principals for a users surface); roleModel (declares operator-visible role labels for a permission matrix); tenancy (declares an organisation abstraction the console can switch across); auditLog (emits an event stream the audit view can read). The vocabulary lives in packages/rcf-lite/docs/blueprint-authoring.md section 6a as a table extending the roles registry; the loader validates capability SHAPE (lower camelCase on ^[a-z][a-zA-Z0-9]*$), not the vocabulary. A future capability lands by adding a table row and adopting it on an identity blueprints minor bump.",
|
|
10
|
-
"consequences": "The console renders only surfaces the applied capabilities enable, so a bare magic-link project gets a users surface but no roles surface (per the
|
|
10
|
+
"consequences": "The console renders only surfaces the applied capabilities enable, so a bare magic-link project gets a users surface but no roles surface (per the shipped spec section 5.5 worked example). A future dedicated audit-log blueprint declaring auditLog directly (rather than through observability-logging) composes cleanly. A new capability lands additively.",
|
|
11
11
|
"alternativesConsidered": [
|
|
12
12
|
{
|
|
13
13
|
"name": "Encode the vocabulary in code as an enum",
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// application-admin-console probe: audit-log surface (AC-21105-1).
|
|
2
|
+
//
|
|
3
|
+
// AC-21105-1 requires: given a role change AND the auditLog capability
|
|
4
|
+
// applied, an audit-log entry writes with actor, target, before, after,
|
|
5
|
+
// timestamp and correlationId from the logging companion; the entry
|
|
6
|
+
// surfaces on the audit view table where every row is enumerable by
|
|
7
|
+
// data-audit-id and every cell exposes its column via a data-column
|
|
8
|
+
// attribute.
|
|
9
|
+
//
|
|
10
|
+
// The probe drives a real role change: POST /api/members/:id/role,
|
|
11
|
+
// then GET /admin/audit and assert the DOM row for the new audit id
|
|
12
|
+
// carries the changed before/after values. Row detail opens on the
|
|
13
|
+
// first eight words of AC-21105-1 (rule 10).
|
|
14
|
+
|
|
15
|
+
import { fixtureFetch, startFixture, excerpt } from './probe-utils.mjs';
|
|
16
|
+
|
|
17
|
+
export const anchorAcId = 'application-admin-console-AC-21105-1';
|
|
18
|
+
export const accountBound = false;
|
|
19
|
+
|
|
20
|
+
export default async function runProbe() {
|
|
21
|
+
const fixture = await startFixture({ env: { ADMIN_CONSOLE_CAPS: 'principalDirectory,auditLog' } });
|
|
22
|
+
const results = [];
|
|
23
|
+
try {
|
|
24
|
+
// Drive the role change and capture the emitted audit id.
|
|
25
|
+
const targetMemberId = 'u3';
|
|
26
|
+
const nextRole = 'Admin';
|
|
27
|
+
const postRes = await fixtureFetch(fixture.url, `/api/members/${targetMemberId}/role`, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers: { 'content-type': 'application/json' },
|
|
30
|
+
body: JSON.stringify({ role: nextRole, actor: 'probe@example.test' }),
|
|
31
|
+
});
|
|
32
|
+
let postBody = null;
|
|
33
|
+
try { postBody = JSON.parse(postRes.body); } catch { postBody = null; }
|
|
34
|
+
const newAuditId = postBody && typeof postBody.auditId === 'string' ? postBody.auditId : null;
|
|
35
|
+
const postBefore = postBody && typeof postBody.before === 'string' ? postBody.before : null;
|
|
36
|
+
const postAfter = postBody && typeof postBody.after === 'string' ? postBody.after : null;
|
|
37
|
+
|
|
38
|
+
// GET the audit view and assert the new audit row is present with
|
|
39
|
+
// the changed before/after and every required column carries a
|
|
40
|
+
// data-column attribute.
|
|
41
|
+
const r = await fixtureFetch(fixture.url, '/admin/audit');
|
|
42
|
+
const rowIds = [...new Set([...r.body.matchAll(/data-audit-id="([^"]+)"/g)].map((m) => m[1]))];
|
|
43
|
+
const requiredColumns = ['actor', 'target', 'before', 'after', 'timestamp', 'correlationId'];
|
|
44
|
+
const allColumnsPresent = requiredColumns.every((col) => new RegExp(`<th data-column="${col}">`).test(r.body));
|
|
45
|
+
const newRowRegex = newAuditId
|
|
46
|
+
? new RegExp(`<tr data-audit-id="${newAuditId}">[^]*?</tr>`)
|
|
47
|
+
: null;
|
|
48
|
+
const newRow = newRowRegex ? (r.body.match(newRowRegex) || [null])[0] : null;
|
|
49
|
+
const rowHasBefore = !!newRow && !!postBefore && new RegExp(`<td data-column="before">${postBefore}</td>`).test(newRow);
|
|
50
|
+
const rowHasAfter = !!newRow && !!postAfter && new RegExp(`<td data-column="after">${postAfter}</td>`).test(newRow);
|
|
51
|
+
const rowHasCorrelation = !!newRow && /<td data-column="correlationId">corr-/.test(newRow);
|
|
52
|
+
const everyCellHasDataColumn = !!newRow && (newRow.match(/<td data-column="[^"]+">/g) || []).length === requiredColumns.length;
|
|
53
|
+
|
|
54
|
+
const pass = postRes.status === 200 && r.status === 200 && !!r.requestId
|
|
55
|
+
&& !!newAuditId && rowIds.includes(newAuditId)
|
|
56
|
+
&& allColumnsPresent
|
|
57
|
+
&& rowHasBefore && rowHasAfter && rowHasCorrelation
|
|
58
|
+
&& everyCellHasDataColumn;
|
|
59
|
+
|
|
60
|
+
results.push({
|
|
61
|
+
anchorAcId: null,
|
|
62
|
+
conformanceOnly: true,
|
|
63
|
+
limitation: 'application-admin-console-AC-21105-1: actor / target / timestamp equality and companion-log source provenance (external correlation from the logging companion) are not verified against a shipped log adapter by this Node HTTP probe; the write-then-read cycle (POST role change, GET audit surfaces the new row with correlationId) is a partial observation of AC-21105-1',
|
|
64
|
+
verdict: pass ? 'warn' : 'fail',
|
|
65
|
+
detail: pass
|
|
66
|
+
? `Given a role change AND the auditLog capability applied: POST /api/members/${targetMemberId}/role returned 200 with auditId=${newAuditId} before=${postBefore} after=${postAfter}; subsequent GET /admin/audit surfaced the new row with data-audit-id=${newAuditId}, before/after cells matching the round-trip and a correlationId cell present; all six required columns (actor/target/before/after/timestamp/correlationId) rendered; x-fixture-request-id=${r.requestId}`
|
|
67
|
+
: `Given a role change AND the auditLog capability applied round-trip gap: postStatus=${postRes.status} auditStatus=${r.status} rid=${r.requestId} newAuditId=${newAuditId} newRowFound=${rowIds.includes(String(newAuditId))} allCols=${allColumnsPresent} rowHasBefore=${rowHasBefore} rowHasAfter=${rowHasAfter} rowHasCorrelation=${rowHasCorrelation} everyCellHasDataColumn=${everyCellHasDataColumn}`,
|
|
68
|
+
evidence: {
|
|
69
|
+
requestId: r.requestId,
|
|
70
|
+
responseStatus: r.status,
|
|
71
|
+
bodyExcerpt: excerpt(newRow || (r.body.match(/<tr data-audit-id="[^"]+">[^]{0,200}/) || [''])[0]),
|
|
72
|
+
derived: { postStatus: postRes.status, newAuditId, postBefore, postAfter, rowCount: rowIds.length, allColumnsPresent, rowHasBefore, rowHasAfter, rowHasCorrelation, everyCellHasDataColumn },
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
} finally {
|
|
76
|
+
await fixture.kill();
|
|
77
|
+
}
|
|
78
|
+
return { results };
|
|
79
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// application-admin-console probe: org switcher surface across the
|
|
2
|
+
// two shipped ACs for the org-switcher story - the tenancy-applied
|
|
3
|
+
// render contract (AC-21104-1) and the tenancy-absent suppression
|
|
4
|
+
// contract (AC-21104-2). Each row detail opens on the first eight
|
|
5
|
+
// words of the shipped AC it anchors (rule 10).
|
|
6
|
+
//
|
|
7
|
+
// AC-21104-1 requires: with tenancy applied, the shell renders
|
|
8
|
+
// [data-role="org-switcher"] on the console header; when tenancy is
|
|
9
|
+
// not applied, neither the control nor the org-scoped invite path is
|
|
10
|
+
// rendered nor reachable.
|
|
11
|
+
//
|
|
12
|
+
// AC-21104-2 requires: when tenancy is NOT applied, the orgs route is
|
|
13
|
+
// suppressed (not linked in the shell navigation and returning 404 or
|
|
14
|
+
// the shared forbidden state on direct URL); the org switcher control
|
|
15
|
+
// is absent from the DOM on every route.
|
|
16
|
+
|
|
17
|
+
import { fixtureFetch, startFixture, excerpt } from './probe-utils.mjs';
|
|
18
|
+
|
|
19
|
+
export const anchorAcId = 'application-admin-console-AC-21104-1';
|
|
20
|
+
export const accountBound = false;
|
|
21
|
+
|
|
22
|
+
export default async function runProbe() {
|
|
23
|
+
const results = [];
|
|
24
|
+
const withTenancy = await startFixture({ env: { ADMIN_CONSOLE_CAPS: 'principalDirectory,tenancy' } });
|
|
25
|
+
try {
|
|
26
|
+
// Row 1: AC-21104-1 tenancy-applied render.
|
|
27
|
+
const r = await fixtureFetch(withTenancy.url, '/admin/orgs');
|
|
28
|
+
const switcherCount = (r.body.match(/data-role="org-switcher"/g) || []).length;
|
|
29
|
+
const orgsLinkInNav = /<nav[^>]*data-role="primary-nav"[^]*?<a[^>]*href="\/admin\/orgs">Orgs<\/a>[^]*?<\/nav>/.test(r.body);
|
|
30
|
+
const pass = r.status === 200 && !!r.requestId && switcherCount >= 1 && orgsLinkInNav;
|
|
31
|
+
results.push({
|
|
32
|
+
anchorAcId: null,
|
|
33
|
+
conformanceOnly: true,
|
|
34
|
+
limitation: 'application-admin-console-AC-21104-1: the users invite-path organization selector for scoping the invite (the AC clause beyond the general header selector) is not present in this fixture and not observed by this Node HTTP probe; the general header org-selector walk is a partial observation of AC-21104-1',
|
|
35
|
+
verdict: pass ? 'warn' : 'fail',
|
|
36
|
+
detail: pass
|
|
37
|
+
? `Given an applied blueprint declaring tenancy, the shell rendered [data-role="org-switcher"] count=${switcherCount} on the console header and the Orgs link is present in the primary navigation; GET /admin/orgs returned 200; x-fixture-request-id=${r.requestId}`
|
|
38
|
+
: `Given an applied blueprint declaring tenancy, the shell tenancy-on gap: status=${r.status} rid=${r.requestId} switcher=${switcherCount} orgsNavLink=${orgsLinkInNav}`,
|
|
39
|
+
evidence: {
|
|
40
|
+
requestId: r.requestId,
|
|
41
|
+
responseStatus: r.status,
|
|
42
|
+
bodyExcerpt: excerpt((r.body.match(/data-role="org-switcher"[^]{0,140}/) || [''])[0]),
|
|
43
|
+
derived: { switcherCount, orgsLinkInNav, capsIncludesTenancy: true },
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
} finally {
|
|
47
|
+
await withTenancy.kill();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const noTenancy = await startFixture({ env: { ADMIN_CONSOLE_CAPS: 'principalDirectory' } });
|
|
51
|
+
try {
|
|
52
|
+
// Row 2: AC-21104-2 tenancy-absent suppression.
|
|
53
|
+
// The AC mandates 404 or forbidden on direct URL AND no orgs link
|
|
54
|
+
// in nav AND no switcher control on any route.
|
|
55
|
+
const directOrgs = await fixtureFetch(noTenancy.url, '/admin/orgs');
|
|
56
|
+
const home = await fixtureFetch(noTenancy.url, '/admin');
|
|
57
|
+
const statusIsRefused = directOrgs.status === 404 || directOrgs.status === 403;
|
|
58
|
+
const orgsLinkInNav = /href="\/admin\/orgs">Orgs</.test(home.body);
|
|
59
|
+
const switcherOnHome = /data-role="org-switcher"/.test(home.body);
|
|
60
|
+
const switcherOnOrgs = /data-role="org-switcher"/.test(directOrgs.body);
|
|
61
|
+
const suppressionPass = !!directOrgs.requestId && !!home.requestId
|
|
62
|
+
&& statusIsRefused
|
|
63
|
+
&& !orgsLinkInNav
|
|
64
|
+
&& !switcherOnHome
|
|
65
|
+
&& !switcherOnOrgs;
|
|
66
|
+
results.push({
|
|
67
|
+
anchorAcId: 'application-admin-console-AC-21104-2',
|
|
68
|
+
verdict: suppressionPass ? 'pass' : 'fail',
|
|
69
|
+
detail: suppressionPass
|
|
70
|
+
? `When tenancy is NOT applied, the orgs route was suppressed: GET /admin/orgs returned ${directOrgs.status} (404 or 403 as the AC requires); no /admin/orgs link in the shell nav; no [data-role="org-switcher"] on /admin or on the refused /admin/orgs response; x-fixture-request-id=${directOrgs.requestId}`
|
|
71
|
+
: `When tenancy is NOT applied, the orgs route suppression gap: orgs status=${directOrgs.status} orgsRid=${directOrgs.requestId} homeRid=${home.requestId} statusRefused=${statusIsRefused} orgsNavLink=${orgsLinkInNav} switcherOnHome=${switcherOnHome} switcherOnOrgs=${switcherOnOrgs}`,
|
|
72
|
+
evidence: {
|
|
73
|
+
requestId: directOrgs.requestId,
|
|
74
|
+
responseStatus: directOrgs.status,
|
|
75
|
+
bodyExcerpt: excerpt(directOrgs.body),
|
|
76
|
+
derived: { statusIsRefused, orgsLinkInNav, switcherOnHome, switcherOnOrgs, capsIncludesTenancy: false },
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
} finally {
|
|
80
|
+
await noTenancy.kill();
|
|
81
|
+
}
|
|
82
|
+
return { results };
|
|
83
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// application-admin-console probe: permission matrix ARIA APG grid
|
|
2
|
+
// (AC-21103-1). Row detail opens on the first eight words of the
|
|
3
|
+
// shipped AC it anchors (rule 10).
|
|
4
|
+
//
|
|
5
|
+
// AC-21103-1 requires: given the roles surface AND an applied auth
|
|
6
|
+
// blueprint declaring roleModel, the permission matrix renders as an
|
|
7
|
+
// ARIA APG grid: role="grid" on the outer element, role="row" on
|
|
8
|
+
// every rank (including the header rank), role="columnheader" on
|
|
9
|
+
// every permission column header, role="rowheader" on the leftmost
|
|
10
|
+
// cell of each role rank, role="gridcell" on every inner cell, and
|
|
11
|
+
// each cell carries an aria-label announcing the exact permission
|
|
12
|
+
// string plus the allowed/denied state on focus.
|
|
13
|
+
|
|
14
|
+
import { fixtureFetch, startFixture, excerpt } from './probe-utils.mjs';
|
|
15
|
+
|
|
16
|
+
export const anchorAcId = 'application-admin-console-AC-21103-1';
|
|
17
|
+
export const accountBound = false;
|
|
18
|
+
|
|
19
|
+
export default async function runProbe() {
|
|
20
|
+
const fixture = await startFixture({ env: { ADMIN_CONSOLE_CAPS: 'principalDirectory,roleModel' } });
|
|
21
|
+
const results = [];
|
|
22
|
+
try {
|
|
23
|
+
const r = await fixtureFetch(fixture.url, '/admin/roles');
|
|
24
|
+
const gridPresent = /role="grid"/.test(r.body);
|
|
25
|
+
const columnCount = (r.body.match(/role="columnheader" data-permission="/g) || []).length;
|
|
26
|
+
const roleRankRows = [...r.body.matchAll(/data-role-rank="([^"]+)"/g)].map((m) => m[1]);
|
|
27
|
+
const rowCount = roleRankRows.length;
|
|
28
|
+
const gridcellCount = (r.body.match(/role="gridcell" data-cell-state="/g) || []).length;
|
|
29
|
+
const rowHeaderCount = (r.body.match(/role="rowheader"/g) || []).length;
|
|
30
|
+
|
|
31
|
+
// Every gridcell must carry an aria-label of the form
|
|
32
|
+
// "<role> (allowed|denied): <permission>". Collect ALL labels
|
|
33
|
+
// (no slicing) so length equality with gridcellCount protects the
|
|
34
|
+
// check against a vacuous every() on an empty array.
|
|
35
|
+
const cellLabels = [...r.body.matchAll(/role="gridcell"[^>]*aria-label="([^"]+)"/g)].map((m) => m[1]);
|
|
36
|
+
const labelShape = /^[A-Za-z]+ (allowed|denied): [A-Za-z ]+$/;
|
|
37
|
+
const everyLabelHonoursContract = cellLabels.length > 0
|
|
38
|
+
&& cellLabels.length === gridcellCount
|
|
39
|
+
&& cellLabels.every((l) => labelShape.test(l));
|
|
40
|
+
|
|
41
|
+
const derivedPass = r.status === 200 && !!r.requestId
|
|
42
|
+
&& gridPresent
|
|
43
|
+
&& columnCount > 0
|
|
44
|
+
&& rowCount > 0
|
|
45
|
+
&& gridcellCount === rowCount * columnCount
|
|
46
|
+
&& rowHeaderCount >= rowCount
|
|
47
|
+
&& everyLabelHonoursContract;
|
|
48
|
+
results.push({
|
|
49
|
+
anchorAcId: null,
|
|
50
|
+
conformanceOnly: true,
|
|
51
|
+
limitation: 'application-admin-console-AC-21103-1: permission-derivation checking against role-permission tables (each cell label corresponding to the actual role permission and state, row-role x column-permission mapping) is not observed by this Node HTTP probe against a fixed fixture; the label-shape walk over gridcell aria-labels is a partial observation of AC-21103-1',
|
|
52
|
+
verdict: derivedPass ? 'warn' : 'fail',
|
|
53
|
+
detail: derivedPass
|
|
54
|
+
? `Given the roles surface AND an applied auth blueprint declaring roleModel: GET /admin/roles returned 200 with role="grid" present, ${rowCount} role ranks, ${columnCount} permission columnheaders, ${gridcellCount} gridcells (=rows*columns), ${rowHeaderCount} rowheader cells, and all ${cellLabels.length} gridcell aria-labels honour the "<role> allowed/denied: <permission>" contract; x-fixture-request-id=${r.requestId}`
|
|
55
|
+
: `Given the roles surface AND an applied auth blueprint declaring roleModel gap: status=${r.status} rid=${r.requestId} grid=${gridPresent} rows=${rowCount} cols=${columnCount} cells=${gridcellCount} rowHeaders=${rowHeaderCount} labelCount=${cellLabels.length} labelsHonourContract=${everyLabelHonoursContract}`,
|
|
56
|
+
evidence: {
|
|
57
|
+
requestId: r.requestId,
|
|
58
|
+
responseStatus: r.status,
|
|
59
|
+
bodyExcerpt: excerpt((r.body.match(/role="gridcell"[^>]{0,180}/) || [''])[0]),
|
|
60
|
+
derived: { rowCount, columnCount, gridcellCount, rowHeaderCount, expectedCells: rowCount * columnCount, labelCount: cellLabels.length, sampledLabels: cellLabels.slice(0, 3) },
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
} finally {
|
|
64
|
+
await fixture.kill();
|
|
65
|
+
}
|
|
66
|
+
return { results };
|
|
67
|
+
}
|