rcf-lite 0.20.0 → 0.22.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 +39 -0
- package/blueprints/application-account-settings/CHANGELOG.md +12 -0
- package/blueprints/application-account-settings/README.md +114 -0
- package/blueprints/application-account-settings/blueprint.json +234 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2601-application-account-settings-capability-vocabulary.json +20 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +20 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2603-application-account-settings-theme-persistence.json +20 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2604-application-account-settings-reauth-window.json +20 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-001.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-002.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-003.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-004.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-005.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-006.json +18 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2601-application-account-settings-shell.json +41 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2602-application-account-settings-capability-discovery.json +28 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2603-application-account-settings-hosted-ui-bridge.json +35 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2604-application-account-settings-session-store.json +40 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25101.json +34 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25102.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25103.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25104.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25105.json +33 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25106.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25107.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25108.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25109.json +33 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25110.json +27 -0
- package/blueprints/application-account-settings/docs/topics.md +48 -0
- package/blueprints/application-account-settings/guide/application-account-settings.md +30 -0
- package/blueprints/application-account-settings/probe-packs/application-account-settings.pack.mjs +246 -0
- package/blueprints/application-admin-console/CHANGELOG.md +11 -0
- package/blueprints/application-admin-console/README.md +98 -0
- package/blueprints/application-admin-console/blueprint.json +226 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +25 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2202-application-admin-console-baseline-roles.json +25 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2203-application-admin-console-invite-transport.json +20 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2204-application-admin-console-audit-retention.json +20 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-001.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-002.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-003.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-004.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-005.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-006.json +18 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2201-application-admin-console-shell.json +40 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2202-application-admin-console-capability-discovery.json +44 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2203-application-admin-console-permission-matrix.json +34 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2204-application-admin-console-audit-view.json +40 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21101.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21102.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21103.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21104.json +28 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21105.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21106.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21107.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21108.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21109.json +33 -0
- package/blueprints/application-admin-console/docs/topics.md +42 -0
- package/blueprints/application-admin-console/guide/application-admin-console.md +29 -0
- package/blueprints/application-admin-console/probe-packs/application-admin-console.pack.mjs +182 -0
- package/blueprints/application-api-rest/docs/topics.md +13 -1
- package/blueprints/application-charts/CHANGELOG.md +12 -0
- package/blueprints/application-charts/README.md +73 -0
- package/blueprints/application-charts/blueprint.json +26 -0
- package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +25 -0
- package/blueprints/application-charts/contributions/adrs/adr-1902-application-charts-accessible-palette.json +25 -0
- package/blueprints/application-charts/contributions/adrs/adr-1903-application-charts-motion.json +25 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-003.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-004.json +15 -0
- package/blueprints/application-charts/contributions/tacs/tac-1901-application-charts-render-shell.json +42 -0
- package/blueprints/application-charts/contributions/tacs/tac-1902-application-charts-keyboard-traversal.json +40 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18102.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18103.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18104.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18105.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +35 -0
- package/blueprints/application-charts/docs/topics.md +44 -0
- package/blueprints/application-charts/guide/application-charts.md +44 -0
- package/blueprints/application-charts/probe-packs/application-charts.pack.mjs +191 -0
- package/blueprints/application-dashboard/CHANGELOG.md +10 -0
- package/blueprints/application-dashboard/README.md +102 -0
- package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +124 -0
- package/blueprints/application-dashboard/blueprint.json +29 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +25 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +25 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2003-application-dashboard-export-formats.json +25 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-001.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-004.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-005.json +15 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2001-application-dashboard-tile-grid.json +47 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +41 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +35 -0
- package/blueprints/application-dashboard/docs/topics.md +50 -0
- package/blueprints/application-dashboard/guide/application-dashboard.md +48 -0
- package/blueprints/application-dashboard/probe-packs/application-dashboard.pack.mjs +231 -0
- package/blueprints/application-datatable/CHANGELOG.md +8 -0
- package/blueprints/application-datatable/README.md +43 -0
- package/blueprints/application-datatable/blueprint.json +33 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1801-application-datatable-pattern-choice.json +25 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1802-application-datatable-url-state.json +20 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1803-application-datatable-page-size.json +20 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1804-application-datatable-selection-persistence.json +20 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-001.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-002.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-003.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-004.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-005.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +15 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1801-application-datatable-shell.json +50 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1802-application-datatable-query-adapter.json +39 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1803-application-datatable-selection-model.json +28 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17101.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17102.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17103.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17104.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17105.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17106.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17107.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17108.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17109.json +44 -0
- package/blueprints/application-datatable/docs/topics.md +42 -0
- package/blueprints/application-datatable/guide/application-datatable.md +38 -0
- package/blueprints/application-datatable/probe-packs/application-datatable.pack.mjs +240 -0
- package/blueprints/application-empty-error-states/CHANGELOG.md +9 -0
- package/blueprints/application-empty-error-states/README.md +88 -0
- package/blueprints/application-empty-error-states/blueprint.json +119 -0
- package/blueprints/application-empty-error-states/contributions/adrs/adr-2301-application-empty-error-states-status-contract.json +25 -0
- package/blueprints/application-empty-error-states/contributions/adrs/adr-2302-application-empty-error-states-stack-trace-visibility.json +25 -0
- package/blueprints/application-empty-error-states/contributions/adrs/adr-2303-application-empty-error-states-offline-strategy.json +25 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-001.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-002.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-003.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-004.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-005.json +18 -0
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2301-application-empty-error-states-state-machine.json +46 -0
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2302-application-empty-error-states-recovery-router.json +36 -0
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2303-application-empty-error-states-offline-buffer.json +40 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22101.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22102.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22103.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22104.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22105.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22106.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22107.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22108.json +29 -0
- package/blueprints/application-empty-error-states/docs/topics.md +53 -0
- package/blueprints/application-empty-error-states/guide/application-empty-error-states.md +50 -0
- package/blueprints/application-empty-error-states/probe-packs/application-empty-error-states.pack.mjs +284 -0
- package/blueprints/application-error-handling/docs/topics.md +12 -0
- package/blueprints/application-file-upload/CHANGELOG.md +9 -0
- package/blueprints/application-file-upload/README.md +85 -0
- package/blueprints/application-file-upload/blueprint.json +114 -0
- package/blueprints/application-file-upload/contributions/adrs/adr-2401-application-file-upload-transport.json +25 -0
- package/blueprints/application-file-upload/contributions/adrs/adr-2402-application-file-upload-accepted-set.json +25 -0
- package/blueprints/application-file-upload/contributions/adrs/adr-2403-application-file-upload-virus-scan.json +25 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +18 -0
- package/blueprints/application-file-upload/contributions/tacs/tac-2401-application-file-upload-input.json +46 -0
- package/blueprints/application-file-upload/contributions/tacs/tac-2402-application-file-upload-transport.json +47 -0
- package/blueprints/application-file-upload/contributions/tacs/tac-2403-application-file-upload-progress-announcer.json +46 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23101.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23102.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23103.json +29 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23104.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23105.json +29 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23106.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23107.json +28 -0
- package/blueprints/application-file-upload/docs/topics.md +58 -0
- package/blueprints/application-file-upload/guide/application-file-upload.md +48 -0
- package/blueprints/application-file-upload/probe-packs/application-file-upload.pack.mjs +238 -0
- package/blueprints/application-forms-wizard/CHANGELOG.md +9 -0
- package/blueprints/application-forms-wizard/README.md +102 -0
- package/blueprints/application-forms-wizard/blueprint.json +120 -0
- package/blueprints/application-forms-wizard/contributions/adrs/adr-2501-application-forms-wizard-navigation.json +25 -0
- package/blueprints/application-forms-wizard/contributions/adrs/adr-2502-application-forms-wizard-save-and-return.json +25 -0
- package/blueprints/application-forms-wizard/contributions/adrs/adr-2503-application-forms-wizard-step-indicator.json +25 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +18 -0
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2501-application-forms-wizard-task-list.json +46 -0
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2502-application-forms-wizard-error-summary.json +40 -0
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2503-application-forms-wizard-draft-store.json +40 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24101.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24102.json +29 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24103.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24104.json +29 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24105.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24106.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24107.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24108.json +29 -0
- package/blueprints/application-forms-wizard/docs/topics.md +49 -0
- package/blueprints/application-forms-wizard/guide/application-forms-wizard.md +48 -0
- package/blueprints/application-forms-wizard/probe-packs/application-forms-wizard.pack.mjs +233 -0
- package/blueprints/application-notifications-in-app/CHANGELOG.md +9 -0
- package/blueprints/application-notifications-in-app/README.md +80 -0
- package/blueprints/application-notifications-in-app/blueprint.json +30 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2102-application-notifications-in-app-toast-timeout-floor.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2103-application-notifications-in-app-retention-window.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-001.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-002.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-003.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-004.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-005.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +46 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +52 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2103-application-notifications-in-app-preferences.json +40 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20104.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20106.json +26 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20107.json +26 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20108.json +26 -0
- package/blueprints/application-notifications-in-app/docs/topics.md +46 -0
- package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +47 -0
- package/blueprints/application-notifications-in-app/probe-packs/application-notifications-in-app.pack.mjs +328 -0
- package/blueprints/application-onboarding-tour/CHANGELOG.md +12 -0
- package/blueprints/application-onboarding-tour/README.md +77 -0
- package/blueprints/application-onboarding-tour/blueprint.json +164 -0
- package/blueprints/application-onboarding-tour/contributions/adrs/adr-2701-application-onboarding-tour-dismissal-policy.json +20 -0
- package/blueprints/application-onboarding-tour/contributions/adrs/adr-2702-application-onboarding-tour-completion-store-shape.json +20 -0
- package/blueprints/application-onboarding-tour/contributions/adrs/adr-2703-application-onboarding-tour-checklist-anchor.json +20 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-001.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-002.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-003.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-004.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2701-application-onboarding-tour-step-runner.json +41 -0
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2702-application-onboarding-tour-checklist-slot.json +35 -0
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2703-application-onboarding-tour-completion-store.json +34 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26101.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26102.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26103.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26104.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26105.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26106.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26107.json +27 -0
- package/blueprints/application-onboarding-tour/docs/topics.md +48 -0
- package/blueprints/application-onboarding-tour/guide/application-onboarding-tour.md +59 -0
- package/blueprints/application-onboarding-tour/probe-packs/application-onboarding-tour.pack.mjs +231 -0
- package/blueprints/application-spa/docs/topics.md +13 -1
- package/blueprints/delivery-ci-workflows/docs/topics.md +13 -1
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +13 -1
- package/blueprints/email-smtp-resend/docs/topics.md +13 -1
- package/blueprints/object-storage-s3/CHANGELOG.md +13 -0
- package/blueprints/object-storage-s3/README.md +108 -0
- package/blueprints/object-storage-s3/blueprint.json +72 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2901-object-storage-s3-adapter.json +30 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2902-object-storage-s3-presigned-ttl-floor.json +25 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2903-object-storage-s3-multipart-threshold.json +25 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2904-object-storage-s3-contract.json +25 -0
- package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +103 -0
- package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +43 -0
- package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +84 -0
- package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +101 -0
- package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +85 -0
- package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +84 -0
- package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +64 -0
- package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +10 -0
- package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +7 -0
- package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-001.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-002.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-003.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-004.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-005.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +18 -0
- package/blueprints/object-storage-s3/contributions/tacs/tac-2901-object-storage-s3-facade.json +57 -0
- package/blueprints/object-storage-s3/contributions/tacs/tac-2902-object-storage-s3-multipart-uploader.json +36 -0
- package/blueprints/object-storage-s3/contributions/tacs/tac-2903-object-storage-s3-event-sink.json +36 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28101.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28102.json +43 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28103.json +25 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28104.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28105.json +25 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28106.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28107.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28108.json +34 -0
- package/blueprints/object-storage-s3/docs/topics.md +62 -0
- package/blueprints/object-storage-s3/guide/object-storage-s3.md +207 -0
- package/blueprints/observability-essentials/docs/topics.md +13 -1
- package/blueprints/observability-logging/CHANGELOG.md +9 -0
- package/blueprints/observability-logging/README.md +4 -1
- package/blueprints/observability-logging/blueprint.json +114 -21
- package/blueprints/observability-logging/docs/topics.md +12 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +13 -1
- package/blueprints/persistence-data-d1/docs/topics.md +13 -1
- package/blueprints/persistence-data-postgres/CHANGELOG.md +12 -0
- package/blueprints/persistence-data-postgres/README.md +101 -0
- package/blueprints/persistence-data-postgres/blueprint.json +80 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +30 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2802-persistence-data-postgres-migration-shape.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2803-persistence-data-postgres-runner-mode.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2804-persistence-data-postgres-recovery.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2805-persistence-data-postgres-connection-pool-posture.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +56 -0
- package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +75 -0
- package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +56 -0
- package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +186 -0
- package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +76 -0
- package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +173 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-facade-round-trip.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-migration-apply.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-pool-posture-smoke.mjs +9 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-prepared-statement-scan.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-recovery-restore-round-trip.mjs +9 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-transaction-atomicity.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +79 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-001.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-002.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-004.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-005.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-006.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-007.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2801-persistence-data-postgres-facade.json +58 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2802-persistence-data-postgres-migration-runner.json +40 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2803-persistence-data-postgres-transaction-helper.json +35 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2804-persistence-data-postgres-recovery-runner.json +40 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27101.json +34 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27102.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27103.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27104.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27105.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27106.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27107.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27108.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27109.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27110.json +25 -0
- package/blueprints/persistence-data-postgres/docs/topics.md +64 -0
- package/blueprints/persistence-data-postgres/guide/persistence-data-postgres.md +172 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +13 -1
- package/blueprints/security-auth-clerk/CHANGELOG.md +9 -0
- package/blueprints/security-auth-clerk/README.md +3 -0
- package/blueprints/security-auth-clerk/blueprint.json +147 -29
- package/blueprints/security-auth-clerk/docs/topics.md +13 -1
- package/blueprints/security-auth-keycloak/CHANGELOG.md +9 -0
- package/blueprints/security-auth-keycloak/README.md +3 -0
- package/blueprints/security-auth-keycloak/blueprint.json +182 -36
- package/blueprints/security-auth-keycloak/docs/topics.md +13 -1
- package/blueprints/security-auth-magic-link/CHANGELOG.md +9 -0
- package/blueprints/security-auth-magic-link/README.md +3 -0
- package/blueprints/security-auth-magic-link/blueprint.json +159 -32
- package/blueprints/security-auth-magic-link/docs/topics.md +13 -1
- package/blueprints/security-auth-oauth2/CHANGELOG.md +9 -0
- package/blueprints/security-auth-oauth2/README.md +3 -0
- package/blueprints/security-auth-oauth2/blueprint.json +158 -31
- package/blueprints/security-auth-oauth2/docs/topics.md +13 -1
- package/blueprints/security-secrets-management/CHANGELOG.md +11 -0
- package/blueprints/security-secrets-management/blueprint.json +2 -1
- package/blueprints/security-secrets-management/docs/topics.md +13 -1
- package/fixtures/canary-manifest.json +9 -9
- package/package.json +2 -2
- package/rcf/code-nodes/cn-106.json +13 -0
- package/rcf/code-nodes/cn-107.json +14 -0
- package/rcf/code-nodes/cn-108.json +13 -0
- package/rcf/code-nodes/cn-109.json +12 -0
- package/rcf/code-nodes/cn-110.json +12 -0
- package/rcf/code-nodes/cn-111.json +14 -0
- package/rcf/code-nodes/cn-112.json +14 -0
- package/rcf/code-nodes/cn-113.json +12 -0
- package/rcf/code-nodes/cn-114.json +13 -0
- package/rcf/code-nodes/cn-115.json +13 -0
- package/rcf/code-nodes/cn-116.json +12 -0
- package/rcf/code-nodes/cn-117.json +13 -0
- package/rcf/code-nodes/cn-118.json +13 -0
- package/rcf/code-nodes/cn-119.json +13 -0
- package/rcf/code-nodes/cn-120.json +13 -0
- package/rcf/code-nodes/cn-121.json +12 -0
- package/rcf/code-nodes/cn-122.json +12 -0
- package/rcf/code-nodes/cn-123.json +13 -0
- package/rcf/code-nodes/cn-124.json +13 -0
- package/rcf/code-nodes/cn-125.json +13 -0
- package/rcf/code-nodes/cn-126.json +13 -0
- package/rcf/code-nodes/cn-127.json +12 -0
- package/rcf/code-nodes/cn-128.json +14 -0
- package/rcf/code-nodes/cn-129.json +14 -0
- package/rcf/code-nodes/cn-130.json +14 -0
- package/rcf/code-nodes/cn-131.json +15 -0
- package/rcf/code-nodes/cn-132.json +12 -0
- package/rcf/code-nodes/cn-133.json +13 -0
- package/rcf/code-nodes/cn-134.json +13 -0
- package/rcf/code-nodes/cn-135.json +12 -0
- package/rcf/code-nodes/cn-136.json +13 -0
- package/rcf/code-nodes/cn-137.json +13 -0
- package/rcf/code-nodes/cn-138.json +12 -0
- package/rcf/code-nodes/cn-139.json +12 -0
- package/rcf/code-nodes/cn-140.json +13 -0
- package/rcf/code-nodes/cn-141.json +13 -0
- package/rcf/code-nodes/cn-142.json +12 -0
- package/rcf/code-nodes/cn-143.json +13 -0
- package/rcf/code-nodes/cn-144.json +13 -0
- package/rcf/code-nodes/cn-145.json +12 -0
- package/rcf/code-nodes/cn-146.json +12 -0
- package/rcf/code-nodes/cn-147.json +13 -0
- package/rcf/code-nodes/cn-148.json +13 -0
- package/rcf/code-nodes/cn-149.json +12 -0
- package/rcf/code-nodes/cn-150.json +13 -0
- package/rcf/code-nodes/cn-151.json +13 -0
- package/rcf/code-nodes/cn-152.json +12 -0
- package/rcf/code-nodes/cn-153.json +12 -0
- package/rcf/code-nodes/cn-154.json +13 -0
- package/rcf/code-nodes/cn-155.json +14 -0
- package/rcf/code-nodes/cn-156.json +13 -0
- package/rcf/code-nodes/cn-157.json +13 -0
- package/rcf/code-nodes/cn-158.json +12 -0
- package/rcf/code-nodes/cn-159.json +13 -0
- package/rcf/code-nodes/cn-160.json +12 -0
- package/rcf/code-nodes/cn-161.json +12 -0
- package/rcf/code-nodes/cn-162.json +13 -0
- package/rcf/code-nodes/cn-163.json +12 -0
- package/rcf/code-nodes/cn-164.json +13 -0
- package/rcf/code-nodes/cn-165.json +12 -0
- package/rcf/code-nodes/cn-166.json +12 -0
- package/rcf/code-nodes/cn-167.json +12 -0
- package/rcf/code-nodes/cn-168.json +12 -0
- package/rcf/code-nodes/cn-169.json +12 -0
- package/rcf/code-nodes/cn-170.json +12 -0
- package/rcf/code-nodes/cn-171.json +12 -0
- package/rcf/code-nodes/cn-172.json +12 -0
- package/rcf/code-nodes/cn-173.json +12 -0
- package/rcf/code-nodes/cn-174.json +12 -0
- package/rcf/code-nodes/cn-175.json +13 -0
- package/rcf/code-nodes/cn-176.json +12 -0
- package/rcf/code-nodes/cn-177.json +12 -0
- package/rcf/code-nodes/cn-178.json +12 -0
- package/rcf/code-nodes/cn-179.json +12 -0
- package/rcf/code-nodes/cn-180.json +13 -0
- package/rcf/code-nodes/cn-181.json +12 -0
- package/rcf/code-nodes/cn-182.json +13 -0
- package/rcf/code-nodes/cn-183.json +12 -0
- package/rcf/code-nodes/cn-184.json +13 -0
- package/rcf/code-nodes/cn-185.json +12 -0
- package/rcf/code-nodes/cn-186.json +12 -0
- package/rcf/code-nodes/cn-200.json +14 -0
- package/rcf/code-nodes/cn-201.json +13 -0
- package/rcf/code-nodes/cn-202.json +14 -0
- package/rcf/code-nodes/cn-203.json +14 -0
- package/rcf/code-nodes/cn-204.json +13 -0
- package/rcf/code-nodes/cn-205.json +14 -0
- package/rcf/fbs/fbs-036.json +22 -0
- package/rcf/fbs/fbs-037.json +19 -0
- package/rcf/fbs/fbs-038.json +19 -0
- package/rcf/fbs/fbs-039.json +21 -0
- package/rcf/fbs/fbs-040.json +20 -0
- package/rcf/fbs/fbs-041.json +13 -0
- package/rcf/fbs/fbs-042.json +13 -0
- package/rcf/fbs/fbs-043.json +23 -0
- package/rcf/fbs/fbs-044.json +23 -0
- package/rcf/fbs/fbs-045.json +23 -0
- package/rcf/fbs/fbs-046.json +24 -0
- package/rcf/fbs/fbs-047.json +24 -0
- package/rcf/fbs/fbs-060.json +22 -0
- package/rcf/fbs/fbs-061.json +20 -0
- package/rcf/requirements/req-017.json +18 -0
- package/rcf/requirements/req-018.json +18 -0
- package/rcf/requirements/req-019.json +38 -0
- package/rcf/requirements/req-020.json +13 -0
- package/rcf/requirements/req-021.json +13 -0
- package/rcf/requirements/req-022.json +13 -0
- package/rcf/requirements/req-023.json +14 -0
- package/rcf/requirements/req-024.json +69 -0
- package/rcf/requirements/req-025.json +59 -0
- package/rcf/requirements/req-026.json +154 -0
- package/rcf/requirements/req-027.json +33 -0
- package/rcf/requirements/req-028.json +13 -0
- package/rcf/requirements/req-040.json +13 -0
- package/rcf/requirements/req-041.json +125 -0
- package/rcf/test-suites/ts-046.json +78 -0
- package/rcf/test-suites/ts-047.json +54 -0
- package/rcf/test-suites/ts-048.json +54 -0
- package/rcf/test-suites/ts-049.json +70 -0
- package/rcf/test-suites/ts-050.json +69 -0
- package/rcf/test-suites/ts-051.json +22 -0
- package/rcf/test-suites/ts-052.json +20 -0
- package/rcf/test-suites/ts-053.json +70 -0
- package/rcf/test-suites/ts-054.json +70 -0
- package/rcf/test-suites/ts-055.json +77 -0
- package/rcf/test-suites/ts-056.json +78 -0
- package/rcf/test-suites/ts-057.json +78 -0
- package/rcf/test-suites/ts-070.json +62 -0
- package/rcf/test-suites/ts-071.json +62 -0
- package/rcf/user-stories/us-1701.json +56 -0
- package/rcf/user-stories/us-1801.json +40 -0
- package/rcf/user-stories/us-1901.json +40 -0
- package/rcf/user-stories/us-2001.json +50 -0
- package/rcf/user-stories/us-2101.json +45 -0
- package/rcf/user-stories/us-2201.json +60 -0
- package/rcf/user-stories/us-2301.json +51 -0
- package/rcf/user-stories/us-2401.json +62 -0
- package/rcf/user-stories/us-2501.json +58 -0
- package/rcf/user-stories/us-2601.json +51 -0
- package/rcf/user-stories/us-2701.json +55 -0
- package/rcf/user-stories/us-2801.json +55 -0
- package/rcf/user-stories/us-4001.json +69 -0
- package/rcf/user-stories/us-4101.json +69 -0
- package/releases/releases.yaml +21 -1
- package/src/blueprint/apply.js +107 -1
- package/src/blueprint/capabilities.js +357 -0
- package/src/blueprint/loader.js +247 -0
- package/src/browser-verify/boot.js +180 -0
- package/src/browser-verify/index.js +13 -0
- package/src/browser-verify/manifest-writer.js +31 -6
- package/src/browser-verify/pack-browser.js +294 -0
- package/src/browser-verify/pack-loader.js +176 -0
- package/src/browser-verify/pack-runner.js +193 -0
- package/src/browser-verify/pack-schema.js +155 -0
- package/src/browser-verify/runner.js +24 -1
- package/src/cli/blueprint.js +99 -0
- package/src/cli/browser-verify.js +147 -7
- package/src/core/errors/index.js +7 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
// Capability-declaration mechanism (visual round T-5 spec section
|
|
2
|
+
// 5.5.1, 5.5.2). Consumer blueprints gate their surfaces on the union
|
|
3
|
+
// of currently-applied blueprints' `capabilities[]` declarations.
|
|
4
|
+
//
|
|
5
|
+
// Why source read-back. The applied-blueprint-record schema in
|
|
6
|
+
// @stravica-ai/rcf-schemas is closed under additionalProperties:false
|
|
7
|
+
// (0.6.0), so `appliedCapabilities[]` cannot land on the manifest
|
|
8
|
+
// record without a schema bump. Rather than block the round on that
|
|
9
|
+
// dependency, this file adopts the core-companions T-2 gate precedent:
|
|
10
|
+
// read the source blueprint.json via manifest.blueprints[].source and
|
|
11
|
+
// union its declared capabilities[]. Per-project answers (elicits) and
|
|
12
|
+
// a per-project applied-capability snapshot are written to a sidecar
|
|
13
|
+
// file at rcf/blueprints/${slug}.applied.json.
|
|
14
|
+
//
|
|
15
|
+
// This file is imported by apply.js at apply time and by the shipped
|
|
16
|
+
// probe pack (blueprints/application-admin-console/probe-packs/) at
|
|
17
|
+
// verify time.
|
|
18
|
+
|
|
19
|
+
import { readFile, writeFile, mkdir, stat } from 'node:fs/promises';
|
|
20
|
+
import { dirname, join, resolve, isAbsolute } from 'node:path';
|
|
21
|
+
|
|
22
|
+
import { rcfError } from '../core/errors/index.js';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Read a single applied blueprint's declared capabilities via
|
|
26
|
+
* source read-back. Silently ignores an applied blueprint whose
|
|
27
|
+
* source path no longer exists (the record's ownership fact is the
|
|
28
|
+
* slug on the manifest; the source file is provenance and can move).
|
|
29
|
+
*
|
|
30
|
+
* @param {{ slug: string, source: string }} appliedRecord
|
|
31
|
+
* @param {string} projectRoot
|
|
32
|
+
* @returns {Promise<string[]>}
|
|
33
|
+
*/
|
|
34
|
+
export async function readAppliedBlueprintCapabilities(appliedRecord, projectRoot) {
|
|
35
|
+
if (!appliedRecord || typeof appliedRecord.source !== 'string') return [];
|
|
36
|
+
const src = appliedRecord.source;
|
|
37
|
+
// A qualified typed ref (`wsd:auth-oauth2`) never resolves as a file
|
|
38
|
+
// path. Skip it; the library-resolved source blueprint is not on
|
|
39
|
+
// this local tree.
|
|
40
|
+
if (/^[a-z][a-z0-9-]*:[a-z]/i.test(src) && !src.startsWith('/') && !src.startsWith('.')) return [];
|
|
41
|
+
const abs = isAbsolute(src) ? src : resolve(projectRoot, src);
|
|
42
|
+
const metaPath = join(abs, 'blueprint.json');
|
|
43
|
+
let raw;
|
|
44
|
+
try {
|
|
45
|
+
raw = await readFile(metaPath, 'utf8');
|
|
46
|
+
} catch {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const doc = JSON.parse(raw);
|
|
51
|
+
if (!Array.isArray(doc.capabilities)) return [];
|
|
52
|
+
return doc.capabilities.filter((s) => typeof s === 'string');
|
|
53
|
+
} catch {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Discover the union of applied capabilities across every applied
|
|
60
|
+
* blueprint on the tree.
|
|
61
|
+
*
|
|
62
|
+
* @param {Array<{ slug: string, source: string }>} appliedRecords
|
|
63
|
+
* @param {string} projectRoot
|
|
64
|
+
* @returns {Promise<{ union: string[], perSlug: Record<string, string[]> }>}
|
|
65
|
+
*/
|
|
66
|
+
export async function discoverAppliedCapabilities(appliedRecords, projectRoot) {
|
|
67
|
+
const perSlug = {};
|
|
68
|
+
const union = new Set();
|
|
69
|
+
for (const rec of appliedRecords ?? []) {
|
|
70
|
+
const caps = await readAppliedBlueprintCapabilities(rec, projectRoot);
|
|
71
|
+
perSlug[rec.slug] = caps;
|
|
72
|
+
for (const c of caps) union.add(c);
|
|
73
|
+
}
|
|
74
|
+
return { union: [...union].sort(), perSlug };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Build the refusal message for a requiresAppliedCapabilities gate.
|
|
79
|
+
* refusalMessageId maps to a known template; a message the loader
|
|
80
|
+
* accepts is used verbatim if the id is unknown (so a future
|
|
81
|
+
* blueprint can ship a bespoke refusal without a core code change).
|
|
82
|
+
*
|
|
83
|
+
* @param {object} args
|
|
84
|
+
* @param {string} args.slug applying blueprint slug
|
|
85
|
+
* @param {string} args.refusalMessageId
|
|
86
|
+
* @param {string[]} args.requiredCapabilities
|
|
87
|
+
* @param {Array<{ slug: string, version: string }>} args.appliedRecords
|
|
88
|
+
* @param {string} args.allowSkipFlag the CLI flag the operator can use to override
|
|
89
|
+
* @returns {string}
|
|
90
|
+
*/
|
|
91
|
+
export function buildRefusalMessage({ slug, refusalMessageId, requiredCapabilities, appliedRecords, allowSkipFlag }) {
|
|
92
|
+
// Applied blueprints list, one per line (indented 2 spaces per spec
|
|
93
|
+
// 5.5.1 formatting).
|
|
94
|
+
const appliedLines = (appliedRecords ?? [])
|
|
95
|
+
.map((r) => ` ${r.slug} v${r.version}`)
|
|
96
|
+
.join('\n');
|
|
97
|
+
const appliedBlock = appliedLines.length > 0 ? appliedLines : ' (none)';
|
|
98
|
+
if (refusalMessageId === 'application-admin-console-bare-spa') {
|
|
99
|
+
return [
|
|
100
|
+
`${slug} requires at least one applied security-auth-* blueprint,`,
|
|
101
|
+
`or an operator override with --${allowSkipFlag}.`,
|
|
102
|
+
'',
|
|
103
|
+
'Applied blueprints on this project:',
|
|
104
|
+
appliedBlock,
|
|
105
|
+
'',
|
|
106
|
+
'Suggested next steps:',
|
|
107
|
+
' 1. Apply an auth blueprint first:',
|
|
108
|
+
' rcf define blueprint add security-auth-magic-link',
|
|
109
|
+
' (or security-auth-clerk, security-auth-oauth2, security-auth-keycloak)',
|
|
110
|
+
` 2. Override for a scaffolding pass (surfaces will refuse at apply until an`,
|
|
111
|
+
` auth blueprint is applied):`,
|
|
112
|
+
` rcf define blueprint add ${slug} --${allowSkipFlag}`,
|
|
113
|
+
].join('\n');
|
|
114
|
+
}
|
|
115
|
+
if (refusalMessageId === 'application-account-settings-bare-spa') {
|
|
116
|
+
return [
|
|
117
|
+
`${slug} requires at least one applied security-auth-* blueprint,`,
|
|
118
|
+
`or an operator override with --${allowSkipFlag}.`,
|
|
119
|
+
'',
|
|
120
|
+
'Applied blueprints on this project:',
|
|
121
|
+
appliedBlock,
|
|
122
|
+
'',
|
|
123
|
+
'Suggested next steps:',
|
|
124
|
+
' 1. Apply an auth blueprint first:',
|
|
125
|
+
' rcf define blueprint add security-auth-magic-link',
|
|
126
|
+
' (or security-auth-clerk, security-auth-oauth2, security-auth-keycloak)',
|
|
127
|
+
` 2. Override for a scaffolding pass (surfaces will refuse at apply until an`,
|
|
128
|
+
` auth blueprint is applied):`,
|
|
129
|
+
` rcf define blueprint add ${slug} --${allowSkipFlag}`,
|
|
130
|
+
].join('\n');
|
|
131
|
+
}
|
|
132
|
+
if (refusalMessageId === 'object-storage-s3-no-secrets') {
|
|
133
|
+
return [
|
|
134
|
+
`[object-storage-s3-no-secrets] ${slug} requires an applied blueprint declaring`,
|
|
135
|
+
`at least one of: ${requiredCapabilities.join(', ')}.`,
|
|
136
|
+
`The shipped predecessor is security-secrets-management (v1.0.1+); the credential`,
|
|
137
|
+
`pair is a secretRef opaque string, never a value (infra round 5 spec 5.2, Baz`,
|
|
138
|
+
`decision 6).`,
|
|
139
|
+
'',
|
|
140
|
+
'Applied blueprints on this project:',
|
|
141
|
+
appliedBlock,
|
|
142
|
+
'',
|
|
143
|
+
'Suggested next steps:',
|
|
144
|
+
' 1. Apply security-secrets-management first:',
|
|
145
|
+
' rcf define blueprint add security-secrets-management',
|
|
146
|
+
` 2. Or override for a scaffolding pass (records a note on source.notes so`,
|
|
147
|
+
` later validation flags the surface as not-yet-activated):`,
|
|
148
|
+
` rcf define blueprint add ${slug} --${allowSkipFlag}`,
|
|
149
|
+
].join('\n');
|
|
150
|
+
}
|
|
151
|
+
// Generic fallback. Names the required capabilities and applied set;
|
|
152
|
+
// the operator has enough to diagnose without a bespoke template. The
|
|
153
|
+
// refusalMessageId is echoed on the first line as a stable dashboard-
|
|
154
|
+
// friendly tag downstream lint / dashboards can bind to.
|
|
155
|
+
const tag = refusalMessageId ? `[${refusalMessageId}] ` : '';
|
|
156
|
+
return [
|
|
157
|
+
`${tag}${slug} requires an applied blueprint declaring at least one of:`,
|
|
158
|
+
` ${requiredCapabilities.join(', ')}`,
|
|
159
|
+
`or an operator override with --${allowSkipFlag}.`,
|
|
160
|
+
'',
|
|
161
|
+
'Applied blueprints on this project:',
|
|
162
|
+
appliedBlock,
|
|
163
|
+
].join('\n');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Run the elicitation phase. Reads a bag of operator-supplied answers
|
|
168
|
+
* (`--answer <id>=<value>` merged with `--answers <file>` in the CLI),
|
|
169
|
+
* evaluates each elicit's `when` predicate against the discovered
|
|
170
|
+
* capability set, coerces the answer per kind, and returns a
|
|
171
|
+
* `{id: value}` map. A missing required answer for an elicit whose
|
|
172
|
+
* predicate fires refuses with a validation rcfError.
|
|
173
|
+
*
|
|
174
|
+
* @param {object} args
|
|
175
|
+
* @param {Array<object>} args.elicits from loader
|
|
176
|
+
* @param {string[]} args.appliedCapabilities discovered union
|
|
177
|
+
* @param {Record<string, string|boolean>} args.answers operator bag
|
|
178
|
+
* @returns {{value: Record<string, string|boolean|null>} | import('../core/errors/index.js').RcfError}
|
|
179
|
+
*/
|
|
180
|
+
export function runElicitationPhase({ elicits, appliedCapabilities, answers }) {
|
|
181
|
+
if (!Array.isArray(elicits) || elicits.length === 0) {
|
|
182
|
+
return { value: {} };
|
|
183
|
+
}
|
|
184
|
+
const capSet = new Set(appliedCapabilities ?? []);
|
|
185
|
+
const bag = answers ?? {};
|
|
186
|
+
const out = {};
|
|
187
|
+
for (const e of elicits) {
|
|
188
|
+
const gated = e.when ? Array.isArray(e.when.requiresCapability) && !e.when.requiresCapability.some((c) => capSet.has(c)) : false;
|
|
189
|
+
if (gated) continue;
|
|
190
|
+
const raw = bag[e.id];
|
|
191
|
+
let coerced;
|
|
192
|
+
if (raw === undefined || raw === null || raw === '') {
|
|
193
|
+
if (e.default === undefined) {
|
|
194
|
+
return rcfError({
|
|
195
|
+
kind: 'validation',
|
|
196
|
+
message: `blueprint apply: elicit '${e.id}' is required (no default declared) and no answer was supplied. Pass --answer ${e.id}=<value> or --answers <file>.`,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
coerced = e.default;
|
|
200
|
+
} else if (e.kind === 'boolean') {
|
|
201
|
+
if (typeof raw === 'boolean') coerced = raw;
|
|
202
|
+
else {
|
|
203
|
+
const s = String(raw).trim().toLowerCase();
|
|
204
|
+
if (s === 'y' || s === 'yes' || s === 'true' || s === '1') coerced = true;
|
|
205
|
+
else if (s === 'n' || s === 'no' || s === 'false' || s === '0') coerced = false;
|
|
206
|
+
else return rcfError({ kind: 'validation', message: `blueprint apply: elicit '${e.id}' expects a boolean; got '${raw}'.` });
|
|
207
|
+
}
|
|
208
|
+
} else if (e.kind === 'enum') {
|
|
209
|
+
const s = String(raw).trim();
|
|
210
|
+
if (!e.options.includes(s)) {
|
|
211
|
+
return rcfError({ kind: 'validation', message: `blueprint apply: elicit '${e.id}' expects one of [${e.options.join(', ')}]; got '${raw}'.` });
|
|
212
|
+
}
|
|
213
|
+
coerced = s;
|
|
214
|
+
} else {
|
|
215
|
+
coerced = String(raw).trim();
|
|
216
|
+
}
|
|
217
|
+
out[e.id] = coerced;
|
|
218
|
+
}
|
|
219
|
+
return { value: out };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Sidecar path for a blueprint's per-project apply-state (relative to
|
|
224
|
+
* the project root). One file per applied blueprint slug.
|
|
225
|
+
*/
|
|
226
|
+
export function sidecarRelPath(slug) {
|
|
227
|
+
return join('rcf', 'blueprints', `${slug}.applied.json`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Write the sidecar. Overwrites the file so re-apply on the same
|
|
232
|
+
* version is idempotent.
|
|
233
|
+
*
|
|
234
|
+
* @param {object} args
|
|
235
|
+
* @param {string} args.projectRoot
|
|
236
|
+
* @param {string} args.slug
|
|
237
|
+
* @param {string} args.version
|
|
238
|
+
* @param {string} args.appliedAt
|
|
239
|
+
* @param {string[]} args.appliedCapabilities
|
|
240
|
+
* @param {Record<string, string|boolean|null>} args.appliedElicitations
|
|
241
|
+
* @param {boolean} [args.allowNoAuthYet]
|
|
242
|
+
* @param {string} [args.notes]
|
|
243
|
+
*/
|
|
244
|
+
export async function writeSidecar({ projectRoot, slug, version, appliedAt, appliedCapabilities, appliedElicitations, allowNoAuthYet, notes }) {
|
|
245
|
+
const rel = sidecarRelPath(slug);
|
|
246
|
+
const abs = join(projectRoot, rel);
|
|
247
|
+
await mkdir(dirname(abs), { recursive: true });
|
|
248
|
+
const payload = { slug, version, appliedAt, appliedCapabilities: [...appliedCapabilities].sort(), appliedElicitations };
|
|
249
|
+
if (allowNoAuthYet === true) payload.allowNoAuthYet = true;
|
|
250
|
+
if (typeof notes === 'string' && notes.length > 0) payload.notes = notes;
|
|
251
|
+
await writeFile(abs, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
|
|
252
|
+
return rel;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Read the sidecar. Missing file returns null (never throws).
|
|
257
|
+
*/
|
|
258
|
+
export async function readSidecar(projectRoot, slug) {
|
|
259
|
+
const abs = join(projectRoot, sidecarRelPath(slug));
|
|
260
|
+
try {
|
|
261
|
+
const raw = await readFile(abs, 'utf8');
|
|
262
|
+
return JSON.parse(raw);
|
|
263
|
+
} catch {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Presence check for the sidecar file (does not parse).
|
|
270
|
+
*/
|
|
271
|
+
export async function sidecarExists(projectRoot, slug) {
|
|
272
|
+
try {
|
|
273
|
+
await stat(join(projectRoot, sidecarRelPath(slug)));
|
|
274
|
+
return true;
|
|
275
|
+
} catch {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Custom-auth capability elicitation (visual round T-5 spec 5.5
|
|
282
|
+
* "Risks": custom auth elicits per capability). Runs BEFORE the
|
|
283
|
+
* requiresAppliedCapabilities refusal gate. Each elicit entry with
|
|
284
|
+
* a truthy `providesCapability` string is a boolean prompt asking
|
|
285
|
+
* whether the operator's own (non-shelf) auth blueprint provides
|
|
286
|
+
* the named capability. A truthy answer folds that capability into
|
|
287
|
+
* the effective applied set, so a project with no shelf auth
|
|
288
|
+
* blueprint can still pass the refusal gate without the allowNoAuthYet
|
|
289
|
+
* override, and the resulting sidecar records the operator-declared
|
|
290
|
+
* appliedCapabilities honestly.
|
|
291
|
+
*
|
|
292
|
+
* Interactive vs non-interactive:
|
|
293
|
+
* - Non-interactive: only the elicits whose id appears in `answers`
|
|
294
|
+
* resolve; the rest are treated as unanswered.
|
|
295
|
+
* - Interactive (tty=true): unanswered custom-auth elicits are read
|
|
296
|
+
* from stdin via readline with a `y/N` prompt; this branch is
|
|
297
|
+
* driven synchronously by the CLI's `apply` wrapper when it
|
|
298
|
+
* detects `process.stdin.isTTY === true`.
|
|
299
|
+
*
|
|
300
|
+
* A malformed boolean answer refuses with a validation rcfError.
|
|
301
|
+
*
|
|
302
|
+
* @param {object} args
|
|
303
|
+
* @param {Array<object>} args.elicits from loader (may include non-providesCapability entries; they are ignored here)
|
|
304
|
+
* @param {Record<string, string|boolean>} args.answers operator bag
|
|
305
|
+
* @param {(prompt: string) => Promise<string>} [args.readLine] test seam for interactive input
|
|
306
|
+
* @returns {Promise<{ capsProvided: string[], answered: Record<string, boolean>, elicitsPresent: boolean, anyAnswered: boolean } | import('../core/errors/index.js').RcfError>}
|
|
307
|
+
*/
|
|
308
|
+
export async function runCustomAuthCapabilityElicits({ elicits, answers, readLine }) {
|
|
309
|
+
const capsProvided = new Set();
|
|
310
|
+
const answered = {};
|
|
311
|
+
let elicitsPresent = false;
|
|
312
|
+
const bag = answers ?? {};
|
|
313
|
+
for (const e of elicits ?? []) {
|
|
314
|
+
if (typeof e.providesCapability !== 'string' || e.providesCapability.length === 0) continue;
|
|
315
|
+
elicitsPresent = true;
|
|
316
|
+
const raw = bag[e.id];
|
|
317
|
+
let coerced;
|
|
318
|
+
if (raw === undefined || raw === null || raw === '') {
|
|
319
|
+
if (typeof readLine !== 'function') {
|
|
320
|
+
// Non-interactive branch, no answer supplied: skip. Default
|
|
321
|
+
// remains false in that case so a missing operator answer does
|
|
322
|
+
// not silently declare a capability.
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
const reply = await readLine(`Custom auth: does your auth provide '${e.providesCapability}'? [y/N]: `);
|
|
326
|
+
const s = String(reply ?? '').trim().toLowerCase();
|
|
327
|
+
if (s === '' || s === 'n' || s === 'no' || s === 'false' || s === '0') coerced = false;
|
|
328
|
+
else if (s === 'y' || s === 'yes' || s === 'true' || s === '1') coerced = true;
|
|
329
|
+
else {
|
|
330
|
+
return rcfError({
|
|
331
|
+
kind: 'validation',
|
|
332
|
+
message: `blueprint apply: elicit '${e.id}' expects a boolean; got '${reply}'.`,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
} else if (typeof raw === 'boolean') {
|
|
336
|
+
coerced = raw;
|
|
337
|
+
} else {
|
|
338
|
+
const s = String(raw).trim().toLowerCase();
|
|
339
|
+
if (s === 'y' || s === 'yes' || s === 'true' || s === '1') coerced = true;
|
|
340
|
+
else if (s === 'n' || s === 'no' || s === 'false' || s === '0') coerced = false;
|
|
341
|
+
else {
|
|
342
|
+
return rcfError({
|
|
343
|
+
kind: 'validation',
|
|
344
|
+
message: `blueprint apply: elicit '${e.id}' expects a boolean; got '${raw}'.`,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
answered[e.id] = coerced;
|
|
349
|
+
if (coerced === true) capsProvided.add(e.providesCapability);
|
|
350
|
+
}
|
|
351
|
+
return {
|
|
352
|
+
capsProvided: [...capsProvided].sort(),
|
|
353
|
+
answered,
|
|
354
|
+
elicitsPresent,
|
|
355
|
+
anyAnswered: Object.keys(answered).length > 0,
|
|
356
|
+
};
|
|
357
|
+
}
|
package/src/blueprint/loader.js
CHANGED
|
@@ -151,10 +151,55 @@ export async function loadBlueprint(source) {
|
|
|
151
151
|
...(Array.isArray(doc.standardsTrace)
|
|
152
152
|
? { standardsTrace: doc.standardsTrace.map((s) => ({ id: s.id, version: s.version })) }
|
|
153
153
|
: {}),
|
|
154
|
+
// Capability-declaration mechanism (visual round T-5 spec section
|
|
155
|
+
// 5.5.2). Blueprints declare identity or platform capabilities they
|
|
156
|
+
// provide (principalDirectory, roleModel, tenancy, auditLog); the
|
|
157
|
+
// vocabulary lives in the section 6a table in blueprint-authoring.md
|
|
158
|
+
// and the shape validation lives in this loader. Consumer blueprints
|
|
159
|
+
// gate surfaces on the union of currently-applied blueprints'
|
|
160
|
+
// capabilities via the apply-time source read-back (see apply.js).
|
|
161
|
+
...(Array.isArray(doc.capabilities) ? { capabilities: doc.capabilities.slice() } : {}),
|
|
162
|
+
// Elicitation phase (visual round T-5 spec section 5.5, T-2 gate
|
|
163
|
+
// note d-2026-09-04-051). ADR-elicited fields on contributions are
|
|
164
|
+
// declarative only; a blueprint that needs apply-time answers
|
|
165
|
+
// declares them on this top-level list. Each entry has an id
|
|
166
|
+
// (kebab), a prompt (operator-facing), a kind (enum|string|boolean)
|
|
167
|
+
// with default and options, and an optional `when` predicate whose
|
|
168
|
+
// capability list gates whether the elicit fires.
|
|
169
|
+
...(Array.isArray(doc.elicits) ? { elicits: doc.elicits.map((e) => normaliseElicit(e)) } : {}),
|
|
170
|
+
// Refusal gate (visual round T-5 spec section 5.5.1). A blueprint
|
|
171
|
+
// that requires at least one applied blueprint declaring a listed
|
|
172
|
+
// capability refuses at apply unless the CLI passes the named skip
|
|
173
|
+
// flag; the message and shape are validated on load, evaluated on
|
|
174
|
+
// apply.
|
|
175
|
+
...(doc.requiresAppliedCapabilities !== undefined
|
|
176
|
+
? {
|
|
177
|
+
requiresAppliedCapabilities: {
|
|
178
|
+
capabilities: doc.requiresAppliedCapabilities.capabilities.slice(),
|
|
179
|
+
allowSkipFlag: doc.requiresAppliedCapabilities.allowSkipFlag,
|
|
180
|
+
refusalMessageId: doc.requiresAppliedCapabilities.refusalMessageId,
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
: {}),
|
|
154
184
|
contributions: Array.isArray(doc.contributions) ? doc.contributions.map(preserveAdrDisciplineFields) : [],
|
|
155
185
|
};
|
|
156
186
|
}
|
|
157
187
|
|
|
188
|
+
// Shape-preserve an elicit entry. The loader's validator has already
|
|
189
|
+
// vetted every field; this copy strips extra keys and freezes shape.
|
|
190
|
+
function normaliseElicit(entry) {
|
|
191
|
+
const out = { id: entry.id, prompt: entry.prompt, kind: entry.kind };
|
|
192
|
+
if (entry.default !== undefined) out.default = entry.default;
|
|
193
|
+
if (Array.isArray(entry.options)) out.options = entry.options.slice();
|
|
194
|
+
if (entry.when !== undefined) {
|
|
195
|
+
out.when = { requiresCapability: entry.when.requiresCapability };
|
|
196
|
+
}
|
|
197
|
+
if (typeof entry.providesCapability === 'string') {
|
|
198
|
+
out.providesCapability = entry.providesCapability;
|
|
199
|
+
}
|
|
200
|
+
return out;
|
|
201
|
+
}
|
|
202
|
+
|
|
158
203
|
// Copy the standards-derived-discipline ADR fields (recommendedDefault,
|
|
159
204
|
// elicited, standardsTraceClause) onto the returned contribution shape
|
|
160
205
|
// verbatim so consumers (apply, tests, tooling) can read them without
|
|
@@ -276,6 +321,208 @@ function validateMetadata(doc, metaPath) {
|
|
|
276
321
|
// severity to kind (per amendment A2); the discipline is prose.
|
|
277
322
|
const stError = validateStandardsTrace(doc, metaPath);
|
|
278
323
|
if (stError) return stError;
|
|
324
|
+
// Capability-declaration mechanism (visual round T-5, spec 5.5.2).
|
|
325
|
+
const capError = validateCapabilities(doc, metaPath);
|
|
326
|
+
if (capError) return capError;
|
|
327
|
+
const elicitError = validateElicits(doc, metaPath);
|
|
328
|
+
if (elicitError) return elicitError;
|
|
329
|
+
const requiresError = validateRequiresAppliedCapabilities(doc, metaPath);
|
|
330
|
+
if (requiresError) return requiresError;
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// The kebab-slug grammar the elicit id uses (matches blueprint slug
|
|
335
|
+
// and category shapes). Elicit ids must be slugs so the CLI's
|
|
336
|
+
// --answer <id>=<value> flag has an unambiguous key vocabulary.
|
|
337
|
+
const KEBAB_SLUG_RE = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
338
|
+
|
|
339
|
+
// Set of legal elicit kinds. `enum` requires options[]; `string` and
|
|
340
|
+
// `boolean` do not.
|
|
341
|
+
const ELICIT_KINDS = new Set(['enum', 'string', 'boolean']);
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Validate capabilities[] shape (visual round T-5 spec 5.5.2). Optional;
|
|
345
|
+
* when present must be a non-empty array of lower camelCase strings on
|
|
346
|
+
* ^[a-z][a-zA-Z0-9]*$, matching the section 6a role convention.
|
|
347
|
+
*/
|
|
348
|
+
function validateCapabilities(doc, metaPath) {
|
|
349
|
+
if (doc.capabilities === undefined) return null;
|
|
350
|
+
if (!Array.isArray(doc.capabilities) || doc.capabilities.length === 0) {
|
|
351
|
+
return rcfError({ kind: 'validation', message: 'blueprint.json: capabilities must be a non-empty array when set', filePath: metaPath });
|
|
352
|
+
}
|
|
353
|
+
for (let i = 0; i < doc.capabilities.length; i += 1) {
|
|
354
|
+
const cap = doc.capabilities[i];
|
|
355
|
+
if (typeof cap !== 'string' || !ROLE_NAME_RE.test(cap)) {
|
|
356
|
+
return rcfError({
|
|
357
|
+
kind: 'validation',
|
|
358
|
+
message: `blueprint.json: capabilities[${i}] '${cap}' is not lower camelCase (^[a-z][a-zA-Z0-9]*$).`,
|
|
359
|
+
filePath: metaPath,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Validate elicits[] shape (visual round T-5 spec 5.5). Optional; when
|
|
368
|
+
* present must be a non-empty array of entries carrying id (kebab
|
|
369
|
+
* slug), prompt (non-empty string, no em-dashes, no emojis), kind
|
|
370
|
+
* (enum|string|boolean), an optional default matching the kind, an
|
|
371
|
+
* options[] array when kind is enum, and an optional when-predicate
|
|
372
|
+
* whose requiresCapability[] is a non-empty array of camelCase
|
|
373
|
+
* capability strings.
|
|
374
|
+
*/
|
|
375
|
+
function validateElicits(doc, metaPath) {
|
|
376
|
+
if (doc.elicits === undefined) return null;
|
|
377
|
+
if (!Array.isArray(doc.elicits) || doc.elicits.length === 0) {
|
|
378
|
+
return rcfError({ kind: 'validation', message: 'blueprint.json: elicits must be a non-empty array when set', filePath: metaPath });
|
|
379
|
+
}
|
|
380
|
+
const seenIds = new Set();
|
|
381
|
+
for (let i = 0; i < doc.elicits.length; i += 1) {
|
|
382
|
+
const entry = doc.elicits[i];
|
|
383
|
+
if (typeof entry !== 'object' || entry === null) {
|
|
384
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] must be an object`, filePath: metaPath });
|
|
385
|
+
}
|
|
386
|
+
if (typeof entry.id !== 'string' || !KEBAB_SLUG_RE.test(entry.id)) {
|
|
387
|
+
return rcfError({
|
|
388
|
+
kind: 'validation',
|
|
389
|
+
message: `blueprint.json: elicits[${i}].id '${entry.id}' is not a kebab slug (^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$).`,
|
|
390
|
+
filePath: metaPath,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
if (seenIds.has(entry.id)) {
|
|
394
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}].id '${entry.id}' duplicates an earlier entry`, filePath: metaPath });
|
|
395
|
+
}
|
|
396
|
+
seenIds.add(entry.id);
|
|
397
|
+
if (typeof entry.prompt !== 'string' || entry.prompt.trim().length === 0) {
|
|
398
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] '${entry.id}' prompt must be a non-empty string`, filePath: metaPath });
|
|
399
|
+
}
|
|
400
|
+
if (EM_DASH.test(entry.prompt)) {
|
|
401
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] '${entry.id}' prompt contains an em-dash; use a comma, a full stop, or a colon.`, filePath: metaPath });
|
|
402
|
+
}
|
|
403
|
+
if (EMOJI_RE.test(entry.prompt)) {
|
|
404
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] '${entry.id}' prompt contains an emoji; operator-facing prose must be plain text.`, filePath: metaPath });
|
|
405
|
+
}
|
|
406
|
+
if (!ELICIT_KINDS.has(entry.kind)) {
|
|
407
|
+
return rcfError({
|
|
408
|
+
kind: 'validation',
|
|
409
|
+
message: `blueprint.json: elicits[${i}] '${entry.id}' kind '${entry.kind}' must be one of: ${[...ELICIT_KINDS].join(', ')}.`,
|
|
410
|
+
filePath: metaPath,
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
if (entry.kind === 'enum') {
|
|
414
|
+
if (!Array.isArray(entry.options) || entry.options.length === 0) {
|
|
415
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] '${entry.id}' kind=enum requires a non-empty options[] array`, filePath: metaPath });
|
|
416
|
+
}
|
|
417
|
+
for (let j = 0; j < entry.options.length; j += 1) {
|
|
418
|
+
if (typeof entry.options[j] !== 'string' || entry.options[j].length === 0) {
|
|
419
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] '${entry.id}' options[${j}] must be a non-empty string`, filePath: metaPath });
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (entry.default !== undefined && !entry.options.includes(entry.default)) {
|
|
423
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] '${entry.id}' default '${entry.default}' is not in options[]`, filePath: metaPath });
|
|
424
|
+
}
|
|
425
|
+
} else if (entry.kind === 'boolean') {
|
|
426
|
+
if (entry.default !== undefined && typeof entry.default !== 'boolean') {
|
|
427
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] '${entry.id}' kind=boolean default must be a boolean`, filePath: metaPath });
|
|
428
|
+
}
|
|
429
|
+
} else if (entry.kind === 'string') {
|
|
430
|
+
if (entry.default !== undefined && typeof entry.default !== 'string') {
|
|
431
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] '${entry.id}' kind=string default must be a string`, filePath: metaPath });
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
if (entry.when !== undefined) {
|
|
435
|
+
if (typeof entry.when !== 'object' || entry.when === null) {
|
|
436
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] '${entry.id}' when must be an object`, filePath: metaPath });
|
|
437
|
+
}
|
|
438
|
+
if (!Array.isArray(entry.when.requiresCapability) || entry.when.requiresCapability.length === 0) {
|
|
439
|
+
return rcfError({ kind: 'validation', message: `blueprint.json: elicits[${i}] '${entry.id}' when.requiresCapability must be a non-empty array`, filePath: metaPath });
|
|
440
|
+
}
|
|
441
|
+
for (let j = 0; j < entry.when.requiresCapability.length; j += 1) {
|
|
442
|
+
const cap = entry.when.requiresCapability[j];
|
|
443
|
+
if (typeof cap !== 'string' || !ROLE_NAME_RE.test(cap)) {
|
|
444
|
+
return rcfError({
|
|
445
|
+
kind: 'validation',
|
|
446
|
+
message: `blueprint.json: elicits[${i}] '${entry.id}' when.requiresCapability[${j}] '${cap}' is not lower camelCase.`,
|
|
447
|
+
filePath: metaPath,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
// Custom-auth capability discovery (visual round T-5 spec 5.5
|
|
453
|
+
// "Risks"). An elicit that declares providesCapability is a
|
|
454
|
+
// boolean prompt asking the operator whether their custom auth
|
|
455
|
+
// provides the named capability; a truthy answer folds the
|
|
456
|
+
// capability into the effective applied set at apply time, so a
|
|
457
|
+
// project with no shelf auth blueprint can still satisfy a
|
|
458
|
+
// consumer blueprint's requiresAppliedCapabilities gate without
|
|
459
|
+
// the allowNoAuthYet override. Rules: kind MUST be boolean,
|
|
460
|
+
// when MUST be absent (custom-auth elicits fire pre-refusal,
|
|
461
|
+
// before any discovered-capability set exists), and the value
|
|
462
|
+
// MUST be lower camelCase (same grammar as capabilities[]).
|
|
463
|
+
if (entry.providesCapability !== undefined) {
|
|
464
|
+
if (entry.kind !== 'boolean') {
|
|
465
|
+
return rcfError({
|
|
466
|
+
kind: 'validation',
|
|
467
|
+
message: `blueprint.json: elicits[${i}] '${entry.id}' providesCapability requires kind=boolean (got '${entry.kind}').`,
|
|
468
|
+
filePath: metaPath,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
if (entry.when !== undefined) {
|
|
472
|
+
return rcfError({
|
|
473
|
+
kind: 'validation',
|
|
474
|
+
message: `blueprint.json: elicits[${i}] '${entry.id}' providesCapability is incompatible with when (custom-auth elicits fire pre-refusal, before applied capabilities are discovered).`,
|
|
475
|
+
filePath: metaPath,
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
if (typeof entry.providesCapability !== 'string' || !ROLE_NAME_RE.test(entry.providesCapability)) {
|
|
479
|
+
return rcfError({
|
|
480
|
+
kind: 'validation',
|
|
481
|
+
message: `blueprint.json: elicits[${i}] '${entry.id}' providesCapability '${entry.providesCapability}' is not lower camelCase (^[a-z][a-zA-Z0-9]*$).`,
|
|
482
|
+
filePath: metaPath,
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Validate requiresAppliedCapabilities shape (visual round T-5 spec
|
|
492
|
+
* 5.5.1). Optional; when present must be an object with capabilities
|
|
493
|
+
* (non-empty array of lower camelCase strings), allowSkipFlag (kebab
|
|
494
|
+
* slug matching a CLI flag name), and refusalMessageId (non-empty
|
|
495
|
+
* string; the apply verb maps it to a message template).
|
|
496
|
+
*/
|
|
497
|
+
function validateRequiresAppliedCapabilities(doc, metaPath) {
|
|
498
|
+
if (doc.requiresAppliedCapabilities === undefined) return null;
|
|
499
|
+
const r = doc.requiresAppliedCapabilities;
|
|
500
|
+
if (typeof r !== 'object' || r === null) {
|
|
501
|
+
return rcfError({ kind: 'validation', message: 'blueprint.json: requiresAppliedCapabilities must be an object', filePath: metaPath });
|
|
502
|
+
}
|
|
503
|
+
if (!Array.isArray(r.capabilities) || r.capabilities.length === 0) {
|
|
504
|
+
return rcfError({ kind: 'validation', message: 'blueprint.json: requiresAppliedCapabilities.capabilities must be a non-empty array', filePath: metaPath });
|
|
505
|
+
}
|
|
506
|
+
for (let i = 0; i < r.capabilities.length; i += 1) {
|
|
507
|
+
const cap = r.capabilities[i];
|
|
508
|
+
if (typeof cap !== 'string' || !ROLE_NAME_RE.test(cap)) {
|
|
509
|
+
return rcfError({
|
|
510
|
+
kind: 'validation',
|
|
511
|
+
message: `blueprint.json: requiresAppliedCapabilities.capabilities[${i}] '${cap}' is not lower camelCase.`,
|
|
512
|
+
filePath: metaPath,
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (typeof r.allowSkipFlag !== 'string' || !KEBAB_SLUG_RE.test(r.allowSkipFlag)) {
|
|
517
|
+
return rcfError({
|
|
518
|
+
kind: 'validation',
|
|
519
|
+
message: `blueprint.json: requiresAppliedCapabilities.allowSkipFlag '${r.allowSkipFlag}' is not a kebab slug (matches a CLI flag name).`,
|
|
520
|
+
filePath: metaPath,
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
if (typeof r.refusalMessageId !== 'string' || r.refusalMessageId.trim().length === 0) {
|
|
524
|
+
return rcfError({ kind: 'validation', message: 'blueprint.json: requiresAppliedCapabilities.refusalMessageId must be a non-empty string', filePath: metaPath });
|
|
525
|
+
}
|
|
279
526
|
return null;
|
|
280
527
|
}
|
|
281
528
|
|