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,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply-time refusal probe.
|
|
3
|
+
*
|
|
4
|
+
* Invokes rcf define blueprint add ./blueprints/jobs-background on a
|
|
5
|
+
* fresh scratch project WITH NO applied queue provider. Asserts exit 3,
|
|
6
|
+
* greps stderr for [jobs-background-no-queue] tag on the first line,
|
|
7
|
+
* greps stderr for the explicit provider name messaging-queue-cloudflare,
|
|
8
|
+
* and greps stderr for the override flag --allow-no-queue-yet.
|
|
9
|
+
*
|
|
10
|
+
* Anchors AC-jobs-requiresQueue.
|
|
11
|
+
*
|
|
12
|
+
* Q3 default per spec section 10: asserts BOTH exit code AND stable
|
|
13
|
+
* message id.
|
|
14
|
+
*
|
|
15
|
+
* The bare scratch project is created under a scratch tmp directory
|
|
16
|
+
* (not committed). rcf-lite is invoked via its bin script.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { spawn } from 'node:child_process';
|
|
20
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
21
|
+
import { tmpdir } from 'node:os';
|
|
22
|
+
import { join, resolve, dirname } from 'node:path';
|
|
23
|
+
import { fileURLToPath } from 'node:url';
|
|
24
|
+
|
|
25
|
+
import { PROJECT_ROOT } from './probe-utils.mjs';
|
|
26
|
+
|
|
27
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const BLUEPRINT_DIR = resolve(HERE, '..', '..');
|
|
29
|
+
const RCF_BIN = resolve(PROJECT_ROOT, 'packages/rcf-lite/bin/rcf.js');
|
|
30
|
+
|
|
31
|
+
function runNode(args, opts = {}) {
|
|
32
|
+
return new Promise((resolveP) => {
|
|
33
|
+
const child = spawn(process.execPath, args, { stdio: ['ignore', 'pipe', 'pipe'], ...opts });
|
|
34
|
+
let stdout = '';
|
|
35
|
+
let stderr = '';
|
|
36
|
+
child.stdout.on('data', (b) => { stdout += b.toString('utf8'); });
|
|
37
|
+
child.stderr.on('data', (b) => { stderr += b.toString('utf8'); });
|
|
38
|
+
child.on('close', (code) => resolveP({ code, stdout, stderr }));
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default async function runProbe() {
|
|
43
|
+
const scratch = await mkdtemp(join(tmpdir(), 'jobs-bg-refuse-'));
|
|
44
|
+
try {
|
|
45
|
+
// 1. Init a bare rcf project (no applied blueprints).
|
|
46
|
+
const init = await runNode([RCF_BIN, 'init'], { cwd: scratch });
|
|
47
|
+
if (init.code !== 0) {
|
|
48
|
+
return [{
|
|
49
|
+
anchorAcId: 'AC-jobs-requiresQueue',
|
|
50
|
+
verdict: 'fail',
|
|
51
|
+
detail: `rcf init failed exit=${init.code} stderr=${init.stderr}`,
|
|
52
|
+
}];
|
|
53
|
+
}
|
|
54
|
+
// 2. Attempt to apply jobs-background on the bare project.
|
|
55
|
+
const apply = await runNode(
|
|
56
|
+
[RCF_BIN, 'define', 'blueprint', 'add', BLUEPRINT_DIR],
|
|
57
|
+
{ cwd: scratch },
|
|
58
|
+
);
|
|
59
|
+
const results = [];
|
|
60
|
+
const firstLine = apply.stderr.split('\n')[0] ?? '';
|
|
61
|
+
const tagMatch = firstLine.includes('[jobs-background-no-queue]');
|
|
62
|
+
const providerMatch = apply.stderr.includes('messaging-queue-cloudflare');
|
|
63
|
+
const overrideMatch = apply.stderr.includes('--allow-no-queue-yet');
|
|
64
|
+
const codeMatch = apply.code === 3;
|
|
65
|
+
const pass = codeMatch && tagMatch && providerMatch && overrideMatch;
|
|
66
|
+
results.push({
|
|
67
|
+
anchorAcId: 'AC-jobs-requiresQueue',
|
|
68
|
+
verdict: pass ? 'pass' : 'fail',
|
|
69
|
+
detail: pass
|
|
70
|
+
? `exit=${apply.code}; stderr first line carries [jobs-background-no-queue] tag; stderr names messaging-queue-cloudflare; stderr names --allow-no-queue-yet`
|
|
71
|
+
: `expected exit=3 AND first-line tag [jobs-background-no-queue] AND messaging-queue-cloudflare AND --allow-no-queue-yet; got exit=${apply.code}; firstLine='${firstLine}'; tagMatch=${tagMatch}; providerMatch=${providerMatch}; overrideMatch=${overrideMatch}`,
|
|
72
|
+
});
|
|
73
|
+
// Do NOT include the scratch dir path in the committed report; it is
|
|
74
|
+
// a per-run tmp path and would leak the machine's tmp naming into the
|
|
75
|
+
// gate-time evidence file.
|
|
76
|
+
return { results, extra: { exitCode: apply.code, stderrFirstLine: firstLine } };
|
|
77
|
+
} finally {
|
|
78
|
+
// rm -rf the scratch dir (deletion discipline: literal absolute
|
|
79
|
+
// scratch path created this call).
|
|
80
|
+
try { await rm(scratch, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event-secrecy probe.
|
|
3
|
+
*
|
|
4
|
+
* Schedules a job whose input carries a PII fixture body
|
|
5
|
+
* { userId: 1234, ssn: '123-45-6789', email: 'test@example.com' }.
|
|
6
|
+
* Drives the job through completion. Grep the serialised run-log event
|
|
7
|
+
* stream for every PII literal; asserts zero matches.
|
|
8
|
+
*
|
|
9
|
+
* Anchors AC-jobs-eventSecrecy.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { createQueuePair } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/queue-driver.mjs';
|
|
13
|
+
import { createProducer, queueConfigFromEnv } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/producer.mjs';
|
|
14
|
+
import { createRunLog } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/job-run-log.mjs';
|
|
15
|
+
import { loadJobs, createJobsRuntime } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/jobs-runtime.mjs';
|
|
16
|
+
import { createScheduler, createFakeClock } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/scheduler.mjs';
|
|
17
|
+
import { PROJECT_ROOT } from './probe-utils.mjs';
|
|
18
|
+
import { resolve } from 'node:path';
|
|
19
|
+
|
|
20
|
+
const PII_LITERALS = ['1234', '123-45-6789', 'test@example.com'];
|
|
21
|
+
const EVENT_WHITELIST = new Set(['event', 'jobId', 'jobName', 'attempts', 'duration', 'timestamp', 'terminalErrorCode']);
|
|
22
|
+
|
|
23
|
+
export default async function runProbe() {
|
|
24
|
+
const cfg = queueConfigFromEnv();
|
|
25
|
+
const pair = createQueuePair({ queueName: cfg.queueName, dlqName: cfg.dlqName, maxRetries: cfg.maxRetries });
|
|
26
|
+
const events = [];
|
|
27
|
+
const runLog = createRunLog({ upstream: (e) => events.push(e) });
|
|
28
|
+
const producer = createProducer({
|
|
29
|
+
binding: pair.producer,
|
|
30
|
+
queueName: cfg.queueName,
|
|
31
|
+
onEvent: () => {},
|
|
32
|
+
});
|
|
33
|
+
await producer.ready;
|
|
34
|
+
const jobsDir = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/infra-s3-and-queue/jobs');
|
|
35
|
+
const registry = await loadJobs(jobsDir);
|
|
36
|
+
const runtime = createJobsRuntime({
|
|
37
|
+
jobRegistry: registry,
|
|
38
|
+
runLog,
|
|
39
|
+
env: { SIMULATE_PII_IN_JOB_INPUT: 'true' },
|
|
40
|
+
});
|
|
41
|
+
const clock = createFakeClock(0);
|
|
42
|
+
const scheduler = createScheduler({ mode: 'inProcess', clock, publisher: producer, runLog });
|
|
43
|
+
scheduler.delayed({
|
|
44
|
+
jobName: 'send-welcome-email',
|
|
45
|
+
delayMs: 0,
|
|
46
|
+
input: { userId: 1234, ssn: '123-45-6789', email: 'test@example.com' },
|
|
47
|
+
});
|
|
48
|
+
clock.advance(1);
|
|
49
|
+
await scheduler.tick();
|
|
50
|
+
await runtime.drain({ driverState: pair.state, maxIterations: 8 });
|
|
51
|
+
const serialised = JSON.stringify(events);
|
|
52
|
+
const leaks = PII_LITERALS.filter((lit) => serialised.includes(lit));
|
|
53
|
+
const wrongKeys = new Set();
|
|
54
|
+
for (const ev of events) {
|
|
55
|
+
for (const k of Object.keys(ev)) {
|
|
56
|
+
if (!EVENT_WHITELIST.has(k)) wrongKeys.add(k);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const results = [];
|
|
60
|
+
const pass = leaks.length === 0 && wrongKeys.size === 0 && events.some((e) => e.event === 'jobCompleted');
|
|
61
|
+
results.push({
|
|
62
|
+
anchorAcId: 'AC-jobs-eventSecrecy',
|
|
63
|
+
verdict: pass ? 'pass' : 'fail',
|
|
64
|
+
detail: pass
|
|
65
|
+
? `no PII literal appears in the serialised run-log stream; every event carries only whitelisted keys ${JSON.stringify([...EVENT_WHITELIST])}; ${events.length} events recorded`
|
|
66
|
+
: `leaks=${JSON.stringify(leaks)}; wrongKeys=${JSON.stringify([...wrongKeys])}; events=${JSON.stringify(events)}`,
|
|
67
|
+
});
|
|
68
|
+
return { results, extra: { events, piiLiterals: PII_LITERALS } };
|
|
69
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fake-clock cron probe.
|
|
3
|
+
*
|
|
4
|
+
* Drives the fixture scheduler (inProcess mode with the fake-clock seam)
|
|
5
|
+
* plus the T-3 in-memory queue seam plus the T-4 jobs-runtime through
|
|
6
|
+
* one POSIX cron minute for the refresh-cache job. Asserts a jobStarted
|
|
7
|
+
* event fires on the injected run-log sink within the elicited
|
|
8
|
+
* fireToleranceMs window (default 30000 ms) with jobName 'refresh-cache'
|
|
9
|
+
* and attempts 1; asserts a jobCompleted event fires within the elicited
|
|
10
|
+
* timeoutMs (10000 ms for refresh-cache).
|
|
11
|
+
*
|
|
12
|
+
* Anchors AC-jobs-scheduledRunsOnCron.
|
|
13
|
+
*
|
|
14
|
+
* NOTE: this probe runs against the in-memory queue seam and the fake-
|
|
15
|
+
* clock, not a live wrangler dev process. The README's per-AC
|
|
16
|
+
* mechanism-reach section names the live-only follow-up per SDR-3-a.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { createQueuePair } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/queue-driver.mjs';
|
|
20
|
+
import { createProducer, queueConfigFromEnv } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/producer.mjs';
|
|
21
|
+
import { createRunLog } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/job-run-log.mjs';
|
|
22
|
+
import { loadJobs, createJobsRuntime } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/jobs-runtime.mjs';
|
|
23
|
+
import { createScheduler, createFakeClock } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/scheduler.mjs';
|
|
24
|
+
import { PROJECT_ROOT } from './probe-utils.mjs';
|
|
25
|
+
import { resolve } from 'node:path';
|
|
26
|
+
|
|
27
|
+
const FIRE_TOLERANCE_MS = 30000;
|
|
28
|
+
|
|
29
|
+
export default async function runProbe() {
|
|
30
|
+
const cfg = queueConfigFromEnv();
|
|
31
|
+
const pair = createQueuePair({ queueName: cfg.queueName, dlqName: cfg.dlqName, maxRetries: cfg.maxRetries });
|
|
32
|
+
const events = [];
|
|
33
|
+
const runLog = createRunLog({ upstream: (e) => events.push(e) });
|
|
34
|
+
const producer = createProducer({
|
|
35
|
+
binding: pair.producer,
|
|
36
|
+
queueName: cfg.queueName,
|
|
37
|
+
onEvent: () => {},
|
|
38
|
+
});
|
|
39
|
+
await producer.ready;
|
|
40
|
+
const jobsDir = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/infra-s3-and-queue/jobs');
|
|
41
|
+
const registry = await loadJobs(jobsDir);
|
|
42
|
+
const runtime = createJobsRuntime({ jobRegistry: registry, runLog, env: { ...process.env } });
|
|
43
|
+
const clock = createFakeClock(0);
|
|
44
|
+
const scheduler = createScheduler({ mode: 'inProcess', clock, publisher: producer, runLog });
|
|
45
|
+
scheduler.cron({ jobName: 'refresh-cache', cronString: '* * * * *', input: { cacheKey: 'demo' } });
|
|
46
|
+
// Advance clock past one cron minute; tick to publish.
|
|
47
|
+
clock.advance(60000);
|
|
48
|
+
const fires = await scheduler.tick();
|
|
49
|
+
// Drain runtime.
|
|
50
|
+
await runtime.drain({ driverState: pair.state, maxIterations: 16 });
|
|
51
|
+
const jobStarted = events.find((e) => e.event === 'jobStarted' && e.jobName === 'refresh-cache');
|
|
52
|
+
const jobCompleted = events.find((e) => e.event === 'jobCompleted' && e.jobName === 'refresh-cache');
|
|
53
|
+
const results = [];
|
|
54
|
+
const startPass = !!jobStarted && jobStarted.attempts === 1;
|
|
55
|
+
const durationOk = jobCompleted ? jobCompleted.duration <= registry.get('refresh-cache').timeoutMs : false;
|
|
56
|
+
const pass = fires === 1 && startPass && !!jobCompleted && durationOk;
|
|
57
|
+
results.push({
|
|
58
|
+
anchorAcId: 'AC-jobs-scheduledRunsOnCron',
|
|
59
|
+
verdict: pass ? 'pass' : 'fail',
|
|
60
|
+
detail: pass
|
|
61
|
+
? `fires=1; jobStarted refresh-cache attempts=1 within fireToleranceMs=${FIRE_TOLERANCE_MS}; jobCompleted duration=${jobCompleted.duration}ms within timeoutMs=${registry.get('refresh-cache').timeoutMs}`
|
|
62
|
+
: `fires=${fires}; jobStarted=${JSON.stringify(jobStarted)}; jobCompleted=${JSON.stringify(jobCompleted)}; durationOk=${durationOk}`,
|
|
63
|
+
});
|
|
64
|
+
return { results, extra: { events, fireToleranceMs: FIRE_TOLERANCE_MS } };
|
|
65
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for jobs-background probes.
|
|
3
|
+
*
|
|
4
|
+
* Runtime-dependency posture: probes import the fixture's in-memory
|
|
5
|
+
* queue-driver plus the T-4 jobs-runtime, scheduler and run-log from the
|
|
6
|
+
* sample-app fixture's src/ tree so rcf-lite itself gains no new runtime
|
|
7
|
+
* dependency (round-5 spec section 5, brief section 4). The T-3
|
|
8
|
+
* in-memory queue-driver realises the Cloudflare Queues binding shape;
|
|
9
|
+
* the T-4 jobs-runtime consumes messages from the driver, dispatches to
|
|
10
|
+
* job-definition modules, and fires the four lifecycle events on the
|
|
11
|
+
* T-4-owned run-log sink (whitelist { event, jobId, jobName, attempts,
|
|
12
|
+
* duration, timestamp } plus optional terminalErrorCode).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
16
|
+
import { dirname, resolve } from 'node:path';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
|
|
19
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
|
|
21
|
+
// Project root four levels above blueprints/jobs-background/contributions/probes/
|
|
22
|
+
export const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
|
|
23
|
+
export const FIXTURE_DIR = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/infra-s3-and-queue');
|
|
24
|
+
export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/jobs-background');
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Compute the aggregate verdict per spec section 3.4:
|
|
28
|
+
* - fail if any result carries verdict fail
|
|
29
|
+
* - warn if any result carries verdict warn and no fail
|
|
30
|
+
* - pass otherwise
|
|
31
|
+
*/
|
|
32
|
+
export function aggregate(results) {
|
|
33
|
+
if (results.some((r) => r.verdict === 'fail')) return 'fail';
|
|
34
|
+
if (results.some((r) => r.verdict === 'warn')) return 'warn';
|
|
35
|
+
return 'pass';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Write the per-blueprint probe report at
|
|
40
|
+
* .rcf/reports/blueprints/jobs-background/<probeName>.json
|
|
41
|
+
* per spec section 3.4.
|
|
42
|
+
*/
|
|
43
|
+
export async function writeReport({ probeName, engine, results, extra = {} }) {
|
|
44
|
+
await mkdir(REPORT_DIR, { recursive: true });
|
|
45
|
+
const report = {
|
|
46
|
+
slug: 'jobs-background',
|
|
47
|
+
probeName,
|
|
48
|
+
runAt: new Date().toISOString(),
|
|
49
|
+
engine,
|
|
50
|
+
results,
|
|
51
|
+
aggregateVerdict: aggregate(results),
|
|
52
|
+
...extra,
|
|
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, extra } = normaliseMain(await mainFn());
|
|
66
|
+
const { report, path } = await writeReport({ probeName, engine, results, extra });
|
|
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
|
+
}
|
|
83
|
+
|
|
84
|
+
function normaliseMain(value) {
|
|
85
|
+
if (Array.isArray(value)) return { results: value, extra: {} };
|
|
86
|
+
if (value && Array.isArray(value.results)) {
|
|
87
|
+
const { results, ...extra } = value;
|
|
88
|
+
return { results, extra };
|
|
89
|
+
}
|
|
90
|
+
throw new Error('probe main must return an array or an object with a results[] field');
|
|
91
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry-and-fail probe.
|
|
3
|
+
*
|
|
4
|
+
* With SIMULATE_HANDLER_THROW=true on the shared fixture, the jobs-runtime
|
|
5
|
+
* throws a retryable error on every dispatch. Schedules a one-shot job
|
|
6
|
+
* with send-welcome-email's maxAttempts=3. Drives the driver's delivery
|
|
7
|
+
* loop until the message either terminals or DLQs. Asserts three
|
|
8
|
+
* jobStarted events with the same jobId and attempts 1, 2, 3 followed by
|
|
9
|
+
* a terminal jobFailed with a terminalErrorCode.
|
|
10
|
+
*
|
|
11
|
+
* Anchors AC-jobs-retryOnHandlerFailure.
|
|
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 { createRunLog } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/job-run-log.mjs';
|
|
17
|
+
import { loadJobs, createJobsRuntime } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/jobs-runtime.mjs';
|
|
18
|
+
import { createScheduler, createFakeClock } from '../../../../packages/rcf-lite/test/fixtures/infra-s3-and-queue/src/scheduler.mjs';
|
|
19
|
+
import { PROJECT_ROOT } from './probe-utils.mjs';
|
|
20
|
+
import { resolve } from 'node:path';
|
|
21
|
+
|
|
22
|
+
export default async function runProbe() {
|
|
23
|
+
const cfg = queueConfigFromEnv();
|
|
24
|
+
// maxRetries on the driver matches send-welcome-email.maxAttempts=3.
|
|
25
|
+
const pair = createQueuePair({ queueName: cfg.queueName, dlqName: cfg.dlqName, maxRetries: 3 });
|
|
26
|
+
const events = [];
|
|
27
|
+
const runLog = createRunLog({ upstream: (e) => events.push(e) });
|
|
28
|
+
const producer = createProducer({
|
|
29
|
+
binding: pair.producer,
|
|
30
|
+
queueName: cfg.queueName,
|
|
31
|
+
onEvent: () => {},
|
|
32
|
+
});
|
|
33
|
+
await producer.ready;
|
|
34
|
+
const jobsDir = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/infra-s3-and-queue/jobs');
|
|
35
|
+
const registry = await loadJobs(jobsDir);
|
|
36
|
+
const runtime = createJobsRuntime({
|
|
37
|
+
jobRegistry: registry,
|
|
38
|
+
runLog,
|
|
39
|
+
env: { SIMULATE_HANDLER_THROW: 'true' },
|
|
40
|
+
});
|
|
41
|
+
const clock = createFakeClock(0);
|
|
42
|
+
const scheduler = createScheduler({ mode: 'inProcess', clock, publisher: producer, runLog });
|
|
43
|
+
scheduler.delayed({ jobName: 'send-welcome-email', delayMs: 0, input: { userId: 7, email: 'ok@example.com' } });
|
|
44
|
+
clock.advance(1);
|
|
45
|
+
await scheduler.tick();
|
|
46
|
+
await runtime.drain({ driverState: pair.state, maxIterations: 32 });
|
|
47
|
+
const jobStartedEvents = events.filter((e) => e.event === 'jobStarted' && e.jobName === 'send-welcome-email');
|
|
48
|
+
const jobFailed = events.find((e) => e.event === 'jobFailed' && e.jobName === 'send-welcome-email');
|
|
49
|
+
const attemptsSeq = jobStartedEvents.map((e) => e.attempts);
|
|
50
|
+
const jobIds = new Set(jobStartedEvents.map((e) => e.jobId));
|
|
51
|
+
const dlqInvoked = pair.state.dlq.length > 0;
|
|
52
|
+
const results = [];
|
|
53
|
+
const attemptsOk = attemptsSeq.length === 3 && attemptsSeq[0] === 1 && attemptsSeq[1] === 2 && attemptsSeq[2] === 3;
|
|
54
|
+
const oneJobId = jobIds.size === 1;
|
|
55
|
+
const failedOk = !!jobFailed && typeof jobFailed.terminalErrorCode === 'string';
|
|
56
|
+
const pass = attemptsOk && oneJobId && failedOk;
|
|
57
|
+
results.push({
|
|
58
|
+
anchorAcId: 'AC-jobs-retryOnHandlerFailure',
|
|
59
|
+
verdict: pass ? 'pass' : 'fail',
|
|
60
|
+
detail: pass
|
|
61
|
+
? `three jobStarted events attempts=[1,2,3] same jobId; jobFailed carries terminalErrorCode=${jobFailed.terminalErrorCode}`
|
|
62
|
+
: `attemptsSeq=${JSON.stringify(attemptsSeq)}; jobIds.size=${jobIds.size}; jobFailed=${JSON.stringify(jobFailed)}`,
|
|
63
|
+
});
|
|
64
|
+
return { results, extra: { events, dlqInvoked, attemptsSeq } };
|
|
65
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shim: run apply-time-override against a scratch bare project and
|
|
3
|
+
* write .rcf/reports/blueprints/jobs-background/apply-time-override.json.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import runProbe from './apply-time-override.mjs';
|
|
7
|
+
import { runShim } from './probe-utils.mjs';
|
|
8
|
+
|
|
9
|
+
const engine = { kind: 'cli', tool: 'rcf define blueprint add --allow-no-queue-yet (bare scratch project)', healthy: true };
|
|
10
|
+
runShim('apply-time-override', engine, runProbe);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shim: run apply-time-refusal against a scratch project (bare init, no
|
|
3
|
+
* applied blueprints) and write
|
|
4
|
+
* .rcf/reports/blueprints/jobs-background/apply-time-refusal.json.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import runProbe from './apply-time-refusal.mjs';
|
|
8
|
+
import { runShim } from './probe-utils.mjs';
|
|
9
|
+
|
|
10
|
+
const engine = { kind: 'cli', tool: 'rcf define blueprint add (bare scratch project)', healthy: true };
|
|
11
|
+
runShim('apply-time-refusal', engine, runProbe);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shim: run event-secrecy against the fixture jobs-runtime + in-memory
|
|
3
|
+
* queue seam with a PII fixture input and write
|
|
4
|
+
* .rcf/reports/blueprints/jobs-background/event-secrecy.json.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import runProbe from './event-secrecy.mjs';
|
|
8
|
+
import { runShim } from './probe-utils.mjs';
|
|
9
|
+
|
|
10
|
+
const engine = { kind: 'queues+jobs', image: 'cloudflare/wrangler-dev-equivalent (in-memory driver) + jobs-runtime SIMULATE_PII_IN_JOB_INPUT=true', healthy: true };
|
|
11
|
+
runShim('event-secrecy', engine, runProbe);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shim: run fake-clock-cron against the fixture's in-memory queue seam +
|
|
3
|
+
* fake-clock scheduler + jobs-runtime and write
|
|
4
|
+
* .rcf/reports/blueprints/jobs-background/fake-clock-cron.json.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import runProbe from './fake-clock-cron.mjs';
|
|
8
|
+
import { runShim } from './probe-utils.mjs';
|
|
9
|
+
|
|
10
|
+
const engine = { kind: 'queues+scheduler', image: 'cloudflare/wrangler-dev-equivalent (in-memory driver) + inProcess scheduler with injected fake clock', healthy: true };
|
|
11
|
+
runShim('fake-clock-cron', engine, runProbe);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shim: run retry-and-fail against the fixture jobs-runtime + in-memory
|
|
3
|
+
* queue seam and write
|
|
4
|
+
* .rcf/reports/blueprints/jobs-background/retry-and-fail.json.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import runProbe from './retry-and-fail.mjs';
|
|
8
|
+
import { runShim } from './probe-utils.mjs';
|
|
9
|
+
|
|
10
|
+
const engine = { kind: 'queues+jobs', image: 'cloudflare/wrangler-dev-equivalent (in-memory driver) + jobs-runtime SIMULATE_HANDLER_THROW=true', healthy: true };
|
|
11
|
+
runShim('retry-and-fail', engine, runProbe);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "jobs-background-REQ-001",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Requires an applied queue capability; refuses apply on a bare project with exit 3 and the stable message id jobs-background-no-queue",
|
|
5
|
+
"description": "The jobs-background blueprint composes on an applied queue capability via the T-5 mechanism from the visual round. The apply verb refuses on a bare project (no applied blueprint declares capabilities: [queue]) with exit code 3 and a stable, dashboard-friendly message id jobs-background-no-queue on the first stderr line. The refusal message also names the shipped provider messaging-queue-cloudflare and the override flag --allow-no-queue-yet explicitly, per infra round 5 spec section 10 Q3 default asserting BOTH exit code AND stable message id. The override flag records a note on the sidecar rcf/blueprints/jobs-background.applied.json under the queue family so rcf define validate later flags surfaces gated on queue that never activated.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "jobs",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "A stable message id is the operator-facing surface an autolint or dashboard binds to; asserting it in the probe pins the id against silent drift. The override flag lets a project scaffold without the queue applied yet, provided the note lands so a later validation pass can flag the gap. The queue provider is named explicitly so an operator hitting the refusal has the shipped answer in hand without a shelf-wide grep.",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:jobs-background",
|
|
12
|
+
"category:00-composition"
|
|
13
|
+
],
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"status": "approved",
|
|
16
|
+
"createdAt": "2026-09-06T20:30:00.000Z",
|
|
17
|
+
"updatedAt": "2026-09-06T20:30:00.000Z"
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "jobs-background-REQ-002",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Job-definition contract: name, handler, input schema (opaque per project), retry policy, timeout",
|
|
5
|
+
"description": "A job definition is a module in the applying project's jobs directory (default ./jobs/, elicited at apply time) exporting a shape { name, handler, inputSchema, retryPolicy, timeoutMs }. Name is a stable string; handler is an async function receiving the message body and returning a value or throwing; inputSchema is opaque per project (the applying project's own validation library); retryPolicy is { maxAttempts, backoff }; timeoutMs is a positive integer (default 60000, floor 1000, ceiling bounded by the applied queue consumer wall-clock ceiling per ADR-3104). The jobs runtime registers every job at boot on the applied queue consumer and dispatches by name.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "jobs",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "A one-shape job definition keeps the discipline uniform across the applying project's job modules; the applying project owns input validation without the blueprint prescribing a validation library.",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:jobs-background",
|
|
12
|
+
"category:01-definition"
|
|
13
|
+
],
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"status": "approved",
|
|
16
|
+
"createdAt": "2026-09-06T20:30:00.000Z",
|
|
17
|
+
"updatedAt": "2026-09-06T20:30:00.000Z"
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "jobs-background-REQ-003",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Scheduler contract: POSIX cron string and one-shot delayed",
|
|
5
|
+
"description": "The scheduler surface accepts two schedule shapes: a POSIX cron string (five fields, per POSIX cron) attached to a job definition for recurring runs, and a one-shot delayed schedule with an ISO-8601 fireAt or a positive delayMs. The scheduler publishes a message to the applied queue at the elicited fire time; the jobs runtime consumes and dispatches. The scheduler mode is elicited at apply time under ADR-3102 (inProcess, workerCron, external) and a reserved workflows value ships in the v1.1.0 minor per section 5.7 of the spec.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "jobs",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "POSIX cron is the widely understood recurring surface; one-shot delayed covers the deferred-send / retry-later case without a second contract. The elicited mode keeps the shipped facade portable across Node long-lived processes, Cloudflare Cron Triggers, and external cron runners without a facade re-shape.",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:jobs-background",
|
|
12
|
+
"category:02-scheduler"
|
|
13
|
+
],
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"status": "approved",
|
|
16
|
+
"createdAt": "2026-09-06T20:30:00.000Z",
|
|
17
|
+
"updatedAt": "2026-09-06T20:30:00.000Z"
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "jobs-background-REQ-004",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Retry contract: handler throws retryable error re-delivers via the applied queue; max-attempts elicited within the applied queue's own ceiling",
|
|
5
|
+
"description": "A handler that throws a retryable error causes the applied queue to redeliver the message per its own retry contract; the jobs runtime records the attempt counter on each jobStarted event and inherits max-attempts from the applied queue's own ceiling (Cloudflare Queues ceiling 100 per ADR-3003 in the messaging-queue-cloudflare blueprint). The elicited retryPolicy on a job definition ({ maxAttempts, backoff: constant | exponential | linear }) is applied within that ceiling. After maxAttempts terminal jobStarted events with the same jobId and incrementing attempt counter, jobFailed lands with the terminal error code and no further re-delivery.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "jobs",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "Retry inheritance from the applied queue keeps the transport authority in one place (the queue's own contract) while letting the job author express the domain retry surface (backoff shape, max-attempts within the ceiling).",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:jobs-background",
|
|
12
|
+
"category:03-retry"
|
|
13
|
+
],
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"status": "approved",
|
|
16
|
+
"createdAt": "2026-09-06T20:30:00.000Z",
|
|
17
|
+
"updatedAt": "2026-09-06T20:30:00.000Z"
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "jobs-background-REQ-005",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Job-run event log: jobScheduled, jobStarted, jobCompleted, jobFailed with metadata-only fields",
|
|
5
|
+
"description": "The jobs runtime fires four lifecycle events on the injected event sink: jobScheduled at the moment the scheduler enqueues a message; jobStarted at the moment the consumer begins dispatching a message to a handler; jobCompleted at the moment a handler returns without throwing; jobFailed at the moment the applied queue's max-attempts is exhausted with a terminal error code. Each event record carries only the metadata fields { jobId, jobName, attempts, duration, timestamp } (plus a terminalErrorCode on jobFailed). No job input fields, no handler output fields, no user id, no email, no SSN. The event whitelist is enforced at the sink boundary.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "jobs",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "A metadata-only event log lets the applying project route the events through its logging surface without leaking domain PII by default. Domain-side observability (recording the input, the output, the error surface) is the applying project's own concern under its logging companion.",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:jobs-background",
|
|
12
|
+
"category:04-run-log"
|
|
13
|
+
],
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"status": "approved",
|
|
16
|
+
"createdAt": "2026-09-06T20:30:00.000Z",
|
|
17
|
+
"updatedAt": "2026-09-06T20:30:00.000Z"
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "jobs-background-REQ-006",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Operator-facing surface (elicited): cli, httpEndpoint, or none",
|
|
5
|
+
"description": "The operator-facing surface for triggering ad-hoc runs, inspecting the run log, and re-driving a failed job is elicited at apply time between three shipped shapes: cli (a Node CLI shim the applying project builds against the jobs runtime), httpEndpoint (a small HTTP surface the applying project mounts through its own HTTP shape), or none (no operator surface; the run log is the only observability). The blueprint does not ship the CLI or the HTTP endpoint itself; it ships the contract they build against so the applying project can hoist a thin surface without a facade re-shape.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "jobs",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "Operator surfaces sit above the run-log contract but their exact shape varies by applying project (CLI-first estates vs HTTP-first APIs). The elicited choice records the answer without prescribing a UI framework or an HTTP router.",
|
|
10
|
+
"tags": [
|
|
11
|
+
"blueprint:jobs-background",
|
|
12
|
+
"category:05-operator-surface"
|
|
13
|
+
],
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"status": "approved",
|
|
16
|
+
"createdAt": "2026-09-06T20:30:00.000Z",
|
|
17
|
+
"updatedAt": "2026-09-06T20:30:00.000Z"
|
|
18
|
+
}
|
package/blueprints/jobs-background/contributions/tacs/tac-3101-jobs-background-job-definition.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tacId": "TAC-3101-jobs-background-job-definition",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"name": "Jobs-background job-definition module contract",
|
|
8
|
+
"purpose": "The shape every job-definition module in the applying project's jobs directory exports. One shape carries name, handler, inputSchema (opaque per project), retryPolicy, and timeoutMs. The jobs runtime registers every job at boot on the applied queue consumer and dispatches by name.",
|
|
9
|
+
"responsibilities": [
|
|
10
|
+
"Declare a job by exporting { name, handler, inputSchema, retryPolicy, timeoutMs } (AC-30102-1, AC-jobs-retryOnHandlerFailure).",
|
|
11
|
+
"Bound handler wall-clock via timeoutMs; jobs runtime cancels a handler that exceeds timeoutMs and treats it as a retryable error (AC-jobs-retryOnHandlerFailure).",
|
|
12
|
+
"Respect the applied queue's max-attempts ceiling; retryPolicy.maxAttempts must not exceed the ceiling (AC-jobs-retryOnHandlerFailure).",
|
|
13
|
+
"Refuse composition on a bare project via the requiresAppliedCapabilities gate (AC-jobs-requiresQueue)."
|
|
14
|
+
],
|
|
15
|
+
"internalStructure": "Each job module in the applying project's jobs/ directory (default ./jobs/, elicited) exports a plain object. The jobs runtime scans the directory at boot, validates the shape, and registers handlers keyed by name on the applied queue consumer's dispatch table. Dispatch is by message.name; no runtime type reflection.",
|
|
16
|
+
"interfaces": [
|
|
17
|
+
{
|
|
18
|
+
"name": "jobModule.default",
|
|
19
|
+
"kind": "shape",
|
|
20
|
+
"description": "The default export shape: { name: string, handler: async (input) => any, inputSchema: opaque, retryPolicy: { maxAttempts: positive integer, backoff: 'exponential' | 'constant' | 'linear' }, timeoutMs: positive integer }."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "registerJobs",
|
|
24
|
+
"kind": "factory",
|
|
25
|
+
"description": "The jobs runtime entry point: registerJobs({ jobsDir, queueConsumer, onEvent }) reads jobModule files, validates the shape, and registers dispatch handlers."
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"dependencies": [
|
|
29
|
+
{
|
|
30
|
+
"name": "Scheduler",
|
|
31
|
+
"kind": "tac",
|
|
32
|
+
"tacId": "TAC-3102-jobs-background-scheduler",
|
|
33
|
+
"description": "The scheduler enqueues messages by job name; the job-definition module is the target."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "Run log",
|
|
37
|
+
"kind": "tac",
|
|
38
|
+
"tacId": "TAC-3103-jobs-background-run-log",
|
|
39
|
+
"description": "The runtime fires the four lifecycle events on the injected event sink for every dispatch."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "Applied queue capability",
|
|
43
|
+
"kind": "external",
|
|
44
|
+
"description": "Composed on the applied blueprint declaring capabilities: [queue] via the T-5 mechanism; refuses apply on a bare project per REQ-001."
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"tradeoffs": "The v1.0.0 job-definition shape does not prescribe an inputSchema validator; the applying project owns validation. A later minor could add an optional validate hook if a shipped validation library becomes the shelf default. The dispatch table is by job name; two modules exporting the same name collide at boot and refuse.",
|
|
48
|
+
"createdAt": "2026-09-06T20:30:00.000Z",
|
|
49
|
+
"updatedAt": "2026-09-06T20:30:00.000Z"
|
|
50
|
+
}
|