@aifabrix/builder 2.45.5 → 2.47.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/.cursor/rules/cli-layout.mdc +2 -0
- package/.cursor/rules/cli-product-neutral.mdc +43 -0
- package/.cursor/rules/project-rules.mdc +1 -0
- package/.npmrc.token +1 -0
- package/.temp/jest-protection-convert/run-IFN2nv/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-IvmKLO/.protection/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-convert/run-SdvblF/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-b51TsW/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-fiLmb1/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-qYGHMU/.protection/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-Mq5re8/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-f3u4YL/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-iQtd1O/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-mdmz5M/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-qbKYxQ/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-yzlJy6/hubspot-companies.yaml +17 -0
- package/.temp/validation/summary.txt +5 -0
- package/README.md +43 -17
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
- package/jest.config.default.js +2 -1
- package/jest.config.isolated.js +2 -1
- package/jest.global-live-fabrix-hooks.js +36 -0
- package/jest.isolated-projects.js +146 -0
- package/jest.projects.js +65 -136
- package/lib/api/api-response-errors.js +124 -0
- package/lib/api/dataplane-health.api.js +19 -7
- package/lib/api/governance-scenario-pack.api.js +159 -0
- package/lib/api/index.js +43 -3
- package/lib/api/lifecycle.api.js +98 -0
- package/lib/api/pipeline.api.js +3 -1
- package/lib/api/records-bulk.api.js +14 -1
- package/lib/api/resource-types.api.js +107 -0
- package/lib/api/runtime-configuration.api.js +72 -0
- package/lib/api/types/resource-types.types.js +45 -0
- package/lib/api/user-groups.api.js +9 -9
- package/lib/api/users.api.js +8 -8
- package/lib/api/validation-runner.js +3 -1
- package/lib/api/wizard.api.js +10 -2
- package/lib/app/deploy-config.js +4 -1
- package/lib/app/down.js +78 -27
- package/lib/app/index.js +2 -2
- package/lib/app/push.js +4 -5
- package/lib/app/register.js +7 -4
- package/lib/app/run-env-compose.js +84 -30
- package/lib/app/run-resolve-image.js +2 -1
- package/lib/app/run-stop-containers.js +113 -0
- package/lib/app/run.js +1 -31
- package/lib/app/show-display.js +35 -0
- package/lib/app/show.js +32 -1
- package/lib/build/index.js +22 -5
- package/lib/build/miso-controller-npm-sdk-guard.js +25 -0
- package/lib/certification/sync-system-certification.js +13 -6
- package/lib/channels/add-channel.js +348 -0
- package/lib/channels/channel-artifact-generator.js +141 -0
- package/lib/channels/channel-audit.js +101 -0
- package/lib/channels/channel-auth-context.js +37 -0
- package/lib/channels/channel-credential.js +200 -0
- package/lib/channels/channel-display-name.js +64 -0
- package/lib/channels/channel-external-system.js +106 -0
- package/lib/channels/channel-integration-generator.js +274 -0
- package/lib/channels/channel-probe.js +89 -0
- package/lib/channels/channel-runtime-resolver.js +152 -0
- package/lib/channels/channel-status-display.js +141 -0
- package/lib/channels/channel-targets.js +115 -0
- package/lib/cli/index.js +20 -4
- package/lib/cli/infra-guided-auth.js +109 -0
- package/lib/cli/infra-guided.js +84 -81
- package/lib/cli/setup-app.help.js +0 -31
- package/lib/cli/setup-app.js +82 -5
- package/lib/cli/setup-app.test-commands.js +5 -57
- package/lib/cli/setup-auth.js +25 -0
- package/lib/cli/setup-certification-commands.js +147 -0
- package/lib/cli/setup-certification.help.js +141 -0
- package/lib/cli/setup-environment.js +19 -2
- package/lib/cli/setup-external-system-help.js +62 -0
- package/lib/cli/setup-external-system.js +25 -3
- package/lib/cli/setup-infra-up-dataplane-action.js +2 -2
- package/lib/cli/setup-infra-up-platform-action.js +2 -1
- package/lib/cli/setup-infra.js +9 -1
- package/lib/cli/setup-platform.js +6 -1
- package/lib/cli/setup-secrets.js +33 -1
- package/lib/cli/setup-utility-help-after.js +25 -2
- package/lib/cli/setup-utility-repair.js +198 -0
- package/lib/cli/setup-utility-resolve.js +44 -5
- package/lib/cli/setup-utility-validate.js +197 -0
- package/lib/cli/setup-utility.js +4 -239
- package/lib/commands/app-logs.js +54 -26
- package/lib/commands/app.js +41 -0
- package/lib/commands/auth-status-client-tokens.js +214 -0
- package/lib/commands/auth-status-dataplane-version.js +142 -68
- package/lib/commands/auth-status.js +43 -54
- package/lib/commands/channel.js +58 -0
- package/lib/commands/datasource-test-trust-cli.js +27 -23
- package/lib/commands/datasource-unified-test-cli.js +6 -3
- package/lib/commands/datasource-unified-test-cli.options.js +5 -1
- package/lib/commands/datasource.js +8 -8
- package/lib/commands/dev-show-display.js +8 -1
- package/lib/commands/governance-cli-shared.js +94 -0
- package/lib/commands/governance-command-action.js +132 -0
- package/lib/commands/governance-download-external.js +34 -0
- package/lib/commands/governance-generate-external.js +71 -0
- package/lib/commands/governance-upload-external.js +36 -0
- package/lib/commands/governance-verify-external.js +64 -0
- package/lib/commands/governance.js +144 -0
- package/lib/commands/identity-apply-sync.js +49 -8
- package/lib/commands/identity-group-cli.js +66 -26
- package/lib/commands/identity-membership-role-cache.js +58 -37
- package/lib/commands/identity-shared.js +22 -1
- package/lib/commands/identity-user-cli.js +80 -34
- package/lib/commands/lifecycle-command-action.js +123 -0
- package/lib/commands/lifecycle-external.js +268 -0
- package/lib/commands/login.js +11 -2
- package/lib/commands/repair-auth-apply.js +153 -0
- package/lib/commands/repair-auth-config.js +8 -13
- package/lib/commands/repair-changed-files.js +41 -0
- package/lib/commands/repair-datasource-com-v2.js +15 -0
- package/lib/commands/repair-datasource-keys.js +4 -1
- package/lib/commands/repair-datasource-run.js +59 -0
- package/lib/commands/repair-datasource-service-contract.js +206 -0
- package/lib/commands/repair-datasource-test-payload.js +259 -0
- package/lib/commands/repair-datasource.js +49 -64
- package/lib/commands/repair-env-template.js +76 -25
- package/lib/commands/repair-external-run.js +216 -0
- package/lib/commands/repair-openapi-sync.js +49 -4
- package/lib/commands/repair-persist.js +4 -0
- package/lib/commands/repair-rbac.js +52 -1
- package/lib/commands/repair-steps.js +160 -0
- package/lib/commands/repair-system-alignment.js +7 -4
- package/lib/commands/repair.js +29 -296
- package/lib/commands/resource-type.js +371 -0
- package/lib/commands/secrets-get.js +184 -0
- package/lib/commands/secrets-remove-all.js +3 -1
- package/lib/commands/setup-image-refresh.js +146 -0
- package/lib/commands/setup-modes.js +158 -162
- package/lib/commands/setup-platform-auth.js +76 -0
- package/lib/commands/setup-prompts-admin.js +244 -0
- package/lib/commands/setup-prompts-platform-mode.js +70 -0
- package/lib/commands/setup-prompts-validators.js +36 -0
- package/lib/commands/setup-prompts.js +24 -76
- package/lib/commands/setup-run-context.js +45 -0
- package/lib/commands/setup-spinners.js +39 -0
- package/lib/commands/setup.js +27 -5
- package/lib/commands/teardown.js +39 -0
- package/lib/commands/test-e2e-external.js +24 -8
- package/lib/commands/test-governance-external.js +3 -24
- package/lib/commands/test-trust-external.js +48 -100
- package/lib/commands/up-common.js +57 -13
- package/lib/commands/up-dataplane.js +56 -15
- package/lib/commands/upload-publish-context.js +75 -0
- package/lib/commands/upload-sidecar-followups.js +89 -0
- package/lib/commands/upload.js +113 -110
- package/lib/commands/verify-governance-combined-external.js +61 -0
- package/lib/commands/verify-governance-command-action.js +64 -0
- package/lib/commands/verify-governance-db.js +102 -0
- package/lib/commands/verify-governance-external.js +77 -0
- package/lib/commands/verify-governance-result-builders.js +71 -0
- package/lib/commands/verify-operations-command-action.js +68 -0
- package/lib/commands/verify-operations-external.js +268 -0
- package/lib/commands/verify-operations-persist.js +75 -0
- package/lib/commands/verify-operations-step-plan.js +68 -0
- package/lib/commands/verify-operations-steps.js +111 -0
- package/lib/commands/verify-trust-command-action.js +73 -0
- package/lib/commands/verify-trust-external.js +59 -0
- package/lib/commands/wizard-config-normalizer.js +43 -23
- package/lib/commands/wizard-core.js +2 -0
- package/lib/core/admin-password-generator.js +38 -0
- package/lib/core/admin-secrets-bundle.js +111 -0
- package/lib/core/admin-secrets-env-overlay.js +62 -0
- package/lib/core/admin-secrets.js +32 -4
- package/lib/core/config-attach-extensions.js +3 -0
- package/lib/core/config-platform-controller.js +44 -0
- package/lib/core/config-setup-installation-profile.js +42 -0
- package/lib/core/config-setup-platform-mode.js +46 -0
- package/lib/core/config.js +46 -36
- package/lib/core/secrets-admin-env.js +6 -2
- package/lib/core/secrets-ensure.js +4 -0
- package/lib/core/secrets-env-content.js +54 -48
- package/lib/core/secrets-env-write.js +10 -1
- package/lib/core/secrets-infra-placeholder-sync.js +2 -0
- package/lib/core/setup-installation-profile.js +43 -0
- package/lib/core/setup-platform-mode.js +90 -0
- package/lib/datasource/agent-trust-debug-log.js +1 -1
- package/lib/datasource/agent-trust-run.js +5 -3
- package/lib/datasource/audit-evidence-extract-debug.js +30 -18
- package/lib/datasource/audit-evidence-extract.js +7 -4
- package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
- package/lib/datasource/bulk-loader-run-batches.js +15 -3
- package/lib/datasource/capability/capability-diff-slice.js +2 -2
- package/lib/datasource/capability/capability-manifest.js +254 -0
- package/lib/datasource/capability/capability-resolve.js +3 -4
- package/lib/datasource/capability/copy-operations.js +5 -3
- package/lib/datasource/capability/remove-operations.js +2 -1
- package/lib/datasource/capability/run-capability-copy.js +32 -4
- package/lib/datasource/capability/run-capability-diff.js +3 -3
- package/lib/datasource/capability/run-capability-dimension.js +2 -4
- package/lib/datasource/capability/run-capability-edit.js +4 -7
- package/lib/datasource/capability/run-capability-relate.js +2 -4
- package/lib/datasource/capability/run-capability-remove.js +2 -4
- package/lib/datasource/capability/validate-capability-slice.js +2 -1
- package/lib/datasource/datasource-identifier.js +2 -1
- package/lib/datasource/datasource-load-export-context.js +3 -0
- package/lib/datasource/datasource-validate-display.js +1 -1
- package/lib/datasource/field-reference-validator.js +24 -3
- package/lib/datasource/log-cleaner.js +2 -2
- package/lib/datasource/log-viewer.js +8 -8
- package/lib/datasource/orphan-profiles-validator.js +98 -0
- package/lib/datasource/test-e2e.js +4 -1
- package/lib/datasource/unified-validation-run-body.js +3 -1
- package/lib/datasource/unified-validation-run.js +5 -2
- package/lib/datasource/validate.js +41 -23
- package/lib/deployment/environment-poll-status.js +138 -0
- package/lib/deployment/environment.js +42 -34
- package/lib/external-system/download-helpers.js +87 -0
- package/lib/external-system/download.js +78 -138
- package/lib/external-system/generator.js +1 -55
- package/lib/external-system/integration-auth-context.js +45 -0
- package/lib/external-system/test-auth.js +12 -5
- package/lib/external-system/test.js +16 -21
- package/lib/generator/builders.js +11 -1
- package/lib/generator/external-controller-manifest.js +18 -0
- package/lib/generator/split.js +3 -1
- package/lib/generator/wizard.js +1 -28
- package/lib/governance/governance-cli-errors.js +96 -0
- package/lib/governance/governance-download-display.js +38 -0
- package/lib/governance/governance-run-display.js +215 -25
- package/lib/identity/fk-reference.js +65 -0
- package/lib/identity/identity-apply-core.js +13 -58
- package/lib/identity/identity-apply-phases.js +5 -1
- package/lib/identity/identity-display.js +243 -0
- package/lib/identity/identity-response-helpers.js +52 -0
- package/lib/identity/identity-sync-errors.js +62 -0
- package/lib/identity/resolve-user-id.js +129 -0
- package/lib/identity/username-default.js +31 -0
- package/lib/infrastructure/admin-secrets-apply.js +84 -0
- package/lib/infrastructure/admin-secrets-ensure.js +130 -0
- package/lib/infrastructure/admin-secrets-resolve.js +95 -0
- package/lib/infrastructure/admin-secrets-sync.js +91 -0
- package/lib/infrastructure/helpers.js +23 -129
- package/lib/infrastructure/index.js +5 -6
- package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
- package/lib/lifecycle/certification-progress.js +231 -0
- package/lib/lifecycle/dataplane-ui-url.js +145 -0
- package/lib/lifecycle/exit-codes.js +24 -0
- package/lib/lifecycle/json-envelope.js +25 -0
- package/lib/lifecycle/lifecycle-governance-options.js +51 -0
- package/lib/lifecycle/logger-quiet.js +29 -0
- package/lib/lifecycle/open-api-published.js +59 -0
- package/lib/lifecycle/operations-readiness-metrics.js +101 -0
- package/lib/lifecycle/product-model.js +196 -0
- package/lib/lifecycle/report-display-trust.js +70 -0
- package/lib/lifecycle/report-display.js +472 -0
- package/lib/lifecycle/scenario-upload.js +191 -0
- package/lib/lifecycle/verify-step-progress.js +87 -0
- package/lib/parameters/infra-kv-discovery.js +27 -2
- package/lib/protection/auth-context.js +10 -4
- package/lib/resolvers/datasource-resolver.js +2 -3
- package/lib/resolvers/resource-type-file.js +159 -0
- package/lib/schema/application-schema.json +17 -1
- package/lib/schema/datasource-test-run.schema.json +89 -6
- package/lib/schema/deployment-rules.yaml +2 -1
- package/lib/schema/external-datasource.schema.json +2947 -2619
- package/lib/schema/external-system.schema.json +1418 -761
- package/lib/schema/infra.parameter.yaml +45 -0
- package/lib/schema/type/credential-field-registry.json +103 -97
- package/lib/schema/type/document-storage.json +9 -5
- package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
- package/lib/utils/api.js +55 -31
- package/lib/utils/app-relative-path-env.js +112 -0
- package/lib/utils/app-run-containers.js +25 -2
- package/lib/utils/authentication-shape.js +224 -0
- package/lib/utils/build-copy.js +36 -5
- package/lib/utils/build-resolve-image.js +66 -12
- package/lib/utils/celery-companion-apps.js +53 -0
- package/lib/utils/cli-secrets-error-format.js +83 -21
- package/lib/utils/cli-utils.js +20 -4
- package/lib/utils/compose-celery-worker.js +23 -0
- package/lib/utils/compose-generate-docker-compose.js +13 -1
- package/lib/utils/compose-traefik-ingress-base.js +16 -1
- package/lib/utils/config-secrets-path.js +46 -0
- package/lib/utils/configuration-env-resolver.js +36 -0
- package/lib/utils/controller-url.js +88 -1
- package/lib/utils/credential-secrets-env-kv.js +216 -0
- package/lib/utils/credential-secrets-env.js +175 -257
- package/lib/utils/dataplane-resolver.js +18 -2
- package/lib/utils/declarative-url-ports.js +27 -4
- package/lib/utils/deployment-auth-mode.js +41 -0
- package/lib/utils/developer-volume-id.js +33 -0
- package/lib/utils/docker-build.js +1 -4
- package/lib/utils/env-copy.js +14 -9
- package/lib/utils/env-kv-orphan-lines.js +43 -0
- package/lib/utils/error-formatters/network-errors.js +13 -4
- package/lib/utils/external-env-template.js +11 -3
- package/lib/utils/external-system-readiness-core.js +10 -0
- package/lib/utils/external-system-readiness-display.js +80 -23
- package/lib/utils/external-system-validators.js +8 -2
- package/lib/utils/health-check.js +4 -1
- package/lib/utils/help-builder.js +13 -8
- package/lib/utils/keycloak-realm-ready.js +101 -0
- package/lib/utils/load-cip-capacity-display-config.js +61 -15
- package/lib/utils/manifest-source-emit.js +2 -0
- package/lib/utils/paths.js +25 -0
- package/lib/utils/pipeline-upload-auth-retry.js +82 -0
- package/lib/utils/platform-controller-url.js +157 -0
- package/lib/utils/platform-kv-ref.js +57 -0
- package/lib/utils/postgres-platform-bootstrap.js +199 -0
- package/lib/utils/postgres-wipe.js +9 -2
- package/lib/utils/resolve-env-mode.js +47 -0
- package/lib/utils/runtime-configuration-download.js +189 -0
- package/lib/utils/runtime-configuration-values.js +119 -0
- package/lib/utils/schema-loader.js +19 -4
- package/lib/utils/secrets-generator.js +31 -25
- package/lib/utils/secrets-missing-error.js +164 -0
- package/lib/utils/service-url-label.js +81 -0
- package/lib/utils/setup-quiet-output.js +25 -0
- package/lib/utils/template-helpers.js +15 -0
- package/lib/utils/token-manager-client-credentials.js +201 -0
- package/lib/utils/token-manager-messages.js +8 -0
- package/lib/utils/token-manager-refresh.js +12 -2
- package/lib/utils/token-manager.js +86 -105
- package/lib/utils/upload-pipeline-ui.js +12 -5
- package/lib/utils/upload-sync-options.js +42 -0
- package/lib/utils/url-declarative-public-base.js +21 -3
- package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
- package/lib/utils/validation-poll-ui.js +8 -0
- package/lib/utils/validation-run-stage.js +45 -0
- package/lib/utils/worker-sidecars.js +142 -0
- package/lib/validation/external-manifest-validator.js +2 -0
- package/lib/validation/runtime-configuration-rules.js +98 -0
- package/lib/validation/validate-display-dimensions.js +154 -0
- package/lib/validation/validate-display-sections.js +276 -0
- package/lib/validation/validate-display-steps.js +67 -0
- package/lib/validation/validate-display.js +24 -402
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +7 -1
- package/templates/applications/dataplane/env.template +50 -14
- package/templates/applications/dataplane/rbac.yaml +108 -1
- package/templates/applications/miso-controller/application.yaml +2 -2
- package/templates/applications/miso-controller/env.template +53 -122
- package/templates/applications/miso-controller/rbac.yaml +28 -13
- package/templates/channels/chatgpt/install.template.md.hbs +49 -0
- package/templates/channels/chatgpt/manifest.template.json.hbs +9 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +49 -0
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +8 -0
- package/templates/channels/slack/install.template.md.hbs +49 -0
- package/templates/channels/slack/manifest.template.json.hbs +66 -0
- package/templates/channels/teams-bot/install.template.md.hbs +49 -0
- package/templates/channels/teams-bot/manifest.template.json.hbs +13 -0
- package/templates/channels/web-embed/install.template.md.hbs +49 -0
- package/templates/channels/web-embed/manifest.template.json.hbs +8 -0
- package/templates/external-system/README.md.hbs +74 -17
- package/templates/python/docker-compose.hbs +75 -18
- package/templates/typescript/docker-compose.hbs +70 -17
- package/lib/commands/test-governance-command-action.js +0 -55
- package/lib/commands/test-trust-command-action.js +0 -118
|
@@ -16,6 +16,9 @@ const { formatProgress } = require('./cli-test-layout-chalk');
|
|
|
16
16
|
* @returns {boolean}
|
|
17
17
|
*/
|
|
18
18
|
function shouldShowUploadPipelineProgress(options = {}) {
|
|
19
|
+
if (options.suppressPipelineSpinner === true) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
19
22
|
return options.json !== true;
|
|
20
23
|
}
|
|
21
24
|
|
|
@@ -35,17 +38,21 @@ function shouldUseUploadPipelineSpinner(options = {}) {
|
|
|
35
38
|
* @param {string} systemKey
|
|
36
39
|
* @returns {string}
|
|
37
40
|
*/
|
|
38
|
-
function buildUploadPipelineSpinnerLabel(systemKey) {
|
|
41
|
+
function buildUploadPipelineSpinnerLabel(systemKey, opts = {}) {
|
|
42
|
+
if (opts.syncMode === true) {
|
|
43
|
+
return 'Checking config on dataplane…';
|
|
44
|
+
}
|
|
39
45
|
const key = systemKey && String(systemKey).trim() ? String(systemKey).trim() : 'integration';
|
|
40
46
|
return `Publishing ${key} to dataplane…`;
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
/**
|
|
44
50
|
* @param {string} systemKey
|
|
51
|
+
* @param {Object} [opts]
|
|
45
52
|
* @returns {string}
|
|
46
53
|
*/
|
|
47
|
-
function buildUploadPipelineProgressText(systemKey) {
|
|
48
|
-
return formatProgress(buildUploadPipelineSpinnerLabel(systemKey));
|
|
54
|
+
function buildUploadPipelineProgressText(systemKey, opts = {}) {
|
|
55
|
+
return formatProgress(buildUploadPipelineSpinnerLabel(systemKey, opts));
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
/**
|
|
@@ -64,12 +71,12 @@ async function runWithUploadPipelineSpinner(work, opts = {}) {
|
|
|
64
71
|
}
|
|
65
72
|
|
|
66
73
|
if (!shouldUseUploadPipelineSpinner(opts)) {
|
|
67
|
-
logger.log(buildUploadPipelineProgressText(opts.systemKey));
|
|
74
|
+
logger.log(buildUploadPipelineProgressText(opts.systemKey, opts));
|
|
68
75
|
return work();
|
|
69
76
|
}
|
|
70
77
|
|
|
71
78
|
const ora = require('ora');
|
|
72
|
-
const label = buildUploadPipelineSpinnerLabel(opts.systemKey);
|
|
79
|
+
const label = buildUploadPipelineSpinnerLabel(opts.systemKey, opts);
|
|
73
80
|
const spinner = ora({
|
|
74
81
|
text: chalk.white(label),
|
|
75
82
|
spinner: 'dots'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build options for `uploadExternalSystem` on test-command --sync paths.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Minimal upload sync options (force, verbose)
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {Object} [options] - CLI options from test / sync callers
|
|
13
|
+
* @returns {{ minimal: true, verbose: boolean, silentResolve: true, syncMode: true, force?: true }}
|
|
14
|
+
*/
|
|
15
|
+
function buildMinimalUploadSyncOptions(options = {}) {
|
|
16
|
+
const out = {
|
|
17
|
+
minimal: true,
|
|
18
|
+
// CLI -v on verify-* / test-* is for run output, not preflight upload banners.
|
|
19
|
+
verbose: false,
|
|
20
|
+
silentResolve: true,
|
|
21
|
+
syncMode: true,
|
|
22
|
+
suppressPipelineSpinner: options.suppressPipelineSpinner === true
|
|
23
|
+
};
|
|
24
|
+
if (options.force === true) {
|
|
25
|
+
out.force = true;
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Minimal sync paths (verify-*, test --sync) always suppress upload sidecar chatter.
|
|
32
|
+
* @param {Object} [options]
|
|
33
|
+
* @returns {boolean}
|
|
34
|
+
*/
|
|
35
|
+
function isQuietMinimalSync(options = {}) {
|
|
36
|
+
return options.minimal === true || options.syncMode === true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = {
|
|
40
|
+
buildMinimalUploadSyncOptions,
|
|
41
|
+
isQuietMinimalSync
|
|
42
|
+
};
|
|
@@ -51,6 +51,12 @@ function hostPortForProfile(profile, listenPort, developerIdNum) {
|
|
|
51
51
|
: localHostPort(listenPort, developerIdNum);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
function localhostFrontDoorBaseForMissingRemote(opts) {
|
|
55
|
+
const { profile, developerIdNum } = opts || {};
|
|
56
|
+
const port = hostPortForProfile(profile, 3000, developerIdNum);
|
|
57
|
+
return `http://localhost:${port}`.replace(/\/+$/, '');
|
|
58
|
+
}
|
|
59
|
+
|
|
54
60
|
/**
|
|
55
61
|
* Scheme for `declarativePublicUrlsUseLocalhost` bases: always **http** for loopback reachability
|
|
56
62
|
* (ignore `tlsEnabled` / `remote-server` https — localhost URLs are not served with TLS in dev).
|
|
@@ -155,14 +161,26 @@ function templateUsesRemoteHostPlaceholder(hostTemplate) {
|
|
|
155
161
|
* @returns {string|null}
|
|
156
162
|
*/
|
|
157
163
|
function buildTraefikPublicBaseIfApplicable(opts) {
|
|
158
|
-
const {
|
|
159
|
-
|
|
164
|
+
const {
|
|
165
|
+
traefik,
|
|
166
|
+
pathActive,
|
|
167
|
+
hostTemplate,
|
|
168
|
+
developerIdRaw,
|
|
169
|
+
remoteServer,
|
|
170
|
+
infraTlsEnabled,
|
|
171
|
+
profile,
|
|
172
|
+
developerIdNum
|
|
173
|
+
} = opts;
|
|
160
174
|
// Plan 124: Traefik host authority only when pathActive (traefik ∧ frontDoorRouting.enabled)
|
|
161
175
|
if (!traefik || !pathActive || !hostTemplate || !String(hostTemplate).trim()) {
|
|
162
176
|
return null;
|
|
163
177
|
}
|
|
164
178
|
if (templateUsesRemoteHostPlaceholder(hostTemplate) && !String(remoteServer || '').trim()) {
|
|
165
|
-
|
|
179
|
+
// Local full-platform (no remote domain): use the single localhost front door port (3000 + devId×100).
|
|
180
|
+
return localhostFrontDoorBaseForMissingRemote({
|
|
181
|
+
profile,
|
|
182
|
+
developerIdNum
|
|
183
|
+
});
|
|
166
184
|
}
|
|
167
185
|
const expanded = expandFrontDoorHostTemplateForUrls(hostTemplate, {
|
|
168
186
|
developerIdRaw,
|
|
@@ -15,6 +15,7 @@ const yaml = require('js-yaml');
|
|
|
15
15
|
const { existsSync, readFileSync } = require('../internal/fs-real-sync');
|
|
16
16
|
const { DECLARATIVE_URL_INFRA_DEFAULTS } = require('./infra-env-defaults');
|
|
17
17
|
const { computePathActive } = require('./url-declarative-url-flags');
|
|
18
|
+
const { resolveInactiveVdirRewriteEnvKeys } = require('./app-relative-path-env');
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Treat common YAML / string forms as enabled (strict `=== true` alone missed some parsers).
|
|
@@ -52,16 +53,22 @@ const INACTIVE_VDIR_PUBLIC_ENV_FALLBACK =
|
|
|
52
53
|
/**
|
|
53
54
|
* @param {string} content - .env template fragment
|
|
54
55
|
* @param {string} replacement
|
|
56
|
+
* @param {ReadonlySet<string>} rewriteKeys
|
|
55
57
|
* @returns {string}
|
|
56
58
|
*/
|
|
57
|
-
function applyInactiveVdirPublicTokenRewrite(content, replacement) {
|
|
59
|
+
function applyInactiveVdirPublicTokenRewrite(content, replacement, rewriteKeys) {
|
|
58
60
|
if (!content || !content.includes(URL_DECLARATIVE_VDIR_PUBLIC_TOKEN)) {
|
|
59
61
|
return content;
|
|
60
62
|
}
|
|
61
63
|
const escaped = URL_DECLARATIVE_VDIR_PUBLIC_TOKEN.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
62
64
|
// End line with [ \t]* only — \s would consume \n and strip line endings from the file.
|
|
63
|
-
const lineRe = new RegExp(`^(\\s*[A-Z][A-Z0-9_]*)\\s*=\\s*${escaped}[ \t]*$`, 'gm');
|
|
64
|
-
return content.replace(lineRe, (
|
|
65
|
+
const lineRe = new RegExp(`^(\\s*)([A-Z][A-Z0-9_]*)\\s*=\\s*${escaped}[ \t]*$`, 'gm');
|
|
66
|
+
return content.replace(lineRe, (match, indent, key) => {
|
|
67
|
+
if (!rewriteKeys.has(key)) {
|
|
68
|
+
return match;
|
|
69
|
+
}
|
|
70
|
+
return `${indent}${key}=${replacement}`;
|
|
71
|
+
});
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
/**
|
|
@@ -88,12 +95,15 @@ function rewriteInactiveDeclarativeVdirPublicContent(content, variablesPath, use
|
|
|
88
95
|
if (pathActive) {
|
|
89
96
|
return content;
|
|
90
97
|
}
|
|
91
|
-
|
|
98
|
+
const appKey = doc && doc.app && doc.app.key;
|
|
99
|
+
const rewriteKeys = resolveInactiveVdirRewriteEnvKeys(appKey);
|
|
100
|
+
return applyInactiveVdirPublicTokenRewrite(content, INACTIVE_VDIR_PUBLIC_ENV_FALLBACK, rewriteKeys);
|
|
92
101
|
}
|
|
93
102
|
|
|
94
103
|
module.exports = {
|
|
95
104
|
URL_DECLARATIVE_VDIR_PUBLIC_TOKEN,
|
|
96
105
|
INACTIVE_VDIR_PUBLIC_ENV_FALLBACK,
|
|
106
|
+
loadApplicationYamlDoc,
|
|
97
107
|
applyInactiveVdirPublicTokenRewrite,
|
|
98
108
|
rewriteInactiveDeclarativeVdirPublicContent,
|
|
99
109
|
isFrontDoorRoutingEnabledInDoc
|
|
@@ -48,6 +48,14 @@ const NON_TTY_THROTTLE_MS = 5000;
|
|
|
48
48
|
* @returns {{ usesSpinner: boolean, onPollProgress: Function, finish: () => void }}
|
|
49
49
|
*/
|
|
50
50
|
function createValidationPollHandlers(deadlineMs, opts = {}) {
|
|
51
|
+
if (opts.quiet === true) {
|
|
52
|
+
return {
|
|
53
|
+
usesSpinner: false,
|
|
54
|
+
onPollProgress: () => {},
|
|
55
|
+
finish: () => {}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
const subject = opts.subject;
|
|
52
60
|
if (shouldUseValidationPollSpinner()) {
|
|
53
61
|
const ora = require('ora');
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Map legacy validation runType to contract stage (dataplane 370.07).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
/** @typedef {'readiness'|'simulation'|'integration'|'e2e'} ValidationRunStage */
|
|
8
|
+
|
|
9
|
+
/** @type {Record<string, ValidationRunStage>} */
|
|
10
|
+
const RUN_TYPE_TO_STAGE = {
|
|
11
|
+
test: 'readiness',
|
|
12
|
+
integration: 'integration',
|
|
13
|
+
e2e: 'e2e'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Contract stage for a CLI/API runType (default product mapping).
|
|
18
|
+
* @param {string} runType - test | integration | e2e
|
|
19
|
+
* @returns {ValidationRunStage}
|
|
20
|
+
*/
|
|
21
|
+
function stageForRunType(runType) {
|
|
22
|
+
const key = String(runType || 'test');
|
|
23
|
+
return RUN_TYPE_TO_STAGE[key] || 'readiness';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Attach stage to a validation/run POST body when absent.
|
|
28
|
+
* @param {Object} body
|
|
29
|
+
* @param {string} [runType]
|
|
30
|
+
* @returns {Object}
|
|
31
|
+
*/
|
|
32
|
+
function withStageOnValidationRunBody(body, runType) {
|
|
33
|
+
const out = { ...body };
|
|
34
|
+
const rt = runType || out.runType || 'test';
|
|
35
|
+
if (!out.stage) {
|
|
36
|
+
out.stage = stageForRunType(rt);
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = {
|
|
42
|
+
RUN_TYPE_TO_STAGE,
|
|
43
|
+
stageForRunType,
|
|
44
|
+
withStageOnValidationRunBody
|
|
45
|
+
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker sidecar resolution from application.yaml build settings.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Generic worker/beat companions driven by build.worker and imageRun* fields
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { buildDefaultLocalContainerName } = require('./environment-scoped-resources');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {object|null|undefined} build
|
|
13
|
+
* @param {string} field
|
|
14
|
+
* @returns {string|null}
|
|
15
|
+
*/
|
|
16
|
+
function readImageRunCommand(build, field) {
|
|
17
|
+
if (!build || typeof build !== 'object') {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const raw = build[field];
|
|
21
|
+
if (typeof raw !== 'string') {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const trimmed = raw.trim();
|
|
25
|
+
return trimmed ? trimmed : null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {object|null|undefined} appConfig
|
|
30
|
+
* @returns {boolean}
|
|
31
|
+
*/
|
|
32
|
+
function isWorkerStackEnabled(appConfig) {
|
|
33
|
+
if (!appConfig || typeof appConfig !== 'object') {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return appConfig.build?.worker === true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {string} appKey
|
|
41
|
+
* @param {object|null|undefined} appConfig
|
|
42
|
+
* @returns {{
|
|
43
|
+
* enabled: boolean,
|
|
44
|
+
* worker: { key: string, command: string }|null,
|
|
45
|
+
* beat: { key: string, command: string }|null,
|
|
46
|
+
* companions: Array<{ role: string, key: string, command: string }>
|
|
47
|
+
* }}
|
|
48
|
+
*/
|
|
49
|
+
function resolveWorkerSidecars(appKey, appConfig) {
|
|
50
|
+
const empty = { enabled: false, worker: null, beat: null, companions: [] };
|
|
51
|
+
if (!isWorkerStackEnabled(appConfig)) {
|
|
52
|
+
return empty;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const build = appConfig.build && typeof appConfig.build === 'object' ? appConfig.build : {};
|
|
56
|
+
const workerCommand = readImageRunCommand(build, 'imageRunWorker');
|
|
57
|
+
const beatCommand = readImageRunCommand(build, 'imageRunBeat');
|
|
58
|
+
const companions = [];
|
|
59
|
+
|
|
60
|
+
if (workerCommand) {
|
|
61
|
+
companions.push({ role: 'worker', key: `${appKey}-worker`, command: workerCommand });
|
|
62
|
+
}
|
|
63
|
+
if (beatCommand) {
|
|
64
|
+
companions.push({ role: 'beat', key: `${appKey}-beat`, command: beatCommand });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (companions.length === 0) {
|
|
68
|
+
return empty;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const worker = companions.find((entry) => entry.role === 'worker') || null;
|
|
72
|
+
const beat = companions.find((entry) => entry.role === 'beat') || null;
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
enabled: true,
|
|
76
|
+
worker,
|
|
77
|
+
beat,
|
|
78
|
+
companions
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @param {string} appKey
|
|
84
|
+
* @param {object|null|undefined} appConfig
|
|
85
|
+
* @returns {string[]}
|
|
86
|
+
*/
|
|
87
|
+
function getWorkerCompanionAppKeys(appKey, appConfig) {
|
|
88
|
+
return resolveWorkerSidecars(appKey, appConfig).companions.map((entry) => entry.key);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param {string} appKey
|
|
93
|
+
* @param {object} appConfig
|
|
94
|
+
* @param {{ devId: string|number, idNum: number }} ids
|
|
95
|
+
* @returns {{
|
|
96
|
+
* enabled: boolean,
|
|
97
|
+
* worker?: { key: string, containerName: string, command: string },
|
|
98
|
+
* beat?: { key: string, containerName: string, command: string }
|
|
99
|
+
* }}
|
|
100
|
+
*/
|
|
101
|
+
function buildWorkerSidecarComposeContext(appKey, appConfig, ids) {
|
|
102
|
+
const sidecars = resolveWorkerSidecars(appKey, appConfig);
|
|
103
|
+
if (!sidecars.enabled) {
|
|
104
|
+
return { enabled: false };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const context = { enabled: true };
|
|
108
|
+
if (sidecars.worker) {
|
|
109
|
+
context.worker = {
|
|
110
|
+
key: sidecars.worker.key,
|
|
111
|
+
containerName: buildDefaultLocalContainerName(sidecars.worker.key, ids.devId, ids.idNum),
|
|
112
|
+
command: sidecars.worker.command
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (sidecars.beat) {
|
|
116
|
+
context.beat = {
|
|
117
|
+
key: sidecars.beat.key,
|
|
118
|
+
containerName: buildDefaultLocalContainerName(sidecars.beat.key, ids.devId, ids.idNum),
|
|
119
|
+
command: sidecars.beat.command
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return context;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Azure startupCommand from compose imageRun (drops leading exec).
|
|
127
|
+
*
|
|
128
|
+
* @param {string} imageRun
|
|
129
|
+
* @returns {string}
|
|
130
|
+
*/
|
|
131
|
+
function imageRunToStartupCommand(imageRun) {
|
|
132
|
+
return imageRun.replace(/^exec\s+/i, '').trim();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
module.exports = {
|
|
136
|
+
readImageRunCommand,
|
|
137
|
+
isWorkerStackEnabled,
|
|
138
|
+
resolveWorkerSidecars,
|
|
139
|
+
getWorkerCompanionAppKeys,
|
|
140
|
+
buildWorkerSidecarComposeContext,
|
|
141
|
+
imageRunToStartupCommand
|
|
142
|
+
};
|
|
@@ -16,6 +16,7 @@ const path = require('path');
|
|
|
16
16
|
const { formatValidationErrors } = require('../utils/error-formatter');
|
|
17
17
|
const { validateFieldReferences } = require('../datasource/field-reference-validator');
|
|
18
18
|
const { validateAbac } = require('../datasource/abac-validator');
|
|
19
|
+
const { validateManifestRuntimeConfiguration } = require('./runtime-configuration-rules');
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Load and normalize external-system + external-datasource schema objects for manifest AJV.
|
|
@@ -247,6 +248,7 @@ async function validateControllerManifest(manifest) {
|
|
|
247
248
|
validateInlineSystem(manifest, ajv, externalSystemSchema, errors);
|
|
248
249
|
validateDatasources(manifest, ajv, externalDatasourceSchema, errors, warnings);
|
|
249
250
|
validateDatasourceSystemKeyAlignment(manifest, errors);
|
|
251
|
+
errors.push(...validateManifestRuntimeConfiguration(manifest));
|
|
250
252
|
validateConditionalRequirements(manifest, errors, warnings);
|
|
251
253
|
validateRequiredFields(manifest, errors);
|
|
252
254
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime configuration validation for external system manifests.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Datasource override rules (v1: no keyvault overrides)
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {Array<{ name?: string, location?: string }>|undefined} systemConfiguration
|
|
11
|
+
* @returns {Map<string, { name?: string, location?: string }>}
|
|
12
|
+
*/
|
|
13
|
+
function systemConfigDefsByName(systemConfiguration) {
|
|
14
|
+
const defsByName = new Map();
|
|
15
|
+
for (const item of systemConfiguration || []) {
|
|
16
|
+
if (item && item.name) {
|
|
17
|
+
defsByName.set(String(item.name).trim(), item);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return defsByName;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {string} prefix
|
|
25
|
+
* @param {Map<string, { name?: string, location?: string }>} defsByName
|
|
26
|
+
* @param {{ name?: string, value?: string }} override
|
|
27
|
+
* @returns {string[]}
|
|
28
|
+
*/
|
|
29
|
+
function validateOverrideEntry(prefix, defsByName, override) {
|
|
30
|
+
if (!override || !override.name) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
const name = String(override.name).trim();
|
|
34
|
+
const def = defsByName.get(name);
|
|
35
|
+
if (!def) {
|
|
36
|
+
return [`${prefix}configuration override '${name}' is not declared on the parent system.`];
|
|
37
|
+
}
|
|
38
|
+
const errors = [];
|
|
39
|
+
if (String(def.location || 'variable').toLowerCase() === 'keyvault') {
|
|
40
|
+
errors.push(
|
|
41
|
+
`${prefix}configuration override '${name}' targets a keyvault system definition (not allowed in v1).`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
const extraKeys = Object.keys(override).filter((key) => key !== 'name' && key !== 'value');
|
|
45
|
+
if (extraKeys.length > 0) {
|
|
46
|
+
errors.push(
|
|
47
|
+
`${prefix}configuration override '${name}' must contain only name and value (found: ${extraKeys.join(', ')}).`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return errors;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validates datasource configuration[] overrides against parent system definitions.
|
|
55
|
+
*
|
|
56
|
+
* @param {Array<{ name?: string, location?: string }>|undefined} systemConfiguration
|
|
57
|
+
* @param {Array<{ name?: string, value?: string }>|undefined} datasourceConfiguration
|
|
58
|
+
* @param {string} [datasourceKey] - For error prefixes
|
|
59
|
+
* @returns {string[]} Validation errors
|
|
60
|
+
*/
|
|
61
|
+
function validateDatasourceConfigurationOverrides(
|
|
62
|
+
systemConfiguration,
|
|
63
|
+
datasourceConfiguration,
|
|
64
|
+
datasourceKey
|
|
65
|
+
) {
|
|
66
|
+
if (!Array.isArray(datasourceConfiguration) || datasourceConfiguration.length === 0) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
const prefix = datasourceKey ? `Datasource '${datasourceKey}': ` : '';
|
|
70
|
+
const defsByName = systemConfigDefsByName(systemConfiguration);
|
|
71
|
+
return datasourceConfiguration.flatMap((override) =>
|
|
72
|
+
validateOverrideEntry(prefix, defsByName, override)
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {{ system?: { configuration?: unknown[] }, dataSources?: Array<{ key?: string, configuration?: unknown[] }> }} manifest
|
|
78
|
+
* @returns {string[]}
|
|
79
|
+
*/
|
|
80
|
+
function validateManifestRuntimeConfiguration(manifest) {
|
|
81
|
+
const errors = [];
|
|
82
|
+
const systemConfiguration = manifest?.system?.configuration;
|
|
83
|
+
for (const ds of manifest?.dataSources || []) {
|
|
84
|
+
errors.push(
|
|
85
|
+
...validateDatasourceConfigurationOverrides(
|
|
86
|
+
systemConfiguration,
|
|
87
|
+
ds?.configuration,
|
|
88
|
+
ds?.key
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return errors;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = {
|
|
96
|
+
validateDatasourceConfigurationOverrides,
|
|
97
|
+
validateManifestRuntimeConfiguration
|
|
98
|
+
};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Dimensions (ABAC) display helpers for validate-display.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { loadConfigFile } = require('../utils/config-format');
|
|
10
|
+
const { flattenRootDimensionsForDisplay } = require('./dimension-display-helpers');
|
|
11
|
+
const { formatDatasourceListRow } = require('../utils/cli-test-layout-chalk');
|
|
12
|
+
const logger = require('../utils/logger');
|
|
13
|
+
const {
|
|
14
|
+
logSectionTitle,
|
|
15
|
+
logWarnRow,
|
|
16
|
+
logDimLine
|
|
17
|
+
} = require('./validate-display-log-helpers');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* True when datasource is orchestration-only (no ABAC dimensions contract).
|
|
21
|
+
* @param {string} filePath - Path to datasource JSON
|
|
22
|
+
* @returns {boolean}
|
|
23
|
+
*/
|
|
24
|
+
function isOrchestrationOnlyDatasource(filePath) {
|
|
25
|
+
try {
|
|
26
|
+
const parsed = loadConfigFile(filePath);
|
|
27
|
+
return String(parsed?.entityType || '').trim() === 'none';
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Extracts dimensions from a datasource file for CLI display.
|
|
35
|
+
* Local bindings become `metadata.<field>`; FK bindings become `fk:<fk>→<dimension>...` plus optional `(actor: ...)`.
|
|
36
|
+
* @function extractDimensionsFromDatasource
|
|
37
|
+
* @param {string} filePath - Path to datasource file
|
|
38
|
+
* @returns {Object} Dimensions info { dimensions: Object, dimensionKeys: string[], hasDimensions: boolean }
|
|
39
|
+
*/
|
|
40
|
+
function extractDimensionsFromDatasource(filePath) {
|
|
41
|
+
try {
|
|
42
|
+
const parsed = loadConfigFile(filePath);
|
|
43
|
+
|
|
44
|
+
const rootFlat = flattenRootDimensionsForDisplay(parsed.dimensions);
|
|
45
|
+
const abacDimensions = parsed.abac?.dimensions || {};
|
|
46
|
+
const allDimensions = { ...rootFlat, ...abacDimensions };
|
|
47
|
+
const dimensionKeys = Object.keys(allDimensions);
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
dimensions: allDimensions,
|
|
51
|
+
dimensionKeys,
|
|
52
|
+
hasDimensions: dimensionKeys.length > 0
|
|
53
|
+
};
|
|
54
|
+
} catch {
|
|
55
|
+
return { dimensions: {}, dimensionKeys: [], hasDimensions: false };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Displays Dimensions (ABAC) validation results for datasources
|
|
61
|
+
* @function displayDimensionsValidation
|
|
62
|
+
* @param {Array} externalFiles - External files validation results
|
|
63
|
+
* @returns {Array} Warnings to add to aggregated warnings
|
|
64
|
+
*/
|
|
65
|
+
function displayDimensionsValidation(externalFiles) {
|
|
66
|
+
if (!externalFiles || externalFiles.length === 0) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const datasourceFiles = externalFiles.filter(f =>
|
|
71
|
+
f.type === 'datasource' || f.type === 'external-datasource'
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if (datasourceFiles.length === 0) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
logSectionTitle('Dimensions (ABAC)');
|
|
79
|
+
|
|
80
|
+
const warnings = [];
|
|
81
|
+
let anyDatasourceHasDimensions = false;
|
|
82
|
+
|
|
83
|
+
datasourceFiles.forEach(file => {
|
|
84
|
+
if (file.path && isOrchestrationOnlyDatasource(file.path)) {
|
|
85
|
+
logger.log(formatDatasourceListRow('ok', file.file, file.type));
|
|
86
|
+
logDimLine('orchestration-only (entityType=none) — dimensions N/A');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const dimensionsInfo = extractDimensionsFromDatasource(file.path);
|
|
90
|
+
|
|
91
|
+
if (dimensionsInfo.hasDimensions) {
|
|
92
|
+
anyDatasourceHasDimensions = true;
|
|
93
|
+
logger.log(formatDatasourceListRow('ok', file.file, file.type));
|
|
94
|
+
dimensionsInfo.dimensionKeys.forEach(key => {
|
|
95
|
+
const mapping = dimensionsInfo.dimensions[key];
|
|
96
|
+
logDimLine(`${key} → ${mapping}`);
|
|
97
|
+
});
|
|
98
|
+
} else {
|
|
99
|
+
logWarnRow(`${file.file} — no dimensions configured`);
|
|
100
|
+
warnings.push(`${file.file} - no dimensions configured, ABAC filtering disabled`);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (!anyDatasourceHasDimensions && datasourceFiles.some(
|
|
105
|
+
(file) => !(file.path && isOrchestrationOnlyDatasource(file.path))
|
|
106
|
+
)) {
|
|
107
|
+
logWarnRow('No dimensions configured — ABAC filtering disabled for all datasources');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return warnings;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Displays dimensions validation for datasources
|
|
115
|
+
* @function displayDimensionsStep
|
|
116
|
+
* @param {Array} datasourceFiles - Datasource files
|
|
117
|
+
* @returns {void}
|
|
118
|
+
*/
|
|
119
|
+
function displayDimensionsStep(datasourceFiles) {
|
|
120
|
+
if (datasourceFiles.length === 0) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
logSectionTitle('Dimensions (ABAC)');
|
|
125
|
+
datasourceFiles.forEach(file => {
|
|
126
|
+
try {
|
|
127
|
+
const dsPath = file.path || file.file;
|
|
128
|
+
if (dsPath && isOrchestrationOnlyDatasource(dsPath)) {
|
|
129
|
+
logger.log(formatDatasourceListRow('ok', file.file, file.type));
|
|
130
|
+
logDimLine('orchestration-only (entityType=none) — dimensions N/A');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const dimensionsInfo = extractDimensionsFromDatasource(dsPath);
|
|
134
|
+
if (dimensionsInfo.hasDimensions) {
|
|
135
|
+
logger.log(formatDatasourceListRow('ok', file.file, file.type));
|
|
136
|
+
dimensionsInfo.dimensionKeys.forEach(key => {
|
|
137
|
+
const mapping = dimensionsInfo.dimensions[key];
|
|
138
|
+
logDimLine(`${key} → ${mapping}`);
|
|
139
|
+
});
|
|
140
|
+
} else {
|
|
141
|
+
logWarnRow(`${file.file} — no dimensions configured`);
|
|
142
|
+
}
|
|
143
|
+
} catch {
|
|
144
|
+
// Skip if file path not available
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = {
|
|
150
|
+
isOrchestrationOnlyDatasource,
|
|
151
|
+
extractDimensionsFromDatasource,
|
|
152
|
+
displayDimensionsValidation,
|
|
153
|
+
displayDimensionsStep
|
|
154
|
+
};
|