rcf-lite 0.21.0 → 0.23.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 +36 -0
- package/bin/rcf.js +13 -2
- package/blueprints/application-account-settings/CHANGELOG.md +12 -0
- package/blueprints/application-account-settings/README.md +114 -0
- package/blueprints/application-account-settings/blueprint.json +234 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2601-application-account-settings-capability-vocabulary.json +20 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +20 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2603-application-account-settings-theme-persistence.json +20 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2604-application-account-settings-reauth-window.json +20 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-001.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-002.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-003.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-004.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-005.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-006.json +18 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2601-application-account-settings-shell.json +41 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2602-application-account-settings-capability-discovery.json +28 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2603-application-account-settings-hosted-ui-bridge.json +35 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2604-application-account-settings-session-store.json +40 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25101.json +34 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25102.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25103.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25104.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25105.json +33 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25106.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25107.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25108.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25109.json +33 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25110.json +27 -0
- package/blueprints/application-account-settings/docs/topics.md +50 -0
- package/blueprints/application-account-settings/guide/application-account-settings.md +30 -0
- package/blueprints/application-account-settings/probe-packs/application-account-settings.pack.mjs +246 -0
- package/blueprints/application-admin-console/docs/topics.md +9 -0
- package/blueprints/application-api-rest/docs/topics.md +10 -1
- package/blueprints/application-charts/docs/topics.md +9 -0
- package/blueprints/application-dashboard/docs/topics.md +9 -0
- package/blueprints/application-datatable/docs/topics.md +9 -0
- package/blueprints/application-empty-error-states/CHANGELOG.md +9 -0
- package/blueprints/application-empty-error-states/README.md +88 -0
- package/blueprints/application-empty-error-states/blueprint.json +119 -0
- package/blueprints/application-empty-error-states/contributions/adrs/adr-2301-application-empty-error-states-status-contract.json +25 -0
- package/blueprints/application-empty-error-states/contributions/adrs/adr-2302-application-empty-error-states-stack-trace-visibility.json +25 -0
- package/blueprints/application-empty-error-states/contributions/adrs/adr-2303-application-empty-error-states-offline-strategy.json +25 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-001.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-002.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-003.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-004.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-005.json +18 -0
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2301-application-empty-error-states-state-machine.json +46 -0
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2302-application-empty-error-states-recovery-router.json +36 -0
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2303-application-empty-error-states-offline-buffer.json +40 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22101.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22102.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22103.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22104.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22105.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22106.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22107.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22108.json +29 -0
- package/blueprints/application-empty-error-states/docs/topics.md +55 -0
- package/blueprints/application-empty-error-states/guide/application-empty-error-states.md +50 -0
- package/blueprints/application-empty-error-states/probe-packs/application-empty-error-states.pack.mjs +284 -0
- package/blueprints/application-error-handling/docs/topics.md +9 -0
- package/blueprints/application-file-upload/CHANGELOG.md +9 -0
- package/blueprints/application-file-upload/README.md +85 -0
- package/blueprints/application-file-upload/blueprint.json +114 -0
- package/blueprints/application-file-upload/contributions/adrs/adr-2401-application-file-upload-transport.json +25 -0
- package/blueprints/application-file-upload/contributions/adrs/adr-2402-application-file-upload-accepted-set.json +25 -0
- package/blueprints/application-file-upload/contributions/adrs/adr-2403-application-file-upload-virus-scan.json +25 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +18 -0
- package/blueprints/application-file-upload/contributions/tacs/tac-2401-application-file-upload-input.json +46 -0
- package/blueprints/application-file-upload/contributions/tacs/tac-2402-application-file-upload-transport.json +47 -0
- package/blueprints/application-file-upload/contributions/tacs/tac-2403-application-file-upload-progress-announcer.json +46 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23101.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23102.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23103.json +29 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23104.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23105.json +29 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23106.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23107.json +28 -0
- package/blueprints/application-file-upload/docs/topics.md +60 -0
- package/blueprints/application-file-upload/guide/application-file-upload.md +48 -0
- package/blueprints/application-file-upload/probe-packs/application-file-upload.pack.mjs +238 -0
- package/blueprints/application-forms-wizard/CHANGELOG.md +9 -0
- package/blueprints/application-forms-wizard/README.md +102 -0
- package/blueprints/application-forms-wizard/blueprint.json +120 -0
- package/blueprints/application-forms-wizard/contributions/adrs/adr-2501-application-forms-wizard-navigation.json +25 -0
- package/blueprints/application-forms-wizard/contributions/adrs/adr-2502-application-forms-wizard-save-and-return.json +25 -0
- package/blueprints/application-forms-wizard/contributions/adrs/adr-2503-application-forms-wizard-step-indicator.json +25 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +18 -0
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2501-application-forms-wizard-task-list.json +46 -0
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2502-application-forms-wizard-error-summary.json +40 -0
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2503-application-forms-wizard-draft-store.json +40 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24101.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24102.json +29 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24103.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24104.json +29 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24105.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24106.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24107.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24108.json +29 -0
- package/blueprints/application-forms-wizard/docs/topics.md +51 -0
- package/blueprints/application-forms-wizard/guide/application-forms-wizard.md +48 -0
- package/blueprints/application-forms-wizard/probe-packs/application-forms-wizard.pack.mjs +233 -0
- package/blueprints/application-notifications-in-app/docs/topics.md +9 -0
- package/blueprints/application-onboarding-tour/CHANGELOG.md +12 -0
- package/blueprints/application-onboarding-tour/README.md +77 -0
- package/blueprints/application-onboarding-tour/blueprint.json +164 -0
- package/blueprints/application-onboarding-tour/contributions/adrs/adr-2701-application-onboarding-tour-dismissal-policy.json +20 -0
- package/blueprints/application-onboarding-tour/contributions/adrs/adr-2702-application-onboarding-tour-completion-store-shape.json +20 -0
- package/blueprints/application-onboarding-tour/contributions/adrs/adr-2703-application-onboarding-tour-checklist-anchor.json +20 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-001.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-002.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-003.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-004.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2701-application-onboarding-tour-step-runner.json +41 -0
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2702-application-onboarding-tour-checklist-slot.json +35 -0
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2703-application-onboarding-tour-completion-store.json +34 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26101.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26102.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26103.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26104.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26105.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26106.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26107.json +27 -0
- package/blueprints/application-onboarding-tour/docs/topics.md +50 -0
- package/blueprints/application-onboarding-tour/guide/application-onboarding-tour.md +59 -0
- package/blueprints/application-onboarding-tour/probe-packs/application-onboarding-tour.pack.mjs +231 -0
- package/blueprints/application-spa/docs/topics.md +11 -2
- package/blueprints/delivery-ci-workflows/docs/topics.md +10 -1
- package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +69 -0
- package/blueprints/deploy-cloudflare-workers/README.md +12 -0
- package/blueprints/deploy-cloudflare-workers/blueprint.json +234 -36
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +30 -0
- package/blueprints/deploy-cloudflare-workers/contributions/probes/assets-manifest-scan.mjs +207 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-013.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-014.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12113.json +36 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12114.json +27 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12115.json +27 -0
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +11 -2
- package/blueprints/deploy-cloudflare-workers/guide/deploy-cloudflare-workers.md +25 -0
- package/blueprints/email-smtp-resend/docs/topics.md +10 -1
- package/blueprints/jobs-background/CHANGELOG.md +16 -0
- package/blueprints/jobs-background/README.md +105 -0
- package/blueprints/jobs-background/blueprint.json +149 -0
- package/blueprints/jobs-background/contributions/adrs/adr-3101-jobs-background-model.json +27 -0
- package/blueprints/jobs-background/contributions/adrs/adr-3102-jobs-background-scheduler-mode.json +25 -0
- package/blueprints/jobs-background/contributions/adrs/adr-3103-jobs-background-requires-applied-capabilities.json +25 -0
- package/blueprints/jobs-background/contributions/adrs/adr-3104-jobs-background-timeout-floor.json +25 -0
- package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +95 -0
- package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +82 -0
- package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +69 -0
- package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +65 -0
- package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +91 -0
- package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +65 -0
- package/blueprints/jobs-background/contributions/probes/run-apply-time-override.mjs +10 -0
- package/blueprints/jobs-background/contributions/probes/run-apply-time-refusal.mjs +11 -0
- package/blueprints/jobs-background/contributions/probes/run-event-secrecy.mjs +11 -0
- package/blueprints/jobs-background/contributions/probes/run-fake-clock-cron.mjs +11 -0
- package/blueprints/jobs-background/contributions/probes/run-retry-and-fail.mjs +11 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-001.json +18 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-002.json +18 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-003.json +18 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-004.json +18 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-005.json +18 -0
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-006.json +18 -0
- package/blueprints/jobs-background/contributions/tacs/tac-3101-jobs-background-job-definition.json +50 -0
- package/blueprints/jobs-background/contributions/tacs/tac-3102-jobs-background-scheduler.json +50 -0
- package/blueprints/jobs-background/contributions/tacs/tac-3103-jobs-background-run-log.json +49 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30101.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30102.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30103.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30104.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30105.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30106.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30107.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30108.json +25 -0
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30109.json +25 -0
- package/blueprints/jobs-background/docs/topics.md +62 -0
- package/blueprints/jobs-background/guide/jobs-background.md +147 -0
- package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +15 -0
- package/blueprints/messaging-queue-cloudflare/README.md +125 -0
- package/blueprints/messaging-queue-cloudflare/blueprint.json +67 -0
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +30 -0
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3003-messaging-queue-cloudflare-max-attempts-floor.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3004-messaging-queue-cloudflare-batch-defaults.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/event-secrecy.mjs +137 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/probe-utils.mjs +82 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/producer-facade-ready.mjs +35 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/publish-to-delivery.mjs +94 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +54 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/retry-and-dlq.mjs +87 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/run-event-secrecy.mjs +5 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/run-producer-facade-ready.mjs +11 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/run-publish-to-delivery.mjs +5 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/run-real-account-concurrency-smoke.mjs +5 -0
- package/blueprints/messaging-queue-cloudflare/contributions/probes/run-retry-and-dlq.mjs +5 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-001.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-002.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-003.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-004.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-005.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +18 -0
- package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3001-messaging-queue-cloudflare-producer-facade.json +56 -0
- package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3002-messaging-queue-cloudflare-consumer-registration.json +40 -0
- package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3003-messaging-queue-cloudflare-event-sink.json +39 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29101.json +34 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29102.json +34 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29103.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29104.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29105.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29106.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29107.json +25 -0
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29108.json +25 -0
- package/blueprints/messaging-queue-cloudflare/docs/topics.md +62 -0
- package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +110 -0
- package/blueprints/object-storage-s3/CHANGELOG.md +13 -0
- package/blueprints/object-storage-s3/README.md +108 -0
- package/blueprints/object-storage-s3/blueprint.json +72 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2901-object-storage-s3-adapter.json +30 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2902-object-storage-s3-presigned-ttl-floor.json +25 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2903-object-storage-s3-multipart-threshold.json +25 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2904-object-storage-s3-contract.json +25 -0
- package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +103 -0
- package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +43 -0
- package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +84 -0
- package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +101 -0
- package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +85 -0
- package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +84 -0
- package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +64 -0
- package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +10 -0
- package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +7 -0
- package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-001.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-002.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-003.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-004.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-005.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +18 -0
- package/blueprints/object-storage-s3/contributions/tacs/tac-2901-object-storage-s3-facade.json +57 -0
- package/blueprints/object-storage-s3/contributions/tacs/tac-2902-object-storage-s3-multipart-uploader.json +36 -0
- package/blueprints/object-storage-s3/contributions/tacs/tac-2903-object-storage-s3-event-sink.json +36 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28101.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28102.json +43 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28103.json +25 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28104.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28105.json +25 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28106.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28107.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28108.json +34 -0
- package/blueprints/object-storage-s3/docs/topics.md +64 -0
- package/blueprints/object-storage-s3/guide/object-storage-s3.md +207 -0
- package/blueprints/observability-essentials/docs/topics.md +10 -1
- package/blueprints/observability-logging/CHANGELOG.md +4 -0
- package/blueprints/observability-logging/README.md +3 -0
- package/blueprints/observability-logging/blueprint.json +3 -2
- package/blueprints/observability-logging/docs/topics.md +9 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +10 -1
- package/blueprints/persistence-data-d1/docs/topics.md +10 -1
- package/blueprints/persistence-data-postgres/CHANGELOG.md +12 -0
- package/blueprints/persistence-data-postgres/README.md +101 -0
- package/blueprints/persistence-data-postgres/blueprint.json +80 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +30 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2802-persistence-data-postgres-migration-shape.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2803-persistence-data-postgres-runner-mode.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2804-persistence-data-postgres-recovery.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2805-persistence-data-postgres-connection-pool-posture.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +56 -0
- package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +75 -0
- package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +56 -0
- package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +186 -0
- package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +76 -0
- package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +173 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-facade-round-trip.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-migration-apply.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-pool-posture-smoke.mjs +9 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-prepared-statement-scan.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-recovery-restore-round-trip.mjs +9 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-transaction-atomicity.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +79 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-001.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-002.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-004.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-005.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-006.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-007.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2801-persistence-data-postgres-facade.json +58 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2802-persistence-data-postgres-migration-runner.json +40 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2803-persistence-data-postgres-transaction-helper.json +35 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2804-persistence-data-postgres-recovery-runner.json +40 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27101.json +34 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27102.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27103.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27104.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27105.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27106.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27107.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27108.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27109.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27110.json +25 -0
- package/blueprints/persistence-data-postgres/docs/topics.md +66 -0
- package/blueprints/persistence-data-postgres/guide/persistence-data-postgres.md +172 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +10 -1
- package/blueprints/security-auth-clerk/CHANGELOG.md +4 -0
- package/blueprints/security-auth-clerk/README.md +3 -0
- package/blueprints/security-auth-clerk/blueprint.json +147 -30
- package/blueprints/security-auth-clerk/docs/topics.md +10 -1
- package/blueprints/security-auth-keycloak/CHANGELOG.md +4 -0
- package/blueprints/security-auth-keycloak/README.md +3 -0
- package/blueprints/security-auth-keycloak/blueprint.json +182 -37
- package/blueprints/security-auth-keycloak/docs/topics.md +10 -1
- package/blueprints/security-auth-magic-link/CHANGELOG.md +4 -0
- package/blueprints/security-auth-magic-link/README.md +3 -0
- package/blueprints/security-auth-magic-link/blueprint.json +159 -33
- package/blueprints/security-auth-magic-link/docs/topics.md +10 -1
- package/blueprints/security-auth-oauth2/CHANGELOG.md +4 -0
- package/blueprints/security-auth-oauth2/README.md +3 -0
- package/blueprints/security-auth-oauth2/blueprint.json +158 -32
- package/blueprints/security-auth-oauth2/docs/topics.md +10 -1
- package/blueprints/security-secrets-management/CHANGELOG.md +11 -0
- package/blueprints/security-secrets-management/blueprint.json +2 -1
- package/blueprints/security-secrets-management/docs/topics.md +10 -1
- package/fixtures/canary-manifest.json +9 -9
- package/package.json +1 -1
- package/rcf/code-nodes/cn-134.json +13 -0
- package/rcf/code-nodes/cn-135.json +12 -0
- package/rcf/code-nodes/cn-136.json +13 -0
- package/rcf/code-nodes/cn-137.json +13 -0
- package/rcf/code-nodes/cn-138.json +12 -0
- package/rcf/code-nodes/cn-139.json +12 -0
- package/rcf/code-nodes/cn-140.json +13 -0
- package/rcf/code-nodes/cn-141.json +13 -0
- package/rcf/code-nodes/cn-142.json +12 -0
- package/rcf/code-nodes/cn-143.json +13 -0
- package/rcf/code-nodes/cn-144.json +13 -0
- package/rcf/code-nodes/cn-145.json +12 -0
- package/rcf/code-nodes/cn-146.json +12 -0
- package/rcf/code-nodes/cn-147.json +13 -0
- package/rcf/code-nodes/cn-148.json +13 -0
- package/rcf/code-nodes/cn-149.json +12 -0
- package/rcf/code-nodes/cn-150.json +13 -0
- package/rcf/code-nodes/cn-151.json +13 -0
- package/rcf/code-nodes/cn-152.json +12 -0
- package/rcf/code-nodes/cn-153.json +12 -0
- package/rcf/code-nodes/cn-154.json +13 -0
- package/rcf/code-nodes/cn-155.json +14 -0
- package/rcf/code-nodes/cn-156.json +13 -0
- package/rcf/code-nodes/cn-157.json +13 -0
- package/rcf/code-nodes/cn-158.json +12 -0
- package/rcf/code-nodes/cn-159.json +13 -0
- package/rcf/code-nodes/cn-160.json +12 -0
- package/rcf/code-nodes/cn-161.json +12 -0
- package/rcf/code-nodes/cn-162.json +13 -0
- package/rcf/code-nodes/cn-163.json +12 -0
- package/rcf/code-nodes/cn-164.json +13 -0
- package/rcf/code-nodes/cn-165.json +12 -0
- package/rcf/code-nodes/cn-166.json +12 -0
- package/rcf/code-nodes/cn-167.json +12 -0
- package/rcf/code-nodes/cn-168.json +12 -0
- package/rcf/code-nodes/cn-169.json +12 -0
- package/rcf/code-nodes/cn-170.json +12 -0
- package/rcf/code-nodes/cn-171.json +12 -0
- package/rcf/code-nodes/cn-172.json +12 -0
- package/rcf/code-nodes/cn-173.json +12 -0
- package/rcf/code-nodes/cn-174.json +12 -0
- package/rcf/code-nodes/cn-175.json +13 -0
- package/rcf/code-nodes/cn-176.json +12 -0
- package/rcf/code-nodes/cn-177.json +12 -0
- package/rcf/code-nodes/cn-178.json +12 -0
- package/rcf/code-nodes/cn-179.json +12 -0
- package/rcf/code-nodes/cn-180.json +13 -0
- package/rcf/code-nodes/cn-181.json +12 -0
- package/rcf/code-nodes/cn-182.json +13 -0
- package/rcf/code-nodes/cn-183.json +12 -0
- package/rcf/code-nodes/cn-184.json +13 -0
- package/rcf/code-nodes/cn-185.json +12 -0
- package/rcf/code-nodes/cn-186.json +12 -0
- package/rcf/code-nodes/cn-200.json +14 -0
- package/rcf/code-nodes/cn-201.json +13 -0
- package/rcf/code-nodes/cn-202.json +14 -0
- package/rcf/code-nodes/cn-203.json +14 -0
- package/rcf/code-nodes/cn-204.json +13 -0
- package/rcf/code-nodes/cn-205.json +14 -0
- package/rcf/code-nodes/cn-206.json +14 -0
- package/rcf/code-nodes/cn-207.json +13 -0
- package/rcf/code-nodes/cn-208.json +14 -0
- package/rcf/code-nodes/cn-209.json +14 -0
- package/rcf/code-nodes/cn-210.json +13 -0
- package/rcf/code-nodes/cn-211.json +12 -0
- package/rcf/code-nodes/cn-212.json +12 -0
- package/rcf/code-nodes/cn-213.json +12 -0
- package/rcf/code-nodes/cn-214.json +15 -0
- package/rcf/code-nodes/cn-215.json +13 -0
- package/rcf/code-nodes/cn-216.json +14 -0
- package/rcf/code-nodes/cn-217.json +13 -0
- package/rcf/fbs/fbs-043.json +23 -0
- package/rcf/fbs/fbs-044.json +23 -0
- package/rcf/fbs/fbs-045.json +23 -0
- package/rcf/fbs/fbs-046.json +24 -0
- package/rcf/fbs/fbs-047.json +24 -0
- package/rcf/fbs/fbs-060.json +22 -0
- package/rcf/fbs/fbs-061.json +20 -0
- package/rcf/fbs/fbs-062.json +20 -0
- package/rcf/fbs/fbs-063.json +22 -0
- package/rcf/fbs/fbs-064.json +23 -0
- package/rcf/requirements/req-024.json +69 -0
- package/rcf/requirements/req-025.json +59 -0
- package/rcf/requirements/req-026.json +154 -0
- package/rcf/requirements/req-027.json +33 -0
- package/rcf/requirements/req-028.json +13 -0
- package/rcf/requirements/req-029.json +57 -0
- package/rcf/requirements/req-030.json +67 -0
- package/rcf/requirements/req-040.json +13 -0
- package/rcf/requirements/req-041.json +125 -0
- package/rcf/requirements/req-042.json +59 -0
- package/rcf/requirements/req-043.json +39 -0
- package/rcf/test-suites/ts-053.json +70 -0
- package/rcf/test-suites/ts-054.json +70 -0
- package/rcf/test-suites/ts-055.json +77 -0
- package/rcf/test-suites/ts-056.json +78 -0
- package/rcf/test-suites/ts-057.json +78 -0
- package/rcf/test-suites/ts-070.json +62 -0
- package/rcf/test-suites/ts-071.json +62 -0
- package/rcf/test-suites/ts-072.json +62 -0
- package/rcf/test-suites/ts-073.json +38 -0
- package/rcf/test-suites/ts-074.json +30 -0
- package/rcf/test-suites/ts-075.json +38 -0
- package/rcf/test-suites/ts-076.json +70 -0
- package/rcf/user-stories/us-2401.json +62 -0
- package/rcf/user-stories/us-2501.json +58 -0
- package/rcf/user-stories/us-2601.json +51 -0
- package/rcf/user-stories/us-2701.json +55 -0
- package/rcf/user-stories/us-2801.json +55 -0
- package/rcf/user-stories/us-2901.json +45 -0
- package/rcf/user-stories/us-2902.json +36 -0
- package/rcf/user-stories/us-3001.json +45 -0
- package/rcf/user-stories/us-4001.json +69 -0
- package/rcf/user-stories/us-4101.json +69 -0
- package/rcf/user-stories/us-4201.json +69 -0
- package/rcf/user-stories/us-4301.json +78 -0
- package/releases/releases.yaml +21 -1
- package/src/blueprint/apply.js +13 -1
- package/src/blueprint/capabilities.js +66 -2
- package/src/cli/blueprint.js +15 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# messaging-queue-cloudflare
|
|
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 (Baz decision 7) 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
|
+
|
|
5
|
+
## What this blueprint gives you
|
|
6
|
+
|
|
7
|
+
- **A producer facade** (TAC-3001) that is the sole reader of the queue binding (`env.RCF_TEST_QUEUE` in the fixture; the elicited binding name in a real project) in your source tree, opens on boot, and exposes typed named domain verbs (`publish`, `publishBatch`). Emits `producerReady` on the first successful ready-check.
|
|
8
|
+
- **A consumer registration** (TAC-3002) on the Worker's `queue` handler; reads a batch, dispatches per-message to the registered handler, acks per message, returns `retry` on retryable failure, drives the retry-to-DLQ trajectory at the elicited `max_retries` per ADR-3003.
|
|
9
|
+
- **An event sink** (TAC-3003) with a metadata-only field discipline: `producerReady`, `messagePublished`, `messageAcked`, `messageDeadLettered`; no body bytes, no header value, no consumer context, no producer context.
|
|
10
|
+
- **Six Node-only probes** proving every runtime observable: four against the wrangler-dev-equivalent seam (`producer-facade-ready`, `publish-to-delivery`, `retry-and-dlq`, `event-secrecy`) plus one accountBound `real-account-concurrency-smoke` that skips cleanly without `CI_HAS_CLOUDFLARE_ACCOUNT` per spec section 3.5, and a shared `probe-utils.mjs` helper module.
|
|
11
|
+
|
|
12
|
+
## The six REQs
|
|
13
|
+
|
|
14
|
+
| REQ | What it commits |
|
|
15
|
+
|---|---|
|
|
16
|
+
| REQ-001 | Producer facade sole reader of the Queues binding; opens on boot; emits `producerReady`. |
|
|
17
|
+
| REQ-002 | Publish / consume / ack contract with stable message-id and producer-supplied trace-id. |
|
|
18
|
+
| REQ-003 | Retry contract: consumer returning `retry` re-delivers with an incremented attempt counter. |
|
|
19
|
+
| REQ-004 | Dead-letter contract: elicited `max_retries` (default 3 per Cloudflare Queues), DLQ per-consumer via wrangler `dead_letter_queue` field, DLQ retention 4 days per https://developers.cloudflare.com/queues/configuration/dead-letter-queues/. |
|
|
20
|
+
| REQ-005 | Batch consume: elicited `max_batch_size` (default 10, ceiling 100) and `max_batch_timeout` (default 5 seconds, ceiling 60 seconds) per https://developers.cloudflare.com/queues/platform/limits/. |
|
|
21
|
+
| REQ-006 | Four lifecycle events with metadata-only fields; event-secrecy probe asserts against a PII fixture body. |
|
|
22
|
+
|
|
23
|
+
## The three TACs
|
|
24
|
+
|
|
25
|
+
- **TAC-3001 producer facade**: sole reader of the queue binding; `publish` and `publishBatch` are the outward surface.
|
|
26
|
+
- **TAC-3002 consumer registration**: the Worker `queue` handler surface; batch envelope; per-message ack / retry semantics.
|
|
27
|
+
- **TAC-3003 event sink**: metadata-only lifecycle event contract; whitelist enforced in code.
|
|
28
|
+
|
|
29
|
+
## The four ADRs
|
|
30
|
+
|
|
31
|
+
- **ADR-3001 adapter**: Cloudflare Queues v1.0.0 shipped first adapter. `recommendedDefault: true`. Standards trace clause: Cloudflare Queues documented per-message and per-batch limits.
|
|
32
|
+
- **ADR-3002 delivery semantics** (`scope: global`, topic `deliverySemantics`): at-least-once as the shipped shape; conflicts by design with future exactly-once or at-most-once siblings. Standards trace clause: WSD-005 clauses on at-least-once and out-of-order tolerance.
|
|
33
|
+
- **ADR-3003 max-attempts floor**: `max_retries` default 3, floor 1, ceiling 100 per Cloudflare Queues platform limits. `elicited: true`. Standards trace clause: Cloudflare Queues default retry limit 3 and documented ceiling 100.
|
|
34
|
+
- **ADR-3004 batch defaults**: `max_batch_size` default 10 (ceiling 100), `max_batch_timeout` default 5 seconds (ceiling 60 seconds). `elicited: true`. Standards trace clause: Cloudflare Queues per-consumer batch settings.
|
|
35
|
+
|
|
36
|
+
## Elicited parameters
|
|
37
|
+
|
|
38
|
+
Queue name (or binding name in a Workers deploy); `max_retries` before DLQ (default 3, floor 1, ceiling 100); DLQ queue name (a second Cloudflare Queue declared via `dead_letter_queue` in wrangler config); `max_batch_size` (default 10, ceiling 100); `max_batch_timeout` (default 5 seconds, ceiling 60 seconds); producer-supplied trace-id header key (default `x-trace-id`).
|
|
39
|
+
|
|
40
|
+
## Companions
|
|
41
|
+
|
|
42
|
+
- **logging**: every publish, every ack, and every DLQ landing writes through the applied logger; a logging companion supplies the factory.
|
|
43
|
+
- **errorHandling**: a publish failure, a DLQ overflow constructs an internal error record; an error-handling companion supplies the record factory and the boundary.
|
|
44
|
+
|
|
45
|
+
## Composition and conflicts
|
|
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 (Baz decision 7, deferred v1.0.0 pending demand) or an exactly-once / at-most-once sibling would conflict here by design. `capabilities: ["queue"]`; `providesRoles: []`.
|
|
48
|
+
|
|
49
|
+
## Reserved sibling
|
|
50
|
+
|
|
51
|
+
`messaging-queue-postgres` (Baz decision 7). 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
|
+
|
|
53
|
+
## The six probes
|
|
54
|
+
|
|
55
|
+
Each probe is a Node module under `contributions/probes/` exporting the round-5 spec section 3.2 verdict envelope, with a matching `run-<probe-name>.mjs` shim that drives the probe against the shared fixture's T-3 slice and writes the per-blueprint report at `.rcf/reports/blueprints/messaging-queue-cloudflare/<probe-name>.json`.
|
|
56
|
+
|
|
57
|
+
| Probe | Anchor AC | What it proves | accountBound |
|
|
58
|
+
|---|---|---|---|
|
|
59
|
+
| `producer-facade-ready` | AC-29101-1 | Producer facade opens against the queue binding; `producerReady` fires with `queueName`. | false |
|
|
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
|
+
| `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
|
+
| `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 | Real 500-message round-trip against `rcf-lite-ci-queue-smoke` when `CI_HAS_CLOUDFLARE_ACCOUNT` set; records `accountBoundSkipped: true` when not. | true |
|
|
64
|
+
|
|
65
|
+
## Anatomy
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
blueprints/messaging-queue-cloudflare/
|
|
69
|
+
blueprint.json
|
|
70
|
+
README.md
|
|
71
|
+
CHANGELOG.md
|
|
72
|
+
guide/
|
|
73
|
+
messaging-queue-cloudflare.md
|
|
74
|
+
docs/
|
|
75
|
+
topics.md
|
|
76
|
+
contributions/
|
|
77
|
+
requirements/
|
|
78
|
+
messaging-queue-cloudflare-req-001.json ... req-006.json
|
|
79
|
+
user-stories/
|
|
80
|
+
messaging-queue-cloudflare-us-29101.json ... us-29108.json
|
|
81
|
+
tacs/
|
|
82
|
+
tac-3001-messaging-queue-cloudflare-producer-facade.json
|
|
83
|
+
tac-3002-messaging-queue-cloudflare-consumer-registration.json
|
|
84
|
+
tac-3003-messaging-queue-cloudflare-event-sink.json
|
|
85
|
+
adrs/
|
|
86
|
+
adr-3001-messaging-queue-cloudflare-adapter.json
|
|
87
|
+
adr-3002-messaging-queue-cloudflare-delivery-semantics.json
|
|
88
|
+
adr-3003-messaging-queue-cloudflare-max-attempts-floor.json
|
|
89
|
+
adr-3004-messaging-queue-cloudflare-batch-defaults.json
|
|
90
|
+
probes/
|
|
91
|
+
probe-utils.mjs
|
|
92
|
+
producer-facade-ready.mjs (+ run-producer-facade-ready.mjs)
|
|
93
|
+
publish-to-delivery.mjs (+ run-publish-to-delivery.mjs)
|
|
94
|
+
retry-and-dlq.mjs (+ run-retry-and-dlq.mjs)
|
|
95
|
+
event-secrecy.mjs (+ run-event-secrecy.mjs)
|
|
96
|
+
real-account-concurrency-smoke.mjs (+ run-real-account-concurrency-smoke.mjs)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Known limitations and mechanism-reach gaps
|
|
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 (SDR-3-a 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
|
+
|
|
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
|
+
|
|
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 a reviewer `wrangler dev` run or the accountBound smoke.
|
|
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 a reviewer `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 a reviewer `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 a reviewer `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 a reviewer `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 a reviewer `wrangler dev` run or the accountBound smoke.
|
|
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 was not driven in this pass. Rationale: SDR-3-a 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 in their own scratch to close the observability gap.
|
|
114
|
+
- **AC-29108-2** (real-account concurrency smoke: 500 messages, consumer concurrency up to 250): NOT proven at v1.0.0 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 live 500-message run rides `deploy-cloudflare-workers`' surface (Cloudflare Queues does not support `wrangler dev --remote` per the local-development doc, so this cannot ride a local wrangler process even with the env var set); the live run is a v1.0.0 follow-up when the shared HQ queue `rcf-lite-ci-queue-smoke` (Q2 default) is provisioned on Baz's account.
|
|
115
|
+
|
|
116
|
+
## Other limitations (not mechanism-reach gaps)
|
|
117
|
+
|
|
118
|
+
- Cloudflare Queues per-message size cap is 128 KB per https://developers.cloudflare.com/queues/platform/limits/. A project sending larger payloads either chunks or moves the body out-of-band to `object-storage-s3`. This is a boundary the shipped facade does not police; it is a project-level concern the guide names.
|
|
119
|
+
- The Miniflare Queues sub-page returned 404 during spec ratification (2026-09-06); the Cloudflare Queues local-development page above is the authoritative reference and the only URL the guide cites for the local seam.
|
|
120
|
+
|
|
121
|
+
## What this blueprint does not do
|
|
122
|
+
|
|
123
|
+
- No fan-out / broadcast pub-sub semantics; that lives in the parked `messaging-eventbus` candidate on a different global topic.
|
|
124
|
+
- No exactly-once transport (Cloudflare Queues implements at-least-once with a stable message-id for consumer-side dedup per ADR-3002); consumer code that needs exactly-once processing dedups on the stable message-id.
|
|
125
|
+
- No schema registry; message bodies are opaque to this blueprint.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"slug": "messaging-queue-cloudflare",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"category": "messaging",
|
|
5
|
+
"capabilities": ["queue"],
|
|
6
|
+
"suggestedCompanions": [
|
|
7
|
+
{
|
|
8
|
+
"role": "logging",
|
|
9
|
+
"reason": "Every publish and every ack writes through the applied logger; a logging companion supplies the factory."
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"role": "errorHandling",
|
|
13
|
+
"reason": "A publish failure, a DLQ overflow constructs an internal error record; an error-handling companion supplies the record factory and the boundary."
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"contributions": [
|
|
17
|
+
{ "id": "messaging-queue-cloudflare-REQ-001", "kind": "req", "path": "requirements/messaging-queue-cloudflare-req-001.json" },
|
|
18
|
+
{ "id": "messaging-queue-cloudflare-REQ-002", "kind": "req", "path": "requirements/messaging-queue-cloudflare-req-002.json" },
|
|
19
|
+
{ "id": "messaging-queue-cloudflare-REQ-003", "kind": "req", "path": "requirements/messaging-queue-cloudflare-req-003.json" },
|
|
20
|
+
{ "id": "messaging-queue-cloudflare-REQ-004", "kind": "req", "path": "requirements/messaging-queue-cloudflare-req-004.json" },
|
|
21
|
+
{ "id": "messaging-queue-cloudflare-REQ-005", "kind": "req", "path": "requirements/messaging-queue-cloudflare-req-005.json" },
|
|
22
|
+
{ "id": "messaging-queue-cloudflare-REQ-006", "kind": "req", "path": "requirements/messaging-queue-cloudflare-req-006.json" },
|
|
23
|
+
{ "id": "messaging-queue-cloudflare-US-29101", "kind": "us", "path": "user-stories/messaging-queue-cloudflare-us-29101.json" },
|
|
24
|
+
{ "id": "messaging-queue-cloudflare-US-29102", "kind": "us", "path": "user-stories/messaging-queue-cloudflare-us-29102.json" },
|
|
25
|
+
{ "id": "messaging-queue-cloudflare-US-29103", "kind": "us", "path": "user-stories/messaging-queue-cloudflare-us-29103.json" },
|
|
26
|
+
{ "id": "messaging-queue-cloudflare-US-29104", "kind": "us", "path": "user-stories/messaging-queue-cloudflare-us-29104.json" },
|
|
27
|
+
{ "id": "messaging-queue-cloudflare-US-29105", "kind": "us", "path": "user-stories/messaging-queue-cloudflare-us-29105.json" },
|
|
28
|
+
{ "id": "messaging-queue-cloudflare-US-29106", "kind": "us", "path": "user-stories/messaging-queue-cloudflare-us-29106.json" },
|
|
29
|
+
{ "id": "messaging-queue-cloudflare-US-29107", "kind": "us", "path": "user-stories/messaging-queue-cloudflare-us-29107.json" },
|
|
30
|
+
{ "id": "messaging-queue-cloudflare-US-29108", "kind": "us", "path": "user-stories/messaging-queue-cloudflare-us-29108.json" },
|
|
31
|
+
{ "id": "TAC-3001-messaging-queue-cloudflare-producer-facade", "kind": "tac", "path": "tacs/tac-3001-messaging-queue-cloudflare-producer-facade.json" },
|
|
32
|
+
{ "id": "TAC-3002-messaging-queue-cloudflare-consumer-registration", "kind": "tac", "path": "tacs/tac-3002-messaging-queue-cloudflare-consumer-registration.json" },
|
|
33
|
+
{ "id": "TAC-3003-messaging-queue-cloudflare-event-sink", "kind": "tac", "path": "tacs/tac-3003-messaging-queue-cloudflare-event-sink.json" },
|
|
34
|
+
{
|
|
35
|
+
"id": "ADR-3001-messaging-queue-cloudflare-adapter",
|
|
36
|
+
"kind": "adr",
|
|
37
|
+
"path": "adrs/adr-3001-messaging-queue-cloudflare-adapter.json",
|
|
38
|
+
"recommendedDefault": true,
|
|
39
|
+
"elicited": false,
|
|
40
|
+
"standardsTraceClause": "Cloudflare Queues documented per-message and per-batch limits"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "ADR-3002-messaging-queue-cloudflare-delivery-semantics",
|
|
44
|
+
"kind": "adr",
|
|
45
|
+
"path": "adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json",
|
|
46
|
+
"scope": "global",
|
|
47
|
+
"topic": "deliverySemantics",
|
|
48
|
+
"standardsTraceClause": "WSD-005 clauses on at-least-once and out-of-order tolerance"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "ADR-3003-messaging-queue-cloudflare-max-attempts-floor",
|
|
52
|
+
"kind": "adr",
|
|
53
|
+
"path": "adrs/adr-3003-messaging-queue-cloudflare-max-attempts-floor.json",
|
|
54
|
+
"recommendedDefault": true,
|
|
55
|
+
"elicited": true,
|
|
56
|
+
"standardsTraceClause": "Cloudflare Queues default retry limit 3 and documented ceiling 100"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "ADR-3004-messaging-queue-cloudflare-batch-defaults",
|
|
60
|
+
"kind": "adr",
|
|
61
|
+
"path": "adrs/adr-3004-messaging-queue-cloudflare-batch-defaults.json",
|
|
62
|
+
"recommendedDefault": true,
|
|
63
|
+
"elicited": true,
|
|
64
|
+
"standardsTraceClause": "Cloudflare Queues per-consumer batch settings"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-3001-messaging-queue-cloudflare-adapter",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Adapter: Cloudflare Queues as the shipped v1.0.0 first adapter",
|
|
8
|
+
"context": "A project deploying a directed producer-to-consumer worklist queue on Cloudflare Workers has one native shipped answer today: Cloudflare Queues. The Queues surface is bound through wrangler configuration (a [[queues.producers]] block for the producer facade to publish through, a [[queues.consumers]] block for the Worker queue handler to consume from), and the shipped Worker runtime binds env.<binding> to a Queues object with send / sendBatch on the producer side and a batch envelope with ack / retry on the consumer side per https://developers.cloudflare.com/queues/configuration/javascript-apis/. The v1.0.0 facade must hold the adapter reference opaque at the facade boundary so a future non-Cloudflare adapter (an SQS shim, the reserved messaging-queue-postgres sibling per Baz decision 7) slots in without a facade re-shape, and so a fixture-time in-memory adapter is testable without live Cloudflare Queues access.",
|
|
9
|
+
"decision": "The shipped v1.0.0 default is Cloudflare Queues, wired through wrangler config (producer binding on [[queues.producers]], consumer on [[queues.consumers]] with dead_letter_queue and max_retries per https://developers.cloudflare.com/queues/configuration/dead-letter-queues/). The producer facade module is the sole holder of the Queues binding reference per REQ-001; the consumer registration module is the sole reader of the batch envelope per REQ-002. The adapter reference is OPAQUE at this ADR: the facade dereferences the elicited binding at the top of the module and any consumer wanting a different adapter (an SQS shim, the messaging-queue-postgres sibling minted on demand) replaces the binding reference here without touching the outward interface. A fixture-time in-memory adapter (used by the local probes) implements the same binding shape (send / sendBatch on the producer side, batch with ack / retry on the consumer side) so the facade and consumer surfaces are indistinguishable from the real Queues binding at the facade boundary. The 128 KB per-message cap and 100 messages per batch cap Cloudflare documents at https://developers.cloudflare.com/queues/platform/limits/ apply to every real-Queues run.",
|
|
10
|
+
"consequences": "The project inherits the Cloudflare Queues wire-format, the platform-assigned stable message-id, and the batch envelope's per-message ack semantics. Standards trace clause: Cloudflare Queues documented per-message and per-batch limits (per https://developers.cloudflare.com/queues/platform/limits/), Cloudflare Queues Worker queue-handler contract (per https://developers.cloudflare.com/queues/configuration/javascript-apis/), and Cloudflare Queues dead-letter documentation (per https://developers.cloudflare.com/queues/configuration/dead-letter-queues/). A future non-Cloudflare adapter mints under a sibling blueprint (reserved slug messaging-queue-postgres, Baz decision 7) and conflicts by design on deliverySemantics (ADR-3002) with this blueprint; the operator picks one queue backend per project via a project-level ADR.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "External SQS or SNS as the shipped v1.0.0 default",
|
|
14
|
+
"summary": "Ship AWS SQS as the primary v1.0.0 queue backend and provide Cloudflare Queues as an elicited alternative.",
|
|
15
|
+
"reasonNotChosen": "The shelf composition target this round is a Cloudflare Workers project (deploy-cloudflare-workers is the applied deploy target on the shared fixture). Shipping SQS as the default would leave a Workers project reaching into a non-Cloudflare vendor for its main worklist, which is not the shipped-shape target of the round-5 spec section 5.3."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Kafka or NATS as the shipped v1.0.0 default",
|
|
19
|
+
"summary": "Ship a self-hosted Kafka or NATS backend as the primary v1.0.0 queue.",
|
|
20
|
+
"reasonNotChosen": "A self-hosted Kafka or NATS backend adds a persistent operational surface every applying project has to run; the round-5 spec section 5.3 targets a directed producer-to-consumer worklist as a shipped shape whose applying project need not host a broker. The reserved messaging-queue-postgres sibling (Baz decision 7) covers the self-hosted-transport family separately when demand mints it."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "Ship a hand-rolled fetch client against the Queues REST API",
|
|
24
|
+
"summary": "Skip the Worker Queues binding and roll a fetch client against the Queues REST-shape endpoints.",
|
|
25
|
+
"reasonNotChosen": "The Worker binding is the shipped Cloudflare surface and the one every Queues doc references; a REST client would ship a second surface with its own auth and its own reliability envelope. The mature binding-based surface is what makes the v1.0.0 facade portable at the boundary."
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"createdAt": "2026-09-06T21:00:00.000Z",
|
|
29
|
+
"updatedAt": "2026-09-06T21:00:00.000Z"
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-3002-messaging-queue-cloudflare-delivery-semantics",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Delivery semantics: at-least-once as the shipped shape (scope global, new topic deliverySemantics)",
|
|
8
|
+
"context": "A directed producer-to-consumer worklist ships one of three delivery shapes at the transport contract: at-most-once (fire and forget, dedup at the producer), at-least-once (guaranteed delivery with duplicates possible, dedup at the consumer), or exactly-once (guaranteed delivery with dedup at the transport, expensive). Cloudflare Queues implements at-least-once with a stable message-id the consumer uses for its own dedup; the WSD-005 messaging standard (operator/knowledge/wsd/wsd-standards/wsd-005-messaging.md) makes at-least-once and out-of-order tolerance the shipped default for domain event handoffs; the messaging-queue-cloudflare blueprint claims the deliverySemantics topic on the shelf so future exactly-once or at-most-once siblings surface as DELIBERATE conflicts and not silent divergences.",
|
|
9
|
+
"decision": "The shipped v1.0.0 shape is at-least-once. Every publish reaches every consumer at least once; duplicates are possible under retry-and-DLQ redelivery paths; consumer code that needs exactly-once semantics maintains its own dedup keyed on the stable message-id per REQ-002. The deliverySemantics topic scope is global on this blueprint; the topic string is deliverySemantics (lower camel case, one concept per topic, no version suffix, per the round-2 rules-for-new-topics clause on the shelf registry). Future exactly-once or at-most-once siblings would contribute the same topic string with a different answer, forcing a DELIBERATE conflict the operator resolves with a project-level ADR per the round-2 conflict pattern.",
|
|
10
|
+
"consequences": "The applying project inherits an at-least-once transport with a stable message-id it uses for consumer-side dedup when the domain calls for exactly-once processing. Standards trace clause: WSD-005 clauses on at-least-once and out-of-order tolerance (satisfied by the message-id and trace-id header contract). The reserved messaging-queue-postgres sibling (Baz decision 7) will claim deliverySemantics with an at-least-once answer too; two shipped answers on one topic surface a DELIBERATE conflict the operator resolves by picking one queue backend per project via a project-level ADR (the same shape as errorEnvelope and authModel conflicts the SPA and API-REST blueprints already carry).",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "At-most-once as the shipped v1.0.0 default",
|
|
14
|
+
"summary": "Ship fire-and-forget publish semantics with producer-side dedup and no DLQ.",
|
|
15
|
+
"reasonNotChosen": "At-most-once loses the DLQ safety net and does not compose with the retry contract REQ-003 requires. The shipped shape's whole reason for existing is the guaranteed handoff for background work; at-most-once is the wrong contract for that use case."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Exactly-once as the shipped v1.0.0 default",
|
|
19
|
+
"summary": "Ship transport-level dedup so the consumer never sees the same message-id twice.",
|
|
20
|
+
"reasonNotChosen": "Cloudflare Queues does not implement transport-level exactly-once; shipping the label would misrepresent the transport. Consumer-side dedup keyed on the stable message-id is the shipped path when exactly-once is the domain requirement."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"createdAt": "2026-09-06T21:00:00.000Z",
|
|
24
|
+
"updatedAt": "2026-09-06T21:00:00.000Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-3003-messaging-queue-cloudflare-max-attempts-floor",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Max-attempts before DLQ: default 3, floor 1, ceiling 100 per Cloudflare Queues platform limits",
|
|
8
|
+
"context": "A retry-and-DLQ contract needs a bounded max-attempts before dead-lettering: too low leaks transient failures into the DLQ before the retry can recover them; too high wastes consumer wall-clock and keeps a permanently-broken message live indefinitely. Cloudflare Queues documents a default retry limit of 3 at https://developers.cloudflare.com/queues/configuration/dead-letter-queues/ and a documented ceiling of 100 at https://developers.cloudflare.com/queues/platform/limits/ (max retries per message). The wrangler config field on the [[queues.consumers]] block is max_retries.",
|
|
9
|
+
"decision": "The shipped v1.0.0 default is max_retries 3, matching the Cloudflare Queues documented default. The floor is 1 (a max_retries of 0 defeats the retry contract REQ-003 requires). The ceiling is 100, matching the Cloudflare Queues documented per-message max. The value is elicited at apply time under the maxAttempts parameter; the fixture wires the default 3 explicitly on the consumer block. Consumer code that needs a tighter or looser bound sets the value at apply time; the boundary check on the elicit rejects values below 1 or above 100 with a stable message id and a pointer at the Cloudflare limits doc.",
|
|
10
|
+
"consequences": "The applying project inherits a bounded retry budget matching Cloudflare's shipped defaults. Standards trace clause: Cloudflare Queues default retry limit 3 (dead-letter-queues doc) and documented ceiling 100 (platform-limits doc). The elicited value carries into the retry-and-dlq probe (SIMULATE_CONSUMER_RETRY switches the fixture to force the retry path; the probe asserts the DLQ landing at exactly the elicited max_retries).",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Hard-code max_retries 3 with no elicited parameter",
|
|
14
|
+
"summary": "Ship the Cloudflare default 3 as a hard-coded value with no project-side override.",
|
|
15
|
+
"reasonNotChosen": "A project running a downstream that recovers over minutes (rate limit, cold cache) may need a higher retry budget; a hard-coded 3 forces the project to bypass the facade to override the limit. Eliciting the value is cheaper than eliciting the escape hatch."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "No ceiling on max_retries",
|
|
19
|
+
"summary": "Accept any max_retries value the operator hands in.",
|
|
20
|
+
"reasonNotChosen": "The Cloudflare Queues platform enforces the 100 ceiling at the transport regardless; the elicit refusing above 100 is what surfaces the failure at apply time rather than at first live redelivery."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"createdAt": "2026-09-06T21:00:00.000Z",
|
|
24
|
+
"updatedAt": "2026-09-06T21:00:00.000Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-3004-messaging-queue-cloudflare-batch-defaults",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Batch settings: max_batch_size default 10 ceiling 100, max_batch_timeout default 5 seconds ceiling 60 seconds",
|
|
8
|
+
"context": "The consumer reads messages in batches whose size and timeout are elicited on the wrangler [[queues.consumers]] block as max_batch_size and max_batch_timeout. Cloudflare Queues documents a max_batch_size ceiling of 100 messages per batch and a max_batch_timeout ceiling of 60 seconds at https://developers.cloudflare.com/queues/platform/limits/. A default sitting at the ceiling wastes throughput when a project's average burstiness is low; a default too far below reduces the batching benefit. The shipped defaults have to sit below the ceilings so tightening in a project is a config change, not a code change.",
|
|
9
|
+
"decision": "The shipped v1.0.0 defaults are max_batch_size 10 and max_batch_timeout 5 seconds. Both sit well below the Cloudflare-documented ceilings (100 messages, 60 seconds respectively) so a project that runs closer to the ceiling changes wrangler config only. Both values are elicited under batchSize and batchTimeoutSeconds; the elicit refuses values above the Cloudflare ceiling with a stable message id and a pointer at the Cloudflare limits doc.",
|
|
10
|
+
"consequences": "The applying project inherits a modest batch envelope that suits most background-work traffic; a project needing near-ceiling batching sets the wrangler config values at apply time. Standards trace clause: Cloudflare Queues per-consumer batch settings, per the limits doc. The publish-to-delivery probe drives 5 messages and asserts the consumer sees them in one batch (5 < the shipped 10, so the batch fills by timeout).",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Ship max_batch_size 100 as the default",
|
|
14
|
+
"summary": "Ship the Cloudflare ceiling as the default so no operator elicits.",
|
|
15
|
+
"reasonNotChosen": "A ceiling default hides the batching decision from the operator and wastes wall-clock on a low-burst project. The elicited 10 is a signal to think about the shape of the project's traffic."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Ship max_batch_size 1 to force per-message invocation",
|
|
19
|
+
"summary": "Skip batching altogether and invoke the consumer once per message.",
|
|
20
|
+
"reasonNotChosen": "Per-message invocation defeats the reason batching exists and puts every project at the Worker invocation limit."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"createdAt": "2026-09-06T21:00:00.000Z",
|
|
24
|
+
"updatedAt": "2026-09-06T21:00:00.000Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event-secrecy probe.
|
|
3
|
+
*
|
|
4
|
+
* Drives publish and ack with a PII fixture body ({userId: 1234, ssn:
|
|
5
|
+
* "123-45-6789"}) and asserts every event record on the sink carries
|
|
6
|
+
* only the whitelist ({event, ts, messageId, queueName, attempts}) and
|
|
7
|
+
* no PII fixture text. The sink adapter (event-sink.mjs) is what
|
|
8
|
+
* enforces the whitelist; this probe proves the enforcement by driving
|
|
9
|
+
* the pattern the induced-failure switch SIMULATE_PII_IN_BODY names.
|
|
10
|
+
*
|
|
11
|
+
* Anchors AC-29106-1.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { createQueuePair } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/queue-driver.mjs';
|
|
15
|
+
import { createProducer, queueConfigFromEnv } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/producer.mjs';
|
|
16
|
+
import { createConsumer, drainLoop } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/consumer.mjs';
|
|
17
|
+
import { createSinkAdapter } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/event-sink.mjs';
|
|
18
|
+
|
|
19
|
+
const PII_STRINGS = ['123-45-6789', '1234'];
|
|
20
|
+
const FORBIDDEN_KEYS = ['body', 'headers', 'userId', 'ssn', 'consumerContext', 'producerContext'];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Event-secrecy probe (with teeth per PR #159 gate finding 2).
|
|
24
|
+
*
|
|
25
|
+
* Two layers of assertion so the whitelist is exercised at the actual
|
|
26
|
+
* boundary AC-29106-1 claims, not only observed via the shipped code
|
|
27
|
+
* path that never hands the sink a body-bearing payload:
|
|
28
|
+
*
|
|
29
|
+
* (1) Direct-boundary assertion: construct a PII-bearing caller record
|
|
30
|
+
* locally, hand it to createSinkAdapter (the exact TAC-3003 boundary
|
|
31
|
+
* the AC claims), assert the forwarded record is stripped to the
|
|
32
|
+
* whitelist and carries no PII substring.
|
|
33
|
+
*
|
|
34
|
+
* (2) Consumer-driven assertion: turn on SIMULATE_LEAK_BODY_TO_SINK on
|
|
35
|
+
* the consumer so the shipped consumer path itself hands the sink
|
|
36
|
+
* a body-bearing payload (body, headers, userId, ssn,
|
|
37
|
+
* consumerContext), then drive publish and ack of a PII fixture
|
|
38
|
+
* body and assert every event record observed on the sink carries
|
|
39
|
+
* only the whitelist and no PII substring survives.
|
|
40
|
+
*
|
|
41
|
+
* A reviewer who disables the whitelist in src/event-sink.mjs and reruns
|
|
42
|
+
* this probe observes it FAIL on both layers: layer (1) surfaces
|
|
43
|
+
* forbidden keys on the direct record; layer (2) surfaces the leaked
|
|
44
|
+
* body / userId / ssn on the acked event. That mutation-run failure is
|
|
45
|
+
* what proves the probe has teeth (the shipped code, with the whitelist
|
|
46
|
+
* in place, passes cleanly on the shipped head).
|
|
47
|
+
*/
|
|
48
|
+
export default async function runProbe() {
|
|
49
|
+
const results = [];
|
|
50
|
+
|
|
51
|
+
// Layer (1): direct-boundary assertion at createSinkAdapter.
|
|
52
|
+
const directCaptured = [];
|
|
53
|
+
const directSink = createSinkAdapter({ onEvent: (rec) => directCaptured.push(rec) });
|
|
54
|
+
directSink({
|
|
55
|
+
event: 'messageAcked',
|
|
56
|
+
ts: new Date().toISOString(),
|
|
57
|
+
messageId: 'direct-boundary-msg-001',
|
|
58
|
+
queueName: 'rcf-test-queue',
|
|
59
|
+
attempts: 1,
|
|
60
|
+
body: { userId: 1234, ssn: '123-45-6789', note: 'direct probe leak attempt' },
|
|
61
|
+
headers: { 'x-trace-id': 'trace-direct', authorization: 'Bearer secret-value' },
|
|
62
|
+
userId: 1234,
|
|
63
|
+
ssn: '123-45-6789',
|
|
64
|
+
consumerContext: { workerId: 'direct-probe', handlerName: 'directHandler' },
|
|
65
|
+
producerContext: { host: 'direct-probe-host' },
|
|
66
|
+
});
|
|
67
|
+
const directSerialised = JSON.stringify(directCaptured);
|
|
68
|
+
const directAllowed = new Set(['event', 'ts', 'messageId', 'queueName', 'attempts']);
|
|
69
|
+
const directForbiddenKeys = directCaptured.length === 1
|
|
70
|
+
? Object.keys(directCaptured[0]).filter((k) => !directAllowed.has(k))
|
|
71
|
+
: ['record-count-mismatch'];
|
|
72
|
+
const directPiiHits = PII_STRINGS.filter((s) => directSerialised.includes(s));
|
|
73
|
+
const directForbiddenKeyHits = FORBIDDEN_KEYS.filter((k) => directSerialised.includes(`"${k}"`));
|
|
74
|
+
const directPass = directCaptured.length === 1 && directForbiddenKeys.length === 0 && directPiiHits.length === 0 && directForbiddenKeyHits.length === 0;
|
|
75
|
+
results.push({
|
|
76
|
+
anchorAcId: 'AC-29106-1',
|
|
77
|
+
verdict: directPass ? 'pass' : 'fail',
|
|
78
|
+
detail: directPass
|
|
79
|
+
? `direct-boundary: PII-bearing caller record stripped by createSinkAdapter to ${Object.keys(directCaptured[0]).join(',')}; no PII / forbidden-key substring survived`
|
|
80
|
+
: `direct-boundary breach: forwardedKeys=${JSON.stringify(directCaptured.map((r) => Object.keys(r)))} piiHits=${JSON.stringify(directPiiHits)} forbiddenKeyHits=${JSON.stringify(directForbiddenKeyHits)}`,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Layer (2): consumer-driven assertion with SIMULATE_LEAK_BODY_TO_SINK.
|
|
84
|
+
const cfg = queueConfigFromEnv();
|
|
85
|
+
const pair = createQueuePair({ queueName: cfg.queueName, dlqName: cfg.dlqName, maxRetries: cfg.maxRetries });
|
|
86
|
+
const events = [];
|
|
87
|
+
const producer = createProducer({
|
|
88
|
+
binding: pair.producer,
|
|
89
|
+
queueName: cfg.queueName,
|
|
90
|
+
onEvent: (e) => events.push(e),
|
|
91
|
+
});
|
|
92
|
+
await producer.ready;
|
|
93
|
+
|
|
94
|
+
const body = { userId: 1234, ssn: '123-45-6789', note: 'secret payload' };
|
|
95
|
+
await producer.publish(body, { headers: { 'x-trace-id': 'trace-event-secrecy', authorization: 'Bearer secret-value' } });
|
|
96
|
+
|
|
97
|
+
const consumer = createConsumer({
|
|
98
|
+
handler: async (_msg) => 'ack',
|
|
99
|
+
onEvent: (e) => events.push(e),
|
|
100
|
+
env: { SIMULATE_PII_IN_BODY: 'true', SIMULATE_LEAK_BODY_TO_SINK: 'true' },
|
|
101
|
+
});
|
|
102
|
+
await drainLoop({ consumer, driver: pair, dlqSink: { baseline: [], onEvent: (e) => events.push(e) } });
|
|
103
|
+
|
|
104
|
+
const allowedKeys = new Set(['event', 'ts', 'messageId', 'queueName', 'attempts']);
|
|
105
|
+
let recordsWithForbiddenKeys = 0;
|
|
106
|
+
for (const rec of events) {
|
|
107
|
+
for (const k of Object.keys(rec)) {
|
|
108
|
+
if (!allowedKeys.has(k)) {
|
|
109
|
+
recordsWithForbiddenKeys += 1;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const serialised = JSON.stringify(events);
|
|
115
|
+
const piiHits = PII_STRINGS.filter((s) => serialised.includes(s));
|
|
116
|
+
const forbiddenKeyHits = FORBIDDEN_KEYS.filter((k) => serialised.includes(`"${k}"`));
|
|
117
|
+
|
|
118
|
+
// Also confirm SIMULATE_LEAK_BODY_TO_SINK actually fired: the consumer
|
|
119
|
+
// hands the sink a body-bearing record on messageAcked, and the sink
|
|
120
|
+
// adapter must have received the body for the whitelist to strip it.
|
|
121
|
+
// We prove the leak-path was taken by observing at least one
|
|
122
|
+
// messageAcked event in the captured records (a probe run where the
|
|
123
|
+
// consumer switch was silently unwired would surface no messageAcked
|
|
124
|
+
// and the assertion falls over even before the whitelist check).
|
|
125
|
+
const ackedCount = events.filter((e) => e.event === 'messageAcked').length;
|
|
126
|
+
|
|
127
|
+
const consumerPass = ackedCount >= 1 && recordsWithForbiddenKeys === 0 && piiHits.length === 0 && forbiddenKeyHits.length === 0;
|
|
128
|
+
results.push({
|
|
129
|
+
anchorAcId: 'AC-29106-1',
|
|
130
|
+
verdict: consumerPass ? 'pass' : 'fail',
|
|
131
|
+
detail: consumerPass
|
|
132
|
+
? `consumer-driven leak-path: SIMULATE_LEAK_BODY_TO_SINK on, ${ackedCount} messageAcked events observed on the sink; whitelist stripped all forbidden fields; no PII substring survived on ${events.length} events total`
|
|
133
|
+
: `consumer-driven breach: ackedCount=${ackedCount} recordsWithForbiddenKeys=${recordsWithForbiddenKeys} piiHits=${JSON.stringify(piiHits)} forbiddenKeyHits=${JSON.stringify(forbiddenKeyHits)}`,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return results;
|
|
137
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for messaging-queue-cloudflare probes.
|
|
3
|
+
*
|
|
4
|
+
* Runtime-dependency posture: probes import the fixture's in-memory
|
|
5
|
+
* queue-driver, producer facade, consumer registration, and DLQ
|
|
6
|
+
* inspector from the sample-app fixture's src/ tree so rcf-lite itself
|
|
7
|
+
* gains no new runtime dependency (round-5 spec section 5, brief
|
|
8
|
+
* section 4). The wrangler.toml alongside declares the real Queues
|
|
9
|
+
* binding shape a project would receive when composing against live
|
|
10
|
+
* Cloudflare Queues; the in-memory driver realises the same binding
|
|
11
|
+
* shape (send / sendBatch on the producer side, batch envelope with
|
|
12
|
+
* ack / retry per message on the consumer side) so the facade module
|
|
13
|
+
* is indistinguishable from a live-Queues run at the facade boundary.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
17
|
+
import { dirname, resolve } from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
|
|
20
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
|
|
22
|
+
// Project root four levels above blueprints/messaging-queue-cloudflare/contributions/probes/
|
|
23
|
+
export const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
|
|
24
|
+
export const FIXTURE_DIR = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/infra-s3-and-queue');
|
|
25
|
+
export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/messaging-queue-cloudflare');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Compute the aggregate verdict per spec section 3.4:
|
|
29
|
+
* - fail if any result carries verdict fail
|
|
30
|
+
* - warn if any result carries verdict warn and no fail
|
|
31
|
+
* - pass otherwise
|
|
32
|
+
*/
|
|
33
|
+
export function aggregate(results) {
|
|
34
|
+
if (results.some((r) => r.verdict === 'fail')) return 'fail';
|
|
35
|
+
if (results.some((r) => r.verdict === 'warn')) return 'warn';
|
|
36
|
+
return 'pass';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Write the per-blueprint probe report at
|
|
41
|
+
* .rcf/reports/blueprints/messaging-queue-cloudflare/<probeName>.json
|
|
42
|
+
* per spec section 3.4.
|
|
43
|
+
*/
|
|
44
|
+
export async function writeReport({ probeName, engine, results }) {
|
|
45
|
+
await mkdir(REPORT_DIR, { recursive: true });
|
|
46
|
+
const report = {
|
|
47
|
+
slug: 'messaging-queue-cloudflare',
|
|
48
|
+
probeName,
|
|
49
|
+
runAt: new Date().toISOString(),
|
|
50
|
+
engine,
|
|
51
|
+
results,
|
|
52
|
+
aggregateVerdict: aggregate(results),
|
|
53
|
+
};
|
|
54
|
+
const path = resolve(REPORT_DIR, `${probeName}.json`);
|
|
55
|
+
await writeFile(path, JSON.stringify(report, null, 2), 'utf8');
|
|
56
|
+
return { report, path };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Drive an async main() and exit 0 on aggregate pass, 1 otherwise.
|
|
61
|
+
* Prints the report JSON to stdout for the gate-reviewer to read.
|
|
62
|
+
*/
|
|
63
|
+
export async function runShim(probeName, engine, mainFn) {
|
|
64
|
+
try {
|
|
65
|
+
const results = await mainFn();
|
|
66
|
+
const { report, path } = await writeReport({ probeName, engine, results });
|
|
67
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
68
|
+
process.stdout.write(`report written to ${path}\n`);
|
|
69
|
+
process.exit(report.aggregateVerdict === 'pass' ? 0 : 1);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
const results = [{
|
|
72
|
+
anchorAcId: 'unknown',
|
|
73
|
+
verdict: 'fail',
|
|
74
|
+
detail: `probe threw: ${err && err.message ? err.message : String(err)}`,
|
|
75
|
+
}];
|
|
76
|
+
const { report, path } = await writeReport({ probeName, engine, results });
|
|
77
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
78
|
+
process.stderr.write(`probe error: ${err && err.stack ? err.stack : String(err)}\n`);
|
|
79
|
+
process.stderr.write(`report written to ${path}\n`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Producer-facade-ready probe.
|
|
3
|
+
*
|
|
4
|
+
* Opens the fixture's producer facade against the in-memory queue driver
|
|
5
|
+
* (the wrangler-dev-equivalent seam per US-29107, SDR-3-a), asserts
|
|
6
|
+
* producerReady fires on the injected event sink with queueName.
|
|
7
|
+
*
|
|
8
|
+
* Anchors AC-29101-1.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { createQueuePair } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/queue-driver.mjs';
|
|
12
|
+
import { createProducer, queueConfigFromEnv } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/producer.mjs';
|
|
13
|
+
|
|
14
|
+
export default async function runProbe() {
|
|
15
|
+
const cfg = queueConfigFromEnv();
|
|
16
|
+
const pair = createQueuePair({ queueName: cfg.queueName, dlqName: cfg.dlqName, maxRetries: cfg.maxRetries });
|
|
17
|
+
const events = [];
|
|
18
|
+
const producer = createProducer({
|
|
19
|
+
binding: pair.producer,
|
|
20
|
+
queueName: cfg.queueName,
|
|
21
|
+
onEvent: (e) => events.push(e),
|
|
22
|
+
});
|
|
23
|
+
const results = [];
|
|
24
|
+
await producer.ready;
|
|
25
|
+
const ready = events.find((e) => e.event === 'producerReady');
|
|
26
|
+
const pass = !!ready && ready.queueName === cfg.queueName && producer.isReady();
|
|
27
|
+
results.push({
|
|
28
|
+
anchorAcId: 'AC-29101-1',
|
|
29
|
+
verdict: pass ? 'pass' : 'fail',
|
|
30
|
+
detail: pass
|
|
31
|
+
? `producerReady fired with queueName=${ready.queueName}; producer.isReady()=true`
|
|
32
|
+
: `producerReady missing or wrong; events=${JSON.stringify(events)}`,
|
|
33
|
+
});
|
|
34
|
+
return results;
|
|
35
|
+
}
|