@aifabrix/builder 2.43.0 → 2.44.1
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/anchor-docs.mdc +15 -0
- package/.cursor/rules/cli-layout.mdc +75 -0
- package/.cursor/rules/project-rules.mdc +8 -0
- package/.npmrc.token +1 -0
- package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
- package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/README.md +1 -1
- package/anchor-docs/README.md +10 -0
- package/anchor-docs/_TEMPLATE +24 -0
- package/bin/aifabrix.js +13 -4
- package/integration/hubspot-test/README.md +31 -0
- package/integration/hubspot-test/create-hubspot.js +5 -5
- package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
- package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
- package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
- package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
- package/integration/hubspot-test/test-dataplane-down.js +3 -3
- package/integration/hubspot-test/test.js +35 -43
- package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
- package/integration/roundtrip-test-local/README.md +144 -0
- package/integration/roundtrip-test-local/application.yaml +13 -0
- package/integration/roundtrip-test-local/env.template +15 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
- package/integration/roundtrip-test-local2/README.md +144 -0
- package/integration/roundtrip-test-local2/application.yaml +13 -0
- package/integration/roundtrip-test-local2/env.template +15 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
- package/integration/test/wizard.yaml +8 -0
- package/jest.config.default.js +10 -0
- package/jest.config.integration.fixtures.js +22 -0
- package/jest.config.integration.js +21 -18
- package/jest.config.isolated.js +10 -0
- package/jest.projects.js +301 -0
- package/lib/api/certificates.api.js +62 -0
- package/lib/api/datasources-core.api.js +3 -3
- package/lib/api/dev-mtls-request.js +110 -0
- package/lib/api/dev-server-https.js +145 -0
- package/lib/api/dev.api.js +133 -144
- package/lib/api/index.js +11 -3
- package/lib/api/pipeline.api.js +67 -20
- package/lib/api/types/certificates.types.js +48 -0
- package/lib/api/types/dev.types.js +4 -3
- package/lib/api/types/pipeline.types.js +8 -5
- package/lib/api/types/validation-run.types.js +56 -0
- package/lib/api/validation-run.api.js +111 -0
- package/lib/api/validation-runner.js +109 -0
- package/lib/app/certification-show-enrich.js +129 -0
- package/lib/app/certification-verify-rows.js +60 -0
- package/lib/app/config.js +1 -1
- package/lib/app/deploy-status-display.js +2 -2
- package/lib/app/deploy.js +7 -6
- package/lib/app/display.js +2 -1
- package/lib/app/dockerfile.js +3 -2
- package/lib/app/down.js +2 -1
- package/lib/app/helpers.js +6 -5
- package/lib/app/index.js +27 -8
- package/lib/app/list.js +7 -6
- package/lib/app/push.js +4 -3
- package/lib/app/register.js +16 -7
- package/lib/app/rotate-secret.js +14 -13
- package/lib/app/run-container-start.js +184 -0
- package/lib/app/run-docker-fallback.js +108 -0
- package/lib/app/run-env-compose.js +30 -42
- package/lib/app/run-helpers.js +49 -126
- package/lib/app/run-infra-requirements.js +30 -0
- package/lib/app/run-resolve-image.js +21 -0
- package/lib/app/run.js +74 -21
- package/lib/app/show-display.js +44 -1
- package/lib/app/show.js +93 -9
- package/lib/build/index.js +13 -10
- package/lib/certification/cli-cert-sync-skip.js +21 -0
- package/lib/certification/merge-certification-from-artifact.js +185 -0
- package/lib/certification/post-unified-cert-sync.js +33 -0
- package/lib/certification/sync-after-external-command.js +52 -0
- package/lib/certification/sync-system-certification.js +197 -0
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.help.js +67 -0
- package/lib/cli/setup-app.js +61 -121
- package/lib/cli/setup-app.test-commands.js +195 -0
- package/lib/cli/setup-auth.js +19 -5
- package/lib/cli/setup-credential-deployment.js +22 -8
- package/lib/cli/setup-dev-path-commands.js +124 -0
- package/lib/cli/setup-dev.js +170 -113
- package/lib/cli/setup-environment.js +7 -1
- package/lib/cli/setup-external-system.js +84 -23
- package/lib/cli/setup-infra.js +126 -47
- package/lib/cli/setup-parameters.js +32 -0
- package/lib/cli/setup-secrets.js +137 -18
- package/lib/cli/setup-service-user.js +1 -1
- package/lib/cli/setup-utility.js +54 -22
- package/lib/commands/app-down.js +5 -7
- package/lib/commands/app-install.js +14 -7
- package/lib/commands/app-logs.js +13 -10
- package/lib/commands/app-shell.js +4 -1
- package/lib/commands/app-test.js +25 -19
- package/lib/commands/app.js +32 -11
- package/lib/commands/auth-config.js +6 -6
- package/lib/commands/auth-status.js +4 -3
- package/lib/commands/credential-env.js +4 -3
- package/lib/commands/credential-list.js +5 -4
- package/lib/commands/credential-push.js +4 -3
- package/lib/commands/datasource-unified-test-cli.js +428 -0
- package/lib/commands/datasource-unified-test-cli.options.js +191 -0
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
- package/lib/commands/datasource-validation-cli.js +143 -0
- package/lib/commands/datasource.js +125 -95
- package/lib/commands/deployment-list.js +6 -5
- package/lib/commands/dev-cli-handlers.js +122 -18
- package/lib/commands/dev-down.js +4 -3
- package/lib/commands/dev-init.js +231 -116
- package/lib/commands/dev-show-display.js +473 -0
- package/lib/commands/login-credentials.js +3 -2
- package/lib/commands/login-device.js +4 -3
- package/lib/commands/login.js +5 -4
- package/lib/commands/logout.js +8 -7
- package/lib/commands/parameters-validate.js +54 -0
- package/lib/commands/repair-datasource.js +314 -68
- package/lib/commands/repair-env-template.js +2 -2
- package/lib/commands/repair.js +21 -3
- package/lib/commands/secrets-list.js +23 -12
- package/lib/commands/secrets-remove-all.js +220 -0
- package/lib/commands/secrets-remove.js +21 -12
- package/lib/commands/secrets-set.js +21 -12
- package/lib/commands/secrets-validate.js +4 -4
- package/lib/commands/secure.js +10 -9
- package/lib/commands/service-user.js +26 -25
- package/lib/commands/test-e2e-external.js +27 -1
- package/lib/commands/up-common.js +3 -2
- package/lib/commands/up-dataplane.js +29 -16
- package/lib/commands/up-miso.js +19 -29
- package/lib/commands/upload.js +149 -39
- package/lib/commands/wizard-core-helpers.js +1 -1
- package/lib/commands/wizard-dataplane.js +4 -3
- package/lib/commands/wizard-helpers.js +3 -3
- package/lib/commands/wizard.js +2 -2
- package/lib/core/admin-secrets.js +14 -5
- package/lib/core/audit-logger.js +12 -4
- package/lib/core/config-attach-extensions.js +46 -0
- package/lib/core/config-runtime-paths.js +29 -0
- package/lib/core/config.js +55 -56
- package/lib/core/diff.js +3 -2
- package/lib/core/ensure-encryption-key.js +1 -1
- package/lib/core/secrets-ensure-infra.js +77 -0
- package/lib/core/secrets-ensure.js +120 -64
- package/lib/core/secrets-env-write.js +35 -7
- package/lib/core/secrets-infra-placeholder-sync.js +61 -0
- package/lib/core/secrets.js +200 -37
- package/lib/core/templates-env.js +4 -3
- package/lib/datasource/abac-validator.js +1 -10
- package/lib/datasource/deploy.js +75 -53
- package/lib/datasource/field-reference-validator.js +9 -6
- package/lib/datasource/integration-context.js +63 -0
- package/lib/datasource/list.js +8 -7
- package/lib/datasource/log-viewer.js +189 -67
- package/lib/datasource/resolve-app.js +4 -4
- package/lib/datasource/test-e2e.js +113 -146
- package/lib/datasource/test-integration.js +114 -122
- package/lib/datasource/unified-validation-run-body.js +68 -0
- package/lib/datasource/unified-validation-run-post.js +23 -0
- package/lib/datasource/unified-validation-run-resolve.js +43 -0
- package/lib/datasource/unified-validation-run.js +93 -0
- package/lib/datasource/validate.js +157 -13
- package/lib/deployment/deployer.js +4 -3
- package/lib/deployment/environment.js +7 -6
- package/lib/deployment/push.js +17 -8
- package/lib/external-system/delete.js +4 -3
- package/lib/external-system/deploy.js +166 -53
- package/lib/external-system/download-helpers.js +1 -1
- package/lib/external-system/download.js +7 -6
- package/lib/external-system/generator.js +92 -6
- package/lib/external-system/integration-test-dispatch.js +26 -0
- package/lib/external-system/test-execution.js +5 -1
- package/lib/external-system/test-helpers.js +0 -4
- package/lib/external-system/test-system-level-helpers.js +110 -0
- package/lib/external-system/test-system-level.js +83 -44
- package/lib/external-system/test.js +59 -8
- package/lib/generator/builders.js +23 -11
- package/lib/generator/deploy-manifest-azure-kv.js +81 -0
- package/lib/generator/external.js +16 -4
- package/lib/generator/helpers.js +58 -3
- package/lib/generator/index.js +4 -0
- package/lib/generator/split-readme.js +12 -7
- package/lib/generator/split-variables.js +2 -1
- package/lib/generator/split.js +1 -1
- package/lib/generator/wizard-readme.js +3 -3
- package/lib/generator/wizard.js +8 -8
- package/lib/infrastructure/compose.js +70 -7
- package/lib/infrastructure/helpers-docker-check.js +67 -0
- package/lib/infrastructure/helpers.js +203 -42
- package/lib/infrastructure/index.js +31 -18
- package/lib/infrastructure/services.js +21 -67
- package/lib/internal/fs-real-sync.js +104 -0
- package/lib/internal/node-fs.js +98 -0
- package/lib/parameters/database-secret-values.js +173 -0
- package/lib/parameters/infra-kv-discovery.js +121 -0
- package/lib/parameters/infra-parameter-catalog.js +458 -0
- package/lib/parameters/infra-parameter-validate.js +64 -0
- package/lib/schema/application-schema.json +37 -17
- package/lib/schema/datasource-test-run.schema.json +493 -0
- package/lib/schema/deployment-rules.yaml +102 -63
- package/lib/schema/external-datasource.schema.json +1200 -442
- package/lib/schema/external-system.schema.json +203 -5
- package/lib/schema/flag-map-validation-run.json +31 -0
- package/lib/schema/infra-parameter.schema.json +106 -0
- package/lib/schema/infra.parameter.yaml +421 -0
- package/lib/schema/type/credential-auth-templates.json +40 -0
- package/lib/schema/type/document-storage.json +226 -0
- package/lib/schema/type/message-service.json +123 -0
- package/lib/schema/type/vector-store.json +88 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
- package/lib/utils/api-error-handler.js +2 -2
- package/lib/utils/api.js +77 -17
- package/lib/utils/app-register-api.js +3 -2
- package/lib/utils/app-register-auth.js +1 -1
- package/lib/utils/app-register-config.js +4 -4
- package/lib/utils/app-register-display.js +3 -2
- package/lib/utils/app-register-validator.js +3 -2
- package/lib/utils/app-run-containers.js +26 -22
- package/lib/utils/app-scoped-config.js +31 -0
- package/lib/utils/app-service-env-from-builder.js +164 -0
- package/lib/utils/build-copy.js +1 -1
- package/lib/utils/build-helpers.js +20 -20
- package/lib/utils/build-resolve-image.js +165 -0
- package/lib/utils/cli-layout-chalk.js +8 -0
- package/lib/utils/cli-test-layout-chalk.js +267 -0
- package/lib/utils/cli-utils.js +88 -11
- package/lib/utils/compose-db-passwords.js +138 -0
- package/lib/utils/compose-generate-docker-compose.js +216 -0
- package/lib/utils/compose-generator.js +197 -291
- package/lib/utils/compose-miso-env.js +18 -0
- package/lib/utils/compose-traefik-ingress-base.js +158 -0
- package/lib/utils/config-paths.js +166 -7
- package/lib/utils/config-scoped-resources-preference.js +41 -0
- package/lib/utils/configuration-env-resolver.js +11 -8
- package/lib/utils/controller-deployment-outcome.js +68 -0
- package/lib/utils/credential-display.js +2 -2
- package/lib/utils/credential-secrets-env.js +5 -5
- package/lib/utils/dataplane-pipeline-warning.js +4 -3
- package/lib/utils/datasource-test-run-capability-scope.js +43 -0
- package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
- package/lib/utils/datasource-test-run-debug-display.js +137 -0
- package/lib/utils/datasource-test-run-debug-slice.js +93 -0
- package/lib/utils/datasource-test-run-display.js +459 -0
- package/lib/utils/datasource-test-run-exit.js +83 -0
- package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
- package/lib/utils/datasource-test-run-report-version.js +51 -0
- package/lib/utils/datasource-test-run-schema-sync.js +59 -0
- package/lib/utils/datasource-test-run-tty-log.js +81 -0
- package/lib/utils/datasource-validation-watch.js +266 -0
- package/lib/utils/declarative-url-ports.js +47 -0
- package/lib/utils/derive-env-key-from-client-id.js +41 -0
- package/lib/utils/dev-ca-install.js +185 -23
- package/lib/utils/dev-cert-helper.js +266 -17
- package/lib/utils/dev-hosts-helper.js +307 -0
- package/lib/utils/dev-init-cert-hints.js +37 -0
- package/lib/utils/dev-init-health-messages.js +52 -0
- package/lib/utils/dev-init-resolve.js +86 -0
- package/lib/utils/dev-init-ssh-merge.js +65 -0
- package/lib/utils/dev-ssh-config-helper.js +196 -0
- package/lib/utils/dev-user-groups.js +93 -0
- package/lib/utils/docker-build.js +42 -17
- package/lib/utils/docker-exec.js +28 -0
- package/lib/utils/docker-manifest-public-port.js +116 -0
- package/lib/utils/docker-not-running-hint.js +52 -0
- package/lib/utils/docker.js +98 -11
- package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
- package/lib/utils/env-config-loader.js +10 -91
- package/lib/utils/env-copy.js +19 -10
- package/lib/utils/env-map.js +35 -8
- package/lib/utils/env-template.js +2 -2
- package/lib/utils/environment-scoped-resources.js +144 -0
- package/lib/utils/error-formatter.js +92 -13
- package/lib/utils/error-formatters/http-status-errors.js +6 -5
- package/lib/utils/error-formatters/network-errors.js +2 -1
- package/lib/utils/error-formatters/permission-errors.js +2 -1
- package/lib/utils/error-formatters/validation-errors.js +2 -1
- package/lib/utils/external-readme.js +8 -1
- package/lib/utils/external-system-display.js +242 -136
- package/lib/utils/external-system-local-test-tty.js +389 -0
- package/lib/utils/external-system-readiness-core.js +377 -0
- package/lib/utils/external-system-readiness-deploy-display.js +270 -0
- package/lib/utils/external-system-readiness-display-internals.js +150 -0
- package/lib/utils/external-system-readiness-display.js +186 -0
- package/lib/utils/external-system-system-test-tty-overview.js +120 -0
- package/lib/utils/external-system-system-test-tty.js +417 -0
- package/lib/utils/external-system-test-helpers.js +24 -6
- package/lib/utils/external-system-validators.js +30 -12
- package/lib/utils/health-check-url.js +119 -0
- package/lib/utils/health-check.js +59 -25
- package/lib/utils/help-builder.js +11 -8
- package/lib/utils/image-version.js +4 -8
- package/lib/utils/infra-containers.js +4 -7
- package/lib/utils/infra-env-defaults.js +162 -0
- package/lib/utils/infra-status-display.js +167 -0
- package/lib/utils/infra-status.js +16 -8
- package/lib/utils/local-secrets.js +3 -4
- package/lib/utils/paths.js +148 -47
- package/lib/utils/port-resolver.js +10 -23
- package/lib/utils/redis-env-scope.js +62 -0
- package/lib/utils/register-aifabrix-shell-env.js +204 -0
- package/lib/utils/remote-builder-validation.js +99 -0
- package/lib/utils/remote-dev-auth.js +117 -21
- package/lib/utils/remote-docker-env.js +67 -15
- package/lib/utils/remote-secrets-loader.js +13 -4
- package/lib/utils/resolve-docker-image-ref.js +124 -0
- package/lib/utils/schema-loader.js +22 -9
- package/lib/utils/secrets-bash-kv.js +25 -0
- package/lib/utils/secrets-generator.js +169 -49
- package/lib/utils/secrets-helpers.js +70 -59
- package/lib/utils/secrets-kv-scope.js +60 -0
- package/lib/utils/secrets-utils.js +32 -38
- package/lib/utils/secrets-validation.js +3 -1
- package/lib/utils/secrets-yaml-preserve.js +109 -0
- package/lib/utils/ssh-key-helper.js +4 -2
- package/lib/utils/template-helpers.js +2 -2
- package/lib/utils/test-log-writer.js +3 -3
- package/lib/utils/token-manager.js +1 -2
- package/lib/utils/url-declarative-public-base.js +188 -0
- package/lib/utils/url-declarative-resolve-build.js +493 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
- package/lib/utils/url-declarative-resolve.js +220 -0
- package/lib/utils/url-declarative-token-parse.js +74 -0
- package/lib/utils/url-declarative-url-flags.js +50 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
- package/lib/utils/url-public-path-prefix.js +34 -0
- package/lib/utils/urls-local-registry.js +220 -0
- package/lib/utils/validation-report-tty-kit.js +77 -0
- package/lib/utils/validation-run-poll.js +112 -0
- package/lib/utils/validation-run-post-retry.js +85 -0
- package/lib/utils/validation-run-request.js +116 -0
- package/lib/utils/variable-transformer.js +21 -4
- package/lib/utils/yaml-preserve.js +33 -14
- package/lib/validation/datasource-warnings.js +56 -0
- package/lib/validation/env-template-auth.js +1 -1
- package/lib/validation/external-manifest-validator.js +27 -7
- package/lib/validation/validate-display.js +37 -31
- package/lib/validation/validate-external-cert-sync.js +23 -0
- package/lib/validation/validate.js +8 -14
- package/lib/validation/validator-unresolved-placeholders.js +98 -0
- package/lib/validation/validator.js +22 -65
- package/lib/validation/wizard-config-validator.js +2 -1
- package/package.json +9 -4
- package/scripts/check-datasource-test-run-schema-sync.js +34 -0
- package/scripts/diagnose-cli.js +150 -0
- package/scripts/install-local.js +307 -55
- package/scripts/pnpm-global-remove.js +48 -0
- package/templates/README.md +15 -2
- package/templates/applications/dataplane/application.yaml +52 -2
- package/templates/applications/dataplane/env.template +79 -17
- package/templates/applications/dataplane/rbac.yaml +8 -0
- package/templates/applications/keycloak/application.yaml +9 -1
- package/templates/applications/keycloak/env.template +15 -6
- package/templates/applications/miso-controller/application.yaml +10 -2
- package/templates/applications/miso-controller/env.template +42 -12
- package/templates/applications/miso-controller/rbac.yaml +5 -0
- package/templates/external-system/README.md.hbs +20 -7
- package/templates/external-system/deploy.js.hbs +5 -5
- package/templates/external-system/external-datasource.yaml.hbs +197 -118
- package/templates/infra/compose.yaml.hbs +33 -16
- package/templates/infra/servers.json.hbs +3 -1
- package/templates/python/docker-compose.hbs +16 -0
- package/templates/typescript/docker-compose.hbs +16 -0
- package/lib/api/external-test.api.js +0 -111
- package/lib/schema/env-config.yaml +0 -60
|
@@ -251,6 +251,35 @@ function collectBlockScalarLines(lines, startIndex, keyIndentLen) {
|
|
|
251
251
|
return { value: parts.join(' '), endIndex: i };
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Processes a single block-scalar key line and its continuation lines.
|
|
256
|
+
* @param {string} line - Line matching BLOCK_SCALAR_PATTERN
|
|
257
|
+
* @param {string[]} lines - All lines
|
|
258
|
+
* @param {number} lineIndex - Index of current line
|
|
259
|
+
* @param {string} encryptionKey - Encryption key
|
|
260
|
+
* @param {Object} stats - Mutable stats object
|
|
261
|
+
* @returns {{ resultLine: string, nextIndex: number }|null} Result or null if not a block scalar
|
|
262
|
+
*/
|
|
263
|
+
function processBlockScalarLine(line, lines, lineIndex, encryptionKey, stats) {
|
|
264
|
+
const blockMatch = line.match(BLOCK_SCALAR_PATTERN);
|
|
265
|
+
if (!blockMatch) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
const [, indent, key, blockIndicator, trailingWhitespace, comment] = blockMatch;
|
|
269
|
+
const keyIndentLen = indent.length;
|
|
270
|
+
const folded = blockIndicator.startsWith('>');
|
|
271
|
+
const { value: rawValue, endIndex } = collectBlockScalarLines(lines, lineIndex + 1, keyIndentLen);
|
|
272
|
+
const value = folded ? rawValue.replace(/\s+/g, ' ').trim() : rawValue;
|
|
273
|
+
stats.total++;
|
|
274
|
+
const needEncrypt = shouldEncryptValue(value);
|
|
275
|
+
const outValue = needEncrypt ? encryptSecret(value, encryptionKey) : value;
|
|
276
|
+
if (needEncrypt) {
|
|
277
|
+
stats.encrypted++;
|
|
278
|
+
}
|
|
279
|
+
const resultLine = `${indent}${key}: ${outValue}${trailingWhitespace || ''}${comment || ''}`;
|
|
280
|
+
return { resultLine, nextIndex: endIndex };
|
|
281
|
+
}
|
|
282
|
+
|
|
254
283
|
function encryptYamlValues(content, encryptionKey) {
|
|
255
284
|
const lines = content.split(/\r?\n/);
|
|
256
285
|
const encryptedLines = [];
|
|
@@ -267,20 +296,10 @@ function encryptYamlValues(content, encryptionKey) {
|
|
|
267
296
|
continue;
|
|
268
297
|
}
|
|
269
298
|
|
|
270
|
-
const
|
|
271
|
-
if (
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const folded = blockIndicator.startsWith('>');
|
|
275
|
-
const { value: rawValue, endIndex } = collectBlockScalarLines(lines, i + 1, keyIndentLen);
|
|
276
|
-
const value = folded ? rawValue.replace(/\s+/g, ' ').trim() : rawValue;
|
|
277
|
-
stats.total++;
|
|
278
|
-
const outValue = shouldEncryptValue(value) ? encryptSecret(value, encryptionKey) : value;
|
|
279
|
-
if (shouldEncryptValue(value)) {
|
|
280
|
-
stats.encrypted++;
|
|
281
|
-
}
|
|
282
|
-
encryptedLines.push(`${indent}${key}: ${outValue}${trailingWhitespace || ''}${comment || ''}`);
|
|
283
|
-
i = endIndex;
|
|
299
|
+
const blockResult = processBlockScalarLine(line, lines, i, encryptionKey, stats);
|
|
300
|
+
if (blockResult) {
|
|
301
|
+
encryptedLines.push(blockResult.resultLine);
|
|
302
|
+
i = blockResult.nextIndex;
|
|
284
303
|
continue;
|
|
285
304
|
}
|
|
286
305
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional v2.4.x datasource validation warnings (beyond JSON Schema).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Post-schema warnings for external datasource configs
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 2.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const STORAGE_ENTITIES = new Set(['recordStorage', 'documentStorage']);
|
|
10
|
+
|
|
11
|
+
function warnMissingDimensions(parsed, warnings) {
|
|
12
|
+
const entityType = parsed.entityType;
|
|
13
|
+
if (!STORAGE_ENTITIES.has(entityType)) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const dims = parsed.dimensions;
|
|
17
|
+
if (!dims || typeof dims !== 'object' || Array.isArray(dims) || Object.keys(dims).length === 0) {
|
|
18
|
+
warnings.push(
|
|
19
|
+
`Datasource "${parsed.key || '(unknown)'}": dimensions missing or empty for entityType=${entityType} (recommended for ABAC; see schema 2.4.x notes).`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function warnFkWithoutActor(parsed, warnings) {
|
|
25
|
+
const dimensions = parsed.dimensions;
|
|
26
|
+
if (!dimensions || typeof dimensions !== 'object' || Array.isArray(dimensions)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
for (const [dimKey, binding] of Object.entries(dimensions)) {
|
|
30
|
+
if (!binding || typeof binding !== 'object' || binding.type !== 'fk') {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (!Object.prototype.hasOwnProperty.call(binding, 'actor')) {
|
|
34
|
+
warnings.push(
|
|
35
|
+
`Datasource "${parsed.key || '(unknown)'}": dimension "${dimKey}" uses type=fk without actor; set actor (displayName, email, userId, groups, roles) for predictable ABAC binding.`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Collects non-fatal warnings for an external datasource document (already parsed).
|
|
43
|
+
* @param {Object} parsed - Parsed datasource JSON
|
|
44
|
+
* @returns {string[]} Warning messages (empty if none)
|
|
45
|
+
*/
|
|
46
|
+
function collectExternalDatasourceWarnings(parsed) {
|
|
47
|
+
const warnings = [];
|
|
48
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
49
|
+
return warnings;
|
|
50
|
+
}
|
|
51
|
+
warnMissingDimensions(parsed, warnings);
|
|
52
|
+
warnFkWithoutActor(parsed, warnings);
|
|
53
|
+
return warnings;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = { collectExternalDatasourceWarnings };
|
|
@@ -184,7 +184,7 @@ async function validateAuthSecurityPathConsistency(appPath, errors, _warnings) {
|
|
|
184
184
|
const canonicalPath = canonicalSegment ? `kv://${systemKey}/${canonicalSegment}` : null;
|
|
185
185
|
if (canonicalPath && value !== canonicalPath) {
|
|
186
186
|
errors.push(
|
|
187
|
-
`authentication.security.${key} has path ${value}; canonical path is ${canonicalPath}. Run \`aifabrix repair <
|
|
187
|
+
`authentication.security.${key} has path ${value}; canonical path is ${canonicalPath}. Run \`aifabrix repair <systemKey>\` to normalize.`
|
|
188
188
|
);
|
|
189
189
|
}
|
|
190
190
|
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
const Ajv = require('ajv');
|
|
13
|
+
const addFormats = require('ajv-formats');
|
|
13
14
|
const fs = require('fs');
|
|
14
15
|
const path = require('path');
|
|
15
16
|
const { formatValidationErrors } = require('../utils/error-formatter');
|
|
@@ -28,6 +29,7 @@ async function setupAjvWithSchemas() {
|
|
|
28
29
|
strict: false,
|
|
29
30
|
removeAdditional: false
|
|
30
31
|
});
|
|
32
|
+
addFormats(ajv);
|
|
31
33
|
|
|
32
34
|
// Load raw schema objects (not compiled validators)
|
|
33
35
|
const externalSystemSchemaPath = path.join(__dirname, '..', 'schema', 'external-system.schema.json');
|
|
@@ -43,11 +45,20 @@ async function setupAjvWithSchemas() {
|
|
|
43
45
|
externalDatasourceSchema = schemaCopy;
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
if (!externalSystemSchema.$id || typeof externalSystemSchema.$id !== 'string') {
|
|
49
|
+
throw new Error('External system schema is missing required $id');
|
|
50
|
+
}
|
|
51
|
+
if (!externalDatasourceSchema.$id || typeof externalDatasourceSchema.$id !== 'string') {
|
|
52
|
+
throw new Error('External datasource schema is missing required $id');
|
|
53
|
+
}
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
ajv.addSchema(
|
|
55
|
+
// external-datasource.schema.json references these by $id (aifabrix://schema/type/*)
|
|
56
|
+
ajv.addSchema(require('../schema/type/document-storage.json'));
|
|
57
|
+
ajv.addSchema(require('../schema/type/message-service.json'));
|
|
58
|
+
ajv.addSchema(require('../schema/type/vector-store.json'));
|
|
59
|
+
|
|
60
|
+
ajv.addSchema(externalSystemSchema, externalSystemSchema.$id);
|
|
61
|
+
ajv.addSchema(externalDatasourceSchema, externalDatasourceSchema.$id);
|
|
51
62
|
|
|
52
63
|
return { ajv, externalSystemSchema, externalDatasourceSchema };
|
|
53
64
|
}
|
|
@@ -66,7 +77,10 @@ function validateManifestStructure(manifest, ajv, applicationSchema, errors) {
|
|
|
66
77
|
const manifestValid = validateManifest(manifest);
|
|
67
78
|
|
|
68
79
|
if (!manifestValid) {
|
|
69
|
-
const manifestErrors = formatValidationErrors(validateManifest.errors
|
|
80
|
+
const manifestErrors = formatValidationErrors(validateManifest.errors, {
|
|
81
|
+
rootData: manifest,
|
|
82
|
+
deploymentManifest: manifest
|
|
83
|
+
});
|
|
70
84
|
errors.push(...manifestErrors.map(err => `Manifest validation: ${err}`));
|
|
71
85
|
}
|
|
72
86
|
}
|
|
@@ -86,7 +100,10 @@ function validateInlineSystem(manifest, ajv, externalSystemSchema, errors) {
|
|
|
86
100
|
const systemValid = validateSystem(manifest.system);
|
|
87
101
|
|
|
88
102
|
if (!systemValid) {
|
|
89
|
-
const systemErrors = formatValidationErrors(validateSystem.errors
|
|
103
|
+
const systemErrors = formatValidationErrors(validateSystem.errors, {
|
|
104
|
+
rootData: manifest.system,
|
|
105
|
+
deploymentManifest: manifest.system
|
|
106
|
+
});
|
|
90
107
|
errors.push(...systemErrors.map(err => `System validation: ${err}`));
|
|
91
108
|
}
|
|
92
109
|
} else if (manifest.type === 'external') {
|
|
@@ -113,7 +130,10 @@ function validateDatasources(manifest, ajv, externalDatasourceSchema, errors, wa
|
|
|
113
130
|
manifest.dataSources.forEach((datasource, index) => {
|
|
114
131
|
const datasourceValid = validateDatasource(datasource);
|
|
115
132
|
if (!datasourceValid) {
|
|
116
|
-
const datasourceErrors = formatValidationErrors(validateDatasource.errors
|
|
133
|
+
const datasourceErrors = formatValidationErrors(validateDatasource.errors, {
|
|
134
|
+
rootData: datasource,
|
|
135
|
+
deploymentManifest: datasource
|
|
136
|
+
});
|
|
117
137
|
errors.push(...datasourceErrors.map(err => `Datasource ${index + 1} (${datasource.key || 'unknown'}): ${err}`));
|
|
118
138
|
} else {
|
|
119
139
|
const fieldRefErrors = validateFieldReferences(datasource);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatBlockingError, formatSuccessLine, formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* Validation Display Utilities
|
|
3
4
|
*
|
|
@@ -25,9 +26,9 @@ function displayApplicationValidation(application) {
|
|
|
25
26
|
|
|
26
27
|
logger.log(chalk.blue('\nApplication:'));
|
|
27
28
|
if (application.valid) {
|
|
28
|
-
logger.log(chalk.green('
|
|
29
|
+
logger.log(chalk.green(' ✔ Application configuration is valid'));
|
|
29
30
|
} else {
|
|
30
|
-
logger.log(chalk.red('
|
|
31
|
+
logger.log(chalk.red(' ✖ Application configuration has errors:'));
|
|
31
32
|
if (application.errors && application.errors.length > 0) {
|
|
32
33
|
application.errors.forEach(error => {
|
|
33
34
|
logger.log(chalk.red(` • ${error}`));
|
|
@@ -51,12 +52,17 @@ function extractDimensionsFromDatasource(filePath) {
|
|
|
51
52
|
try {
|
|
52
53
|
const parsed = loadConfigFile(filePath);
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
const
|
|
55
|
+
const rootFlat = {};
|
|
56
|
+
const root = parsed.dimensions;
|
|
57
|
+
if (root && typeof root === 'object' && !Array.isArray(root)) {
|
|
58
|
+
for (const [dimKey, binding] of Object.entries(root)) {
|
|
59
|
+
if (binding && typeof binding === 'object' && typeof binding.field === 'string') {
|
|
60
|
+
rootFlat[dimKey] = `metadata.${binding.field}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
56
64
|
const abacDimensions = parsed.abac?.dimensions || {};
|
|
57
|
-
|
|
58
|
-
// Merge both sources (abac.dimensions can override fieldMappings.dimensions)
|
|
59
|
-
const allDimensions = { ...dimensions, ...abacDimensions };
|
|
65
|
+
const allDimensions = { ...rootFlat, ...abacDimensions };
|
|
60
66
|
const dimensionKeys = Object.keys(allDimensions);
|
|
61
67
|
|
|
62
68
|
return {
|
|
@@ -82,9 +88,9 @@ function displayExternalFilesValidation(externalFiles) {
|
|
|
82
88
|
logger.log(chalk.blue('\nExternal Integration Files:'));
|
|
83
89
|
externalFiles.forEach(file => {
|
|
84
90
|
if (file.valid) {
|
|
85
|
-
logger.log(chalk.green(`
|
|
91
|
+
logger.log(chalk.green(` ✔ ${file.file} (${file.type})`));
|
|
86
92
|
} else {
|
|
87
|
-
logger.log(chalk.red(`
|
|
93
|
+
logger.log(chalk.red(` ✖ ${file.file} (${file.type}):`));
|
|
88
94
|
file.errors.forEach(error => {
|
|
89
95
|
logger.log(chalk.red(` • ${error}`));
|
|
90
96
|
});
|
|
@@ -126,7 +132,7 @@ function displayDimensionsValidation(externalFiles) {
|
|
|
126
132
|
|
|
127
133
|
if (dimensionsInfo.hasDimensions) {
|
|
128
134
|
anyDatasourceHasDimensions = true;
|
|
129
|
-
logger.log(chalk.green(`
|
|
135
|
+
logger.log(chalk.green(` ✔ ${file.file}`));
|
|
130
136
|
dimensionsInfo.dimensionKeys.forEach(key => {
|
|
131
137
|
const mapping = dimensionsInfo.dimensions[key];
|
|
132
138
|
logger.log(chalk.gray(` ${key} → ${mapping}`));
|
|
@@ -156,9 +162,9 @@ function displayRbacValidation(rbac) {
|
|
|
156
162
|
|
|
157
163
|
logger.log(chalk.blue('\nRBAC Configuration:'));
|
|
158
164
|
if (rbac.valid) {
|
|
159
|
-
logger.log(chalk.green('
|
|
165
|
+
logger.log(chalk.green(' ✔ RBAC configuration is valid'));
|
|
160
166
|
} else {
|
|
161
|
-
logger.log(chalk.red('
|
|
167
|
+
logger.log(chalk.red(' ✖ RBAC configuration has errors:'));
|
|
162
168
|
rbac.errors.forEach(error => {
|
|
163
169
|
logger.log(chalk.red(` • ${error}`));
|
|
164
170
|
});
|
|
@@ -183,9 +189,9 @@ function displayFileValidation(result) {
|
|
|
183
189
|
logger.log(chalk.blue(`\nFile: ${result.file}`));
|
|
184
190
|
logger.log(chalk.blue(`Type: ${result.type}`));
|
|
185
191
|
if (result.valid) {
|
|
186
|
-
logger.log(chalk.green('
|
|
192
|
+
logger.log(chalk.green(' ✔ File is valid'));
|
|
187
193
|
} else {
|
|
188
|
-
logger.log(chalk.red('
|
|
194
|
+
logger.log(chalk.red(' ✖ File has errors:'));
|
|
189
195
|
result.errors.forEach(error => {
|
|
190
196
|
logger.log(chalk.red(` • ${error}`));
|
|
191
197
|
});
|
|
@@ -222,9 +228,9 @@ function displayAggregatedWarnings(warnings) {
|
|
|
222
228
|
function displayApplicationStep(application) {
|
|
223
229
|
logger.log(chalk.blue('\nApplication:'));
|
|
224
230
|
if (application.valid) {
|
|
225
|
-
logger.log(chalk.green('
|
|
231
|
+
logger.log(chalk.green(' ✔ Application configuration is valid'));
|
|
226
232
|
} else {
|
|
227
|
-
logger.log(chalk.red('
|
|
233
|
+
logger.log(chalk.red(' ✖ Application configuration has errors:'));
|
|
228
234
|
application.errors.forEach(error => {
|
|
229
235
|
logger.log(chalk.red(` • ${error}`));
|
|
230
236
|
});
|
|
@@ -253,9 +259,9 @@ function displayComponentsStep(components) {
|
|
|
253
259
|
if (hasFiles) {
|
|
254
260
|
components.files.forEach(file => {
|
|
255
261
|
if (file.valid) {
|
|
256
|
-
logger.log(chalk.green(`
|
|
262
|
+
logger.log(chalk.green(` ✔ ${file.file} (${file.type})`));
|
|
257
263
|
} else {
|
|
258
|
-
logger.log(chalk.red(`
|
|
264
|
+
logger.log(chalk.red(` ✖ ${file.file} (${file.type})`));
|
|
259
265
|
}
|
|
260
266
|
});
|
|
261
267
|
}
|
|
@@ -282,7 +288,7 @@ function displayDimensionsStep(datasourceFiles) {
|
|
|
282
288
|
try {
|
|
283
289
|
const dimensionsInfo = extractDimensionsFromDatasource(file.path || file.file);
|
|
284
290
|
if (dimensionsInfo.hasDimensions) {
|
|
285
|
-
logger.log(chalk.green(`
|
|
291
|
+
logger.log(chalk.green(` ✔ ${file.file}`));
|
|
286
292
|
dimensionsInfo.dimensionKeys.forEach(key => {
|
|
287
293
|
const mapping = dimensionsInfo.dimensions[key];
|
|
288
294
|
logger.log(chalk.gray(` ${key} → ${mapping}`));
|
|
@@ -308,15 +314,15 @@ function displayManifestStep(manifest, componentFiles) {
|
|
|
308
314
|
if (manifest.skipped) {
|
|
309
315
|
logger.log(chalk.yellow(' ⊘ Skipped (fix errors above first)'));
|
|
310
316
|
} else if (manifest.valid) {
|
|
311
|
-
logger.log(chalk.green('
|
|
317
|
+
logger.log(chalk.green(' ✔ Full deployment manifest is valid'));
|
|
312
318
|
if (componentFiles) {
|
|
313
319
|
const datasourceFiles = componentFiles.filter(f => f.type === 'datasource' || f.type === 'external-datasource');
|
|
314
|
-
logger.log(chalk.green('
|
|
315
|
-
logger.log(chalk.green(`
|
|
316
|
-
logger.log(chalk.green('
|
|
320
|
+
logger.log(chalk.green(' ✔ System configuration valid'));
|
|
321
|
+
logger.log(chalk.green(` ✔ ${datasourceFiles.length} datasource(s) valid`));
|
|
322
|
+
logger.log(chalk.green(' ✔ Schema validation passed'));
|
|
317
323
|
}
|
|
318
324
|
} else {
|
|
319
|
-
logger.log(chalk.red('
|
|
325
|
+
logger.log(chalk.red(' ✖ Full deployment manifest validation failed:'));
|
|
320
326
|
const errs = manifest.errors && manifest.errors.length > 0 ? manifest.errors : [];
|
|
321
327
|
if (errs.length > 0) {
|
|
322
328
|
errs.forEach(error => {
|
|
@@ -341,9 +347,9 @@ function displayManifestStep(manifest, componentFiles) {
|
|
|
341
347
|
*/
|
|
342
348
|
function displayStepByStepValidation(result) {
|
|
343
349
|
if (result.valid) {
|
|
344
|
-
logger.log(
|
|
350
|
+
logger.log(formatSuccessParagraph('Validation passed!'));
|
|
345
351
|
} else {
|
|
346
|
-
logger.log(chalk.red('\n
|
|
352
|
+
logger.log(chalk.red('\n✖ Validation failed!'));
|
|
347
353
|
}
|
|
348
354
|
|
|
349
355
|
displayApplicationStep(result.steps.application);
|
|
@@ -388,7 +394,7 @@ function displayBatchValidationResults(batchResult) {
|
|
|
388
394
|
results.forEach(item => {
|
|
389
395
|
logger.log(chalk.blue(`\n--- ${item.appName} ---`));
|
|
390
396
|
if (item.error) {
|
|
391
|
-
logger.log(chalk.red(`
|
|
397
|
+
logger.log(chalk.red(` ✖ ${item.error}`));
|
|
392
398
|
} else if (item.result) {
|
|
393
399
|
displayValidationResults(item.result);
|
|
394
400
|
}
|
|
@@ -398,10 +404,10 @@ function displayBatchValidationResults(batchResult) {
|
|
|
398
404
|
const failed = results.length - passed;
|
|
399
405
|
logger.log(chalk.blue('\n--- Summary ---'));
|
|
400
406
|
if (failed === 0) {
|
|
401
|
-
logger.log(
|
|
407
|
+
logger.log(formatSuccessLine(`${passed} passed, 0 failed`));
|
|
402
408
|
logger.log(chalk.green('Overall: Passed'));
|
|
403
409
|
} else {
|
|
404
|
-
logger.log(
|
|
410
|
+
logger.log(formatBlockingError(`${passed} passed, ${failed} failed`));
|
|
405
411
|
logger.log(chalk.red('Overall: Failed'));
|
|
406
412
|
}
|
|
407
413
|
}
|
|
@@ -445,9 +451,9 @@ function displayValidationResults(result) {
|
|
|
445
451
|
|
|
446
452
|
// Legacy format (for regular apps)
|
|
447
453
|
if (result.valid) {
|
|
448
|
-
logger.log(
|
|
454
|
+
logger.log(formatSuccessParagraph('Validation passed!'));
|
|
449
455
|
} else {
|
|
450
|
-
logger.log(chalk.red('\n
|
|
456
|
+
logger.log(chalk.red('\n✖ Validation failed!'));
|
|
451
457
|
}
|
|
452
458
|
|
|
453
459
|
displayApplicationValidation(result.application);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Optional certification sync after external validate (keeps validate.js under max-lines).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} appName
|
|
11
|
+
* @param {Object} options
|
|
12
|
+
* @param {function(string, Object): Promise<Object>} validateExternalSystemComplete
|
|
13
|
+
*/
|
|
14
|
+
async function runExternalValidateWithOptionalCertSync(appName, options, validateExternalSystemComplete) {
|
|
15
|
+
const result = await validateExternalSystemComplete(appName, options);
|
|
16
|
+
if (result.valid && options.certSync === true) {
|
|
17
|
+
const { trySyncCertificationFromDataplaneForExternalApp } = require('../certification/sync-after-external-command');
|
|
18
|
+
await trySyncCertificationFromDataplaneForExternalApp(appName, 'validate');
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = { runExternalValidateWithOptionalCertSync };
|
|
@@ -28,6 +28,7 @@ const {
|
|
|
28
28
|
validateOAuth2GrantTypeAndAuthorizationUrl,
|
|
29
29
|
validateConfigurationNoStandardAuthVariables
|
|
30
30
|
} = require('./external-system-auth-rules');
|
|
31
|
+
const { runExternalValidateWithOptionalCertSync } = require('./validate-external-cert-sync');
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Validates a file path (detects type and validates)
|
|
@@ -104,15 +105,6 @@ function aggregateValidationResults(appValidation, externalValidations, rbacVali
|
|
|
104
105
|
};
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
/**
|
|
108
|
-
* Validates a single external file against its schema
|
|
109
|
-
*
|
|
110
|
-
* @async
|
|
111
|
-
* @function validateExternalFile
|
|
112
|
-
* @param {string} filePath - Path to the file
|
|
113
|
-
* @param {string} type - File type: 'system' | 'datasource'
|
|
114
|
-
* @returns {Promise<Object>} Validation result
|
|
115
|
-
*/
|
|
116
108
|
/**
|
|
117
109
|
* Parses external system/datasource file content (JSON or YAML).
|
|
118
110
|
* @function parseJsonFileContent
|
|
@@ -179,6 +171,7 @@ function validateRoleReferences(parsed, errors) {
|
|
|
179
171
|
});
|
|
180
172
|
}
|
|
181
173
|
|
|
174
|
+
/** @async */
|
|
182
175
|
async function validateExternalFile(filePath, type) {
|
|
183
176
|
if (!fs.existsSync(filePath)) {
|
|
184
177
|
throw new Error(`File not found: ${filePath}`);
|
|
@@ -203,9 +196,9 @@ async function validateExternalFile(filePath, type) {
|
|
|
203
196
|
}
|
|
204
197
|
|
|
205
198
|
if (normalizedType === 'datasource') {
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
199
|
+
const { collectExternalDatasourceWarnings } = require('./datasource-warnings');
|
|
200
|
+
errors.push(...validateFieldReferences(parseResult.parsed), ...validateAbac(parseResult.parsed));
|
|
201
|
+
warnings.push(...collectExternalDatasourceWarnings(parseResult.parsed));
|
|
209
202
|
}
|
|
210
203
|
|
|
211
204
|
return {
|
|
@@ -470,7 +463,9 @@ async function validateAppOrFile(appOrFile, options = {}) {
|
|
|
470
463
|
const { appPath, isExternal } = await detectAppType(appName);
|
|
471
464
|
logOfflinePathWhenType(appPath);
|
|
472
465
|
|
|
473
|
-
if (isExternal)
|
|
466
|
+
if (isExternal) {
|
|
467
|
+
return await runExternalValidateWithOptionalCertSync(appName, options, validateExternalSystemComplete);
|
|
468
|
+
}
|
|
474
469
|
|
|
475
470
|
const appValidation = await validator.validateApplication(appName, options);
|
|
476
471
|
const rbacValidation = await validateRbacForExternalSystem(isExternal, appName);
|
|
@@ -497,4 +492,3 @@ module.exports = {
|
|
|
497
492
|
validateAll: (opts = {}) => batch.validateAll(validateAppOrFile, opts),
|
|
498
493
|
buildBatchResult: batch.buildBatchResult
|
|
499
494
|
};
|
|
500
|
-
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scan deployment/config objects for unresolved ${VAR} placeholders (validator helper).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Extracted from validator.js for ESLint max-lines
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
/** Pattern matching ${VAR} style unresolved variables in strings */
|
|
12
|
+
const UNRESOLVED_VAR_REGEX = /\$\{[^}]+\}/g;
|
|
13
|
+
|
|
14
|
+
/** Allowed manifest placeholders in frontDoorRouting.host (expanded at run/resolve time; plan 122). */
|
|
15
|
+
const FRONT_DOOR_HOST_ALLOWED = /\$\{DEV_USERNAME\}|\$\{REMOTE_HOST\}/g;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* First ${...} still present after stripping allowed DEV_USERNAME / REMOTE_HOST segments, or null.
|
|
19
|
+
* @param {string} str
|
|
20
|
+
* @returns {string|null}
|
|
21
|
+
*/
|
|
22
|
+
function getFrontDoorHostFirstForbiddenPlaceholder(str) {
|
|
23
|
+
let t = String(str).trim();
|
|
24
|
+
t = t.replace(FRONT_DOOR_HOST_ALLOWED, '');
|
|
25
|
+
t = t.replace(/^\.+|\.+$/g, '').trim();
|
|
26
|
+
const m = t.match(UNRESOLVED_VAR_REGEX);
|
|
27
|
+
return m ? m[0] : null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} obj
|
|
32
|
+
* @param {string} prefix
|
|
33
|
+
* @returns {string[]}
|
|
34
|
+
*/
|
|
35
|
+
function collectStringUnresolved(obj, prefix) {
|
|
36
|
+
if (prefix === 'frontDoorRouting.host') {
|
|
37
|
+
const bad = getFrontDoorHostFirstForbiddenPlaceholder(obj);
|
|
38
|
+
return bad ? [`${prefix}: ${bad}`] : [];
|
|
39
|
+
}
|
|
40
|
+
const matches = obj.match(UNRESOLVED_VAR_REGEX);
|
|
41
|
+
if (matches && matches.length > 0) {
|
|
42
|
+
const pathLabel = prefix || 'value';
|
|
43
|
+
return [`${pathLabel}: ${matches[0]}`];
|
|
44
|
+
}
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Recursively finds all string values in obj that contain ${...} placeholders.
|
|
50
|
+
*
|
|
51
|
+
* @param {Object} obj - Object to scan (e.g. deployment manifest)
|
|
52
|
+
* @param {string} [prefix=''] - Path prefix for error reporting
|
|
53
|
+
* @returns {string[]} List of paths with example placeholder (e.g. "port: ${PORT}")
|
|
54
|
+
*/
|
|
55
|
+
function findUnresolvedVariablesInObject(obj, prefix = '') {
|
|
56
|
+
const found = [];
|
|
57
|
+
if (obj === null || obj === undefined) {
|
|
58
|
+
return found;
|
|
59
|
+
}
|
|
60
|
+
if (typeof obj === 'string') {
|
|
61
|
+
return collectStringUnresolved(obj, prefix);
|
|
62
|
+
}
|
|
63
|
+
if (Array.isArray(obj)) {
|
|
64
|
+
obj.forEach((item, i) => {
|
|
65
|
+
found.push(...findUnresolvedVariablesInObject(item, `${prefix}[${i}]`));
|
|
66
|
+
});
|
|
67
|
+
return found;
|
|
68
|
+
}
|
|
69
|
+
if (typeof obj === 'object') {
|
|
70
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
71
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
72
|
+
found.push(...findUnresolvedVariablesInObject(value, path));
|
|
73
|
+
}
|
|
74
|
+
return found;
|
|
75
|
+
}
|
|
76
|
+
return found;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Validates that deployment manifest contains no unresolved ${...} variables.
|
|
81
|
+
* @param {Object} deployment - Deployment manifest object
|
|
82
|
+
* @throws {Error} If any ${...} placeholders are found
|
|
83
|
+
*/
|
|
84
|
+
function validateNoUnresolvedVariablesInDeployment(deployment) {
|
|
85
|
+
const unresolved = findUnresolvedVariablesInObject(deployment);
|
|
86
|
+
if (unresolved.length > 0) {
|
|
87
|
+
const examples = [...new Set(unresolved)].slice(0, 5).join(', ');
|
|
88
|
+
throw new Error(
|
|
89
|
+
`Deployment manifest contains unresolved variables (e.g. ${examples}). ` +
|
|
90
|
+
'Use secret variables (kv://) in env.template for sensitive values, and set the application port as a number in application.yaml.'
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = {
|
|
96
|
+
findUnresolvedVariablesInObject,
|
|
97
|
+
validateNoUnresolvedVariablesInDeployment
|
|
98
|
+
};
|