rcf-lite 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +10 -0
- package/bin/rcf.js +2 -0
- package/blueprints/application-account-settings/CHANGELOG.md +35 -6
- package/blueprints/application-account-settings/README.md +1 -1
- package/blueprints/application-account-settings/blueprint.json +4 -2
- package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +1 -1
- package/blueprints/application-account-settings/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-account-settings/contributions/probes/profile-form-autocomplete.mjs +67 -0
- package/blueprints/application-account-settings/contributions/probes/run-profile-form-autocomplete.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-adapter-uniform.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-surface-shape.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-shell-tablist-per-capability.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-theme-radiogroup.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-adapter-uniform.mjs +130 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-surface-shape.mjs +70 -0
- package/blueprints/application-account-settings/contributions/probes/shell-tablist-per-capability.mjs +60 -0
- package/blueprints/application-account-settings/contributions/probes/theme-radiogroup.mjs +126 -0
- package/blueprints/application-admin-console/CHANGELOG.md +32 -6
- package/blueprints/application-admin-console/README.md +1 -1
- package/blueprints/application-admin-console/blueprint.json +4 -2
- package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +1 -1
- package/blueprints/application-admin-console/contributions/probes/audit-log-surface.mjs +79 -0
- package/blueprints/application-admin-console/contributions/probes/org-switcher-surface.mjs +83 -0
- package/blueprints/application-admin-console/contributions/probes/permission-matrix-grid.mjs +67 -0
- package/blueprints/application-admin-console/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-admin-console/contributions/probes/run-audit-log-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-org-switcher-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-permission-matrix-grid.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-sign-in-access-gated-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-users-directory-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/sign-in-access-gated-surface.mjs +117 -0
- package/blueprints/application-admin-console/contributions/probes/users-directory-surface.mjs +145 -0
- package/blueprints/application-api-rest/CHANGELOG.md +16 -8
- package/blueprints/application-api-rest/README.md +3 -3
- package/blueprints/application-api-rest/blueprint.json +3 -2
- package/blueprints/application-api-rest/contributions/adrs/adr-302-application-api-rest-auth-model.json +1 -1
- package/blueprints/application-api-rest/contributions/probes/cursor-pagination-round-trip.mjs +154 -0
- package/blueprints/application-api-rest/contributions/probes/health-probes-distinct.mjs +124 -0
- package/blueprints/application-api-rest/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-api-rest/contributions/probes/problem-details-on-error.mjs +77 -0
- package/blueprints/application-api-rest/contributions/probes/request-id-echoed.mjs +76 -0
- package/blueprints/application-api-rest/contributions/probes/run-cursor-pagination-round-trip.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-health-probes-distinct.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-problem-details-on-error.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-request-id-echoed.mjs +5 -0
- package/blueprints/application-api-rest/docs/topics.md +1 -1
- package/blueprints/application-charts/CHANGELOG.md +35 -9
- package/blueprints/application-charts/README.md +6 -6
- package/blueprints/application-charts/blueprint.json +5 -3
- package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +1 -1
- package/blueprints/application-charts/contributions/probes/keyboard-traversal.mjs +151 -0
- package/blueprints/application-charts/contributions/probes/non-colour-distinction.mjs +67 -0
- package/blueprints/application-charts/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-charts/contributions/probes/run-keyboard-traversal.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-non-colour-distinction.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-text-alternative-table.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/text-alternative-table.mjs +139 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +1 -1
- package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +1 -1
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +5 -5
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +1 -1
- package/blueprints/application-charts/guide/application-charts.md +1 -1
- package/blueprints/application-dashboard/CHANGELOG.md +20 -10
- package/blueprints/application-dashboard/README.md +6 -6
- package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +2 -2
- package/blueprints/application-dashboard/blueprint.json +3 -2
- package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +1 -1
- package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +1 -1
- package/blueprints/application-dashboard/contributions/probes/export-handle-formats.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/four-tile-states.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/primary-kpi-top-left.mjs +58 -0
- package/blueprints/application-dashboard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-dashboard/contributions/probes/run-export-handle-formats.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-four-tile-states.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-primary-kpi-top-left.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-shell-five-regions.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/shell-five-regions.mjs +93 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +1 -1
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +5 -5
- package/blueprints/application-dashboard/docs/topics.md +2 -2
- package/blueprints/application-dashboard/guide/application-dashboard.md +2 -2
- package/blueprints/application-datatable/CHANGELOG.md +19 -9
- package/blueprints/application-datatable/README.md +2 -2
- package/blueprints/application-datatable/blueprint.json +3 -2
- package/blueprints/application-datatable/contributions/probes/apg-table-shape.mjs +57 -0
- package/blueprints/application-datatable/contributions/probes/four-states-regions.mjs +80 -0
- package/blueprints/application-datatable/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-datatable/contributions/probes/run-apg-table-shape.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-four-states-regions.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-search-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-sort-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/search-adapter-round-trip.mjs +58 -0
- package/blueprints/application-datatable/contributions/probes/sort-adapter-round-trip.mjs +60 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +1 -1
- package/blueprints/application-datatable/docs/topics.md +1 -1
- package/blueprints/application-empty-error-states/CHANGELOG.md +33 -3
- package/blueprints/application-empty-error-states/blueprint.json +4 -2
- package/blueprints/application-empty-error-states/contributions/probes/empty-list-and-no-search.mjs +66 -0
- package/blueprints/application-empty-error-states/contributions/probes/error-boundary-alert.mjs +65 -0
- package/blueprints/application-empty-error-states/contributions/probes/forbidden-and-server-error.mjs +167 -0
- package/blueprints/application-empty-error-states/contributions/probes/not-found-and-recovery.mjs +61 -0
- package/blueprints/application-empty-error-states/contributions/probes/permission-denied-and-offline.mjs +155 -0
- package/blueprints/application-empty-error-states/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-empty-list-and-no-search.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-error-boundary-alert.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-forbidden-and-server-error.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-not-found-and-recovery.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-permission-denied-and-offline.mjs +5 -0
- package/blueprints/application-error-handling/CHANGELOG.md +45 -6
- package/blueprints/application-error-handling/blueprint.json +3 -2
- package/blueprints/application-error-handling/contributions/probes/category-vocabulary.mjs +90 -0
- package/blueprints/application-error-handling/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-error-handling/contributions/probes/record-shape-adr-1701.mjs +78 -0
- package/blueprints/application-error-handling/contributions/probes/run-category-vocabulary.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-record-shape-adr-1701.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-two-boundaries-registered.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/two-boundaries-registered.mjs +343 -0
- package/blueprints/application-file-upload/CHANGELOG.md +28 -6
- package/blueprints/application-file-upload/README.md +1 -1
- package/blueprints/application-file-upload/blueprint.json +3 -2
- package/blueprints/application-file-upload/contributions/probes/assertive-completion-slot.mjs +78 -0
- package/blueprints/application-file-upload/contributions/probes/chunked-transport-endpoints.mjs +173 -0
- package/blueprints/application-file-upload/contributions/probes/per-file-progressbar.mjs +124 -0
- package/blueprints/application-file-upload/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-file-upload/contributions/probes/run-assertive-completion-slot.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-chunked-transport-endpoints.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-per-file-progressbar.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-upload-surface-shape.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/upload-surface-shape.mjs +55 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +1 -1
- package/blueprints/application-file-upload/probe-packs/application-file-upload.pack.mjs +1 -1
- package/blueprints/application-forms-wizard/CHANGELOG.md +20 -6
- package/blueprints/application-forms-wizard/README.md +2 -2
- package/blueprints/application-forms-wizard/blueprint.json +3 -2
- package/blueprints/application-forms-wizard/contributions/probes/draft-persistence-round-trip.mjs +110 -0
- package/blueprints/application-forms-wizard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-draft-persistence-round-trip.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-step-page-shape.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-task-list-surface.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/step-page-shape.mjs +61 -0
- package/blueprints/application-forms-wizard/contributions/probes/task-list-surface.mjs +109 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +1 -1
- package/blueprints/application-forms-wizard/probe-packs/application-forms-wizard.pack.mjs +1 -1
- package/blueprints/application-notifications-in-app/CHANGELOG.md +38 -5
- package/blueprints/application-notifications-in-app/README.md +4 -4
- package/blueprints/application-notifications-in-app/blueprint.json +4 -2
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/probes/centre-acknowledge-round-trip.mjs +210 -0
- package/blueprints/application-notifications-in-app/contributions/probes/live-region-preseeding.mjs +93 -0
- package/blueprints/application-notifications-in-app/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-centre-acknowledge-round-trip.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-live-region-preseeding.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-toast-contract.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/toast-contract.mjs +92 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +3 -3
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +1 -1
- package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +3 -3
- package/blueprints/application-onboarding-tour/CHANGELOG.md +31 -5
- package/blueprints/application-onboarding-tour/README.md +1 -1
- package/blueprints/application-onboarding-tour/blueprint.json +5 -3
- package/blueprints/application-onboarding-tour/contributions/probes/checklist-anchor-open.mjs +81 -0
- package/blueprints/application-onboarding-tour/contributions/probes/completion-persistence.mjs +159 -0
- package/blueprints/application-onboarding-tour/contributions/probes/first-run-detection.mjs +67 -0
- package/blueprints/application-onboarding-tour/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-checklist-anchor-open.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-completion-persistence.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-first-run-detection.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-stepper-role-dialog.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/stepper-role-dialog.mjs +45 -0
- package/blueprints/application-spa/CHANGELOG.md +20 -11
- package/blueprints/application-spa/README.md +9 -10
- package/blueprints/application-spa/blueprint.json +3 -2
- package/blueprints/application-spa/contributions/adrs/adr-202-application-spa-theming.json +1 -1
- package/blueprints/application-spa/contributions/adrs/adr-206-application-spa-iconography.json +1 -1
- package/blueprints/application-spa/contributions/probes/designed-empty-state.mjs +72 -0
- package/blueprints/application-spa/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-spa/contributions/probes/route-inventory-published.mjs +185 -0
- package/blueprints/application-spa/contributions/probes/run-designed-empty-state.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-route-inventory-published.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-shell-nav-present.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/shell-nav-present.mjs +69 -0
- package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +1 -1
- package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +3 -3
- package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +2 -2
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +1 -1
- package/blueprints/application-spa/docs/topics.md +1 -1
- package/blueprints/delivery-ci-workflows/CHANGELOG.md +31 -11
- package/blueprints/delivery-ci-workflows/README.md +3 -3
- package/blueprints/delivery-ci-workflows/blueprint.json +3 -2
- package/blueprints/delivery-ci-workflows/contributions/adrs/adr-702-delivery-ci-workflows-strict-coverage-gate.json +2 -2
- package/blueprints/delivery-ci-workflows/contributions/probes/node-gate-entrypoint.mjs +76 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/probe-utils.mjs +56 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/real-account-github-actions-run-record.mjs +139 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-node-gate-entrypoint.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-real-account-github-actions-run-record.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-workflow-template-shape.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/workflow-template-shape.mjs +94 -0
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-004.json +1 -1
- package/blueprints/delivery-ci-workflows/docs/topics.md +2 -3
- package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +4 -4
- package/blueprints/deploy-cloudflare-workers/README.md +3 -3
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +2 -2
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +2 -2
- package/blueprints/deploy-hetzner-server/CHANGELOG.md +98 -7
- package/blueprints/deploy-hetzner-server/blueprint.json +7 -6
- package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +46 -21
- package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +344 -83
- package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +211 -42
- package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +140 -22
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +111 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +158 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +154 -32
- package/blueprints/edge-cloudflare-access/CHANGELOG.md +6 -5
- package/blueprints/edge-cloudflare-access/blueprint.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +9 -1
- package/blueprints/edge-cloudflare-access/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +4 -7
- package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +4 -6
- package/blueprints/edge-cloudflare-tunnel/README.md +1 -2
- package/blueprints/edge-cloudflare-tunnel/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +2 -3
- package/blueprints/edge-cloudflare-turnstile/docs/topics.md +1 -1
- package/blueprints/email-smtp-resend/CHANGELOG.md +24 -8
- package/blueprints/email-smtp-resend/README.md +2 -2
- package/blueprints/email-smtp-resend/blueprint.json +3 -2
- package/blueprints/email-smtp-resend/contributions/probes/probe-utils.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/real-account-resend-send.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-real-account-resend-send.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-smtp-round-trip.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-unverified-sender-refusal.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/smtp-round-trip.mjs +43 -0
- package/blueprints/email-smtp-resend/contributions/probes/unverified-sender-refusal.mjs +99 -0
- package/blueprints/email-smtp-resend/docs/topics.md +2 -3
- package/blueprints/jobs-background/CHANGELOG.md +66 -5
- package/blueprints/jobs-background/README.md +2 -2
- package/blueprints/jobs-background/blueprint.json +3 -2
- package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +38 -10
- package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +28 -6
- package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +16 -2
- package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +102 -21
- package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +10 -2
- package/blueprints/jobs-background/contributions/probes/retry-and-fail-real-account.mjs +355 -0
- package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +33 -2
- package/blueprints/jobs-background/contributions/probes/run-retry-and-fail-real-account.mjs +12 -0
- package/blueprints/jobs-background/docs/topics.md +1 -1
- package/blueprints/jobs-background/guide/jobs-background.md +1 -1
- package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +25 -19
- package/blueprints/messaging-queue-cloudflare/README.md +12 -12
- package/blueprints/messaging-queue-cloudflare/blueprint.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +2 -2
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +180 -12
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +1 -1
- package/blueprints/messaging-queue-cloudflare/docs/topics.md +2 -2
- package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +2 -2
- package/blueprints/object-storage-s3/CHANGELOG.md +75 -4
- package/blueprints/object-storage-s3/blueprint.json +3 -2
- package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +73 -12
- package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +55 -7
- package/blueprints/object-storage-s3/contributions/probes/hetzner-object-storage-round-trip.mjs +102 -18
- package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +105 -36
- package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +104 -55
- package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +129 -7
- package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +80 -18
- package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +291 -37
- package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +5 -5
- package/blueprints/object-storage-s3/contributions/probes/run-hetzner-object-storage-round-trip.mjs +8 -5
- package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +6 -3
- package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +10 -2
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +1 -1
- package/blueprints/object-storage-s3/docs/topics.md +1 -1
- package/blueprints/object-storage-s3/guide/object-storage-s3.md +1 -1
- package/blueprints/observability-essentials/CHANGELOG.md +23 -7
- package/blueprints/observability-essentials/README.md +2 -2
- package/blueprints/observability-essentials/assets/probe-samples/probe-response-baseline.v2.json +1 -1
- package/blueprints/observability-essentials/blueprint.json +3 -2
- package/blueprints/observability-essentials/contributions/probes/liveness-probe.mjs +84 -0
- package/blueprints/observability-essentials/contributions/probes/metrics-endpoint.mjs +96 -0
- package/blueprints/observability-essentials/contributions/probes/probe-utils.mjs +52 -0
- package/blueprints/observability-essentials/contributions/probes/readiness-probe.mjs +171 -0
- package/blueprints/observability-essentials/contributions/probes/run-liveness-probe.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-metrics-endpoint.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-readiness-probe.mjs +3 -0
- package/blueprints/observability-essentials/docs/topics.md +2 -3
- package/blueprints/observability-logging/CHANGELOG.md +29 -4
- package/blueprints/observability-logging/README.md +2 -2
- package/blueprints/observability-logging/blueprint.json +3 -2
- package/blueprints/observability-logging/contributions/probes/correlation-id-flow.mjs +173 -0
- package/blueprints/observability-logging/contributions/probes/line-shape-and-fields.mjs +82 -0
- package/blueprints/observability-logging/contributions/probes/probe-utils.mjs +47 -0
- package/blueprints/observability-logging/contributions/probes/redaction-boundary.mjs +130 -0
- package/blueprints/observability-logging/contributions/probes/run-correlation-id-flow.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-line-shape-and-fields.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-redaction-boundary.mjs +3 -0
- package/blueprints/observability-probe-endpoints/CHANGELOG.md +23 -8
- package/blueprints/observability-probe-endpoints/README.md +3 -3
- package/blueprints/observability-probe-endpoints/blueprint.json +3 -2
- package/blueprints/observability-probe-endpoints/contributions/probes/kubernetes-startup-enabled.mjs +80 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/partial-profile-refusal.mjs +101 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/probe-utils.mjs +49 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/profile-boot-materialisation.mjs +69 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-kubernetes-startup-enabled.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-partial-profile-refusal.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-profile-boot-materialisation.mjs +3 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +2 -2
- package/blueprints/persistence-data-d1/CHANGELOG.md +16 -3
- package/blueprints/persistence-data-d1/README.md +2 -2
- package/blueprints/persistence-data-d1/blueprint.json +3 -2
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1404-persistence-data-d1-store-boundary.json +1 -1
- package/blueprints/persistence-data-d1/contributions/probes/facade-round-trip.mjs +140 -0
- package/blueprints/persistence-data-d1/contributions/probes/migrations-forward-only.mjs +66 -0
- package/blueprints/persistence-data-d1/contributions/probes/probe-utils.mjs +51 -0
- package/blueprints/persistence-data-d1/contributions/probes/real-account-d1-round-trip.mjs +133 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-facade-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-migrations-forward-only.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-real-account-d1-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/docs/topics.md +2 -3
- package/blueprints/persistence-data-postgres/CHANGELOG.md +84 -4
- package/blueprints/persistence-data-postgres/README.md +2 -2
- package/blueprints/persistence-data-postgres/blueprint.json +3 -2
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +87 -12
- package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +245 -19
- package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +109 -26
- package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +151 -38
- package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +24 -6
- package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +261 -48
- package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +76 -20
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +1 -1
- package/blueprints/persistence-data-postgres/docs/topics.md +1 -1
- package/blueprints/persistence-data-sqlite/CHANGELOG.md +16 -2
- package/blueprints/persistence-data-sqlite/README.md +2 -2
- package/blueprints/persistence-data-sqlite/blueprint.json +3 -2
- package/blueprints/persistence-data-sqlite/contributions/probes/boot-open-migrate.mjs +90 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/facade-round-trip.mjs +82 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/probe-utils.mjs +83 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-boot-open-migrate.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-facade-round-trip.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-wal-checkpoint.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/wal-checkpoint.mjs +137 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +5 -5
- package/blueprints/platform-cloudflare-cron-triggers/README.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +6 -10
- package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-kv/CHANGELOG.md +16 -12
- package/blueprints/platform-cloudflare-kv/README.md +2 -4
- package/blueprints/platform-cloudflare-kv/blueprint.json +2 -2
- package/blueprints/platform-cloudflare-kv/docs/topics.md +1 -1
- package/blueprints/platform-docker-compose-host/CHANGELOG.md +92 -5
- package/blueprints/platform-docker-compose-host/blueprint.json +2 -2
- package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +116 -29
- package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +181 -109
- package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +146 -26
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +238 -24
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +207 -21
- package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +246 -42
- package/blueprints/platform-docker-compose-host/docs/topics.md +1 -1
- package/blueprints/security-auth-clerk/CHANGELOG.md +18 -6
- package/blueprints/security-auth-clerk/README.md +3 -3
- package/blueprints/security-auth-clerk/assets/wiring/workers-wrangler-toml-shape.md +1 -1
- package/blueprints/security-auth-clerk/blueprint.json +3 -2
- package/blueprints/security-auth-clerk/contributions/probes/hosted-identity-ui-config.mjs +61 -0
- package/blueprints/security-auth-clerk/contributions/probes/probe-utils.mjs +188 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-principal-directory-round-trip.mjs +216 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-session-inventory.mjs +260 -0
- package/blueprints/security-auth-clerk/contributions/probes/role-model-adapter.mjs +53 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-hosted-identity-ui-config.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-principal-directory-round-trip.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-session-inventory.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-role-model-adapter.mjs +4 -0
- package/blueprints/security-auth-clerk/docs/topics.md +2 -3
- package/blueprints/security-auth-keycloak/CHANGELOG.md +18 -7
- package/blueprints/security-auth-keycloak/README.md +2 -2
- package/blueprints/security-auth-keycloak/blueprint.json +3 -2
- package/blueprints/security-auth-keycloak/contributions/probes/discovery-shape.mjs +68 -0
- package/blueprints/security-auth-keycloak/contributions/probes/introspection-shape.mjs +88 -0
- package/blueprints/security-auth-keycloak/contributions/probes/jwt-verifier-shape.mjs +86 -0
- package/blueprints/security-auth-keycloak/contributions/probes/probe-utils.mjs +180 -0
- package/blueprints/security-auth-keycloak/contributions/probes/real-account-realm-round-trip.mjs +91 -0
- package/blueprints/security-auth-keycloak/contributions/probes/role-adapter-shape.mjs +69 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-discovery-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-introspection-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-jwt-verifier-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-real-account-realm-round-trip.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-role-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/docs/topics.md +1 -2
- package/blueprints/security-auth-magic-link/CHANGELOG.md +15 -4
- package/blueprints/security-auth-magic-link/README.md +2 -2
- package/blueprints/security-auth-magic-link/assets/principal-registry-samples/single-address.md +1 -1
- package/blueprints/security-auth-magic-link/blueprint.json +3 -2
- package/blueprints/security-auth-magic-link/contributions/probes/probe-utils.mjs +174 -0
- package/blueprints/security-auth-magic-link/contributions/probes/real-account-magic-link-send.mjs +139 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-real-account-magic-link-send.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-entropy-shape.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-issue-verify.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-entropy-shape.mjs +60 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-issue-verify.mjs +90 -0
- package/blueprints/security-auth-magic-link/docs/topics.md +1 -1
- package/blueprints/security-auth-oauth2/CHANGELOG.md +16 -5
- package/blueprints/security-auth-oauth2/README.md +2 -2
- package/blueprints/security-auth-oauth2/blueprint.json +3 -2
- package/blueprints/security-auth-oauth2/contributions/probes/authorisation-code-flow-shape.mjs +259 -0
- package/blueprints/security-auth-oauth2/contributions/probes/pkce-challenge-shape.mjs +58 -0
- package/blueprints/security-auth-oauth2/contributions/probes/probe-utils.mjs +190 -0
- package/blueprints/security-auth-oauth2/contributions/probes/provider-adapter-shape.mjs +64 -0
- package/blueprints/security-auth-oauth2/contributions/probes/real-account-authorisation-code-flow.mjs +93 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-authorisation-code-flow-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-pkce-challenge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-provider-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-real-account-authorisation-code-flow.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-session-bridge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/session-bridge-shape.mjs +78 -0
- package/blueprints/security-auth-oauth2/docs/topics.md +1 -2
- package/blueprints/security-secrets-management/CHANGELOG.md +15 -4
- package/blueprints/security-secrets-management/README.md +2 -2
- package/blueprints/security-secrets-management/blueprint.json +3 -2
- package/blueprints/security-secrets-management/contributions/probes/add-recipient-rotation.mjs +107 -0
- package/blueprints/security-secrets-management/contributions/probes/encrypt-decrypt-round-trip.mjs +122 -0
- package/blueprints/security-secrets-management/contributions/probes/key-rotation.mjs +93 -0
- package/blueprints/security-secrets-management/contributions/probes/mismatched-key-refusal.mjs +74 -0
- package/blueprints/security-secrets-management/contributions/probes/probe-utils.mjs +214 -0
- package/blueprints/security-secrets-management/contributions/probes/run-add-recipient-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-encrypt-decrypt-round-trip.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-key-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-mismatched-key-refusal.mjs +4 -0
- package/blueprints/security-secrets-management/docs/topics.md +2 -3
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/harness-template.md +25 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +25 -0
- package/package.json +2 -2
- package/rcf/adrs/adr-4101-feedback-store-gitignored.json +20 -0
- package/rcf/adrs/adr-4102-fingerprint-and-labels.json +25 -0
- package/rcf/adrs/adr-4103-redaction-rule-based.json +20 -0
- package/rcf/adrs/adr-4104-destination-on-library.json +25 -0
- package/rcf/adrs/adr-4105-gh-ambient-auth.json +20 -0
- package/rcf/adrs/adr-4106-bundled-entries-terminal.json +20 -0
- package/rcf/adrs/adr-4107-stop-is-ask-event.json +30 -0
- package/rcf/adrs/adr-4108-hooks-in-committed-config.json +25 -0
- package/rcf/adrs/adr-4109-referee-validate-adr-crosslinks.json +25 -0
- package/rcf/adrs/adr-4110-referee-coverage-strict-by-default.json +25 -0
- package/rcf/adrs/adr-4111-referee-finalise-refusals.json +20 -0
- package/rcf/adrs/adr-4112-referee-finalise-verified-invariant.json +30 -0
- package/rcf/code-nodes/cn-600.json +45 -0
- package/rcf/code-nodes/cn-601.json +18 -0
- package/rcf/code-nodes/cn-602.json +15 -0
- package/rcf/code-nodes/cn-603.json +12 -0
- package/rcf/code-nodes/cn-604.json +14 -0
- package/rcf/code-nodes/cn-605.json +17 -0
- package/rcf/code-nodes/cn-606.json +12 -0
- package/rcf/code-nodes/cn-607.json +12 -0
- package/rcf/code-nodes/cn-608.json +14 -0
- package/rcf/code-nodes/cn-609.json +17 -0
- package/rcf/code-nodes/cn-620.json +18 -0
- package/rcf/code-nodes/cn-621.json +14 -0
- package/rcf/code-nodes/cn-622.json +15 -0
- package/rcf/code-nodes/cn-623.json +16 -0
- package/rcf/code-nodes/cn-624.json +14 -0
- package/rcf/code-nodes/cn-625.json +15 -0
- package/rcf/code-nodes/cn-626.json +13 -0
- package/rcf/code-nodes/cn-627.json +13 -0
- package/rcf/code-nodes/cn-628.json +14 -0
- package/rcf/code-nodes/cn-629.json +12 -0
- package/rcf/code-nodes/cn-630.json +12 -0
- package/rcf/code-nodes/cn-631.json +13 -0
- package/rcf/code-nodes/cn-632.json +13 -0
- package/rcf/fbs/fbs-180.json +45 -0
- package/rcf/fbs/fbs-181.json +45 -0
- package/rcf/fbs/fbs-182.json +42 -0
- package/rcf/fbs/fbs-183.json +50 -0
- package/rcf/fbs/fbs-184.json +49 -0
- package/rcf/fbs/fbs-185.json +34 -0
- package/rcf/fbs/fbs-186.json +16 -0
- package/rcf/fbs/fbs-187.json +17 -0
- package/rcf/fbs/fbs-188.json +17 -0
- package/rcf/fbs/fbs-189.json +17 -0
- package/rcf/requirements/req-155.json +13 -0
- package/rcf/requirements/req-156.json +13 -0
- package/rcf/requirements/req-157.json +13 -0
- package/rcf/requirements/req-158.json +13 -0
- package/rcf/requirements/req-159.json +13 -0
- package/rcf/requirements/req-160.json +13 -0
- package/rcf/requirements/req-161.json +13 -0
- package/rcf/requirements/req-162.json +13 -0
- package/rcf/requirements/req-163.json +13 -0
- package/rcf/requirements/req-164.json +13 -0
- package/rcf/requirements/req-165.json +13 -0
- package/rcf/tacs/tac-4101-feedback-cli.json +77 -0
- package/rcf/tacs/tac-4102-feedback-store.json +50 -0
- package/rcf/tacs/tac-4103-feedback-redact.json +39 -0
- package/rcf/tacs/tac-4104-feedback-fingerprint.json +33 -0
- package/rcf/tacs/tac-4105-feedback-render.json +45 -0
- package/rcf/tacs/tac-4106-feedback-destination.json +39 -0
- package/rcf/tacs/tac-4107-feedback-gh.json +43 -0
- package/rcf/tacs/tac-4108-feedback-hook.json +46 -0
- package/rcf/tacs/tac-4109-referee-validate-adr-crosslinks.json +20 -0
- package/rcf/tacs/tac-4110-referee-coverage-mode-selector.json +21 -0
- package/rcf/tacs/tac-4111-referee-finalise-per-ac-refusals.json +21 -0
- package/rcf/tacs/tac-4112-referee-finalise-verified-invariant.json +22 -0
- package/rcf/test-suites/ts-140.json +9 -9
- package/rcf/test-suites/ts-150.json +9 -9
- package/rcf/test-suites/ts-185.json +54 -0
- package/rcf/test-suites/ts-186.json +58 -0
- package/rcf/test-suites/ts-187.json +44 -0
- package/rcf/test-suites/ts-188.json +166 -0
- package/rcf/test-suites/ts-189.json +38 -0
- package/rcf/test-suites/ts-190.json +30 -0
- package/rcf/test-suites/ts-191.json +51 -0
- package/rcf/test-suites/ts-192.json +37 -0
- package/rcf/test-suites/ts-193.json +60 -0
- package/rcf/test-suites/ts-194.json +67 -0
- package/rcf/test-suites/ts-195.json +52 -0
- package/rcf/test-suites/ts-196.json +58 -0
- package/rcf/test-suites/ts-197.json +66 -0
- package/rcf/test-suites/ts-198.json +87 -0
- package/rcf/test-suites/ts-199.json +51 -0
- package/rcf/test-suites/ts-200.json +30 -0
- package/rcf/test-suites/ts-201.json +38 -0
- package/rcf/test-suites/ts-202.json +38 -0
- package/rcf/test-suites/ts-203.json +38 -0
- package/rcf/user-stories/us-15501.json +60 -0
- package/rcf/user-stories/us-15502.json +33 -0
- package/rcf/user-stories/us-15503.json +33 -0
- package/rcf/user-stories/us-15601.json +51 -0
- package/rcf/user-stories/us-15701.json +42 -0
- package/rcf/user-stories/us-15801.json +42 -0
- package/rcf/user-stories/us-15802.json +33 -0
- package/rcf/user-stories/us-15901.json +33 -0
- package/rcf/user-stories/us-15902.json +51 -0
- package/rcf/user-stories/us-16001.json +51 -0
- package/rcf/user-stories/us-16101.json +42 -0
- package/rcf/user-stories/us-16102.json +33 -0
- package/rcf/user-stories/us-16103.json +42 -0
- package/rcf/user-stories/us-16104.json +42 -0
- package/rcf/user-stories/us-16201.json +33 -0
- package/rcf/user-stories/us-16301.json +36 -0
- package/rcf/user-stories/us-16401.json +45 -0
- package/rcf/user-stories/us-16501.json +45 -0
- package/rcf/user-stories/us-16502.json +45 -0
- package/releases/releases.yaml +11 -1
- package/src/blueprint/library-loader.js +48 -0
- package/src/blueprint/library-registry.js +13 -0
- package/src/browser-verify/pack-runner.js +7 -12
- package/src/build/mark.js +1 -1
- package/src/cli/blueprint-library.js +149 -0
- package/src/cli/coverage.js +49 -24
- package/src/cli/doctor.js +195 -7
- package/src/cli/feedback.js +2204 -0
- package/src/cli/finalise.js +158 -1
- package/src/cli/help.js +6 -0
- package/src/cli/init.js +63 -0
- package/src/cli/update.js +21 -1
- package/src/core/store/walker.js +33 -0
- package/src/core/store/writer.js +23 -0
- package/src/feedback/destination.js +361 -0
- package/src/feedback/fingerprint.js +132 -0
- package/src/feedback/gh.js +376 -0
- package/src/feedback/hook.js +183 -0
- package/src/feedback/labels.js +87 -0
- package/src/feedback/redact-allowlist.json +14 -0
- package/src/feedback/redact.js +1108 -0
- package/src/feedback/render.js +267 -0
- package/src/feedback/store.js +604 -0
- package/src/finalise/index.js +4 -0
- package/src/finalise/ingest.js +61 -0
- package/src/finalise/ship-without-eval.js +19 -7
- package/src/mcp/tools.js +8 -2
- package/src/setup/feedback-hooks.js +397 -0
- package/src/setup/managed-gitignore.js +3 -0
- package/src/view/html-page.js +5 -5
- package/src/view/style.css +2 -2
package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs
CHANGED
|
@@ -46,7 +46,15 @@ async function bootServer() {
|
|
|
46
46
|
|
|
47
47
|
async function fetchDom(url, caps) {
|
|
48
48
|
const target = `${url}/admin/sign-in?caps=${encodeURIComponent(caps)}`;
|
|
49
|
-
|
|
49
|
+
// The admin-console fixture refuses unauthenticated gated requests
|
|
50
|
+
// with HTTP 403 (AC-21815-2), so the probe supplies a fixture
|
|
51
|
+
// Authorization header when the capability set includes
|
|
52
|
+
// zeroTrustGate so the gated surface can be observed.
|
|
53
|
+
const capsList = caps.split(',').map((s) => s.trim());
|
|
54
|
+
const headers = capsList.includes('zeroTrustGate')
|
|
55
|
+
? { Authorization: 'Principal probe-signin@example.test' }
|
|
56
|
+
: undefined;
|
|
57
|
+
const res = await fetch(target, headers ? { headers } : undefined);
|
|
50
58
|
return { status: res.status, body: await res.text(), target };
|
|
51
59
|
}
|
|
52
60
|
|
|
@@ -59,7 +59,7 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
59
59
|
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
60
60
|
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
61
61
|
|
|
62
|
-
US 34101-34109 sit at the LOW end of the 34101-34899 band on purpose
|
|
62
|
+
US 34101-34109 sit at the LOW end of the 34101-34899 band on purpose. ADR/TAC suffixes for this blueprint use the 3501-3599 block, continuing the shelf pattern.
|
|
63
63
|
|
|
64
64
|
## Shared expectations for future composing blueprints
|
|
65
65
|
|
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
Positive-evidence rule alignment on the probe pack skip path (authoring standard section 7d); vendor citation on the guide-section AC; register tidy in shipped prose (no capability change).
|
|
6
6
|
|
|
7
7
|
- Probes and fixture: the account-bound skip return on `contributions/probes/real-account-burst-and-429.mjs` now carries a `reason` field naming the exact env var(s) that were unset; added a "Declared env vars" section to the shared fixture README (`packages/rcf-lite/test/fixtures/cf-edge/README.md`), per authoring standard section 7d. Skip-path probe reports regenerated so the shipped shape carries the new field.
|
|
8
|
-
-
|
|
9
|
-
- Closes F-7: README trailing clause with the internal spec reference removed.
|
|
10
|
-
- Closes F-8: guide leading provenance sentence removed.
|
|
8
|
+
- AC-36102-1 on US-36102 now carries a vendorCitation pointing at the Cloudflare WAF rate-limiting rules documentation.
|
|
11
9
|
|
|
12
10
|
## 1.1.2 - 2026-09-10
|
|
13
11
|
|
|
@@ -24,19 +22,18 @@ Capability token named in the requirements layer; single-mechanism story legalit
|
|
|
24
22
|
|
|
25
23
|
## 1.1.0 - 2026-09-09
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
Adds REQ-layer backing for elicited options and extends the AC set to cover every documented failure path.
|
|
29
26
|
- Added failure-path ACs to US-36103 (origin-not-executed AC-36103-2 closes F-1: 429 refuses before origin), US-36104 (AC-36104-2 fake-clock cadence assertion closes F-2; AC-36104-3..7 close F-5 drift-runner failure paths for missing zone id, API auth, throttled, malformed and timeout).
|
|
30
27
|
- Split the drift-audit record shape from the runtime request-event record shape: drift records carry `{ruleId, outcome, timestamp, diff}` (no `clientIpHash`, no client on the API path); request-event records carry `{ruleId, clientIpHash, outcome, timestamp}` with a hashed prefix. REQ-004, TAC-3703 responsibilities, AC-36104-1 and AC-36107-1 all now use these exact shapes (closes specimen F-3).
|
|
31
28
|
- Clarified TAC-3701 and REQ-001 that the manifest schema has seven required fields plus one optional `description` field (aligns TAC with the shipped schema; closes specimen F-4).
|
|
32
29
|
- Every REQ now carries `deliveredBy`; every AC carries `disposition`; ACs referencing owner-owned literals carry `ownerRef`.
|
|
33
30
|
- Chain-consistency lint reports 0 findings on both passes.
|
|
34
|
-
-
|
|
31
|
+
- Finished the split of the drift-audit record shape from the request-event shape by rewriting the TAC-3703 purpose second sentence and the guide's `## Drift audit` section to state the drift record as `{ruleId, outcome, timestamp, diff}` and the request-event record as `{ruleId, clientIpHash, outcome, timestamp}`; the README event-secrecy row assertion now names both shapes. Split every bundled single-AC story on a per-failure-path basis: US-36106 (canonical-pass + SIMULATE_SCHEMA_INVALID-fail), US-36107 (canonical-shape + SIMULATE_EVENT_LEAK_IP-fail), US-36108 (canonical-pass + SIMULATE_MANIFEST_MISSING-fail); each new AC carries a concrete oracle (probe verdict + named field) and an `ownerRef`. US-36101 AC-36101-1 and US-36103 AC-36103-1/-2 are marked `template` naming the values the applying agent sets (the rate-limit-rules-dir path, per-rule id/expression/threshold/period/characteristics/action/duration, the elicited rate-limit-zone-id, and CF_RATE_LIMIT_URL for the account-bound probe). Genuinely single-mechanism stories (US-36101, US-36102, US-36105) carry the section-7a note inside the story `description` field, not in a schema-illegal new field.
|
|
35
32
|
|
|
36
33
|
|
|
37
34
|
## 1.0.0 (round 6, 2026-09-07)
|
|
38
35
|
|
|
39
|
-
- First shipped version. Zone-level rate limiting as an edge gate in front of Worker handlers
|
|
36
|
+
- First shipped version. Zone-level rate limiting as an edge gate in front of Worker handlers.
|
|
40
37
|
- Five REQs, eight USs, three TACs, four ADRs. Twenty contributions total.
|
|
41
38
|
- Ships the local rate-limit rules manifest schema (draft-07), the operator-facing management surface guide with both wrangler and dashboard flows, the drift-audit runner realisation on the `cf-edge` fixture and the composition ADR with `security-auth-magic-link`.
|
|
42
39
|
- Mints capability `edgeRateLimit` and global topic `edgeThrottleContract` (ADR-3701, scope global).
|
|
@@ -59,7 +59,7 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
59
59
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
60
60
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
61
61
|
|
|
62
|
-
US 36101-36108 sit at the LOW end of the 36101-36899 band on purpose
|
|
62
|
+
US 36101-36108 sit at the LOW end of the 36101-36899 band on purpose. ADR/TAC suffixes for this blueprint use the 3701-3799 block, continuing the shelf pattern.
|
|
63
63
|
|
|
64
64
|
## Shared expectations for future composing blueprints
|
|
65
65
|
|
|
@@ -6,8 +6,7 @@ Positive-evidence rule alignment on the probe pack skip path (authoring standard
|
|
|
6
6
|
|
|
7
7
|
- Probes and fixture: extended the shared `accountBoundSkippedResult` helper in `contributions/probes/probe-utils.mjs` to carry a `reason` field naming the exact env var(s) that were unset on the skip return; added a "Declared env vars" section for the tunnel probes to the shared fixture README (`packages/rcf-lite/test/fixtures/hetzner-throwaway-server/README.md`), per authoring standard section 7d.
|
|
8
8
|
- Probe report detail hygiene: `accountBoundSkippedResult` now names only the actually-unset variables in its `detail` string (a partial skip with one first-tier gate set and the other unset reads honestly, instead of claiming the whole input list is unset). The `reason` field was already exact; this aligns the human-readable detail with it.
|
|
9
|
-
-
|
|
10
|
-
- Closes F-6: guide drops the leading provenance line and rewrites two trailing clauses without internal spec references.
|
|
9
|
+
- README now leads with a category-neutral opening line.
|
|
11
10
|
|
|
12
11
|
## 1.1.2 - 2026-09-10
|
|
13
12
|
|
|
@@ -22,9 +21,8 @@ Capability token named in the requirements layer.
|
|
|
22
21
|
|
|
23
22
|
## 1.1.0 - 2026-09-09
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- Added REQ-006 (zone resolution via the vault seam; AUD-mandatory-when-gated) and REQ-007 (public-hostname template expansion at apply with malformed and duplicate refusals). Closes review P0 findings F-1 (cloudflare-zone-secret elicit had no covering requirement) and F-2 (public-hostname-template elicit had no covering requirement). Neither elicit or capability token was removed; both are now backed by a `must`-priority requirement.
|
|
24
|
+
Adds REQ-layer backing for zone resolution and hostname expansion, and extends the AC set to cover every documented failure path.
|
|
25
|
+
- Added REQ-006 (zone resolution via the vault seam; AUD-mandatory-when-gated) and REQ-007 (public-hostname template expansion at apply with malformed and duplicate refusals). Neither elicit or capability token was removed; both are now backed by a `must`-priority requirement.
|
|
28
26
|
- Added TAC-4004-edge-cloudflare-tunnel-zone-and-hostname-apply naming the apply-time responsibilities for zone resolution, hostname expansion and AUD-mandatory refusals.
|
|
29
27
|
- Added user stories US-39109 (four apply-time ACs across the zone-resolution and AUD-mandatory-when-gated paths) and US-39110 (three apply-time ACs across the hostname-template expansion, malformed and duplicate paths).
|
|
30
28
|
- Added the following failure-path ACs to existing stories: AC-tunnel-cloudflaredReady on US-39102 (boot event observation; closes F-4 event-name inconsistency by naming both `cloudflaredReady` (process boot) and `tunnelConnectorUp` (per-connector) as distinct events); AC-tunnel-connectorPrecedence on US-39101 (four-combination precedence with two apply-refusal codes; closes F-5); four `AC-tunnel-accessGatedReject*/Accept*` ACs on US-39106 covering missing, invalid and wrong-audience JWT paths plus the valid-audience accept path (closes F-6); AC-tunnel-credentialsHostMode and AC-tunnel-credentialsTrackedTreeScan on US-39108 (closes F-7).
|
|
@@ -33,7 +31,7 @@ Hardening pass on the edge family (criterion a REQ-layer backing; criterion b AC
|
|
|
33
31
|
- Guide updated in the "Hostname mode: when to reach for Access-gated vs public-hostname" section to name the AUD-mandatory-when-gated rule; the earlier "Graceful degrade" wording is retired.
|
|
34
32
|
- De-identified operator-internal names across the blueprint (operator-internal path prefixes renamed to `vault/*`; other in-house references neutralised) to keep the shipped package customer-facing.
|
|
35
33
|
- Chain-consistency lint (`rcf define blueprint lint-consistency`) reports 0 findings on both passes for this blueprint.
|
|
36
|
-
-
|
|
34
|
+
- Split every bundled single-AC story on a per-failure-path basis so each named path (SIMULATE_MANIFEST_INVALID_TUNNEL_ID / _CREDENTIALS_INLINE / _MISSING_CATCHALL on US-39103; SIMULATE_INGRESS_INVALID on US-39104 with the happy path split off; SIMULATE_ORIGIN_PORT_OPEN on US-39105 with the happy path split off; SIMULATE_AUD_DROP on US-39107 with the happy path split off) is its own AC on the owning story with a concrete oracle (probe verdict + named field) and an `ownerRef` into the owning TAC. Vendor citations added on the US-39106 four AUD ACs (Cloudflare Access self-hosted-public-app-owned literals) and on the vendor cloudflared local-configuration-file reference (US-39104); the four US-39106 AUD ACs and AC-tunnel-hostnameTemplateExpand on US-39110 marked `template` naming the values the applying agent sets (elicited access-aud tag; ingress rule service names and resolved zone). Filled `ownerRef` and given/when/then on AC-tunnel-connectorShape (US-39101). Filled given/when/then on AC-tunnel-accessGated (US-39106). Reworded the US-39102 title and `iWant` to name both `cloudflaredReady` (boot) and `tunnelConnectorUp` (per-connector) as distinct events. Added `## Zone resolution` and `## Public-hostname template expansion` sections to the shipped guide.
|
|
37
35
|
|
|
38
36
|
|
|
39
37
|
## 1.0.1 - 2026-09-08
|
|
@@ -124,8 +124,7 @@ Graceful degrade: when Access is not applied (the `zeroTrustGate` capability is
|
|
|
124
124
|
`origin/main` or the applying project simply does not want the gate),
|
|
125
125
|
the blueprint still ships in public-hostname mode. The probe assertion
|
|
126
126
|
runs on both fixture variants so the shape flip is proven on every
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
operator boot.
|
|
129
128
|
## No-public-ports rule
|
|
130
129
|
|
|
131
130
|
The deploy-hetzner-server firewall on a `cloudHost` allows 22 unconditionally and 80/443
|
|
@@ -59,7 +59,7 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
59
59
|
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
60
60
|
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
61
61
|
|
|
62
|
-
US 39101-39108 sit at the LOW end of the 39101-39899 band on purpose
|
|
62
|
+
US 39101-39108 sit at the LOW end of the 39101-39899 band on purpose. A project-side story mechanically derived from an edge-cloudflare-tunnel REQ id into the number 39108 would collide against the shipped US-39108; band headroom (39109-39899) leaves that space.
|
|
63
63
|
|
|
64
64
|
Edge-cloudflare-tunnel suffixes for this blueprint use the 4001-4003 block, continuing the widening pattern (deploy-hetzner-server 3801-3804 for the host sibling, platform-docker-compose-host 3901-3904 for the compose-host sibling).
|
|
65
65
|
|
|
@@ -22,8 +22,7 @@ Capability token named in the requirements layer; single-mechanism story legalit
|
|
|
22
22
|
|
|
23
23
|
## 1.1.0 - 2026-09-09
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
Adds REQ-layer backing and extends the AC set to cover every documented failure path.
|
|
27
26
|
- Normalised the `cf-turnstile-response` token casing across the shipped guide, README, REQs, TACs and user stories to the lowercase form-field literal Cloudflare's client-side rendering and server-side validation docs specify verbatim (closes specimen F-1 in the vendor-fact direction under 7b; earlier interim pass mistakenly took the pre-existing TAC-3601 title-case as canonical). TAC-3601 owns the literal with a `vendorCitation` and US-35101 AC-35101-1 is re-marked `fixed` with the same citation. The consistency-lint AC-3 spec test continues to assert the specimen is closed on the shipped blueprint.
|
|
28
27
|
- Added failure-path ACs to US-35102 (AC-35102-2..4 close F-3: missing sitekey, missing secret, only-one-of-pair boot refusal) and US-35103 (AC-35103-2..6 close F-2: siteverify timeout, network failure, non-2xx upstream, invalid JSON, missing success-field fail-closed).
|
|
29
28
|
- Every REQ now carries `deliveredBy`; every AC carries `disposition` (`AC-35102-1` and `AC-35103-1` marked `fixed` with vendor citations to the Cloudflare Turnstile testing docs); ACs referencing owner-owned literals carry `ownerRef`.
|
|
@@ -31,7 +30,7 @@ hardening pass edge (criterion a REQ-layer backing; criterion b AC-set sufficien
|
|
|
31
30
|
|
|
32
31
|
|
|
33
32
|
All notable changes to `edge-cloudflare-turnstile` are recorded here. The shape follows Keep a Changelog and Semantic Versioning per the blueprint authoring standard.
|
|
34
|
-
-
|
|
33
|
+
- Flipped `cf-turnstile-response` to the lowercase vendor literal per Cloudflare's client-side rendering and server-side validation docs across guide, README, CHANGELOG, REQ-001, REQ-003, TAC-3601, TAC-3602, US-35101, US-35104 and US-35105; TAC-3601 responsibility 3 owns the literal and US-35101 AC-35101-1 is marked `fixed` with `vendorCitation` at the client-side-rendering page. Added `AC-35101-2` for the always-fail test-sitekey mount branch (`fixed`, `vendorCitation` at the Cloudflare testing docs). Split US-35104 into canonical-shape (guard-shape-scan) and missing-token-runtime (400 turnstile.token-missing) ACs each with a concrete oracle and an `ownerRef` into TAC-3602. Vendor citations added on US-35101 AC-35101-1/2, US-35102 AC-35102-1, US-35103 AC-35103-1, US-35104 AC-35104-2, US-35105 AC-35105-2 and US-35106 AC-35106-1. Every AC in this blueprint is `fixed` (refusal codes, event-secrecy record shapes, probe verdicts and vendor test-key observables are all mechanism-invariant). Genuinely single-mechanism stories (US-35106, US-35107, US-35108) carry the section-7a note inside the story `description` field, not in a schema-illegal new field.
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
## 1.0.0 (2026-09-07)
|
|
@@ -59,7 +59,7 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
59
59
|
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
60
60
|
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
61
61
|
|
|
62
|
-
US 35101-35108 sit at the LOW end of the 35101-35899 band on purpose
|
|
62
|
+
US 35101-35108 sit at the LOW end of the 35101-35899 band on purpose. ADR/TAC suffixes for this blueprint use the 3601-3699 block, continuing the shelf pattern.
|
|
63
63
|
|
|
64
64
|
## Shared expectations for future composing blueprints
|
|
65
65
|
|
|
@@ -1,8 +1,24 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.1.7 - 2026-09-11
|
|
4
|
+
|
|
5
|
+
unverified-sender-refusal AC-4102-1 and AC-4102-2 rows are de-claimed to conformanceOnly. The refusal is driven by the local catch-all SMTP fixture (fixture-as-engine) and carries no Resend-returned message id, so the identifier half of the strict-evidence contract is not satisfied here. The live real-account-resend-send row (AC-4101-2) is unchanged.
|
|
6
|
+
|
|
7
|
+
## 1.1.6 - 2026-09-11
|
|
8
|
+
|
|
9
|
+
unverified-sender-refusal AC-4102-1 verdict now requires the complete refusal outcome shape owned on TAC-401.interfaces.send: providerStatus a valid positive integer AND providerMessageId===null AND thrownMessage===null, alongside the RESEND_SENDER_UNVERIFIED class prefix.
|
|
10
|
+
|
|
1
11
|
# email-smtp-resend CHANGELOG
|
|
2
12
|
|
|
13
|
+
## 1.1.5 - 2026-09-11
|
|
14
|
+
|
|
15
|
+
Adds a contributions/probes/ pack (smtp-round-trip, unverified-sender-refusal, real-account-resend-send) with a fixture-side send adapter (realises TAC-401.interfaces.send), a catch-all SMTP provider seam and a Resend REST provider seam under packages/rcf-lite/test/fixtures/probe-pack-email-smtp-resend/. Probes run against the fixture on Node 24 and against real Resend on the account-bound branch (CI_HAS_RESEND_ACCOUNT gate + RESEND_API_KEY, one variable per skip row).
|
|
16
|
+
|
|
17
|
+
Anchoring: unverified-sender-refusal anchors AC-4102-1 (adapter classifies the fixture's 550 5.7.1 refusal to a RESEND_SENDER_UNVERIFIED-prefixed error string) and AC-4102-2 (recipient, subject, body do not appear on the returned error string, on any emitted log line, or on any thrown exception; server accepted zero messages on the unverified path). real-account-resend-send anchors AC-4101-2; the row verdict requires ok=true, error=null, a non-empty providerMessageId AND providerStatus to be an integer in the accepted 200-299 range. smtp-round-trip de-claims (conformanceOnly, anchorAcId=null) with the limitation naming AC-4101-3: the row observes a local catch-all SMTP dispatch via a helper, not a call through the adapter and not the Resend endpoint. probe-utils normalisation and thrown-error rows carry an evidence object; the fallback anchorAcId is null.
|
|
18
|
+
|
|
3
19
|
## 1.1.3 - 2026-09-10
|
|
4
20
|
|
|
5
|
-
|
|
21
|
+
Removed the send-signature and outcome-field restatements from `AC-4101-2` (description and then-clause), `AC-4102-1` (description and then-clause), and the guide's "What a good outcome looks like" bullets; each surface now references the outcome record owned on `TAC-401-email-smtp-resend-send-adapter.interfaces.send` and, where relevant, the classification owned on `responsibilities[3]`. The AC-4101-2 and AC-4102-1 when-clauses now reference the send interface owned on `TAC-401-email-smtp-resend-send-adapter.interfaces.send` instead of restating the `adapter.send(...)` signature. US-4101 and US-4102 patch-bumped.
|
|
6
22
|
|
|
7
23
|
## 1.1.2 - 2026-09-10
|
|
8
24
|
|
|
@@ -12,13 +28,13 @@ Dimension-d single-definition-ownership cleanup on REQ-001: REQ description now
|
|
|
12
28
|
|
|
13
29
|
- Register: neutral wording in shipped prose (no capability change).
|
|
14
30
|
|
|
15
|
-
## 1.1.0 (
|
|
31
|
+
## 1.1.0 (2026-09-09)
|
|
16
32
|
|
|
17
33
|
- Adds `elicits[]` with six apply-time answers: `smtp-host-ref`, `smtp-username-ref`, `smtp-password-ref`, `verified-sender-ref` (string placeholder references the send adapter resolves at boot per REQ-002), `webhook-signing-secret-ref` (string placeholder reference the WEBHOOK VERIFIER resolves per REQ-005 - owned by TAC-402, not TAC-401), `replay-tolerance-ms` (string milliseconds, default 300000; REQ-006).
|
|
18
|
-
- Adds `deliveredBy` to every REQ (REQ-001/003/004 -> TAC-401 interfaces; REQ-002 -> TAC-401.interfaces.secretResolver; REQ-005 -> TAC-402.interfaces.verify; REQ-006 -> TAC-402.interfaces.eventIdStore).
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
34
|
+
- Adds `deliveredBy` to every REQ (REQ-001/003/004 -> TAC-401 interfaces; REQ-002 -> TAC-401.interfaces.secretResolver; REQ-005 -> TAC-402.interfaces.verify; REQ-006 -> TAC-402.interfaces.eventIdStore).
|
|
35
|
+
- Webhook secret ownership: AC-4106-2 rewritten to name only the three SMTP references plus the verified-sender-address (owned by TAC-401.responsibilities[8]); AC-4106-3 added asserting the webhook signing secret is resolved by TAC-402 and does not appear in the send adapter's source.
|
|
36
|
+
- The transport class retry not asserted gap is fixed: adds AC-4103-4 (transient transport failure ECONNRESET succeeds on retry with the returned envelope id) and AC-4103-5 (exhausted retry -> RESEND_TRANSPORT_ERROR naming the class and attempt count).
|
|
37
|
+
- The backoff delay range not asserted gap is fixed: adds AC-4103-6 with a deterministic jitter source and clock, asserting scheduled delay under exponential full-jitter caps within [0, 250] for the first retry at the ADR-402 baseline; no delay negative, no delay above the 8000ms cap.
|
|
38
|
+
- The TTL expiry not asserted gap is fixed: adds AC-4105-3 asserting the eventIdStore `putIfAbsentWithExpiry` receives expiryMs equal to the configured replay tolerance window; a re-post inside the window is refused as duplicate, a re-post after the window expires is accepted.
|
|
23
39
|
- Re-sweeps every existing AC's `disposition` per section 7b: ACs referencing placeholder references and the tolerance window flipped to `template` with `templateFillIns`; the remaining ACs stay `fixed`.
|
|
24
|
-
-
|
|
40
|
+
- adds `secretResolver` interface entry to TAC-402 (mirrors the TAC-401 shape) naming the boot-time secret-reference resolver the webhook verifier consumes; corrects TAC-402.responsibilities[5] cross-reference from AC-4106-2 to AC-4106-3 (the earlier split of webhook-secret ownership off from the SMTP-secrets AC left the responsibility trailer citing the older AC); updates AC-4106-3.ownerRef from `TAC-402.interfaces.verify` to `TAC-402.interfaces.secretResolver` so the ownership pointer names the actual secret-resolution interface.
|
|
@@ -26,9 +26,9 @@ The doc set is contributions (copied into the project tree by `rcf define bluepr
|
|
|
26
26
|
|
|
27
27
|
## What it contributes, and what it deliberately does not
|
|
28
28
|
|
|
29
|
-
Contributed kinds: REQ, US (with inline ACs), TAC, ADR. Adherence is expressed as ACs; the blueprint ships no test files (
|
|
29
|
+
Contributed kinds: REQ, US (with inline ACs), TAC, ADR. Adherence is expressed as ACs; the blueprint ships no test files (shipped policy 5) and no code.
|
|
30
30
|
|
|
31
|
-
No FBS contributions, as a matter of principle (
|
|
31
|
+
No FBS contributions, as a matter of principle (policy): FBSes are the work of the implementing agent, not the blueprint; project constraints have to be applied at the time of creation. The blueprint contributes the WHAT (the send-contract shape, the SMTP transport choice, the four-class error taxonomy, the retry-and-backoff posture, the webhook signature verification, the replay defence, the boundary discipline on the SMTP client library and the secret references); the implementing agent derives the HOW-tasks (FBS) in the host project, where the ACs contributed here get picked up by the project's own build sequencing.
|
|
32
32
|
|
|
33
33
|
Deliberately not contributed: the magic-link blueprint's auth routes themselves (they live on the magic-link blueprint; this blueprint is an ADAPTER only); the mail-adapter interface as a global topic (the interface belongs to the magic-link blueprint's `TAC-504`, not to this blueprint); an SMTP client library or an HTTP client library (project picks from what it already carries; the adapter injects the client at boot); a specific YAML or JSON schema library; a Secrets Manager client (composable with the shipped `security-secrets-management` blueprint or with a project-authored secret-reference resolver of the same shape); a shared event bus for delivery events (the verifier hands parsed events to a downstream handler the project realises; where those events go beyond the handler is a project concern); regulatory or compliance workflow (double-opt-in surfaces, unsubscribe UI, retention of consent records live outside this blueprint's scope); the Resend HTTP API path (project supersedes ADR-401 and swaps the adapter's internal client if the API path is preferred, without changing the interface the auth routes call).
|
|
34
34
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"slug": "email-smtp-resend",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"category": "email",
|
|
5
5
|
"elicits": [
|
|
6
6
|
{
|
|
@@ -121,5 +121,6 @@
|
|
|
121
121
|
"kind": "adr",
|
|
122
122
|
"path": "adrs/adr-402-email-smtp-resend-retry-and-backoff-posture.json"
|
|
123
123
|
}
|
|
124
|
-
]
|
|
124
|
+
],
|
|
125
|
+
"updatedAt": "2026-09-11"
|
|
125
126
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
export const PROJECT_ROOT = resolve(HERE, '..', '..', '..', '..');
|
|
7
|
+
export const FIXTURE_DIR = resolve(PROJECT_ROOT, 'packages/rcf-lite/test/fixtures/probe-pack-email-smtp-resend');
|
|
8
|
+
export const REPORT_DIR = resolve(PROJECT_ROOT, '.rcf/reports/blueprints/email-smtp-resend');
|
|
9
|
+
export const DECLARED_ENV = new Set(['RCF_FIXTURE_SMTP_PORT', 'CI_HAS_RESEND_ACCOUNT', 'RESEND_API_KEY']);
|
|
10
|
+
|
|
11
|
+
export function aggregate(results) {
|
|
12
|
+
if (!Array.isArray(results) || results.length === 0) return 'fail';
|
|
13
|
+
if (results.some((r) => r.verdict === 'fail')) return 'fail';
|
|
14
|
+
if (results.some((r) => r.verdict === 'warn')) return 'warn';
|
|
15
|
+
return 'pass';
|
|
16
|
+
}
|
|
17
|
+
export function isSkipped(results) { return Array.isArray(results) && results.length > 0 && results.every((r) => r.accountBoundSkipped === true); }
|
|
18
|
+
export async function writeReport({ probeName, engine, results, extra }) {
|
|
19
|
+
await mkdir(REPORT_DIR, { recursive: true });
|
|
20
|
+
const normalised = (Array.isArray(results) && results.length > 0)
|
|
21
|
+
? results
|
|
22
|
+
: [{ anchorAcId: null, harnessError: true, verdict: 'fail', detail: 'no checks ran', evidence: { reason: 'no checks ran', probeName, runAt: new Date().toISOString(), engine } }];
|
|
23
|
+
const raw = aggregate(normalised); const aggregateVerdict = isSkipped(normalised) ? 'pass' : raw;
|
|
24
|
+
const report = { slug: 'email-smtp-resend', probeName, runAt: new Date().toISOString(), engine, results: normalised, aggregateVerdict, ...(extra ?? {}) };
|
|
25
|
+
const path = resolve(REPORT_DIR, `${probeName}.json`);
|
|
26
|
+
await writeFile(path, JSON.stringify(report, null, 2) + '\n', 'utf8');
|
|
27
|
+
return { report, path };
|
|
28
|
+
}
|
|
29
|
+
export async function runShim(probeName, engine, mainFn) {
|
|
30
|
+
try {
|
|
31
|
+
const outcome = (await mainFn()) ?? { results: [] };
|
|
32
|
+
const { results, extra } = outcome;
|
|
33
|
+
const { report, path } = await writeReport({ probeName, engine, results, extra });
|
|
34
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
35
|
+
process.stdout.write(`report written to ${path}\n`);
|
|
36
|
+
if (report.aggregateVerdict === 'fail') process.exitCode = 1;
|
|
37
|
+
} catch (err) {
|
|
38
|
+
const results = [{ anchorAcId: null, harnessError: true, verdict: 'fail', detail: `probe threw: ${err?.message ?? err}`, evidence: { thrown: true, message: err?.message ?? String(err), name: err?.name ?? 'Error', probeName, runAt: new Date().toISOString(), engine } }];
|
|
39
|
+
const { report, path } = await writeReport({ probeName, engine, results });
|
|
40
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
41
|
+
process.stderr.write(`probe error: ${err?.stack ?? err}\n`);
|
|
42
|
+
process.stderr.write(`report written to ${path}\n`);
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function portFrom(v) { if (v === undefined || v === '') return 0; const n = Number(v); return Number.isInteger(n) && n >= 0 && n <= 65535 ? n : 0; }
|
|
47
|
+
export function envPort(name) {
|
|
48
|
+
if (name === 'RCF_FIXTURE_SMTP_PORT') return portFrom(process.env.RCF_FIXTURE_SMTP_PORT);
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Real-account Resend send probe for email-smtp-resend.
|
|
2
|
+
//
|
|
3
|
+
// Routes the send through the fixture email-delivery adapter (which
|
|
4
|
+
// realises TAC-401.interfaces.send) with Resend REST as the provider
|
|
5
|
+
// seam behind it. The probe observes the adapter's outcome record
|
|
6
|
+
// (ok, providerStatus, providerMessageId) and asserts AC-4101-2's
|
|
7
|
+
// success shape, including that providerStatus is a positive integer
|
|
8
|
+
// in the accepted 200-299 range (per TAC-401's accepted status
|
|
9
|
+
// contract) alongside a non-empty providerMessageId.
|
|
10
|
+
import { createSendAdapter, createResendRestProvider } from '../../../../packages/rcf-lite/test/fixtures/probe-pack-email-smtp-resend/src/send-adapter.mjs';
|
|
11
|
+
|
|
12
|
+
export const anchorAcId = 'AC-4101-2';
|
|
13
|
+
export const accountBound = true;
|
|
14
|
+
const AC2 = 'A successful send resolves the outcome record owned';
|
|
15
|
+
|
|
16
|
+
function skipResult(reason, detail) {
|
|
17
|
+
return {
|
|
18
|
+
results: [{ anchorAcId: null, accountBoundSkipped: true, reason, verdict: 'pass', detail, evidence: { reason, declared: 'gate variable' } }],
|
|
19
|
+
extra: {
|
|
20
|
+
accountBoundSkipped: true, reason,
|
|
21
|
+
envDeclared: ['CI_HAS_RESEND_ACCOUNT', 'RESEND_API_KEY'],
|
|
22
|
+
vendorFact: { url: 'https://resend.com/docs/dashboard/emails/send-test-emails', verifiedOn: '2026-09-11' },
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default async function runProbe() {
|
|
28
|
+
if (process.env.CI_HAS_RESEND_ACCOUNT !== 'true') return skipResult('CI_HAS_RESEND_ACCOUNT', `accountBoundSkipped: CI_HAS_RESEND_ACCOUNT is not set to true; the adapter did not dispatch.`);
|
|
29
|
+
if (!process.env.RESEND_API_KEY) return skipResult('RESEND_API_KEY', `accountBoundSkipped: RESEND_API_KEY unset; the adapter did not dispatch.`);
|
|
30
|
+
const results = [];
|
|
31
|
+
const provider = createResendRestProvider({ apiKey: process.env.RESEND_API_KEY, from: 'onboarding@resend.dev' });
|
|
32
|
+
const adapter = createSendAdapter({ provider });
|
|
33
|
+
const outcome = await adapter.send({ to: 'delivered@resend.dev', subject: 'rcf-lite criterion e probe', textBody: 'criterion e probe send at ' + new Date().toISOString(), htmlBody: null });
|
|
34
|
+
const statusIsAccepted = typeof outcome.providerStatus === 'number' && Number.isInteger(outcome.providerStatus) && outcome.providerStatus >= 200 && outcome.providerStatus < 300;
|
|
35
|
+
results.push({
|
|
36
|
+
anchorAcId: 'AC-4101-2',
|
|
37
|
+
verdict: outcome.ok === true && statusIsAccepted && typeof outcome.providerMessageId === 'string' && outcome.providerMessageId.length > 0 && outcome.error === null ? 'pass' : 'fail',
|
|
38
|
+
detail: `${AC2} on TAC-401.interfaces.send - observed adapter.send() returned { ok: ${outcome.ok}, providerStatus: ${outcome.providerStatus}, providerMessageId: '${outcome.providerMessageId}', error: ${outcome.error === null ? 'null' : `'${outcome.error}'`} }; providerStatus is an integer in the accepted 200-299 range: ${statusIsAccepted}; the adapter dispatched through Resend REST as the provider seam.`,
|
|
39
|
+
evidence: { ok: outcome.ok, providerStatus: outcome.providerStatus, providerMessageId: outcome.providerMessageId, error: outcome.error, statusIsAccepted },
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
results,
|
|
43
|
+
extra: {
|
|
44
|
+
envDeclared: ['CI_HAS_RESEND_ACCOUNT', 'RESEND_API_KEY'],
|
|
45
|
+
sentTo: 'delivered@resend.dev', sentFrom: 'onboarding@resend.dev',
|
|
46
|
+
adapterOutcome: outcome,
|
|
47
|
+
vendorFact: { url: 'https://resend.com/docs/dashboard/emails/send-test-emails', verifiedOn: '2026-09-11' },
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// SMTP round-trip probe for email-smtp-resend.
|
|
2
|
+
//
|
|
3
|
+
// Boots the fixture SMTP catch-all on 127.0.0.1 and dials it via the
|
|
4
|
+
// fixture's sendViaSmtp helper. Asserts the transcript reports 250 Ok
|
|
5
|
+
// on MAIL/RCPT/DATA and that the server's recorded envelope carries
|
|
6
|
+
// the sender, recipient and body bytes.
|
|
7
|
+
//
|
|
8
|
+
// The nearest shipped AC is AC-4101-3 ("Exactly one SMTP submission
|
|
9
|
+
// is dispatched per adapter call on the successful path"). This row
|
|
10
|
+
// observes a local catch-all SMTP dispatch, not Resend's SMTP endpoint,
|
|
11
|
+
// and does not go through the send adapter. Row de-claimed
|
|
12
|
+
// (conformanceOnly, anchorAcId=null) with the limitation naming
|
|
13
|
+
// AC-4101-3.
|
|
14
|
+
import { createCatchAllSmtp, sendViaSmtp } from '../../../../packages/rcf-lite/test/fixtures/probe-pack-email-smtp-resend/src/smtp-catch-all.mjs';
|
|
15
|
+
import { envPort } from './probe-utils.mjs';
|
|
16
|
+
|
|
17
|
+
export const anchorAcId = 'AC-4101-3';
|
|
18
|
+
export const accountBound = false;
|
|
19
|
+
const LIM_4101_3 = `AC-4101-3: requires exactly one SMTP submission per adapter call on the successful path. This row observes a local catch-all SMTP dispatch via a helper (sendViaSmtp), not a call through the send adapter, and the transport is not the Resend SMTP endpoint.`;
|
|
20
|
+
|
|
21
|
+
export default async function runProbe() {
|
|
22
|
+
const srv = createCatchAllSmtp();
|
|
23
|
+
const { port } = await srv.listen(envPort('RCF_FIXTURE_SMTP_PORT'));
|
|
24
|
+
const results = [];
|
|
25
|
+
let outcome;
|
|
26
|
+
try {
|
|
27
|
+
outcome = await sendViaSmtp({ host: '127.0.0.1', port, from: 'probe@verified.example', to: 'x@example.com', subject: 'probe', body: 'hi\n' });
|
|
28
|
+
const queuedLine = outcome.transcript.find((l) => l.startsWith('250') && l.includes('queued as '));
|
|
29
|
+
const idFromServer = queuedLine ? queuedLine.split('queued as ')[1] : null;
|
|
30
|
+
const recorded = srv.messages[0];
|
|
31
|
+
results.push({
|
|
32
|
+
anchorAcId: null,
|
|
33
|
+
conformanceOnly: true,
|
|
34
|
+
limitation: LIM_4101_3,
|
|
35
|
+
verdict: outcome.ok && queuedLine && recorded && recorded.from === 'probe@verified.example' && recorded.to[0] === 'x@example.com' ? 'pass' : 'fail',
|
|
36
|
+
detail: `observed local SMTP round-trip via sendViaSmtp ok=${outcome.ok}; queuedId=${idFromServer}; server recorded envelope from=${recorded?.from} to=${recorded?.to?.[0]}. Not the Resend endpoint; not through the send adapter.`,
|
|
37
|
+
evidence: { queuedLine, messageId: idFromServer, envelope: recorded ? { from: recorded.from, to: recorded.to, dataExcerpt: recorded.dataText?.slice(0, 200) } : null },
|
|
38
|
+
});
|
|
39
|
+
} finally {
|
|
40
|
+
await srv.close();
|
|
41
|
+
}
|
|
42
|
+
return { results, extra: { envDeclared: ['RCF_FIXTURE_SMTP_PORT'], port, transcript: outcome?.transcript } };
|
|
43
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Unverified-sender-refusal probe for email-smtp-resend.
|
|
2
|
+
//
|
|
3
|
+
// Routes an offline unverified-sender send through the fixture
|
|
4
|
+
// email-delivery adapter (which realises TAC-401.interfaces.send)
|
|
5
|
+
// with a catch-all SMTP provider seam behind it. The catch-all
|
|
6
|
+
// fixture is booted in unverified-sender mode, so the underlying
|
|
7
|
+
// SMTP reply is 550 5.7.1; the provider seam classifies that to
|
|
8
|
+
// RESEND_SENDER_UNVERIFIED, and the ADAPTER returns the refusal
|
|
9
|
+
// outcome record { ok:false, providerStatus, providerMessageId:null,
|
|
10
|
+
// error: 'RESEND_SENDER_UNVERIFIED: ...' }.
|
|
11
|
+
//
|
|
12
|
+
// AC-4102-1: the adapter's `error` begins with 'RESEND_SENDER_UNVERIFIED'
|
|
13
|
+
// (adapter refusal outcome).
|
|
14
|
+
// AC-4102-2: recipient, subject, textBody do not appear on the
|
|
15
|
+
// adapter's returned `error`, on any line emitted to the adapter's
|
|
16
|
+
// injected log sink during the call, or on any exception the adapter
|
|
17
|
+
// throws.
|
|
18
|
+
// Every detail line begins with the first eight words of the AC text.
|
|
19
|
+
import { createCatchAllSmtp } from '../../../../packages/rcf-lite/test/fixtures/probe-pack-email-smtp-resend/src/smtp-catch-all.mjs';
|
|
20
|
+
import { createSendAdapter, createCatchAllSmtpProvider } from '../../../../packages/rcf-lite/test/fixtures/probe-pack-email-smtp-resend/src/send-adapter.mjs';
|
|
21
|
+
import { envPort } from './probe-utils.mjs';
|
|
22
|
+
|
|
23
|
+
// the strict-evidence contract tightening: the refusal is driven by a local catch-all
|
|
24
|
+
// SMTP fixture, which is a fixture-as-engine substitute for the
|
|
25
|
+
// Resend provider; the outcome record carries no Resend-returned
|
|
26
|
+
// message id or request id (providerMessageId is required to be
|
|
27
|
+
// null on the refusal). Both rows are de-claimed to conformanceOnly
|
|
28
|
+
// naming AC-4102-1 and AC-4102-2. The Resend API is not driven for
|
|
29
|
+
// this refusal because there is no way to elicit an unverified-sender
|
|
30
|
+
// refusal on Resend without an unverified sender identity available
|
|
31
|
+
// to the harness.
|
|
32
|
+
// The module anchor names the AC this probe observes as a property;
|
|
33
|
+
// individual rows may still de-claim (conformanceOnly) when the
|
|
34
|
+
// evidence shape does not carry an engine-returned identifier.
|
|
35
|
+
export const anchorAcId = 'AC-4102-1';
|
|
36
|
+
export const accountBound = false;
|
|
37
|
+
const AC1 = 'When the provider refuses the submission because the';
|
|
38
|
+
const AC2 = 'On any adapter refusal, the recipient address, subject,';
|
|
39
|
+
const LIM_4102_1 = `AC-4102-1: requires the refusal outcome shape returned by the Resend send interface when the provider refuses the submission. This probe drives a local catch-all SMTP fixture (fixture-as-engine), not the Resend API, and the adapter's error string is derived content rather than a Resend-returned identifier; the identifier half of the strict-evidence contract is not satisfied here.`;
|
|
40
|
+
const LIM_4102_2 = `AC-4102-2: requires the refusal outcome from the same Resend send interface to hold no recipient/subject/body echo across the returned error, adapter log lines, and thrown exception. This probe observes the property against the local catch-all SMTP fixture; the row is de-claimed because the observation is fixture-as-engine and carries no Resend-returned identifier.`;
|
|
41
|
+
|
|
42
|
+
export default async function runProbe() {
|
|
43
|
+
const srv = createCatchAllSmtp();
|
|
44
|
+
srv.setUnverifiedSenderMode(true);
|
|
45
|
+
const { port } = await srv.listen(envPort('RCF_FIXTURE_SMTP_PORT'));
|
|
46
|
+
const results = [];
|
|
47
|
+
const distinctiveRecipient = 'distinct-recipient@example.test';
|
|
48
|
+
const distinctiveSubject = 'DISTINCT-SUBJECT-LINE-XYZ';
|
|
49
|
+
const distinctiveBody = 'DISTINCT-BODY-BYTES-ABC123-DO-NOT-LEAK';
|
|
50
|
+
const emittedLines = [];
|
|
51
|
+
let outcome;
|
|
52
|
+
let thrownMessage = null;
|
|
53
|
+
try {
|
|
54
|
+
const provider = createCatchAllSmtpProvider({ host: '127.0.0.1', port, from: 'unverified@somewhere.example' });
|
|
55
|
+
const adapter = createSendAdapter({ provider, logSink: (l) => emittedLines.push(l) });
|
|
56
|
+
try {
|
|
57
|
+
outcome = await adapter.send({ to: distinctiveRecipient, subject: distinctiveSubject, textBody: distinctiveBody, htmlBody: null });
|
|
58
|
+
} catch (e) {
|
|
59
|
+
thrownMessage = e?.message ?? String(e);
|
|
60
|
+
}
|
|
61
|
+
const errorString = outcome?.error ?? '';
|
|
62
|
+
const startsWithClass = errorString.startsWith('RESEND_SENDER_UNVERIFIED');
|
|
63
|
+
const recipientInError = errorString.toLowerCase().includes(distinctiveRecipient.toLowerCase());
|
|
64
|
+
const subjectInError = errorString.includes(distinctiveSubject);
|
|
65
|
+
const bodyInError = errorString.includes(distinctiveBody);
|
|
66
|
+
const recipientInLogs = emittedLines.some((l) => l.toLowerCase().includes(distinctiveRecipient.toLowerCase()));
|
|
67
|
+
const subjectInLogs = emittedLines.some((l) => l.includes(distinctiveSubject));
|
|
68
|
+
const bodyInLogs = emittedLines.some((l) => l.includes(distinctiveBody));
|
|
69
|
+
const recipientInThrown = Boolean(thrownMessage && thrownMessage.toLowerCase().includes(distinctiveRecipient.toLowerCase()));
|
|
70
|
+
const subjectInThrown = Boolean(thrownMessage && thrownMessage.includes(distinctiveSubject));
|
|
71
|
+
const bodyInThrown = Boolean(thrownMessage && thrownMessage.includes(distinctiveBody));
|
|
72
|
+
const cleanCall = !recipientInError && !subjectInError && !bodyInError && !recipientInLogs && !subjectInLogs && !bodyInLogs && !recipientInThrown && !subjectInThrown && !bodyInThrown;
|
|
73
|
+
// AC-4102-1 refusal outcome: the strict-evidence contract requires the row to
|
|
74
|
+
// assert BOTH a valid providerStatus AND providerMessageId===null
|
|
75
|
+
// alongside the RESEND_SENDER_UNVERIFIED class prefix; the shape
|
|
76
|
+
// is owned on TAC-401-email-smtp-resend-send-adapter.interfaces.send.
|
|
77
|
+
const providerStatusValid = typeof outcome?.providerStatus === 'number' && Number.isInteger(outcome.providerStatus) && outcome.providerStatus > 0;
|
|
78
|
+
const providerMessageIdIsNull = outcome?.providerMessageId === null;
|
|
79
|
+
results.push({
|
|
80
|
+
anchorAcId: null,
|
|
81
|
+
conformanceOnly: true,
|
|
82
|
+
limitation: LIM_4102_1,
|
|
83
|
+
verdict: outcome?.ok === false && startsWithClass && providerStatusValid && providerMessageIdIsNull && thrownMessage === null ? 'pass' : 'fail',
|
|
84
|
+
detail: `observed adapter.send() against the local catch-all SMTP fixture: ok=${outcome?.ok} providerStatus=${outcome?.providerStatus} providerStatusValid=${providerStatusValid} providerMessageId=${JSON.stringify(outcome?.providerMessageId ?? null)} providerMessageIdIsNull=${providerMessageIdIsNull} error='${errorString}' startsWithClass=${startsWithClass} thrown=${thrownMessage === null ? 'null' : `'${thrownMessage}'`}. Fixture-as-engine; Resend API not called for this refusal.`,
|
|
85
|
+
evidence: { ok: outcome?.ok, providerStatus: outcome?.providerStatus, providerStatusValid, providerMessageIdIsNull, errorString, startsWithClass, thrownMessage, code: outcome?.providerStatus, messageId: outcome?.providerMessageId ?? null, lastLine: emittedLines[emittedLines.length - 1] ?? null, bodyExcerpt: `refusal ok=${outcome?.ok} providerStatus=${outcome?.providerStatus} error='${errorString}'` },
|
|
86
|
+
});
|
|
87
|
+
results.push({
|
|
88
|
+
anchorAcId: null,
|
|
89
|
+
conformanceOnly: true,
|
|
90
|
+
limitation: LIM_4102_2,
|
|
91
|
+
verdict: cleanCall && srv.messages.length === 0 ? 'pass' : 'fail',
|
|
92
|
+
detail: `observed recipient/subject/body in adapter.error=${recipientInError}/${subjectInError}/${bodyInError}; in emitted log lines=${recipientInLogs}/${subjectInLogs}/${bodyInLogs}; in thrown exception=${recipientInThrown}/${subjectInThrown}/${bodyInThrown}; server accepted messages=${srv.messages.length} (must be 0 on unverified-sender refusal). Fixture-as-engine; Resend API not called for this refusal.`,
|
|
93
|
+
evidence: { recipientInError, subjectInError, bodyInError, recipientInLogs, subjectInLogs, bodyInLogs, recipientInThrown, subjectInThrown, bodyInThrown, serverAcceptedMessages: srv.messages.length, errorString, recipientInRefusal: recipientInError, lastLine: emittedLines[emittedLines.length - 1] ?? null, emittedLines, bodyExcerpt: `cleanCall=${cleanCall} serverAcceptedMessages=${srv.messages.length}` },
|
|
94
|
+
});
|
|
95
|
+
} finally {
|
|
96
|
+
await srv.close();
|
|
97
|
+
}
|
|
98
|
+
return { results, extra: { envDeclared: ['RCF_FIXTURE_SMTP_PORT'], port, adapterOutcome: outcome, emittedLogLines: emittedLines, thrownMessage } };
|
|
99
|
+
}
|
|
@@ -10,7 +10,7 @@ The neutrality rule (round-2 amendment) applies: `email-smtp-resend` ships alone
|
|
|
10
10
|
|
|
11
11
|
## Id number bands (registry bootstrap)
|
|
12
12
|
|
|
13
|
-
AC ids (and therefore US numeric ids, which anchor them) are NOT namespaced by the 0.4.4 schema grammar; the band allocation IS the AC-collision enforcement mechanism. Composing blueprints take a fresh band rather than proposing namespaced AC ids. Band allocation is
|
|
13
|
+
AC ids (and therefore US numeric ids, which anchor them) are NOT namespaced by the 0.4.4 schema grammar; the band allocation IS the AC-collision enforcement mechanism. Composing blueprints take a fresh band rather than proposing namespaced AC ids. Band allocation is policy; this table is the shared registry-bootstrap replicated across every shipped and forthcoming blueprint's `docs/topics.md` until a mechanism-side central registry lands.
|
|
14
14
|
|
|
15
15
|
This table is maintained shelf-wide across every blueprint's `docs/topics.md`. Rows are recorded at ship, never predicted.
|
|
16
16
|
|
|
@@ -55,8 +55,7 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
55
55
|
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
56
56
|
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
57
57
|
|
|
58
|
-
US 4101-4106 sit at the LOW end of the 4101-4899 band on purpose. A project-side story that mechanically derives from an email-smtp-resend REQ id into the number `4106` (leading `4` + sequence `106`) would collide against email-smtp-resend-US-4106 in this package; the band leaves headroom at the HIGH end (US 4181-4899) so a project's own stories anchored to email-smtp-resend REQs can allocate without conflict.
|
|
59
|
-
|
|
58
|
+
US 4101-4106 sit at the LOW end of the 4101-4899 band on purpose. A project-side story that mechanically derives from an email-smtp-resend REQ id into the number `4106` (leading `4` + sequence `106`) would collide against email-smtp-resend-US-4106 in this package; the band leaves headroom at the HIGH end (US 4181-4899) so a project's own stories anchored to email-smtp-resend REQs can allocate without conflict.
|
|
60
59
|
## Shared expectations for future composing blueprints
|
|
61
60
|
|
|
62
61
|
- The mail-adapter contract itself is owned by the magic-link blueprint's `TAC-504-security-auth-magic-link-email-delivery-adapter`, not by this blueprint. A sibling `email-smtp-<othervendor>` blueprint that plugs into the same slot inherits the four-class error taxonomy (`RESEND_*` codes generalise to a `<VENDOR>_*` prefix on the sibling; the class semantics stay the same), the retry-and-backoff posture (ADR-402 is a supersede target), and the webhook signature-and-replay discipline (the header names, the algorithm identifier, and the tolerance window remain configuration references; the vendor's specifics live on the sibling's own `docs/topics.md`).
|