rcf-lite 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +10 -0
- package/bin/rcf.js +2 -0
- package/blueprints/application-account-settings/CHANGELOG.md +35 -6
- package/blueprints/application-account-settings/README.md +1 -1
- package/blueprints/application-account-settings/blueprint.json +4 -2
- package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +1 -1
- package/blueprints/application-account-settings/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-account-settings/contributions/probes/profile-form-autocomplete.mjs +67 -0
- package/blueprints/application-account-settings/contributions/probes/run-profile-form-autocomplete.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-adapter-uniform.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-surface-shape.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-shell-tablist-per-capability.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-theme-radiogroup.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-adapter-uniform.mjs +130 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-surface-shape.mjs +70 -0
- package/blueprints/application-account-settings/contributions/probes/shell-tablist-per-capability.mjs +60 -0
- package/blueprints/application-account-settings/contributions/probes/theme-radiogroup.mjs +126 -0
- package/blueprints/application-admin-console/CHANGELOG.md +32 -6
- package/blueprints/application-admin-console/README.md +1 -1
- package/blueprints/application-admin-console/blueprint.json +4 -2
- package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +1 -1
- package/blueprints/application-admin-console/contributions/probes/audit-log-surface.mjs +79 -0
- package/blueprints/application-admin-console/contributions/probes/org-switcher-surface.mjs +83 -0
- package/blueprints/application-admin-console/contributions/probes/permission-matrix-grid.mjs +67 -0
- package/blueprints/application-admin-console/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-admin-console/contributions/probes/run-audit-log-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-org-switcher-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-permission-matrix-grid.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-sign-in-access-gated-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-users-directory-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/sign-in-access-gated-surface.mjs +117 -0
- package/blueprints/application-admin-console/contributions/probes/users-directory-surface.mjs +145 -0
- package/blueprints/application-api-rest/CHANGELOG.md +16 -8
- package/blueprints/application-api-rest/README.md +3 -3
- package/blueprints/application-api-rest/blueprint.json +3 -2
- package/blueprints/application-api-rest/contributions/adrs/adr-302-application-api-rest-auth-model.json +1 -1
- package/blueprints/application-api-rest/contributions/probes/cursor-pagination-round-trip.mjs +154 -0
- package/blueprints/application-api-rest/contributions/probes/health-probes-distinct.mjs +124 -0
- package/blueprints/application-api-rest/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-api-rest/contributions/probes/problem-details-on-error.mjs +77 -0
- package/blueprints/application-api-rest/contributions/probes/request-id-echoed.mjs +76 -0
- package/blueprints/application-api-rest/contributions/probes/run-cursor-pagination-round-trip.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-health-probes-distinct.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-problem-details-on-error.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-request-id-echoed.mjs +5 -0
- package/blueprints/application-api-rest/docs/topics.md +1 -1
- package/blueprints/application-charts/CHANGELOG.md +35 -9
- package/blueprints/application-charts/README.md +6 -6
- package/blueprints/application-charts/blueprint.json +5 -3
- package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +1 -1
- package/blueprints/application-charts/contributions/probes/keyboard-traversal.mjs +151 -0
- package/blueprints/application-charts/contributions/probes/non-colour-distinction.mjs +67 -0
- package/blueprints/application-charts/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-charts/contributions/probes/run-keyboard-traversal.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-non-colour-distinction.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-text-alternative-table.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/text-alternative-table.mjs +139 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +1 -1
- package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +1 -1
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +5 -5
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +1 -1
- package/blueprints/application-charts/guide/application-charts.md +1 -1
- package/blueprints/application-dashboard/CHANGELOG.md +20 -10
- package/blueprints/application-dashboard/README.md +6 -6
- package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +2 -2
- package/blueprints/application-dashboard/blueprint.json +3 -2
- package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +1 -1
- package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +1 -1
- package/blueprints/application-dashboard/contributions/probes/export-handle-formats.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/four-tile-states.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/primary-kpi-top-left.mjs +58 -0
- package/blueprints/application-dashboard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-dashboard/contributions/probes/run-export-handle-formats.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-four-tile-states.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-primary-kpi-top-left.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-shell-five-regions.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/shell-five-regions.mjs +93 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +1 -1
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +5 -5
- package/blueprints/application-dashboard/docs/topics.md +2 -2
- package/blueprints/application-dashboard/guide/application-dashboard.md +2 -2
- package/blueprints/application-datatable/CHANGELOG.md +19 -9
- package/blueprints/application-datatable/README.md +2 -2
- package/blueprints/application-datatable/blueprint.json +3 -2
- package/blueprints/application-datatable/contributions/probes/apg-table-shape.mjs +57 -0
- package/blueprints/application-datatable/contributions/probes/four-states-regions.mjs +80 -0
- package/blueprints/application-datatable/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-datatable/contributions/probes/run-apg-table-shape.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-four-states-regions.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-search-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-sort-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/search-adapter-round-trip.mjs +58 -0
- package/blueprints/application-datatable/contributions/probes/sort-adapter-round-trip.mjs +60 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +1 -1
- package/blueprints/application-datatable/docs/topics.md +1 -1
- package/blueprints/application-empty-error-states/CHANGELOG.md +33 -3
- package/blueprints/application-empty-error-states/blueprint.json +4 -2
- package/blueprints/application-empty-error-states/contributions/probes/empty-list-and-no-search.mjs +66 -0
- package/blueprints/application-empty-error-states/contributions/probes/error-boundary-alert.mjs +65 -0
- package/blueprints/application-empty-error-states/contributions/probes/forbidden-and-server-error.mjs +167 -0
- package/blueprints/application-empty-error-states/contributions/probes/not-found-and-recovery.mjs +61 -0
- package/blueprints/application-empty-error-states/contributions/probes/permission-denied-and-offline.mjs +155 -0
- package/blueprints/application-empty-error-states/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-empty-list-and-no-search.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-error-boundary-alert.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-forbidden-and-server-error.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-not-found-and-recovery.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-permission-denied-and-offline.mjs +5 -0
- package/blueprints/application-error-handling/CHANGELOG.md +45 -6
- package/blueprints/application-error-handling/blueprint.json +3 -2
- package/blueprints/application-error-handling/contributions/probes/category-vocabulary.mjs +90 -0
- package/blueprints/application-error-handling/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-error-handling/contributions/probes/record-shape-adr-1701.mjs +78 -0
- package/blueprints/application-error-handling/contributions/probes/run-category-vocabulary.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-record-shape-adr-1701.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-two-boundaries-registered.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/two-boundaries-registered.mjs +343 -0
- package/blueprints/application-file-upload/CHANGELOG.md +28 -6
- package/blueprints/application-file-upload/README.md +1 -1
- package/blueprints/application-file-upload/blueprint.json +3 -2
- package/blueprints/application-file-upload/contributions/probes/assertive-completion-slot.mjs +78 -0
- package/blueprints/application-file-upload/contributions/probes/chunked-transport-endpoints.mjs +173 -0
- package/blueprints/application-file-upload/contributions/probes/per-file-progressbar.mjs +124 -0
- package/blueprints/application-file-upload/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-file-upload/contributions/probes/run-assertive-completion-slot.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-chunked-transport-endpoints.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-per-file-progressbar.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-upload-surface-shape.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/upload-surface-shape.mjs +55 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +1 -1
- package/blueprints/application-file-upload/probe-packs/application-file-upload.pack.mjs +1 -1
- package/blueprints/application-forms-wizard/CHANGELOG.md +20 -6
- package/blueprints/application-forms-wizard/README.md +2 -2
- package/blueprints/application-forms-wizard/blueprint.json +3 -2
- package/blueprints/application-forms-wizard/contributions/probes/draft-persistence-round-trip.mjs +110 -0
- package/blueprints/application-forms-wizard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-draft-persistence-round-trip.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-step-page-shape.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-task-list-surface.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/step-page-shape.mjs +61 -0
- package/blueprints/application-forms-wizard/contributions/probes/task-list-surface.mjs +109 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +1 -1
- package/blueprints/application-forms-wizard/probe-packs/application-forms-wizard.pack.mjs +1 -1
- package/blueprints/application-notifications-in-app/CHANGELOG.md +38 -5
- package/blueprints/application-notifications-in-app/README.md +4 -4
- package/blueprints/application-notifications-in-app/blueprint.json +4 -2
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/probes/centre-acknowledge-round-trip.mjs +210 -0
- package/blueprints/application-notifications-in-app/contributions/probes/live-region-preseeding.mjs +93 -0
- package/blueprints/application-notifications-in-app/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-centre-acknowledge-round-trip.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-live-region-preseeding.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-toast-contract.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/toast-contract.mjs +92 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +3 -3
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +1 -1
- package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +3 -3
- package/blueprints/application-onboarding-tour/CHANGELOG.md +31 -5
- package/blueprints/application-onboarding-tour/README.md +1 -1
- package/blueprints/application-onboarding-tour/blueprint.json +5 -3
- package/blueprints/application-onboarding-tour/contributions/probes/checklist-anchor-open.mjs +81 -0
- package/blueprints/application-onboarding-tour/contributions/probes/completion-persistence.mjs +159 -0
- package/blueprints/application-onboarding-tour/contributions/probes/first-run-detection.mjs +67 -0
- package/blueprints/application-onboarding-tour/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-checklist-anchor-open.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-completion-persistence.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-first-run-detection.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-stepper-role-dialog.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/stepper-role-dialog.mjs +45 -0
- package/blueprints/application-spa/CHANGELOG.md +20 -11
- package/blueprints/application-spa/README.md +9 -10
- package/blueprints/application-spa/blueprint.json +3 -2
- package/blueprints/application-spa/contributions/adrs/adr-202-application-spa-theming.json +1 -1
- package/blueprints/application-spa/contributions/adrs/adr-206-application-spa-iconography.json +1 -1
- package/blueprints/application-spa/contributions/probes/designed-empty-state.mjs +72 -0
- package/blueprints/application-spa/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-spa/contributions/probes/route-inventory-published.mjs +185 -0
- package/blueprints/application-spa/contributions/probes/run-designed-empty-state.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-route-inventory-published.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-shell-nav-present.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/shell-nav-present.mjs +69 -0
- package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +1 -1
- package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +3 -3
- package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +2 -2
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +1 -1
- package/blueprints/application-spa/docs/topics.md +1 -1
- package/blueprints/delivery-ci-workflows/CHANGELOG.md +31 -11
- package/blueprints/delivery-ci-workflows/README.md +3 -3
- package/blueprints/delivery-ci-workflows/blueprint.json +3 -2
- package/blueprints/delivery-ci-workflows/contributions/adrs/adr-702-delivery-ci-workflows-strict-coverage-gate.json +2 -2
- package/blueprints/delivery-ci-workflows/contributions/probes/node-gate-entrypoint.mjs +76 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/probe-utils.mjs +56 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/real-account-github-actions-run-record.mjs +139 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-node-gate-entrypoint.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-real-account-github-actions-run-record.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-workflow-template-shape.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/workflow-template-shape.mjs +94 -0
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-004.json +1 -1
- package/blueprints/delivery-ci-workflows/docs/topics.md +2 -3
- package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +4 -4
- package/blueprints/deploy-cloudflare-workers/README.md +3 -3
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +2 -2
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +2 -2
- package/blueprints/deploy-hetzner-server/CHANGELOG.md +98 -7
- package/blueprints/deploy-hetzner-server/blueprint.json +7 -6
- package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +46 -21
- package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +344 -83
- package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +211 -42
- package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +140 -22
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +111 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +158 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +154 -32
- package/blueprints/edge-cloudflare-access/CHANGELOG.md +6 -5
- package/blueprints/edge-cloudflare-access/blueprint.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +9 -1
- package/blueprints/edge-cloudflare-access/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +4 -7
- package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +4 -6
- package/blueprints/edge-cloudflare-tunnel/README.md +1 -2
- package/blueprints/edge-cloudflare-tunnel/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +2 -3
- package/blueprints/edge-cloudflare-turnstile/docs/topics.md +1 -1
- package/blueprints/email-smtp-resend/CHANGELOG.md +24 -8
- package/blueprints/email-smtp-resend/README.md +2 -2
- package/blueprints/email-smtp-resend/blueprint.json +3 -2
- package/blueprints/email-smtp-resend/contributions/probes/probe-utils.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/real-account-resend-send.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-real-account-resend-send.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-smtp-round-trip.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-unverified-sender-refusal.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/smtp-round-trip.mjs +43 -0
- package/blueprints/email-smtp-resend/contributions/probes/unverified-sender-refusal.mjs +99 -0
- package/blueprints/email-smtp-resend/docs/topics.md +2 -3
- package/blueprints/jobs-background/CHANGELOG.md +66 -5
- package/blueprints/jobs-background/README.md +2 -2
- package/blueprints/jobs-background/blueprint.json +3 -2
- package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +38 -10
- package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +28 -6
- package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +16 -2
- package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +102 -21
- package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +10 -2
- package/blueprints/jobs-background/contributions/probes/retry-and-fail-real-account.mjs +355 -0
- package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +33 -2
- package/blueprints/jobs-background/contributions/probes/run-retry-and-fail-real-account.mjs +12 -0
- package/blueprints/jobs-background/docs/topics.md +1 -1
- package/blueprints/jobs-background/guide/jobs-background.md +1 -1
- package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +25 -19
- package/blueprints/messaging-queue-cloudflare/README.md +12 -12
- package/blueprints/messaging-queue-cloudflare/blueprint.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +2 -2
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +180 -12
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +1 -1
- package/blueprints/messaging-queue-cloudflare/docs/topics.md +2 -2
- package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +2 -2
- package/blueprints/object-storage-s3/CHANGELOG.md +75 -4
- package/blueprints/object-storage-s3/blueprint.json +3 -2
- package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +73 -12
- package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +55 -7
- package/blueprints/object-storage-s3/contributions/probes/hetzner-object-storage-round-trip.mjs +102 -18
- package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +105 -36
- package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +104 -55
- package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +129 -7
- package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +80 -18
- package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +291 -37
- package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +5 -5
- package/blueprints/object-storage-s3/contributions/probes/run-hetzner-object-storage-round-trip.mjs +8 -5
- package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +6 -3
- package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +10 -2
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +1 -1
- package/blueprints/object-storage-s3/docs/topics.md +1 -1
- package/blueprints/object-storage-s3/guide/object-storage-s3.md +1 -1
- package/blueprints/observability-essentials/CHANGELOG.md +23 -7
- package/blueprints/observability-essentials/README.md +2 -2
- package/blueprints/observability-essentials/assets/probe-samples/probe-response-baseline.v2.json +1 -1
- package/blueprints/observability-essentials/blueprint.json +3 -2
- package/blueprints/observability-essentials/contributions/probes/liveness-probe.mjs +84 -0
- package/blueprints/observability-essentials/contributions/probes/metrics-endpoint.mjs +96 -0
- package/blueprints/observability-essentials/contributions/probes/probe-utils.mjs +52 -0
- package/blueprints/observability-essentials/contributions/probes/readiness-probe.mjs +171 -0
- package/blueprints/observability-essentials/contributions/probes/run-liveness-probe.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-metrics-endpoint.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-readiness-probe.mjs +3 -0
- package/blueprints/observability-essentials/docs/topics.md +2 -3
- package/blueprints/observability-logging/CHANGELOG.md +29 -4
- package/blueprints/observability-logging/README.md +2 -2
- package/blueprints/observability-logging/blueprint.json +3 -2
- package/blueprints/observability-logging/contributions/probes/correlation-id-flow.mjs +173 -0
- package/blueprints/observability-logging/contributions/probes/line-shape-and-fields.mjs +82 -0
- package/blueprints/observability-logging/contributions/probes/probe-utils.mjs +47 -0
- package/blueprints/observability-logging/contributions/probes/redaction-boundary.mjs +130 -0
- package/blueprints/observability-logging/contributions/probes/run-correlation-id-flow.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-line-shape-and-fields.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-redaction-boundary.mjs +3 -0
- package/blueprints/observability-probe-endpoints/CHANGELOG.md +23 -8
- package/blueprints/observability-probe-endpoints/README.md +3 -3
- package/blueprints/observability-probe-endpoints/blueprint.json +3 -2
- package/blueprints/observability-probe-endpoints/contributions/probes/kubernetes-startup-enabled.mjs +80 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/partial-profile-refusal.mjs +101 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/probe-utils.mjs +49 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/profile-boot-materialisation.mjs +69 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-kubernetes-startup-enabled.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-partial-profile-refusal.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-profile-boot-materialisation.mjs +3 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +2 -2
- package/blueprints/persistence-data-d1/CHANGELOG.md +16 -3
- package/blueprints/persistence-data-d1/README.md +2 -2
- package/blueprints/persistence-data-d1/blueprint.json +3 -2
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1404-persistence-data-d1-store-boundary.json +1 -1
- package/blueprints/persistence-data-d1/contributions/probes/facade-round-trip.mjs +140 -0
- package/blueprints/persistence-data-d1/contributions/probes/migrations-forward-only.mjs +66 -0
- package/blueprints/persistence-data-d1/contributions/probes/probe-utils.mjs +51 -0
- package/blueprints/persistence-data-d1/contributions/probes/real-account-d1-round-trip.mjs +133 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-facade-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-migrations-forward-only.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-real-account-d1-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/docs/topics.md +2 -3
- package/blueprints/persistence-data-postgres/CHANGELOG.md +84 -4
- package/blueprints/persistence-data-postgres/README.md +2 -2
- package/blueprints/persistence-data-postgres/blueprint.json +3 -2
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +87 -12
- package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +245 -19
- package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +109 -26
- package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +151 -38
- package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +24 -6
- package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +261 -48
- package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +76 -20
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +1 -1
- package/blueprints/persistence-data-postgres/docs/topics.md +1 -1
- package/blueprints/persistence-data-sqlite/CHANGELOG.md +16 -2
- package/blueprints/persistence-data-sqlite/README.md +2 -2
- package/blueprints/persistence-data-sqlite/blueprint.json +3 -2
- package/blueprints/persistence-data-sqlite/contributions/probes/boot-open-migrate.mjs +90 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/facade-round-trip.mjs +82 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/probe-utils.mjs +83 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-boot-open-migrate.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-facade-round-trip.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-wal-checkpoint.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/wal-checkpoint.mjs +137 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +5 -5
- package/blueprints/platform-cloudflare-cron-triggers/README.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +6 -10
- package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-kv/CHANGELOG.md +16 -12
- package/blueprints/platform-cloudflare-kv/README.md +2 -4
- package/blueprints/platform-cloudflare-kv/blueprint.json +2 -2
- package/blueprints/platform-cloudflare-kv/docs/topics.md +1 -1
- package/blueprints/platform-docker-compose-host/CHANGELOG.md +92 -5
- package/blueprints/platform-docker-compose-host/blueprint.json +2 -2
- package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +116 -29
- package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +181 -109
- package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +146 -26
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +238 -24
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +207 -21
- package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +246 -42
- package/blueprints/platform-docker-compose-host/docs/topics.md +1 -1
- package/blueprints/security-auth-clerk/CHANGELOG.md +18 -6
- package/blueprints/security-auth-clerk/README.md +3 -3
- package/blueprints/security-auth-clerk/assets/wiring/workers-wrangler-toml-shape.md +1 -1
- package/blueprints/security-auth-clerk/blueprint.json +3 -2
- package/blueprints/security-auth-clerk/contributions/probes/hosted-identity-ui-config.mjs +61 -0
- package/blueprints/security-auth-clerk/contributions/probes/probe-utils.mjs +188 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-principal-directory-round-trip.mjs +216 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-session-inventory.mjs +260 -0
- package/blueprints/security-auth-clerk/contributions/probes/role-model-adapter.mjs +53 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-hosted-identity-ui-config.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-principal-directory-round-trip.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-session-inventory.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-role-model-adapter.mjs +4 -0
- package/blueprints/security-auth-clerk/docs/topics.md +2 -3
- package/blueprints/security-auth-keycloak/CHANGELOG.md +18 -7
- package/blueprints/security-auth-keycloak/README.md +2 -2
- package/blueprints/security-auth-keycloak/blueprint.json +3 -2
- package/blueprints/security-auth-keycloak/contributions/probes/discovery-shape.mjs +68 -0
- package/blueprints/security-auth-keycloak/contributions/probes/introspection-shape.mjs +88 -0
- package/blueprints/security-auth-keycloak/contributions/probes/jwt-verifier-shape.mjs +86 -0
- package/blueprints/security-auth-keycloak/contributions/probes/probe-utils.mjs +180 -0
- package/blueprints/security-auth-keycloak/contributions/probes/real-account-realm-round-trip.mjs +91 -0
- package/blueprints/security-auth-keycloak/contributions/probes/role-adapter-shape.mjs +69 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-discovery-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-introspection-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-jwt-verifier-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-real-account-realm-round-trip.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-role-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/docs/topics.md +1 -2
- package/blueprints/security-auth-magic-link/CHANGELOG.md +15 -4
- package/blueprints/security-auth-magic-link/README.md +2 -2
- package/blueprints/security-auth-magic-link/assets/principal-registry-samples/single-address.md +1 -1
- package/blueprints/security-auth-magic-link/blueprint.json +3 -2
- package/blueprints/security-auth-magic-link/contributions/probes/probe-utils.mjs +174 -0
- package/blueprints/security-auth-magic-link/contributions/probes/real-account-magic-link-send.mjs +139 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-real-account-magic-link-send.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-entropy-shape.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-issue-verify.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-entropy-shape.mjs +60 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-issue-verify.mjs +90 -0
- package/blueprints/security-auth-magic-link/docs/topics.md +1 -1
- package/blueprints/security-auth-oauth2/CHANGELOG.md +16 -5
- package/blueprints/security-auth-oauth2/README.md +2 -2
- package/blueprints/security-auth-oauth2/blueprint.json +3 -2
- package/blueprints/security-auth-oauth2/contributions/probes/authorisation-code-flow-shape.mjs +259 -0
- package/blueprints/security-auth-oauth2/contributions/probes/pkce-challenge-shape.mjs +58 -0
- package/blueprints/security-auth-oauth2/contributions/probes/probe-utils.mjs +190 -0
- package/blueprints/security-auth-oauth2/contributions/probes/provider-adapter-shape.mjs +64 -0
- package/blueprints/security-auth-oauth2/contributions/probes/real-account-authorisation-code-flow.mjs +93 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-authorisation-code-flow-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-pkce-challenge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-provider-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-real-account-authorisation-code-flow.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-session-bridge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/session-bridge-shape.mjs +78 -0
- package/blueprints/security-auth-oauth2/docs/topics.md +1 -2
- package/blueprints/security-secrets-management/CHANGELOG.md +15 -4
- package/blueprints/security-secrets-management/README.md +2 -2
- package/blueprints/security-secrets-management/blueprint.json +3 -2
- package/blueprints/security-secrets-management/contributions/probes/add-recipient-rotation.mjs +107 -0
- package/blueprints/security-secrets-management/contributions/probes/encrypt-decrypt-round-trip.mjs +122 -0
- package/blueprints/security-secrets-management/contributions/probes/key-rotation.mjs +93 -0
- package/blueprints/security-secrets-management/contributions/probes/mismatched-key-refusal.mjs +74 -0
- package/blueprints/security-secrets-management/contributions/probes/probe-utils.mjs +214 -0
- package/blueprints/security-secrets-management/contributions/probes/run-add-recipient-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-encrypt-decrypt-round-trip.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-key-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-mismatched-key-refusal.mjs +4 -0
- package/blueprints/security-secrets-management/docs/topics.md +2 -3
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/harness-template.md +25 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +25 -0
- package/package.json +2 -2
- package/rcf/adrs/adr-4101-feedback-store-gitignored.json +20 -0
- package/rcf/adrs/adr-4102-fingerprint-and-labels.json +25 -0
- package/rcf/adrs/adr-4103-redaction-rule-based.json +20 -0
- package/rcf/adrs/adr-4104-destination-on-library.json +25 -0
- package/rcf/adrs/adr-4105-gh-ambient-auth.json +20 -0
- package/rcf/adrs/adr-4106-bundled-entries-terminal.json +20 -0
- package/rcf/adrs/adr-4107-stop-is-ask-event.json +30 -0
- package/rcf/adrs/adr-4108-hooks-in-committed-config.json +25 -0
- package/rcf/adrs/adr-4109-referee-validate-adr-crosslinks.json +25 -0
- package/rcf/adrs/adr-4110-referee-coverage-strict-by-default.json +25 -0
- package/rcf/adrs/adr-4111-referee-finalise-refusals.json +20 -0
- package/rcf/adrs/adr-4112-referee-finalise-verified-invariant.json +30 -0
- package/rcf/code-nodes/cn-600.json +45 -0
- package/rcf/code-nodes/cn-601.json +18 -0
- package/rcf/code-nodes/cn-602.json +15 -0
- package/rcf/code-nodes/cn-603.json +12 -0
- package/rcf/code-nodes/cn-604.json +14 -0
- package/rcf/code-nodes/cn-605.json +17 -0
- package/rcf/code-nodes/cn-606.json +12 -0
- package/rcf/code-nodes/cn-607.json +12 -0
- package/rcf/code-nodes/cn-608.json +14 -0
- package/rcf/code-nodes/cn-609.json +17 -0
- package/rcf/code-nodes/cn-620.json +18 -0
- package/rcf/code-nodes/cn-621.json +14 -0
- package/rcf/code-nodes/cn-622.json +15 -0
- package/rcf/code-nodes/cn-623.json +16 -0
- package/rcf/code-nodes/cn-624.json +14 -0
- package/rcf/code-nodes/cn-625.json +15 -0
- package/rcf/code-nodes/cn-626.json +13 -0
- package/rcf/code-nodes/cn-627.json +13 -0
- package/rcf/code-nodes/cn-628.json +14 -0
- package/rcf/code-nodes/cn-629.json +12 -0
- package/rcf/code-nodes/cn-630.json +12 -0
- package/rcf/code-nodes/cn-631.json +13 -0
- package/rcf/code-nodes/cn-632.json +13 -0
- package/rcf/fbs/fbs-180.json +45 -0
- package/rcf/fbs/fbs-181.json +45 -0
- package/rcf/fbs/fbs-182.json +42 -0
- package/rcf/fbs/fbs-183.json +50 -0
- package/rcf/fbs/fbs-184.json +49 -0
- package/rcf/fbs/fbs-185.json +34 -0
- package/rcf/fbs/fbs-186.json +16 -0
- package/rcf/fbs/fbs-187.json +17 -0
- package/rcf/fbs/fbs-188.json +17 -0
- package/rcf/fbs/fbs-189.json +17 -0
- package/rcf/requirements/req-155.json +13 -0
- package/rcf/requirements/req-156.json +13 -0
- package/rcf/requirements/req-157.json +13 -0
- package/rcf/requirements/req-158.json +13 -0
- package/rcf/requirements/req-159.json +13 -0
- package/rcf/requirements/req-160.json +13 -0
- package/rcf/requirements/req-161.json +13 -0
- package/rcf/requirements/req-162.json +13 -0
- package/rcf/requirements/req-163.json +13 -0
- package/rcf/requirements/req-164.json +13 -0
- package/rcf/requirements/req-165.json +13 -0
- package/rcf/tacs/tac-4101-feedback-cli.json +77 -0
- package/rcf/tacs/tac-4102-feedback-store.json +50 -0
- package/rcf/tacs/tac-4103-feedback-redact.json +39 -0
- package/rcf/tacs/tac-4104-feedback-fingerprint.json +33 -0
- package/rcf/tacs/tac-4105-feedback-render.json +45 -0
- package/rcf/tacs/tac-4106-feedback-destination.json +39 -0
- package/rcf/tacs/tac-4107-feedback-gh.json +43 -0
- package/rcf/tacs/tac-4108-feedback-hook.json +46 -0
- package/rcf/tacs/tac-4109-referee-validate-adr-crosslinks.json +20 -0
- package/rcf/tacs/tac-4110-referee-coverage-mode-selector.json +21 -0
- package/rcf/tacs/tac-4111-referee-finalise-per-ac-refusals.json +21 -0
- package/rcf/tacs/tac-4112-referee-finalise-verified-invariant.json +22 -0
- package/rcf/test-suites/ts-140.json +9 -9
- package/rcf/test-suites/ts-150.json +9 -9
- package/rcf/test-suites/ts-185.json +54 -0
- package/rcf/test-suites/ts-186.json +58 -0
- package/rcf/test-suites/ts-187.json +44 -0
- package/rcf/test-suites/ts-188.json +166 -0
- package/rcf/test-suites/ts-189.json +38 -0
- package/rcf/test-suites/ts-190.json +30 -0
- package/rcf/test-suites/ts-191.json +51 -0
- package/rcf/test-suites/ts-192.json +37 -0
- package/rcf/test-suites/ts-193.json +60 -0
- package/rcf/test-suites/ts-194.json +67 -0
- package/rcf/test-suites/ts-195.json +52 -0
- package/rcf/test-suites/ts-196.json +58 -0
- package/rcf/test-suites/ts-197.json +66 -0
- package/rcf/test-suites/ts-198.json +87 -0
- package/rcf/test-suites/ts-199.json +51 -0
- package/rcf/test-suites/ts-200.json +30 -0
- package/rcf/test-suites/ts-201.json +38 -0
- package/rcf/test-suites/ts-202.json +38 -0
- package/rcf/test-suites/ts-203.json +38 -0
- package/rcf/user-stories/us-15501.json +60 -0
- package/rcf/user-stories/us-15502.json +33 -0
- package/rcf/user-stories/us-15503.json +33 -0
- package/rcf/user-stories/us-15601.json +51 -0
- package/rcf/user-stories/us-15701.json +42 -0
- package/rcf/user-stories/us-15801.json +42 -0
- package/rcf/user-stories/us-15802.json +33 -0
- package/rcf/user-stories/us-15901.json +33 -0
- package/rcf/user-stories/us-15902.json +51 -0
- package/rcf/user-stories/us-16001.json +51 -0
- package/rcf/user-stories/us-16101.json +42 -0
- package/rcf/user-stories/us-16102.json +33 -0
- package/rcf/user-stories/us-16103.json +42 -0
- package/rcf/user-stories/us-16104.json +42 -0
- package/rcf/user-stories/us-16201.json +33 -0
- package/rcf/user-stories/us-16301.json +36 -0
- package/rcf/user-stories/us-16401.json +45 -0
- package/rcf/user-stories/us-16501.json +45 -0
- package/rcf/user-stories/us-16502.json +45 -0
- package/releases/releases.yaml +11 -1
- package/src/blueprint/library-loader.js +48 -0
- package/src/blueprint/library-registry.js +13 -0
- package/src/browser-verify/pack-runner.js +7 -12
- package/src/build/mark.js +1 -1
- package/src/cli/blueprint-library.js +149 -0
- package/src/cli/coverage.js +49 -24
- package/src/cli/doctor.js +195 -7
- package/src/cli/feedback.js +2204 -0
- package/src/cli/finalise.js +158 -1
- package/src/cli/help.js +6 -0
- package/src/cli/init.js +63 -0
- package/src/cli/update.js +21 -1
- package/src/core/store/walker.js +33 -0
- package/src/core/store/writer.js +23 -0
- package/src/feedback/destination.js +361 -0
- package/src/feedback/fingerprint.js +132 -0
- package/src/feedback/gh.js +376 -0
- package/src/feedback/hook.js +183 -0
- package/src/feedback/labels.js +87 -0
- package/src/feedback/redact-allowlist.json +14 -0
- package/src/feedback/redact.js +1108 -0
- package/src/feedback/render.js +267 -0
- package/src/feedback/store.js +604 -0
- package/src/finalise/index.js +4 -0
- package/src/finalise/ingest.js +61 -0
- package/src/finalise/ship-without-eval.js +19 -7
- package/src/mcp/tools.js +8 -2
- package/src/setup/feedback-hooks.js +397 -0
- package/src/setup/managed-gitignore.js +3 -0
- package/src/view/html-page.js +5 -5
- package/src/view/style.css +2 -2
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry-and-fail real-account probe (live-engine coverage).
|
|
3
|
+
*
|
|
4
|
+
* Exercises REAL Cloudflare Queues end-to-end through the vendor's
|
|
5
|
+
* pull-consumer + dead-letter-queue mechanism (per
|
|
6
|
+
* https://developers.cloudflare.com/queues/configuration/pull-consumers/
|
|
7
|
+
* and https://developers.cloudflare.com/queues/configuration/dead-letter-queues/).
|
|
8
|
+
*
|
|
9
|
+
* Flow:
|
|
10
|
+
* 1. Mint a scratch queue (name minted at run time from a probe
|
|
11
|
+
* constant plus a short random suffix; see the code below and
|
|
12
|
+
* the run-notes.md in the evidence tree for the resolved name)
|
|
13
|
+
* and a paired DLQ via the CF REST Queues API.
|
|
14
|
+
* 2. Attach an `http_pull` consumer to the main queue with
|
|
15
|
+
* max_retries=3, dead_letter_queue=<dlq name>, visibility timeout
|
|
16
|
+
* short (2 s) so the observation window stays tight. Attach an
|
|
17
|
+
* `http_pull` consumer to the DLQ so a subsequent pull can
|
|
18
|
+
* positively record DLQ landing.
|
|
19
|
+
* 3. Publish one message.
|
|
20
|
+
* 4. Pull, retry, repeat until the message no longer appears on the
|
|
21
|
+
* primary queue (Cloudflare moved it to the DLQ after
|
|
22
|
+
* max_retries+1 deliveries). Record the observed attempts on each
|
|
23
|
+
* pull.
|
|
24
|
+
* 5. Pull the DLQ and assert the message id landed there.
|
|
25
|
+
* 6. Teardown: delete both queues; confirm each is absent from the
|
|
26
|
+
* account queue listing.
|
|
27
|
+
*
|
|
28
|
+
* Skip on missing account creds: exactly one variable per skip row.
|
|
29
|
+
*
|
|
30
|
+
* Row anchoring:
|
|
31
|
+
* - The account-bound skip row anchors AC-jobs-retryOnHandlerFailure
|
|
32
|
+
* (the shipped retry AC) with `accountBoundSkipped: true` and a
|
|
33
|
+
* `reason` naming the one unset gate variable.
|
|
34
|
+
* - Every non-skip row is CONFORMANCE-ONLY with `anchorAcId: null`
|
|
35
|
+
* and a `limitation` naming the nearest shipped AC id and the
|
|
36
|
+
* property it states that this probe does NOT positively observe:
|
|
37
|
+
* - Provisioning row -> AC-jobs-requiresQueue (states init-time
|
|
38
|
+
* queue requirement; this row records vendor queue creation).
|
|
39
|
+
* - Attempts-counter row -> AC-jobs-retryOnHandlerFailure (states
|
|
40
|
+
* the applied in-memory queue redelivery and three jobStarted
|
|
41
|
+
* events on the sink; this row records Cloudflare Queues'
|
|
42
|
+
* vendor attempts counter, not the sink events).
|
|
43
|
+
* - DLQ landing row -> AC-30109-1 (states DLQ-producer invocation
|
|
44
|
+
* on the in-memory driver; this row records real Cloudflare
|
|
45
|
+
* Queues DLQ landing).
|
|
46
|
+
* - Teardown row -> AC-jobs-requiresQueue (no AC states scratch
|
|
47
|
+
* teardown; this row records DELETE + post-run absence).
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
export const accountBound = true;
|
|
51
|
+
export const DECLARED_ENV = Object.freeze([
|
|
52
|
+
'CI_HAS_CLOUDFLARE_ACCOUNT',
|
|
53
|
+
'CF_ACCOUNT_ID',
|
|
54
|
+
'CF_API_TOKEN',
|
|
55
|
+
'CF_API_BASE',
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
// CF_API_BASE is a required declared variable per the endpoint-hosts rule;
|
|
59
|
+
// no literal endpoint host in probe source. The runProbe() gate checks
|
|
60
|
+
// it before use and returns an exact one-variable skip when unset.
|
|
61
|
+
|
|
62
|
+
const AC_RETRY_FIRST8 = 'With SIMULATE_HANDLER_THROW=true set on the shared sample-app fixture,';
|
|
63
|
+
const AC_REQUIRES_FIRST8 = 'On a fresh init scratch project with NO';
|
|
64
|
+
const AC_PROVISION_LIMITATION = 'AC-jobs-requiresQueue: On a fresh init scratch project with NO messaging-queue provider applied, rcf-lite refuses to apply jobs-background with the stable message id jobs-background-no-queue. Not observed on this row: this row records vendor queue and DLQ provisioning on a real Cloudflare account, which the AC does not state (its property is CLI refusal at init time, not vendor-side queue creation).';
|
|
65
|
+
const AC_ATTEMPTS_LIMITATION = 'AC-jobs-retryOnHandlerFailure: With SIMULATE_HANDLER_THROW=true set on the shared sample-app fixture, the retry-and-fail probe schedules a job whose handler throws a retryable error; the applied in-memory queue redelivers the message per retryPolicy.maxAttempts. Three jobStarted events fire on the sink with the same jobId and attempts counter 1, 2, 3; after the third failure jobFailed fires with a terminal error code and no further re-delivery follows. Not observed on this row: the AC states applied in-memory queue redelivery and jobStarted-on-sink events; this row records the vendor Cloudflare Queues attempts counter across pulls [0,1,2,3], not the jobStarted sink events the AC states.';
|
|
66
|
+
const AC_DLQ_LIMITATION = 'AC-30109-1: The retry-and-fail probe report, after the three failing attempts, records the DLQ-producer invocation on the in-memory driver via a jobDeadLettered event carrying the terminal job id and the original job body. Not observed on this row: the AC pins the in-memory driver DLQ-producer invocation; this row records real Cloudflare Queues DLQ landing (backlog + payload-id match on a real DLQ), which the AC does not state.';
|
|
67
|
+
const AC_TEARDOWN_LIMITATION = 'AC-jobs-requiresQueue: On a fresh init scratch project with NO messaging-queue provider applied, rcf-lite refuses to apply jobs-background with the stable message id jobs-background-no-queue. Not observed on this row: this row records scratch Cloudflare Queues DELETE + post-run absence via the account queue listing, which no jobs-background AC or REQ states; the AC used as a signpost is the nearest shipped AC on queue existence.';
|
|
68
|
+
|
|
69
|
+
function skipRow(reason) {
|
|
70
|
+
return {
|
|
71
|
+
results: [{
|
|
72
|
+
anchorAcId: 'AC-jobs-retryOnHandlerFailure',
|
|
73
|
+
verdict: 'pass',
|
|
74
|
+
detail: `${AC_RETRY_FIRST8} - accountBound: skipped (${reason})`,
|
|
75
|
+
accountBoundSkipped: true,
|
|
76
|
+
reason,
|
|
77
|
+
evidence: { skip: true, reason, envDeclared: [...DECLARED_ENV] },
|
|
78
|
+
}],
|
|
79
|
+
extra: { accountBoundSkipped: true, reason, envDeclared: [...DECLARED_ENV] },
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function cf(apiBase, method, path, token, body) {
|
|
84
|
+
const res = await fetch(`${apiBase}${path}`, {
|
|
85
|
+
method,
|
|
86
|
+
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
|
|
87
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
88
|
+
});
|
|
89
|
+
const text = await res.text();
|
|
90
|
+
let json = null;
|
|
91
|
+
try { json = JSON.parse(text); } catch { /* keep raw */ }
|
|
92
|
+
return { httpStatus: res.status, json, raw: text };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function shortId() {
|
|
96
|
+
return Math.random().toString(36).slice(2, 8);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
100
|
+
|
|
101
|
+
export default async function runProbe() {
|
|
102
|
+
const gate = process.env.CI_HAS_CLOUDFLARE_ACCOUNT;
|
|
103
|
+
if (gate == null || gate === '') return skipRow('CI_HAS_CLOUDFLARE_ACCOUNT unset');
|
|
104
|
+
if (gate !== 'true') return skipRow('CI_HAS_CLOUDFLARE_ACCOUNT (not "true")');
|
|
105
|
+
if (!process.env.CF_ACCOUNT_ID) return skipRow('CF_ACCOUNT_ID unset');
|
|
106
|
+
if (!process.env.CF_API_TOKEN) return skipRow('CF_API_TOKEN unset');
|
|
107
|
+
if (!process.env.CF_API_BASE) return skipRow('CF_API_BASE unset');
|
|
108
|
+
|
|
109
|
+
const API_BASE = process.env.CF_API_BASE;
|
|
110
|
+
const accountId = process.env.CF_ACCOUNT_ID;
|
|
111
|
+
const token = process.env.CF_API_TOKEN;
|
|
112
|
+
const short = shortId();
|
|
113
|
+
const queueName = `qa-e-jobs-q-${short}`;
|
|
114
|
+
const dlqName = `qa-e-jobs-dlq-${short}`;
|
|
115
|
+
const results = [];
|
|
116
|
+
const teardown = { deletePrimary: null, deleteDlq: null, primaryAbsent: null, dlqAbsent: null };
|
|
117
|
+
let qid = null;
|
|
118
|
+
let dlqId = null;
|
|
119
|
+
try {
|
|
120
|
+
// 1. mint DLQ first, then the main queue (main queue's consumer
|
|
121
|
+
// config references the DLQ by name).
|
|
122
|
+
const dlqCreate = await cf(API_BASE, 'POST', `/accounts/${accountId}/queues`, token, { queue_name: dlqName });
|
|
123
|
+
dlqId = dlqCreate.json && dlqCreate.json.result && dlqCreate.json.result.queue_id;
|
|
124
|
+
if (!dlqId) throw new Error(`DLQ create failed: httpStatus=${dlqCreate.httpStatus} body=${dlqCreate.raw}`);
|
|
125
|
+
const dlqConsumer = await cf(API_BASE, 'POST', `/accounts/${accountId}/queues/${dlqId}/consumers`, token, {
|
|
126
|
+
type: 'http_pull',
|
|
127
|
+
settings: { batch_size: 10, visibility_timeout_ms: 10000, max_retries: 3, retry_delay: 0 },
|
|
128
|
+
});
|
|
129
|
+
if (!(dlqConsumer.json && dlqConsumer.json.success)) throw new Error(`DLQ consumer attach failed: ${dlqConsumer.raw}`);
|
|
130
|
+
|
|
131
|
+
const primaryCreate = await cf(API_BASE, 'POST', `/accounts/${accountId}/queues`, token, { queue_name: queueName });
|
|
132
|
+
qid = primaryCreate.json && primaryCreate.json.result && primaryCreate.json.result.queue_id;
|
|
133
|
+
if (!qid) throw new Error(`primary create failed: httpStatus=${primaryCreate.httpStatus} body=${primaryCreate.raw}`);
|
|
134
|
+
const primaryConsumer = await cf(API_BASE, 'POST', `/accounts/${accountId}/queues/${qid}/consumers`, token, {
|
|
135
|
+
type: 'http_pull',
|
|
136
|
+
dead_letter_queue: dlqName,
|
|
137
|
+
settings: { batch_size: 10, visibility_timeout_ms: 2000, max_retries: 3, retry_delay: 0 },
|
|
138
|
+
});
|
|
139
|
+
if (!(primaryConsumer.json && primaryConsumer.json.success)) throw new Error(`primary consumer attach failed: ${primaryConsumer.raw}`);
|
|
140
|
+
|
|
141
|
+
results.push({
|
|
142
|
+
anchorAcId: null,
|
|
143
|
+
conformanceOnly: true,
|
|
144
|
+
limitation: AC_PROVISION_LIMITATION,
|
|
145
|
+
verdict: 'pass',
|
|
146
|
+
detail: `conformanceOnly (${AC_PROVISION_LIMITATION}) - provisioned scratch queue ${queueName} (id=${qid}) with DLQ ${dlqName} (id=${dlqId}), both with http_pull consumers, max_retries=3`,
|
|
147
|
+
evidence: {
|
|
148
|
+
queueName, dlqName,
|
|
149
|
+
primaryConsumerResponseMetadata: primaryConsumer.json && primaryConsumer.json.result,
|
|
150
|
+
dlqConsumerResponseMetadata: dlqConsumer.json && dlqConsumer.json.result,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// 3. publish one message
|
|
155
|
+
const publishJobId = `job-${short}`;
|
|
156
|
+
const pubBody = { jobId: publishJobId, jobName: 'send-welcome-email', jobInput: { userId: 7, email: 'ok@example.com' } };
|
|
157
|
+
const pub = await cf(API_BASE, 'POST', `/accounts/${accountId}/queues/${qid}/messages`, token, { body: pubBody, content_type: 'json' });
|
|
158
|
+
if (!(pub.json && pub.json.success)) throw new Error(`publish failed: ${pub.raw}`);
|
|
159
|
+
|
|
160
|
+
// 4. pull + retry loop; observe attempts increasing to 3, then absent
|
|
161
|
+
const attemptsObserved = [];
|
|
162
|
+
let messageIdObserved = null;
|
|
163
|
+
for (let i = 0; i < 20; i += 1) {
|
|
164
|
+
const pull = await cf(API_BASE, 'POST', `/accounts/${accountId}/queues/${qid}/messages/pull`, token, {
|
|
165
|
+
batch_size: 10,
|
|
166
|
+
visibility_timeout_ms: 2000,
|
|
167
|
+
});
|
|
168
|
+
const msgs = (pull.json && pull.json.result && pull.json.result.messages) || [];
|
|
169
|
+
if (msgs.length === 0) {
|
|
170
|
+
// Wait a bit; message may have been consumed by the retry cycle
|
|
171
|
+
// and not yet visible again, OR moved to DLQ.
|
|
172
|
+
attemptsObserved.push({ pulled: 0 });
|
|
173
|
+
await sleep(2500);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const m = msgs[0];
|
|
177
|
+
messageIdObserved = m.id;
|
|
178
|
+
attemptsObserved.push({ pulled: msgs.length, attempts: m.attempts, id: m.id });
|
|
179
|
+
// Retry: tell CF to reschedule with retry_delay=0
|
|
180
|
+
const ack = await cf(API_BASE, 'POST', `/accounts/${accountId}/queues/${qid}/messages/ack`, token, {
|
|
181
|
+
retries: [{ lease_id: m.lease_id, delay_seconds: 0 }],
|
|
182
|
+
});
|
|
183
|
+
if (!(ack.json && ack.json.success)) throw new Error(`ack retry failed: ${ack.raw}`);
|
|
184
|
+
await sleep(500);
|
|
185
|
+
}
|
|
186
|
+
// After the loop, message should be either absent (moved to DLQ) or
|
|
187
|
+
// in the DLQ. Poll the DLQ a few times to allow for the vendor's
|
|
188
|
+
// internal retry-to-DLQ transfer window.
|
|
189
|
+
let dlqMsgs = [];
|
|
190
|
+
let dlqBacklog = 0;
|
|
191
|
+
let dlqPullAttempts = 0;
|
|
192
|
+
for (let dp = 0; dp < 10; dp += 1) {
|
|
193
|
+
await sleep(2000);
|
|
194
|
+
dlqPullAttempts += 1;
|
|
195
|
+
const dlqPull = await cf(API_BASE, 'POST', `/accounts/${accountId}/queues/${dlqId}/messages/pull`, token, {
|
|
196
|
+
batch_size: 10,
|
|
197
|
+
visibility_timeout_ms: 30000,
|
|
198
|
+
});
|
|
199
|
+
dlqMsgs = (dlqPull.json && dlqPull.json.result && dlqPull.json.result.messages) || [];
|
|
200
|
+
dlqBacklog = (dlqPull.json && dlqPull.json.result && dlqPull.json.result.message_backlog_count) || dlqMsgs.length;
|
|
201
|
+
if (dlqMsgs.length > 0 || dlqBacklog >= 1) break;
|
|
202
|
+
}
|
|
203
|
+
// Cloudflare Queues assigns fresh transport message ids when a
|
|
204
|
+
// message lands in the DLQ, so a strict transport id-match is not
|
|
205
|
+
// achievable at the vendor surface. The probe carries its own
|
|
206
|
+
// application-level correlation id in the message body payload
|
|
207
|
+
// (`publishJobId`) and matches on that: the row is only a pass
|
|
208
|
+
// when the same payload jobId that was published to the primary
|
|
209
|
+
// is observed on the DLQ landing.
|
|
210
|
+
const dlqPayloadIds = dlqMsgs.map((mm) => (mm.body && (typeof mm.body === 'string'
|
|
211
|
+
? (() => { try { return JSON.parse(mm.body).jobId; } catch { return null; } })()
|
|
212
|
+
: mm.body.jobId))).filter(Boolean);
|
|
213
|
+
const idMatch = dlqPayloadIds.includes(publishJobId);
|
|
214
|
+
const seenInDlq = idMatch; // strict: payload correlation-id match required
|
|
215
|
+
// Ack the DLQ message so it doesn't loiter (deletion also happens
|
|
216
|
+
// in teardown). Ack failures are NOT swallowed - they land on
|
|
217
|
+
// teardown.dlqAcks so a failure surfaces on the teardown row.
|
|
218
|
+
teardown.dlqAcks = [];
|
|
219
|
+
for (const mm of dlqMsgs) {
|
|
220
|
+
try {
|
|
221
|
+
const ack = await cf(API_BASE, 'POST', `/accounts/${accountId}/queues/${dlqId}/messages/ack`, token, {
|
|
222
|
+
acks: [{ lease_id: mm.lease_id }],
|
|
223
|
+
});
|
|
224
|
+
teardown.dlqAcks.push({
|
|
225
|
+
lease_id: mm.lease_id,
|
|
226
|
+
httpStatus: ack.httpStatus,
|
|
227
|
+
success: !!(ack.json && ack.json.success === true),
|
|
228
|
+
});
|
|
229
|
+
} catch (err) {
|
|
230
|
+
teardown.dlqAcks.push({ lease_id: mm.lease_id, ok: false, error: err && err.message });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Assertion 1: observed attempts sequence includes non-zero values
|
|
235
|
+
// (real engine incremented the counter).
|
|
236
|
+
const uniqueAttempts = [...new Set(attemptsObserved.filter((a) => a.attempts != null).map((a) => a.attempts))].sort((a, b) => a - b);
|
|
237
|
+
// REQ-004 states the applied queue redelivers per its own retry
|
|
238
|
+
// contract (Cloudflare Queues ceiling 100 per ADR-3003) and the
|
|
239
|
+
// jobs runtime records the attempt counter on each jobStarted
|
|
240
|
+
// event. With max_retries=3 the vendor's attempts counter must
|
|
241
|
+
// reach exactly the [0..3] consecutive sequence (initial delivery
|
|
242
|
+
// 0 plus three retries 1, 2, 3). A gapped sequence such as [0,2,3]
|
|
243
|
+
// fails the row.
|
|
244
|
+
const expectedAttempts = [0, 1, 2, 3];
|
|
245
|
+
const sawRetries = uniqueAttempts.length === expectedAttempts.length
|
|
246
|
+
&& uniqueAttempts.every((v, i) => v === expectedAttempts[i]);
|
|
247
|
+
results.push({
|
|
248
|
+
anchorAcId: null,
|
|
249
|
+
conformanceOnly: true,
|
|
250
|
+
limitation: AC_ATTEMPTS_LIMITATION,
|
|
251
|
+
verdict: sawRetries ? 'pass' : 'fail',
|
|
252
|
+
detail: sawRetries
|
|
253
|
+
? `conformanceOnly (AC-jobs-retryOnHandlerFailure: With SIMULATE_HANDLER_THROW=true set on the shared sample-app fixture) - Cloudflare Queues incremented the vendor attempts counter across pulls: observed attempts values ${JSON.stringify(uniqueAttempts)}`
|
|
254
|
+
: `conformanceOnly (AC-jobs-retryOnHandlerFailure: With SIMULATE_HANDLER_THROW=true set on the shared sample-app fixture) - did not observe the vendor attempts counter increment across pulls; attemptsObserved=${JSON.stringify(attemptsObserved)}`,
|
|
255
|
+
evidence: { attemptsObserved, uniqueAttempts, messageId: messageIdObserved, queueName },
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// Assertion 2: message ended up on DLQ (positive dead-letter
|
|
259
|
+
// landing in a real Cloudflare Queue).
|
|
260
|
+
results.push({
|
|
261
|
+
anchorAcId: null,
|
|
262
|
+
conformanceOnly: true,
|
|
263
|
+
limitation: AC_DLQ_LIMITATION,
|
|
264
|
+
verdict: seenInDlq ? 'pass' : 'fail',
|
|
265
|
+
detail: seenInDlq
|
|
266
|
+
? `conformanceOnly (${AC_DLQ_LIMITATION}) - after ${attemptsObserved.length} primary pulls and ${dlqPullAttempts} DLQ polls the message landed on the DLQ ${dlqName} (backlog=${dlqBacklog}, payload-id-match=true for ${publishJobId})`
|
|
267
|
+
: `conformanceOnly (${AC_DLQ_LIMITATION}) - published payload jobId ${publishJobId} did not appear on the DLQ ${dlqName} within ${dlqPullAttempts} polls; dlqBacklog=${dlqBacklog} observedDlqPayloadIds=${JSON.stringify(dlqPayloadIds)} primary pulls=${attemptsObserved.length}`,
|
|
268
|
+
evidence: { dlqName, dlqId, dlqBacklog, dlqTransportMessageIds: dlqMsgs.map((mm) => mm.id), dlqPayloadJobIds: dlqPayloadIds, expectedPayloadJobId: publishJobId, primaryTransportMessageId: messageIdObserved, payloadIdMatch: idMatch, dlqPollAttempts: dlqPullAttempts },
|
|
269
|
+
});
|
|
270
|
+
} finally {
|
|
271
|
+
// 6. Teardown: delete both queues; confirm absent from listing.
|
|
272
|
+
// A teardown failure FAILS the verdict (authoring-standard rule 5).
|
|
273
|
+
if (qid) {
|
|
274
|
+
try {
|
|
275
|
+
const d = await cf(API_BASE, 'DELETE', `/accounts/${accountId}/queues/${qid}`, token);
|
|
276
|
+
teardown.deletePrimary = { queueId: qid, ok: d.json && d.json.success === true, httpStatus: d.httpStatus };
|
|
277
|
+
} catch (err) {
|
|
278
|
+
teardown.deletePrimary = { queueId: qid, ok: false, error: err && err.message };
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (dlqId) {
|
|
282
|
+
try {
|
|
283
|
+
const d = await cf(API_BASE, 'DELETE', `/accounts/${accountId}/queues/${dlqId}`, token);
|
|
284
|
+
teardown.deleteDlq = { queueId: dlqId, ok: d.json && d.json.success === true, httpStatus: d.httpStatus };
|
|
285
|
+
} catch (err) {
|
|
286
|
+
teardown.deleteDlq = { queueId: dlqId, ok: false, error: err && err.message };
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Confirm absence via a queue list. Assert HTTP status 200 AND
|
|
290
|
+
// json.success === true before treating the listing as authoritative;
|
|
291
|
+
// record both on the teardown so an unsuccessful response never
|
|
292
|
+
// normalises to an empty list (absence must be positive evidence).
|
|
293
|
+
// Cloudflare Queues DELETE is asynchronous - the listing can still
|
|
294
|
+
// carry the queue for a few seconds after DELETE 200. Poll the
|
|
295
|
+
// listing up to ~30 s (six 5-second sleeps) before accepting the
|
|
296
|
+
// result as authoritative. The final observed listing (with the
|
|
297
|
+
// number of polls it took) lands on teardown.listing.
|
|
298
|
+
let listingPolls = 0;
|
|
299
|
+
let list = null;
|
|
300
|
+
try {
|
|
301
|
+
for (let i = 0; i < 6; i += 1) {
|
|
302
|
+
listingPolls += 1;
|
|
303
|
+
list = await cf(API_BASE, 'GET', `/accounts/${accountId}/queues`, token);
|
|
304
|
+
const httpOk = list.httpStatus === 200;
|
|
305
|
+
const successFlag = !!(list.json && list.json.success === true);
|
|
306
|
+
if (!httpOk || !successFlag) break;
|
|
307
|
+
const nms = (list.json.result || []).map((q) => q.queue_name);
|
|
308
|
+
if (!nms.includes(queueName) && !nms.includes(dlqName)) break;
|
|
309
|
+
await sleep(5000);
|
|
310
|
+
}
|
|
311
|
+
const httpOk = list && list.httpStatus === 200;
|
|
312
|
+
const successFlag = !!(list && list.json && list.json.success === true);
|
|
313
|
+
const listingOk = httpOk && successFlag;
|
|
314
|
+
const names = listingOk
|
|
315
|
+
? ((list.json && list.json.result) || []).map((q) => q.queue_name)
|
|
316
|
+
: [];
|
|
317
|
+
teardown.listing = {
|
|
318
|
+
httpStatus: list ? list.httpStatus : null,
|
|
319
|
+
success: successFlag,
|
|
320
|
+
listingOk,
|
|
321
|
+
listedCount: names.length,
|
|
322
|
+
pollsTaken: listingPolls,
|
|
323
|
+
errors: list && list.json && list.json.errors ? list.json.errors : null,
|
|
324
|
+
};
|
|
325
|
+
teardown.primaryAbsent = listingOk
|
|
326
|
+
? { ok: !names.includes(queueName), listedCount: names.length, httpStatus: list.httpStatus, success: successFlag }
|
|
327
|
+
: { ok: false, listedCount: names.length, httpStatus: list.httpStatus, success: successFlag, note: 'listing unsuccessful; absence cannot be asserted' };
|
|
328
|
+
teardown.dlqAbsent = listingOk
|
|
329
|
+
? { ok: !names.includes(dlqName), listedCount: names.length, httpStatus: list.httpStatus, success: successFlag }
|
|
330
|
+
: { ok: false, listedCount: names.length, httpStatus: list.httpStatus, success: successFlag, note: 'listing unsuccessful; absence cannot be asserted' };
|
|
331
|
+
} catch (err) {
|
|
332
|
+
teardown.listing = { httpStatus: null, success: false, listingOk: false, error: err && err.message };
|
|
333
|
+
teardown.primaryAbsent = { ok: false, error: err && err.message };
|
|
334
|
+
teardown.dlqAbsent = { ok: false, error: err && err.message };
|
|
335
|
+
}
|
|
336
|
+
const dlqAcksOk = Array.isArray(teardown.dlqAcks)
|
|
337
|
+
&& teardown.dlqAcks.every((a) => a.success === true);
|
|
338
|
+
const teardownOk = teardown.deletePrimary && teardown.deletePrimary.ok
|
|
339
|
+
&& teardown.deleteDlq && teardown.deleteDlq.ok
|
|
340
|
+
&& teardown.primaryAbsent && teardown.primaryAbsent.ok
|
|
341
|
+
&& teardown.dlqAbsent && teardown.dlqAbsent.ok
|
|
342
|
+
&& dlqAcksOk;
|
|
343
|
+
results.push({
|
|
344
|
+
anchorAcId: null,
|
|
345
|
+
conformanceOnly: true,
|
|
346
|
+
limitation: AC_TEARDOWN_LIMITATION,
|
|
347
|
+
verdict: teardownOk ? 'pass' : 'fail',
|
|
348
|
+
detail: teardownOk
|
|
349
|
+
? `conformanceOnly (${AC_TEARDOWN_LIMITATION}) - scratch queues ${queueName} and ${dlqName} deleted and confirmed absent from post-run account queue listing`
|
|
350
|
+
: `conformanceOnly (${AC_TEARDOWN_LIMITATION}) - queue teardown FAILED: ${JSON.stringify(teardown)}`,
|
|
351
|
+
evidence: { teardown },
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
return { results, extra: { envDeclared: [...DECLARED_ENV], queueName, dlqName, teardown } };
|
|
355
|
+
}
|
|
@@ -19,6 +19,8 @@ import { createScheduler, createFakeClock } from '../../../../packages/rcf-lite/
|
|
|
19
19
|
import { PROJECT_ROOT } from './probe-utils.mjs';
|
|
20
20
|
import { resolve } from 'node:path';
|
|
21
21
|
|
|
22
|
+
const AC_FIRST8 = 'With SIMULATE_HANDLER_THROW=true set on the shared sample-app fixture,';
|
|
23
|
+
|
|
22
24
|
export default async function runProbe() {
|
|
23
25
|
const cfg = queueConfigFromEnv();
|
|
24
26
|
// maxRetries on the driver matches send-welcome-email.maxAttempts=3.
|
|
@@ -54,12 +56,41 @@ export default async function runProbe() {
|
|
|
54
56
|
const oneJobId = jobIds.size === 1;
|
|
55
57
|
const failedOk = !!jobFailed && typeof jobFailed.terminalErrorCode === 'string';
|
|
56
58
|
const pass = attemptsOk && oneJobId && failedOk;
|
|
59
|
+
const scalarJobId = jobIds.size > 0 ? [...jobIds][0] : null;
|
|
57
60
|
results.push({
|
|
58
61
|
anchorAcId: 'AC-jobs-retryOnHandlerFailure',
|
|
59
62
|
verdict: pass ? 'pass' : 'fail',
|
|
60
63
|
detail: pass
|
|
61
|
-
?
|
|
62
|
-
:
|
|
64
|
+
? `${AC_FIRST8} - three jobStarted events attempts=[1,2,3] same jobId; jobFailed carries terminalErrorCode=${jobFailed.terminalErrorCode}`
|
|
65
|
+
: `${AC_FIRST8} - attemptsSeq=${JSON.stringify(attemptsSeq)}; jobIds.size=${jobIds.size}; jobFailed=${JSON.stringify(jobFailed)}`,
|
|
66
|
+
evidence: {
|
|
67
|
+
jobId: scalarJobId,
|
|
68
|
+
attemptsSequence: attemptsSeq,
|
|
69
|
+
distinctJobIdList: [...jobIds],
|
|
70
|
+
jobStartedCount: jobStartedEvents.length,
|
|
71
|
+
terminalJobFailed: jobFailed || null,
|
|
72
|
+
dlqInvoked,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
// AC-30109-1: after the three failing jobStarted events and the
|
|
76
|
+
// terminal jobFailed event, the underlying in-memory queue driver
|
|
77
|
+
// invoked the DLQ producer path. Observed as `dlqInvoked:true`
|
|
78
|
+
// (state.dlq carries the failing message id after the drain).
|
|
79
|
+
const dlqEntry = pair.state.dlq[0] || null;
|
|
80
|
+
const dlqPass = dlqInvoked === true && failedOk;
|
|
81
|
+
results.push({
|
|
82
|
+
anchorAcId: 'AC-30109-1',
|
|
83
|
+
verdict: dlqPass ? 'pass' : 'fail',
|
|
84
|
+
detail: dlqPass
|
|
85
|
+
? `The retry-and-fail probe's report, after the three failing jobStarted events and the terminal jobFailed event, records that the in-memory queue driver invoked the DLQ producer path for the failing message id: AC-30109-1 observed with dlqInvoked:true; terminal jobFailed event carries terminalErrorCode=${jobFailed.terminalErrorCode}; the failing message id was routed to state.dlq after maxAttempts exhausted`
|
|
86
|
+
: `The retry-and-fail probe's report, after the three failing jobStarted events and the terminal jobFailed event, did not record dlqInvoked true: AC-30109-1 not observed - dlqInvoked=${dlqInvoked} jobFailed=${JSON.stringify(jobFailed)}`,
|
|
87
|
+
evidence: {
|
|
88
|
+
jobId: scalarJobId,
|
|
89
|
+
dlqInvoked,
|
|
90
|
+
dlqLength: pair.state.dlq.length,
|
|
91
|
+
attemptsSequence: attemptsSeq,
|
|
92
|
+
terminalJobFailed: jobFailed || null,
|
|
93
|
+
},
|
|
63
94
|
});
|
|
64
95
|
return { results, extra: { events, dlqInvoked, attemptsSeq } };
|
|
65
96
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shim: run retry-and-fail-real-account against the the real-account credentials
|
|
3
|
+
* Cloudflare account. Records real HTTP status + per-pull observations
|
|
4
|
+
* as engine descriptor.
|
|
5
|
+
*/
|
|
6
|
+
import runProbe from './retry-and-fail-real-account.mjs';
|
|
7
|
+
import { runShim } from './probe-utils.mjs';
|
|
8
|
+
|
|
9
|
+
const engine = process.env.CI_HAS_CLOUDFLARE_ACCOUNT === 'true'
|
|
10
|
+
? { kind: 'queue', vendor: 'cloudflare-queues', observed: 'per-request on results' }
|
|
11
|
+
: { kind: 'queue', vendor: 'cloudflare-queues', observed: false, reason: 'CI_HAS_CLOUDFLARE_ACCOUNT unset' };
|
|
12
|
+
runShim('retry-and-fail-real-account', engine, runProbe);
|
|
@@ -56,7 +56,7 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
56
56
|
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
57
57
|
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
58
58
|
|
|
59
|
-
US 30101-30109 sit at the LOW end of the 30101-30899 band on purpose
|
|
59
|
+
US 30101-30109 sit at the LOW end of the 30101-30899 band on purpose. A project-side story mechanically derived from a jobs-background REQ id into the number 30110 would collide against a shipped US-30110; band headroom (30110-30899) leaves that space.
|
|
60
60
|
|
|
61
61
|
ADR/TAC suffixes for this blueprint use the 3101-3199 block, continuing the shelf pattern.
|
|
62
62
|
|
|
@@ -144,4 +144,4 @@ What does NOT change:
|
|
|
144
144
|
|
|
145
145
|
- `observability-logging` (companion): supplies the run-log upstream so the four lifecycle events flow through the applied logger's channel policy.
|
|
146
146
|
- `application-error-handling` (companion): supplies the error record factory a `jobFailed` constructs on the terminal path.
|
|
147
|
-
- `messaging-queue-cloudflare`: the shipped `queue` capability provider today. The `messaging-queue-postgres` sibling (reserved slug per
|
|
147
|
+
- `messaging-queue-cloudflare`: the shipped `queue` capability provider today. The `messaging-queue-postgres` sibling (reserved slug per policy in the documentation) mints on demand and composes here without any change to `jobs-background`.
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.3 (positive-evidence patch, 2026-09-10)
|
|
4
|
+
|
|
5
|
+
- `real-account-concurrency-smoke.mjs`: skip results now carry a discrete `reason` field naming the exact unset environment variable or missing account prerequisite. The credential-missing branch (`CF_ACCOUNT_ID` or `CF_API_TOKEN` unset with `CI_HAS_CLOUDFLARE_ACCOUNT=true`) records `accountBoundSkipped: true` naming only the missing variables (never the gate variable that is set on that branch) rather than a bare fail, closing the authoring standard section 7d shape.
|
|
6
|
+
- Adds a live pre-flight observation of the target Cloudflare account's workers.dev subdomain state via `GET /accounts/{id}/workers/subdomain` (verifiedOn 2026-09-10 per https://developers.cloudflare.com/api/resources/workers/subresources/subdomain/methods/get/). A `404` response or an empty `result.subdomain` marks the account as unprovisioned and the probe records `accountBoundSkipped: true` with a reason naming the missing account prerequisite and a detail carrying the observed status and Cloudflare error code as positive evidence. A provisioned subdomain causes the probe to run the mint / drive / teardown sequence unconditionally.
|
|
7
|
+
- Teardown discipline hardened: if `destroyScratchQueueAndWorker` throws, the probe now records an additional `verdict: fail` result naming the potentially orphaned queue id, consumer worker name and telemetry KV id (`teardownFailed: true`, `orphaned: {...}`), so the aggregate verdict fails when live-account state may be dirty rather than passing on a stderr-only note.
|
|
8
|
+
- `GITHUB_RUN_ID` is declared on the probe's `envDeclared` output and on the fixture's "Declared env vars" table (already read by the shim's run-id derivation, previously undeclared).
|
|
9
|
+
- No capability change.
|
|
10
|
+
|
|
3
11
|
## 1.1.2 - 2026-09-10
|
|
4
12
|
|
|
5
|
-
|
|
13
|
+
- README six-probes paragraph now describes the probe module envelope directly. Guide `publishBatch` sample updated: the `x-trace-id` example values are `trace-order-1001` and `trace-order-1002`, and a one-line pointer follows the sample to the owner at `TAC-3001.interfaces[2].description`. Anatomy pin updated to 1.1.2.
|
|
6
14
|
|
|
7
15
|
## 1.1.1 (register-sweep patch, 2026-09-10)
|
|
8
16
|
|
|
@@ -10,41 +18,39 @@ Register cleanup on shipped prose: neutral wording in the README six-probes para
|
|
|
10
18
|
|
|
11
19
|
## 1.1.0 - 2026-09-09
|
|
12
20
|
|
|
13
|
-
Adds the elicits block (queue-binding-name, queue-name, max-attempts, dead-letter-queue, batch-size, batch-timeout-seconds) that the REQs and guide were already describing in prose. Adds deliveredBy on REQ-002 and REQ-006.
|
|
21
|
+
Adds the elicits block (queue-binding-name, queue-name, max-attempts, dead-letter-queue, batch-size, batch-timeout-seconds) that the REQs and guide were already describing in prose. Adds deliveredBy on REQ-002 and REQ-006. REQ-004 and AC-29104-1 name maxDeliveries and map to the vendor max_retries as maxDeliveries - 1, with new AC-29104-2 asserting the maxDeliveries=1 boundary case. REQ-006 and AC-29106-1 standardise on ts as the wall-clock milliseconds-since-epoch field name, aligning with TAC-3001, TAC-3003 and the guide. REQ-002 replaces the "idempotent" label with an explicit at-least-once semantics naming ADR-3002 as the shipped delivery contract. Adds disposition to every AC.
|
|
14
22
|
|
|
15
23
|
# messaging-queue-cloudflare changelog
|
|
16
24
|
|
|
17
25
|
## 1.0.2 - 2026-09-08
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- `real-account-concurrency-smoke.mjs` rewritten against a new self-provisioning fixture shim at `packages/rcf-lite/test/fixtures/cf-platform/h2-cf-queue-real-account-shim.mjs`. AC-29108-2 requires a real consumer to process the published messages ("the consumer processes them concurrently up to the documented 250-invocation cap"), so the shim mints a scratch Cloudflare Queue under `h2-cf-probe-integrity-scratch-q-`, a scratch KV namespace for consumer telemetry under `h2-cf-probe-integrity-scratch-kv-tel-`, and a throwaway consumer Worker under `h2-cf-probe-integrity-scratch-w-` bound to the queue (consumer) with `RCF_TEST_QUEUE` (shipped queue producer binding name matching `packages/rcf-lite/test/fixtures/infra-s3-and-queue/wrangler.toml`) + `RCF_TEST_TELEMETRY_KV` bindings. NO workers.dev subdomain is enabled (operator ruling): the consumer is invoked BY THE QUEUE, not over HTTP; the driver publishes via the Cloudflare Queues REST publish endpoint and reads consumer telemetry via the KV REST list + get endpoints. The consumer Worker's source is a plain module (`h2-cf-queue-consumer-worker.mjs`); its `queue()` handler records one telemetry entry per invocation (start / end timestamps + batchSize) to the bound telemetry KV namespace; the driver computes `maxConcurrent` from an interval-overlap analysis on those timestamps.
|
|
27
|
+
Fixture-side fix: the real-account queue probe now self-provisions its own throwaway Queue + consumer Worker + telemetry KV namespace, closing the second-tier undeclared-env skip at the real-account gate. No shipped-code capability change.
|
|
28
|
+
- `real-account-concurrency-smoke.mjs` rewritten against a new self-provisioning fixture shim at `packages/rcf-lite/test/fixtures/cf-platform/h2-cf-queue-real-account-shim.mjs`. AC-29108-2 requires a real consumer to process the published messages ("the consumer processes them concurrently up to the documented 250-invocation cap"), so the shim mints a scratch Cloudflare Queue under `h2-cf-probe-integrity-scratch-q-`, a scratch KV namespace for consumer telemetry under `h2-cf-probe-integrity-scratch-kv-tel-`, and a throwaway consumer Worker under `h2-cf-probe-integrity-scratch-w-` bound to the queue (consumer) with `RCF_TEST_QUEUE` (shipped queue producer binding name matching `packages/rcf-lite/test/fixtures/infra-s3-and-queue/wrangler.toml`) + `RCF_TEST_TELEMETRY_KV` bindings. No workers.dev subdomain is enabled: the consumer is invoked BY THE QUEUE, not over HTTP; the driver publishes via the Cloudflare Queues REST publish endpoint and reads consumer telemetry via the KV REST list + get endpoints. The consumer Worker's source is a plain module (`h2-cf-queue-consumer-worker.mjs`); its `queue()` handler records one telemetry entry per invocation (start / end timestamps + batchSize) to the bound telemetry KV namespace; the driver computes `maxConcurrent` from an interval-overlap analysis on those timestamps.
|
|
22
29
|
- Declared env for a real-account run is now `CI_HAS_CLOUDFLARE_ACCOUNT` + `CF_ACCOUNT_ID` + `CF_API_TOKEN` (optional `CF_API_BASE_URL` test override; optional `CF_QUEUE_MESSAGE_COUNT` per section 3.5). The `CF_QUEUE_WORKER_URL` and `CF_QUEUE_NAME` second-tier gates are removed; the fixture provides them itself. Every skip-causing env var enumerated in `report.extra.envDeclared` on the probe result and mirrored in the shim's `DECLARED_ENV` export.
|
|
23
|
-
- Teardown deletes the consumer Worker first (so the queue has no active consumer at delete time), then the Queue, then the telemetry KV namespace, all by EXACT id / EXACT name against the mint record with three independent prefix guards per resource. `workerDelete` and `queueDelete` are idempotent on 404
|
|
24
|
-
- Separate crash-recovery `sweepOrphans` code path filters over the account by the frozen throwaway prefix constants and deletes each match by exact identity; the sweep is structurally unable to select a non-prefixed name. All account listings paginate to completion
|
|
25
|
-
- Queue consumer-attach body sends `type: "worker"` (
|
|
30
|
+
- Teardown deletes the consumer Worker first (so the queue has no active consumer at delete time), then the Queue, then the telemetry KV namespace, all by EXACT id / EXACT name against the mint record with three independent prefix guards per resource. `workerDelete` and `queueDelete` are idempotent on 404: a botched-retry teardown treats an already-gone resource as success rather than stranding siblings.
|
|
31
|
+
- Separate crash-recovery `sweepOrphans` code path filters over the account by the frozen throwaway prefix constants and deletes each match by exact identity; the sweep is structurally unable to select a non-prefixed name. All account listings paginate to completion: KV namespaces + Queues use the documented `per_page` + `page` loop, Workers scripts use the cursor loop, so `sweepOrphans` is not silently truncated to page one on a busy account. Dedicated sweep-safety test at `packages/rcf-lite/test/fixtures/cf-platform/test/h2-cf-sweep-safety.test.mjs` seeds the mock account with the ten live production Worker script names on the operator account plus mid-string-prefix decoys AND a 250-per-type multi-page cover, and asserts sweep selects zero of them.
|
|
32
|
+
- Queue consumer-attach body sends `type: "worker"` (survives CF schema tightening on the discriminated attach union) and omits `dead_letter_queue` entirely rather than sending an explicit `null`.
|
|
26
33
|
- Local proof harness (`packages/rcf-lite/test/fixtures/cf-platform/test/mock-cf-api-server.mjs`) is a zero-dep in-process mock of the Cloudflare REST contract, not the wire. **The local run exercises OUR lifecycle logic against a mock of Cloudflare's contract; the real-account gate is the only surface that proves the wire format.** The probe is therefore never described as "locally verified" - the local runs are our own lifecycle-logic proof; wire correctness is proven at the operator estate real-account gate.
|
|
27
34
|
|
|
28
35
|
## 1.0.1 - 2026-09-08
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
Probe-integrity patch (`h2-cf-platform-probe-integrity`). No capability change.
|
|
32
38
|
- Replaced the `accountBoundSkipped: true` pass-stub in `real-account-concurrency-smoke.mjs` with a real 500-message concurrency driver against a live Queues binding on a deployed Worker. When `CI_HAS_CLOUDFLARE_ACCOUNT` is set with `CF_QUEUE_WORKER_URL` and `CF_QUEUE_NAME`, the driver publishes 500 messages through the producer facade in 10 concurrent 50-message batches, polls consumer telemetry via `/stats`, and asserts `drained`, `withinCap` and `observedConcurrency > 1` against Cloudflare's documented push-invocation cap (250). The env-absent branch keeps the pass-with-skip shape. Locally proven against `wrangler dev --local` end-to-end (500/500 messages in 583 ms; local queue serialises so the concurrency assertion FAIL tail is the expected local-proof outcome; on real Cloudflare push consumers the assertion passes at the operator estate gate time).
|
|
33
|
-
-
|
|
39
|
+
- The Cloudflare Queues limits URL `https://developers.cloudflare.com/queues/platform/limits/` supports the documented push-invocation cap.
|
|
34
40
|
- Extended the fixture Worker at `packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/worker.mjs` with consumer telemetry and `/publish-batch`, `/stats` and `/reset` endpoints; added `wrangler ^4.0.0` as devDep on the fixture package.
|
|
35
41
|
|
|
36
42
|
## 1.0.0 - 2026-09-06
|
|
37
43
|
|
|
38
|
-
Initial release. Directed producer-to-consumer worklist queue on Cloudflare Queues; first shipped adapter with the reserved `messaging-queue-postgres` sibling (
|
|
44
|
+
Initial release. Directed producer-to-consumer worklist queue on Cloudflare Queues; first shipped adapter with the reserved `messaging-queue-postgres` sibling (sibling reservation) named beside it in the section 6a capability table. Accessed through a producer facade that is the sole reader of the Cloudflare Queues binding (`env.RCF_TEST_QUEUE` in the fixture).
|
|
39
45
|
|
|
40
46
|
- 21 contributions: 6 REQs on producer facade sole-reader / publish-consume-ack / retry / dead-letter / batch / lifecycle events; 8 USs at 29101-29108; 3 TACs (3001 producer facade, 3002 consumer registration, 3003 event sink); 4 ADRs (3001 adapter Cloudflare Queues shipped, 3002 `deliverySemantics` scope global at-least-once, 3003 max_retries default 3 floor 1 ceiling 100, 3004 batch size default 10 batch timeout default 5 seconds).
|
|
41
|
-
- Five Node-only probes under `contributions/probes/` proven against the wrangler-dev-equivalent seam (in-memory queue driver realising the Cloudflare Queues binding shape per
|
|
47
|
+
- Five Node-only probes under `contributions/probes/` proven against the wrangler-dev-equivalent seam (in-memory queue driver realising the Cloudflare Queues binding shape per the wrangler-dev-equivalent seam decision on US-29107): `producer-facade-ready`, `publish-to-delivery`, `retry-and-dlq`, `event-secrecy`, and the accountBound `real-account-concurrency-smoke`. The real-account smoke records `accountBoundSkipped: true` when `CI_HAS_CLOUDFLARE_ACCOUNT` is unset per spec section 3.5.
|
|
42
48
|
- The messaging-queue-cloudflare slice of the shared sample-app fixture at `packages/rcf-lite/test/fixtures/infra-s3-and-queue/` adds a `wrangler.toml` declaring the queue binding (`RCF_TEST_QUEUE`), DLQ binding (`RCF_TEST_DLQ`), `dead_letter_queue = "rcf-test-dlq"`, `max_retries = 3`, `max_batch_size = 10`, `max_batch_timeout = 5`; plus `src/queue-driver.mjs`, `src/producer.mjs`, `src/consumer.mjs`, `src/dlq-inspector.mjs`, `src/event-sink.mjs`. Three wired induced-failure switches (`SIMULATE_CONSUMER_RETRY`, `SIMULATE_DLQ_OVERFLOW`, `SIMULATE_PII_IN_BODY`) drive the negative-run paths.
|
|
43
|
-
- Declares `capabilities: ["queue"]`, `suggestedCompanions: [{role: "logging"}, {role: "errorHandling"}]`, `providesRoles` absent, `requiresAppliedCapabilities` absent. Composes on `deploy-cloudflare-workers` transitively via the wrangler binding (not through the capability mechanism), so `jobs-background` reads the `queue` capability at apply time via the capability-consumer mechanism
|
|
49
|
+
- Declares `capabilities: ["queue"]`, `suggestedCompanions: [{role: "logging"}, {role: "errorHandling"}]`, `providesRoles` absent, `requiresAppliedCapabilities` absent. Composes on `deploy-cloudflare-workers` transitively via the wrangler binding (not through the capability mechanism), so `jobs-background` reads the `queue` capability at apply time via the capability-consumer mechanism.
|
|
44
50
|
- Contributes ADR-3002 as `scope: global` on new topic `deliverySemantics`. Future exactly-once, at-most-once or `messaging-queue-postgres` siblings conflict here by design.
|
|
45
|
-
- Every ADR contribution entry on `blueprint.json` carries a `standardsTraceClause` per section 8a.2 (mandatory
|
|
46
|
-
- Extends `packages/rcf-lite/docs/blueprint-authoring.md` section 6a capability-declaration table with one row for `queue` naming the reserved `messaging-queue-postgres` sibling per
|
|
47
|
-
- The Miniflare Queues sub-page under the workers testing miniflare storage tree is NOT cited
|
|
48
|
-
- Lifecycle event whitelist reuses the object-storage-s3 blueprint's `{event, ts, ...}` common envelope prefix
|
|
51
|
+
- Every ADR contribution entry on `blueprint.json` carries a `standardsTraceClause` per section 8a.2 (mandatory).
|
|
52
|
+
- Extends `packages/rcf-lite/docs/blueprint-authoring.md` section 6a capability-declaration table with one row for `queue` naming the reserved `messaging-queue-postgres` sibling per the sibling reservation in spec section 5.6.
|
|
53
|
+
- The Miniflare Queues sub-page under the workers testing miniflare storage tree is NOT cited (it returns 404). The Cloudflare Queues local-development page (`https://developers.cloudflare.com/queues/configuration/local-development/`) is the sole vendor citation supporting the local seam.
|
|
54
|
+
- Lifecycle event whitelist reuses the object-storage-s3 blueprint's `{event, ts, ...}` common envelope prefix so a future v1.1 minor can promote one shared shape to schema enforcement.
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
Adds deliveredBy on REQ-003 and REQ-004. AC-29107-2 and AC-29108-2 carry vendorCitation.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# messaging-queue-cloudflare
|
|
2
2
|
|
|
3
|
-
A directed producer-to-consumer worklist queue on Cloudflare Queues, accessed through a producer facade that is the sole reader of the Queues binding. Cloudflare Queues is the first adapter (queue binding under wrangler config, consumer registered on the Worker `queue` handler); the reserved `messaging-queue-postgres` sibling (
|
|
3
|
+
A directed producer-to-consumer worklist queue on Cloudflare Queues, accessed through a producer facade that is the sole reader of the Queues binding. Cloudflare Queues is the first adapter (queue binding under wrangler config, consumer registered on the Worker `queue` handler); the reserved `messaging-queue-postgres` sibling (sibling reservation) mints on demand. Ships publish, consume, ack, retry, and DLQ; four lifecycle events (`producerReady`, `messagePublished`, `messageAcked`, `messageDeadLettered`) with a metadata-only field discipline. Composes on `deploy-cloudflare-workers` transitively via the wrangler binding, not through the capability mechanism, so `capabilities: ["queue"]` is what `jobs-background` reads to obtain the producer facade at apply time; no `requiresAppliedCapabilities` block ships at v1.0.0.
|
|
4
4
|
|
|
5
5
|
## What this blueprint gives you
|
|
6
6
|
|
|
@@ -44,11 +44,11 @@ Queue name (or binding name in a Workers deploy); `max_retries` before DLQ (defa
|
|
|
44
44
|
|
|
45
45
|
## Composition and conflicts
|
|
46
46
|
|
|
47
|
-
Composes on `deploy-cloudflare-workers` transitively via the wrangler binding (not through the capability mechanism), so no `requiresAppliedCapabilities` block ships at v1.0.0. Contributes ADR-3002 as `scope: global` on new topic `deliverySemantics`; a future `messaging-queue-postgres` sibling (
|
|
47
|
+
Composes on `deploy-cloudflare-workers` transitively via the wrangler binding (not through the capability mechanism), so no `requiresAppliedCapabilities` block ships at v1.0.0. Contributes ADR-3002 as `scope: global` on new topic `deliverySemantics`; a future `messaging-queue-postgres` sibling (sibling reservation, deferred v1.0.0 pending demand) or an exactly-once / at-most-once sibling would conflict here by design. `capabilities: ["queue"]`; `providesRoles: []`.
|
|
48
48
|
|
|
49
49
|
## Reserved sibling
|
|
50
50
|
|
|
51
|
-
`messaging-queue-postgres` (
|
|
51
|
+
`messaging-queue-postgres` (sibling reservation). Reserved slug beside the `queue` capability row in `packages/rcf-lite/docs/blueprint-authoring.md` section 6a. When demand mints it, the sibling composes on `persistence-data-postgres` as its transport and conflicts by design on `deliverySemantics` with this blueprint; the operator picks one queue backend per project via a project-level ADR.
|
|
52
52
|
|
|
53
53
|
## The six probes
|
|
54
54
|
|
|
@@ -60,7 +60,7 @@ Each probe is a Node module under `contributions/probes/` exporting the shipped
|
|
|
60
60
|
| `publish-to-delivery` | AC-29102-1, AC-29102-2, AC-29105-1, AC-29108-1 | 5 messages round-trip body byte-equal with stable message-ids and producer-supplied trace-ids preserved; per-message ack; wrangler-dev-equivalent seam. | false |
|
|
61
61
|
| `retry-and-dlq` | AC-29103-1, AC-29104-1 | Consumer returning `retry` observes same stable message-id with attempts 1..max_retries; DLQ landing fires `messageDeadLettered` at `max_retries + 1`; DLQ contents body byte-equal via the DLQ inspector helper. | false |
|
|
62
62
|
| `event-secrecy` | AC-29106-1 | Every event record carries only the whitelist (event, ts, messageId, queueName, attempts); no PII fixture text on JSON grep. | false |
|
|
63
|
-
| `real-account-concurrency-smoke` | AC-29108-2 | Self-provisioning (v1.0.2): the fixture shim (`packages/rcf-lite/test/fixtures/cf-platform/h2-cf-queue-real-account-shim.mjs`) mints a scratch Cloudflare Queue under the CI scratch prefix `h2-cf-probe-integrity-scratch-q-`, a scratch KV namespace for consumer telemetry under `h2-cf-probe-integrity-scratch-kv-tel-`, and a throwaway consumer Worker under `h2-cf-probe-integrity-scratch-w-` bound to the queue (consumer) with `RCF_TEST_QUEUE` (shipped queue binding name) + `RCF_TEST_TELEMETRY_KV` bindings. The Worker has
|
|
63
|
+
| `real-account-concurrency-smoke` | AC-29108-2 | Self-provisioning (v1.0.2): the fixture shim (`packages/rcf-lite/test/fixtures/cf-platform/h2-cf-queue-real-account-shim.mjs`) mints a scratch Cloudflare Queue under the CI scratch prefix `h2-cf-probe-integrity-scratch-q-`, a scratch KV namespace for consumer telemetry under `h2-cf-probe-integrity-scratch-kv-tel-`, and a throwaway consumer Worker under `h2-cf-probe-integrity-scratch-w-` bound to the queue (consumer) with `RCF_TEST_QUEUE` (shipped queue binding name) + `RCF_TEST_TELEMETRY_KV` bindings. The Worker has no fetch surface and no workers.dev subdomain is enabled: the consumer is invoked BY THE QUEUE, not over HTTP. Driver publishes 500 messages in 10 concurrent 50-message batches via the Cloudflare Queues REST publish endpoint, polls the telemetry KV namespace via the KV REST list + get endpoints until drained, and asserts `totalConsumed === published` and `1 < maxConcurrent <= 250` per https://developers.cloudflare.com/queues/platform/limits/. Teardown deletes Worker, Queue and telemetry KV namespace on exit; the shim's separate `sweepOrphans` path lists over the account with full pagination and deletes any prefixed residue after a mid-run crash. Without `CI_HAS_CLOUDFLARE_ACCOUNT` records `accountBoundSkipped: true`. | true |
|
|
64
64
|
|
|
65
65
|
## Anatomy
|
|
66
66
|
|
|
@@ -98,19 +98,19 @@ blueprints/messaging-queue-cloudflare/
|
|
|
98
98
|
|
|
99
99
|
## Known limitations and mechanism-reach gaps
|
|
100
100
|
|
|
101
|
-
The five local probes drive the fixture's in-memory queue-driver (`src/queue-driver.mjs`), which realises the Cloudflare Queues binding shape (`send` / `sendBatch` on the producer side, batch envelope with per-message `ack` / `retry` on the consumer side) so the producer facade module and consumer registration are indistinguishable from a live Queues run at the facade boundary. The wrangler-dev-equivalent seam (
|
|
101
|
+
The five local probes drive the fixture's in-memory queue-driver (`src/queue-driver.mjs`), which realises the Cloudflare Queues binding shape (`send` / `sendBatch` on the producer side, batch envelope with per-message `ack` / `retry` on the consumer side) so the producer facade module and consumer registration are indistinguishable from a live Queues run at the facade boundary. The wrangler-dev-equivalent seam (the wrangler-dev-equivalent seam decision on US-29107) is a deliberate v1.0.0 posture: rcf-lite gains no runtime dependency, CI stays reproducible without a live Cloudflare account, and Cloudflare Queues does not support consumer concurrency under `wrangler dev` per https://developers.cloudflare.com/queues/configuration/local-development/ (that assertion is what `real-account-concurrency-smoke` carries as `accountBound: true`).
|
|
102
102
|
|
|
103
103
|
Two live paths are unproven at v1.0.0 and are recorded per AC below so the gate reviewer and any downstream composing blueprint see exactly what is and is not proven for each AC. The gate reviewer's own single `wrangler dev` run and the `accountBound` smoke are what promote these gaps to proven.
|
|
104
104
|
|
|
105
|
-
- **AC-29101-1** (producer facade opens on boot; `producerReady` fires with `queueName`): proven against the in-memory realisation of the Cloudflare Queues binding shape (probe `producer-facade-ready`, verdict pass); live Queues delivery unproven pending
|
|
105
|
+
- **AC-29101-1** (producer facade opens on boot; `producerReady` fires with `queueName`): proven against the in-memory realisation of the Cloudflare Queues binding shape (probe `producer-facade-ready`, verdict pass); live Queues delivery unproven pending an operator `wrangler dev` run or the accountBound smoke.
|
|
106
106
|
- **AC-29101-2** (sole-reader grep on the applied fixture): proven against the in-memory realisation (source-tree scan of `src/producer.mjs` against `src/consumer.mjs` peers); live-Queues source-tree posture is identical (the grep target is the fixture tree, not the vendor surface), so this AC has no live-only gap.
|
|
107
|
-
- **AC-29102-1** (5 messages round-trip body byte-equal with stable message-id and producer-supplied trace-id): proven against the in-memory realisation of the binding shape (probe `publish-to-delivery`, verdict pass); live Queues delivery of the same 5-message batch unproven pending
|
|
108
|
-
- **AC-29102-2** (`messageAcked` fires per successful consumer return; message not redelivered): proven against the in-memory realisation of the binding shape (probe `publish-to-delivery`, verdict pass); live Queues per-message ack behaviour unproven pending
|
|
109
|
-
- **AC-29103-1** (retry trajectory: same stable message-id across attempts 1..max_retries with incrementing attempt counter): proven against the in-memory realisation of the binding shape (probe `retry-and-dlq`, verdict pass with attempts 1,2,3 on the same message-id); live Queues retry counter observation unproven pending
|
|
110
|
-
- **AC-29104-1** (DLQ landing at `max_retries + 1` with `messageDeadLettered` event and body byte-equal on DLQ inspection): proven against the in-memory realisation of the binding shape (probe `retry-and-dlq`, verdict pass with DLQ landing at attempts=4 and byte-equal body); live Queues DLQ landing via wrangler `dead_letter_queue` field and inspection via `wrangler queues consumer add --dead-letter-queue` unproven pending
|
|
111
|
-
- **AC-29105-1** (batch consume: 5 messages in one batch, per-message ack semantics under `max_batch_size = 10`): proven against the in-memory realisation of the binding shape (probe `publish-to-delivery`, verdict pass); live Queues `max_batch_size` / `max_batch_timeout` behaviour on the [[queues.consumers]] block unproven pending
|
|
107
|
+
- **AC-29102-1** (5 messages round-trip body byte-equal with stable message-id and producer-supplied trace-id): proven against the in-memory realisation of the binding shape (probe `publish-to-delivery`, verdict pass); live Queues delivery of the same 5-message batch unproven pending an operator `wrangler dev` run or the accountBound smoke.
|
|
108
|
+
- **AC-29102-2** (`messageAcked` fires per successful consumer return; message not redelivered): proven against the in-memory realisation of the binding shape (probe `publish-to-delivery`, verdict pass); live Queues per-message ack behaviour unproven pending an operator `wrangler dev` run or the accountBound smoke.
|
|
109
|
+
- **AC-29103-1** (retry trajectory: same stable message-id across attempts 1..max_retries with incrementing attempt counter): proven against the in-memory realisation of the binding shape (probe `retry-and-dlq`, verdict pass with attempts 1,2,3 on the same message-id); live Queues retry counter observation unproven pending an operator `wrangler dev` run or the accountBound smoke.
|
|
110
|
+
- **AC-29104-1** (DLQ landing at `max_retries + 1` with `messageDeadLettered` event and body byte-equal on DLQ inspection): proven against the in-memory realisation of the binding shape (probe `retry-and-dlq`, verdict pass with DLQ landing at attempts=4 and byte-equal body); live Queues DLQ landing via wrangler `dead_letter_queue` field and inspection via `wrangler queues consumer add --dead-letter-queue` unproven pending an operator `wrangler dev` run or the accountBound smoke.
|
|
111
|
+
- **AC-29105-1** (batch consume: 5 messages in one batch, per-message ack semantics under `max_batch_size = 10`): proven against the in-memory realisation of the binding shape (probe `publish-to-delivery`, verdict pass); live Queues `max_batch_size` / `max_batch_timeout` behaviour on the [[queues.consumers]] block unproven pending an operator `wrangler dev` run or the accountBound smoke.
|
|
112
112
|
- **AC-29106-1** (metadata-only event whitelist; no PII body / header value / consumer context leaks): proven end-to-end against the in-memory realisation (probe `event-secrecy`, verdict pass; the whitelist is code-enforced in `src/event-sink.mjs`, independent of transport); live-Queues run does not change the sink code path, so this AC has no live-only gap.
|
|
113
|
-
- **AC-29108-1** (wrangler-dev-equivalent seam round-trip): proven end-to-end against the in-memory realisation of the binding shape (probe `publish-to-delivery`, verdict pass); a live `wrangler dev` process
|
|
113
|
+
- **AC-29108-1** (wrangler-dev-equivalent seam round-trip): proven end-to-end against the in-memory realisation of the binding shape (probe `publish-to-delivery`, verdict pass); a live `wrangler dev` process is not driven by this seam. Rationale: the wrangler-dev-equivalent seam decision on US-29107 makes the wrangler-dev-equivalent seam the shipped local seam because Cloudflare Queues does not support consumer concurrency under `wrangler dev` and does not support `wrangler dev --remote` per the local-development doc, so a live-wrangler run adds observability (a real process on port 8787) but does not add facade-contract certainty over the in-memory realisation. The gate reviewer drives one live `wrangler dev` run to close the observability gap.
|
|
114
114
|
- **AC-29108-2** (real-account concurrency smoke: 500 messages, consumer concurrency up to 250): as of v1.0.2 the probe SELF-PROVISIONS the throwaway Queue + consumer Worker + telemetry KV namespace under the CI scratch prefixes and requires no hand-provisioned CI infrastructure . Declared env for a live run: `CI_HAS_CLOUDFLARE_ACCOUNT` + `CF_ACCOUNT_ID` + `CF_API_TOKEN`. Without `CI_HAS_CLOUDFLARE_ACCOUNT` the probe records `accountBoundSkipped: true` per spec section 3.5 and the per-blueprint report carries `aggregateVerdict: pass` on the skipped shape. **The local proof harness under `packages/rcf-lite/test/fixtures/cf-platform/test/` is a mock of Cloudflare's REST contract, not the wire; the local runs exercise OUR lifecycle logic against that mock, and the real-account gate is the only surface that proves the wire format.**
|
|
115
115
|
|
|
116
116
|
## Other limitations (not mechanism-reach gaps)
|