@aifabrix/builder 2.42.1 → 2.44.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/anchor-docs.mdc +15 -0
- package/README.md +2 -2
- 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 +157 -0
- package/integration/{hubspot → hubspot-test}/application.json +6 -6
- package/integration/{hubspot → hubspot-test}/create-hubspot.js +10 -10
- package/integration/hubspot-test/env.template +4 -0
- package/integration/hubspot-test/hubspot-test-datasource-company.json +138 -0
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +146 -0
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +146 -0
- package/integration/hubspot-test/hubspot-test-datasource-users.json +76 -0
- package/integration/{hubspot/hubspot-deploy.json → hubspot-test/hubspot-test-deploy.json} +201 -24
- package/integration/{hubspot/hubspot-system.json → hubspot-test/hubspot-test-system.json} +8 -7
- package/integration/hubspot-test/rbac.json +166 -0
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-hubspot-credential-real.yaml +3 -3
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-hubspot-env-vars.yaml +2 -2
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-add-datasource.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-credential-create.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-credential-select.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-known-platform.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +2 -0
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-mode.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-openapi-file.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-openapi-url.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-source.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-dimension-array-test.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +5 -0
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +5 -0
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-dimension-test.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-rbac-test.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +1 -1
- package/integration/{hubspot → hubspot-test}/test-dataplane-down-tests.js +1 -7
- package/integration/{hubspot → hubspot-test}/test-dataplane-down.js +3 -3
- package/integration/{hubspot → hubspot-test}/test.js +137 -102
- package/integration/{hubspot → hubspot-test}/wizard-hubspot-e2e.yaml +2 -2
- package/integration/{hubspot → hubspot-test}/wizard-hubspot-platform.yaml +1 -1
- 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 +288 -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 +0 -1
- package/lib/api/pipeline.api.js +67 -20
- package/lib/api/service-users.api.js +111 -2
- package/lib/api/types/dev.types.js +4 -3
- package/lib/api/types/pipeline.types.js +8 -5
- package/lib/api/types/service-users.types.js +41 -0
- package/lib/api/types/validation-run.types.js +56 -0
- package/lib/api/validation-run.api.js +99 -0
- package/lib/api/validation-runner.js +99 -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 +19 -8
- package/lib/app/rotate-secret.js +17 -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 +1 -1
- package/lib/app/show.js +1 -1
- package/lib/build/index.js +13 -10
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.help.js +67 -0
- package/lib/cli/setup-app.js +59 -123
- package/lib/cli/setup-app.test-commands.js +179 -0
- package/lib/cli/setup-auth.js +36 -14
- 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 +190 -103
- package/lib/cli/setup-environment.js +11 -20
- package/lib/cli/setup-external-system.js +62 -22
- package/lib/cli/setup-infra.js +139 -47
- package/lib/cli/setup-parameters.js +32 -0
- package/lib/cli/setup-secrets.js +147 -10
- package/lib/cli/setup-service-user.js +146 -20
- package/lib/cli/setup-utility.js +47 -19
- 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 +22 -10
- package/lib/commands/auth-config.js +10 -14
- 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 +495 -0
- package/lib/commands/datasource-unified-test-cli.options.js +149 -0
- package/lib/commands/datasource-validation-cli.js +129 -0
- package/lib/commands/datasource.js +123 -71
- 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 +16 -10
- package/lib/commands/repair-rbac.js +25 -19
- package/lib/commands/repair.js +116 -32
- package/lib/commands/secrets-list.js +23 -12
- package/lib/commands/secrets-remove-all.js +220 -0
- package/lib/commands/secrets-remove.js +22 -13
- package/lib/commands/secrets-set.js +21 -12
- package/lib/commands/secrets-validate.js +20 -7
- package/lib/commands/secure.js +10 -9
- package/lib/commands/service-user.js +243 -13
- package/lib/commands/test-e2e-external.js +27 -1
- package/lib/commands/up-common.js +28 -2
- package/lib/commands/up-dataplane.js +31 -18
- package/lib/commands/up-miso.js +19 -29
- package/lib/commands/upload.js +138 -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 +16 -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 +59 -58
- package/lib/core/diff.js +3 -2
- package/lib/core/ensure-encryption-key.js +2 -4
- 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 +228 -42
- package/lib/core/templates-env.js +4 -3
- package/lib/core/templates.js +1 -1
- package/lib/datasource/abac-validator.js +148 -0
- package/lib/datasource/deploy.js +75 -53
- package/lib/datasource/field-reference-validator.js +77 -36
- package/lib/datasource/integration-context.js +63 -0
- package/lib/datasource/list.js +8 -7
- package/lib/datasource/log-viewer.js +252 -0
- package/lib/datasource/resolve-app.js +109 -0
- package/lib/datasource/test-e2e.js +95 -155
- package/lib/datasource/test-integration.js +121 -109
- package/lib/datasource/unified-validation-run-body.js +65 -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 +92 -0
- package/lib/datasource/validate.js +162 -15
- 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 +131 -53
- package/lib/external-system/download-helpers.js +1 -1
- package/lib/external-system/download.js +7 -6
- package/lib/external-system/generator.js +104 -14
- 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-controller-manifest.js +3 -3
- package/lib/generator/external.js +23 -11
- package/lib/generator/helpers.js +71 -12
- package/lib/generator/index.js +8 -4
- package/lib/generator/split-readme.js +12 -7
- package/lib/generator/split-variables.js +2 -1
- package/lib/generator/split.js +46 -11
- package/lib/generator/wizard-readme.js +3 -3
- package/lib/generator/wizard.js +16 -13
- package/lib/infrastructure/compose.js +60 -6
- package/lib/infrastructure/helpers.js +238 -51
- package/lib/infrastructure/index.js +64 -37
- package/lib/infrastructure/services.js +21 -15
- 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 +1201 -433
- package/lib/schema/external-system.schema.json +181 -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 +213 -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 +49 -14
- package/lib/utils/app-config-resolver.js +23 -1
- 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 +209 -6
- package/lib/utils/config-scoped-resources-preference.js +41 -0
- package/lib/utils/controller-deployment-outcome.js +68 -0
- package/lib/utils/credential-display.js +2 -2
- package/lib/utils/credential-secrets-env.js +16 -1
- 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-debug-display.js +137 -0
- package/lib/utils/datasource-test-run-debug-slice.js +93 -0
- package/lib/utils/datasource-test-run-display.js +442 -0
- package/lib/utils/datasource-test-run-exit.js +58 -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 +42 -11
- package/lib/utils/env-template.js +2 -2
- package/lib/utils/environment-scoped-resources.js +144 -0
- package/lib/utils/error-formatter.js +125 -9
- 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-env-template.js +180 -0
- package/lib/utils/external-readme.js +8 -1
- package/lib/utils/external-system-display.js +277 -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-test-helpers.js +24 -6
- package/lib/utils/external-system-validators.js +32 -14
- package/lib/utils/health-check-url.js +119 -0
- package/lib/utils/health-check.js +59 -25
- package/lib/utils/help-builder.js +14 -13
- 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 +29 -7
- package/lib/utils/paths.js +136 -48
- 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 +171 -51
- package/lib/utils/secrets-helpers.js +70 -59
- package/lib/utils/secrets-kv-scope.js +60 -0
- package/lib/utils/secrets-utils.js +35 -37
- package/lib/utils/secrets-validation.js +3 -1
- package/lib/utils/secrets-yaml-preserve.js +109 -0
- package/lib/utils/secure-file-permissions.js +91 -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 +37 -5
- 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 +89 -0
- package/lib/utils/validation-run-post-retry.js +73 -0
- package/lib/utils/validation-run-request.js +98 -0
- package/lib/utils/variable-transformer.js +21 -4
- package/lib/utils/yaml-preserve.js +78 -1
- package/lib/validation/datasource-warnings.js +56 -0
- package/lib/validation/env-template-auth.js +50 -2
- package/lib/validation/external-manifest-validator.js +35 -7
- package/lib/validation/validate-display.js +37 -31
- package/lib/validation/validate.js +9 -10
- package/lib/validation/validator-unresolved-placeholders.js +98 -0
- package/lib/validation/validator.js +32 -78
- package/lib/validation/wizard-config-validator.js +2 -1
- package/package.json +11 -3
- package/scripts/check-datasource-test-run-schema-sync.js +34 -0
- package/scripts/diagnose-cli.js +150 -0
- package/scripts/install-local.js +304 -55
- package/templates/README.md +15 -2
- package/templates/applications/dataplane/application.yaml +52 -2
- package/templates/applications/dataplane/env.template +80 -18
- 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 +55 -14
- 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/env.template.hbs +22 -0
- package/templates/external-system/external-datasource.yaml.hbs +197 -118
- package/templates/infra/compose.yaml.hbs +20 -4
- package/templates/python/docker-compose.hbs +16 -0
- package/templates/typescript/docker-compose.hbs +16 -0
- package/integration/hubspot/README.md +0 -102
- package/integration/hubspot/env.template +0 -4
- package/integration/hubspot/hubspot-datasource-company.json +0 -541
- package/integration/hubspot/hubspot-datasource-contact.json +0 -639
- package/integration/hubspot/hubspot-datasource-deal.json +0 -588
- package/integration/hubspot/hubspot-datasource-users.json +0 -116
- package/integration/hubspot/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
- package/lib/api/external-test.api.js +0 -111
- package/lib/schema/env-config.yaml +0 -43
- /package/integration/{hubspot → hubspot-test}/companies.json +0 -0
- /package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-app-name.yaml +0 -0
- /package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-missing-app.yaml +0 -0
- /package/integration/{hubspot → hubspot-test}/test-dataplane-down-helpers.js +0 -0
|
@@ -10,9 +10,12 @@
|
|
|
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');
|
|
17
|
+
const { validateFieldReferences } = require('../datasource/field-reference-validator');
|
|
18
|
+
const { validateAbac } = require('../datasource/abac-validator');
|
|
16
19
|
|
|
17
20
|
/**
|
|
18
21
|
* Sets up AJV validator with external schemas
|
|
@@ -26,6 +29,7 @@ async function setupAjvWithSchemas() {
|
|
|
26
29
|
strict: false,
|
|
27
30
|
removeAdditional: false
|
|
28
31
|
});
|
|
32
|
+
addFormats(ajv);
|
|
29
33
|
|
|
30
34
|
// Load raw schema objects (not compiled validators)
|
|
31
35
|
const externalSystemSchemaPath = path.join(__dirname, '..', 'schema', 'external-system.schema.json');
|
|
@@ -41,11 +45,20 @@ async function setupAjvWithSchemas() {
|
|
|
41
45
|
externalDatasourceSchema = schemaCopy;
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
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
|
+
}
|
|
46
54
|
|
|
47
|
-
|
|
48
|
-
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);
|
|
49
62
|
|
|
50
63
|
return { ajv, externalSystemSchema, externalDatasourceSchema };
|
|
51
64
|
}
|
|
@@ -64,7 +77,10 @@ function validateManifestStructure(manifest, ajv, applicationSchema, errors) {
|
|
|
64
77
|
const manifestValid = validateManifest(manifest);
|
|
65
78
|
|
|
66
79
|
if (!manifestValid) {
|
|
67
|
-
const manifestErrors = formatValidationErrors(validateManifest.errors
|
|
80
|
+
const manifestErrors = formatValidationErrors(validateManifest.errors, {
|
|
81
|
+
rootData: manifest,
|
|
82
|
+
deploymentManifest: manifest
|
|
83
|
+
});
|
|
68
84
|
errors.push(...manifestErrors.map(err => `Manifest validation: ${err}`));
|
|
69
85
|
}
|
|
70
86
|
}
|
|
@@ -84,7 +100,10 @@ function validateInlineSystem(manifest, ajv, externalSystemSchema, errors) {
|
|
|
84
100
|
const systemValid = validateSystem(manifest.system);
|
|
85
101
|
|
|
86
102
|
if (!systemValid) {
|
|
87
|
-
const systemErrors = formatValidationErrors(validateSystem.errors
|
|
103
|
+
const systemErrors = formatValidationErrors(validateSystem.errors, {
|
|
104
|
+
rootData: manifest.system,
|
|
105
|
+
deploymentManifest: manifest.system
|
|
106
|
+
});
|
|
88
107
|
errors.push(...systemErrors.map(err => `System validation: ${err}`));
|
|
89
108
|
}
|
|
90
109
|
} else if (manifest.type === 'external') {
|
|
@@ -111,8 +130,17 @@ function validateDatasources(manifest, ajv, externalDatasourceSchema, errors, wa
|
|
|
111
130
|
manifest.dataSources.forEach((datasource, index) => {
|
|
112
131
|
const datasourceValid = validateDatasource(datasource);
|
|
113
132
|
if (!datasourceValid) {
|
|
114
|
-
const datasourceErrors = formatValidationErrors(validateDatasource.errors
|
|
133
|
+
const datasourceErrors = formatValidationErrors(validateDatasource.errors, {
|
|
134
|
+
rootData: datasource,
|
|
135
|
+
deploymentManifest: datasource
|
|
136
|
+
});
|
|
115
137
|
errors.push(...datasourceErrors.map(err => `Datasource ${index + 1} (${datasource.key || 'unknown'}): ${err}`));
|
|
138
|
+
} else {
|
|
139
|
+
const fieldRefErrors = validateFieldReferences(datasource);
|
|
140
|
+
const abacErrors = validateAbac(datasource);
|
|
141
|
+
const prefix = `Datasource ${index + 1} (${datasource.key || 'unknown'}): `;
|
|
142
|
+
fieldRefErrors.forEach(e => errors.push(prefix + e));
|
|
143
|
+
abacErrors.forEach(e => errors.push(prefix + e));
|
|
116
144
|
}
|
|
117
145
|
});
|
|
118
146
|
}
|
|
@@ -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);
|
|
@@ -15,6 +15,8 @@ const validator = require('./validator');
|
|
|
15
15
|
const { resolveExternalFiles } = require('../utils/schema-resolver');
|
|
16
16
|
const { loadExternalSystemSchema, loadExternalDataSourceSchema, detectSchemaType } = require('../utils/schema-loader');
|
|
17
17
|
const { formatValidationErrors } = require('../utils/error-formatter');
|
|
18
|
+
const { validateFieldReferences } = require('../datasource/field-reference-validator');
|
|
19
|
+
const { validateAbac } = require('../datasource/abac-validator');
|
|
18
20
|
const { detectAppType } = require('../utils/paths');
|
|
19
21
|
const batch = require('./validate-batch');
|
|
20
22
|
const { logOfflinePathWhenType } = require('../utils/cli-utils');
|
|
@@ -102,15 +104,6 @@ function aggregateValidationResults(appValidation, externalValidations, rbacVali
|
|
|
102
104
|
};
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
/**
|
|
106
|
-
* Validates a single external file against its schema
|
|
107
|
-
*
|
|
108
|
-
* @async
|
|
109
|
-
* @function validateExternalFile
|
|
110
|
-
* @param {string} filePath - Path to the file
|
|
111
|
-
* @param {string} type - File type: 'system' | 'datasource'
|
|
112
|
-
* @returns {Promise<Object>} Validation result
|
|
113
|
-
*/
|
|
114
107
|
/**
|
|
115
108
|
* Parses external system/datasource file content (JSON or YAML).
|
|
116
109
|
* @function parseJsonFileContent
|
|
@@ -177,6 +170,7 @@ function validateRoleReferences(parsed, errors) {
|
|
|
177
170
|
});
|
|
178
171
|
}
|
|
179
172
|
|
|
173
|
+
/** @async */
|
|
180
174
|
async function validateExternalFile(filePath, type) {
|
|
181
175
|
if (!fs.existsSync(filePath)) {
|
|
182
176
|
throw new Error(`File not found: ${filePath}`);
|
|
@@ -200,6 +194,12 @@ async function validateExternalFile(filePath, type) {
|
|
|
200
194
|
validateConfigurationNoStandardAuthVariables(parseResult.parsed, errors);
|
|
201
195
|
}
|
|
202
196
|
|
|
197
|
+
if (normalizedType === 'datasource') {
|
|
198
|
+
const { collectExternalDatasourceWarnings } = require('./datasource-warnings');
|
|
199
|
+
errors.push(...validateFieldReferences(parseResult.parsed), ...validateAbac(parseResult.parsed));
|
|
200
|
+
warnings.push(...collectExternalDatasourceWarnings(parseResult.parsed));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
203
|
return {
|
|
204
204
|
valid: errors.length === 0,
|
|
205
205
|
errors,
|
|
@@ -489,4 +489,3 @@ module.exports = {
|
|
|
489
489
|
validateAll: (opts = {}) => batch.validateAll(validateAppOrFile, opts),
|
|
490
490
|
buildBatchResult: batch.buildBatchResult
|
|
491
491
|
};
|
|
492
|
-
|
|
@@ -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
|
+
};
|
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
|
|
12
12
|
const fs = require('fs');
|
|
13
13
|
const path = require('path');
|
|
14
|
-
const yaml = require('js-yaml');
|
|
15
14
|
const Ajv = require('ajv');
|
|
15
|
+
const addFormats = require('ajv-formats');
|
|
16
16
|
const applicationSchema = require('../schema/application-schema.json');
|
|
17
17
|
const externalSystemSchema = require('../schema/external-system.schema.json');
|
|
18
18
|
const externalDataSourceSchema = require('../schema/external-datasource.schema.json');
|
|
19
19
|
const { transformVariablesForValidation } = require('../utils/variable-transformer');
|
|
20
20
|
const { checkEnvironment } = require('../utils/environment-checker');
|
|
21
21
|
const { formatValidationErrors } = require('../utils/error-formatter');
|
|
22
|
-
const { detectAppType, resolveApplicationConfigPath } = require('../utils/paths');
|
|
22
|
+
const { detectAppType, resolveApplicationConfigPath, resolveRbacPath } = require('../utils/paths');
|
|
23
23
|
const { loadConfigFile } = require('../utils/config-format');
|
|
24
|
-
const { validateAuthKvCoverage } = require('./env-template-auth');
|
|
24
|
+
const { validateAuthKvCoverage, validateAuthSecurityPathConsistency } = require('./env-template-auth');
|
|
25
25
|
const { validateKvReferencesInLines } = require('./env-template-kv');
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -58,7 +58,8 @@ async function loadVariablesYaml(appName, options = {}) {
|
|
|
58
58
|
* @returns {Function} Compiled validator function
|
|
59
59
|
*/
|
|
60
60
|
function setupAjvValidator() {
|
|
61
|
-
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
61
|
+
const ajv = new Ajv({ allErrors: true, strict: false, verbose: true });
|
|
62
|
+
addFormats(ajv);
|
|
62
63
|
const externalSystemSchemaCopy = { ...externalSystemSchema };
|
|
63
64
|
const externalDataSourceSchemaCopy = { ...externalDataSourceSchema };
|
|
64
65
|
|
|
@@ -66,6 +67,11 @@ function setupAjvValidator() {
|
|
|
66
67
|
delete externalDataSourceSchemaCopy.$schema;
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
// external-datasource.schema.json references these by $id (aifabrix://schema/type/*)
|
|
71
|
+
ajv.addSchema(require('../schema/type/document-storage.json'));
|
|
72
|
+
ajv.addSchema(require('../schema/type/message-service.json'));
|
|
73
|
+
ajv.addSchema(require('../schema/type/vector-store.json'));
|
|
74
|
+
|
|
69
75
|
ajv.addSchema(externalSystemSchemaCopy, externalSystemSchema.$id);
|
|
70
76
|
ajv.addSchema(externalDataSourceSchemaCopy, externalDataSourceSchema.$id);
|
|
71
77
|
return ajv.compile(applicationSchema);
|
|
@@ -155,7 +161,7 @@ async function validateVariables(appName, options = {}) {
|
|
|
155
161
|
function validateRoles(roles) {
|
|
156
162
|
const errors = [];
|
|
157
163
|
if (!roles || !Array.isArray(roles)) {
|
|
158
|
-
errors.push('rbac
|
|
164
|
+
errors.push('rbac file must contain a "roles" array');
|
|
159
165
|
return errors;
|
|
160
166
|
}
|
|
161
167
|
|
|
@@ -179,7 +185,7 @@ function validateRoles(roles) {
|
|
|
179
185
|
function validatePermissions(permissions) {
|
|
180
186
|
const errors = [];
|
|
181
187
|
if (!permissions || !Array.isArray(permissions)) {
|
|
182
|
-
errors.push('rbac
|
|
188
|
+
errors.push('rbac file must contain a "permissions" array');
|
|
183
189
|
return errors;
|
|
184
190
|
}
|
|
185
191
|
|
|
@@ -203,21 +209,18 @@ async function validateRbac(appName, options = {}) {
|
|
|
203
209
|
|
|
204
210
|
// Support both builder/ and integration/ directories using detectAppType
|
|
205
211
|
const { appPath } = await detectAppType(appName, options);
|
|
206
|
-
const
|
|
207
|
-
const rbacYml = path.join(appPath, 'rbac.yml');
|
|
208
|
-
const rbacPath = fs.existsSync(rbacYaml) ? rbacYaml : (fs.existsSync(rbacYml) ? rbacYml : null);
|
|
212
|
+
const rbacPath = resolveRbacPath(appPath);
|
|
209
213
|
|
|
210
214
|
if (!rbacPath) {
|
|
211
|
-
return { valid: true, errors: [], warnings: ['rbac
|
|
215
|
+
return { valid: true, errors: [], warnings: ['rbac file not found - authentication disabled'] };
|
|
212
216
|
}
|
|
213
217
|
|
|
214
|
-
const content = fs.readFileSync(rbacPath, 'utf8');
|
|
215
218
|
let rbac;
|
|
216
|
-
|
|
217
219
|
try {
|
|
218
|
-
rbac =
|
|
220
|
+
rbac = loadConfigFile(rbacPath);
|
|
219
221
|
} catch (error) {
|
|
220
|
-
|
|
222
|
+
const basename = path.basename(rbacPath);
|
|
223
|
+
throw new Error(`Invalid syntax in ${basename}: ${error.message}`);
|
|
221
224
|
}
|
|
222
225
|
|
|
223
226
|
const errors = [
|
|
@@ -287,6 +290,7 @@ async function validateEnvTemplate(appName, options = {}) {
|
|
|
287
290
|
|
|
288
291
|
if (isExternal) {
|
|
289
292
|
await validateAuthKvCoverage(appPath, content, errors, warnings, options);
|
|
293
|
+
await validateAuthSecurityPathConsistency(appPath, errors, warnings);
|
|
290
294
|
}
|
|
291
295
|
|
|
292
296
|
return {
|
|
@@ -344,7 +348,8 @@ function validateDeploymentJson(deployment) {
|
|
|
344
348
|
|
|
345
349
|
// verbose: true includes the actual data value in error objects for better error messages
|
|
346
350
|
const ajv = new Ajv({ allErrors: true, strict: false, verbose: true });
|
|
347
|
-
|
|
351
|
+
addFormats(ajv);
|
|
352
|
+
// Register external schemas with their $id
|
|
348
353
|
// Create copies to avoid modifying the original schemas
|
|
349
354
|
const externalSystemSchemaCopy = { ...externalSystemSchema };
|
|
350
355
|
const externalDataSourceSchemaCopy = { ...externalDataSourceSchema };
|
|
@@ -352,6 +357,10 @@ function validateDeploymentJson(deployment) {
|
|
|
352
357
|
if (externalDataSourceSchemaCopy.$schema && externalDataSourceSchemaCopy.$schema.includes('2020-12')) {
|
|
353
358
|
delete externalDataSourceSchemaCopy.$schema;
|
|
354
359
|
}
|
|
360
|
+
// external-datasource.schema.json references these by $id (aifabrix://schema/type/*)
|
|
361
|
+
ajv.addSchema(require('../schema/type/document-storage.json'));
|
|
362
|
+
ajv.addSchema(require('../schema/type/message-service.json'));
|
|
363
|
+
ajv.addSchema(require('../schema/type/vector-store.json'));
|
|
355
364
|
ajv.addSchema(externalSystemSchemaCopy, externalSystemSchema.$id);
|
|
356
365
|
ajv.addSchema(externalDataSourceSchemaCopy, externalDataSourceSchema.$id);
|
|
357
366
|
const validate = ajv.compile(applicationSchema);
|
|
@@ -359,72 +368,17 @@ function validateDeploymentJson(deployment) {
|
|
|
359
368
|
|
|
360
369
|
return {
|
|
361
370
|
valid,
|
|
362
|
-
errors: valid ? [] : formatValidationErrors(validate.errors
|
|
371
|
+
errors: valid ? [] : formatValidationErrors(validate.errors, {
|
|
372
|
+
deploymentManifest: deployment,
|
|
373
|
+
rootData: deployment
|
|
374
|
+
})
|
|
363
375
|
};
|
|
364
376
|
}
|
|
365
377
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
* Recursively finds all string values in obj that contain ${...} placeholders.
|
|
371
|
-
* Used to ensure deployment manifest has no unresolved variables before deploy.
|
|
372
|
-
*
|
|
373
|
-
* @function findUnresolvedVariablesInObject
|
|
374
|
-
* @param {Object} obj - Object to scan (e.g. deployment manifest)
|
|
375
|
-
* @param {string} [prefix=''] - Path prefix for error reporting
|
|
376
|
-
* @returns {string[]} List of paths with example placeholder (e.g. "port: ${PORT}")
|
|
377
|
-
*
|
|
378
|
-
* @example
|
|
379
|
-
* findUnresolvedVariablesInObject({ port: '${PORT}' }) // ['port: ${PORT}']
|
|
380
|
-
*/
|
|
381
|
-
function findUnresolvedVariablesInObject(obj, prefix = '') {
|
|
382
|
-
const found = [];
|
|
383
|
-
if (obj === null || obj === undefined) {
|
|
384
|
-
return found;
|
|
385
|
-
}
|
|
386
|
-
if (typeof obj === 'string') {
|
|
387
|
-
const matches = obj.match(UNRESOLVED_VAR_REGEX);
|
|
388
|
-
if (matches && matches.length > 0) {
|
|
389
|
-
const pathLabel = prefix || 'value';
|
|
390
|
-
found.push(`${pathLabel}: ${matches[0]}`);
|
|
391
|
-
}
|
|
392
|
-
return found;
|
|
393
|
-
}
|
|
394
|
-
if (Array.isArray(obj)) {
|
|
395
|
-
obj.forEach((item, i) => {
|
|
396
|
-
found.push(...findUnresolvedVariablesInObject(item, `${prefix}[${i}]`));
|
|
397
|
-
});
|
|
398
|
-
return found;
|
|
399
|
-
}
|
|
400
|
-
if (typeof obj === 'object') {
|
|
401
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
402
|
-
const path = prefix ? `${prefix}.${key}` : key;
|
|
403
|
-
found.push(...findUnresolvedVariablesInObject(value, path));
|
|
404
|
-
}
|
|
405
|
-
return found;
|
|
406
|
-
}
|
|
407
|
-
return found;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
/**
|
|
411
|
-
* Validates that deployment manifest contains no unresolved ${...} variables.
|
|
412
|
-
* Throws if any are found, with a message to use secret variables or literal values.
|
|
413
|
-
*
|
|
414
|
-
* @function validateNoUnresolvedVariablesInDeployment
|
|
415
|
-
* @param {Object} deployment - Deployment manifest object
|
|
416
|
-
* @throws {Error} If any ${...} placeholders are found
|
|
417
|
-
*/
|
|
418
|
-
function validateNoUnresolvedVariablesInDeployment(deployment) {
|
|
419
|
-
const unresolved = findUnresolvedVariablesInObject(deployment);
|
|
420
|
-
if (unresolved.length > 0) {
|
|
421
|
-
const examples = [...new Set(unresolved)].slice(0, 5).join(', ');
|
|
422
|
-
throw new Error(
|
|
423
|
-
`Deployment manifest contains unresolved variables (e.g. ${examples}). ` +
|
|
424
|
-
'Use secret variables (kv://) in env.template for sensitive values, and set the application port as a number in application.yaml.'
|
|
425
|
-
);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
378
|
+
const {
|
|
379
|
+
findUnresolvedVariablesInObject,
|
|
380
|
+
validateNoUnresolvedVariablesInDeployment
|
|
381
|
+
} = require('./validator-unresolved-placeholders');
|
|
428
382
|
|
|
429
383
|
/**
|
|
430
384
|
* Validates all application configuration files
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* @fileoverview Wizard configuration validator for wizard.yaml files
|
|
3
4
|
* @author AI Fabrix Team
|
|
@@ -281,7 +282,7 @@ function displayValidationResults(result) {
|
|
|
281
282
|
console.log(chalk.green('Wizard configuration is valid'));
|
|
282
283
|
} else {
|
|
283
284
|
// eslint-disable-next-line no-console
|
|
284
|
-
console.log(
|
|
285
|
+
console.log(formatBlockingError('Wizard configuration validation failed:'));
|
|
285
286
|
result.errors.forEach(error => {
|
|
286
287
|
// eslint-disable-next-line no-console
|
|
287
288
|
console.log(chalk.red(` - ${error}`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aifabrix/builder",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.44.0",
|
|
4
4
|
"description": "AI Fabrix Local Fabric & Deployment SDK",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"af": "bin/aifabrix.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
+
"all": "npm run precommit && npm run test:manual && npm run test:integration:fixtures && npm run test:hubspot-wizard",
|
|
11
12
|
"test": "node tests/scripts/test-wrapper.js",
|
|
12
13
|
"test:ci": "bash tests/scripts/ci-simulate.sh",
|
|
13
14
|
"test:same-as-github": "npm run build:ci",
|
|
@@ -15,8 +16,13 @@
|
|
|
15
16
|
"test:coverage:nyc": "nyc --reporter=text --reporter=lcov --reporter=html jest --config jest.config.coverage.js --runInBand",
|
|
16
17
|
"test:watch": "jest --watch",
|
|
17
18
|
"test:integration": "jest --config jest.config.integration.js --runInBand",
|
|
19
|
+
"test:integration:fixtures": "jest --config jest.config.integration.fixtures.js --runInBand",
|
|
18
20
|
"test:integration:python": "cross-env TEST_LANGUAGE=python jest --config jest.config.integration.js --runInBand",
|
|
19
21
|
"test:integration:typescript": "cross-env TEST_LANGUAGE=typescript jest --config jest.config.integration.js --runInBand",
|
|
22
|
+
"test:hubspot-wizard": "node integration/hubspot-test/test.js",
|
|
23
|
+
"test:hubspot-wizard:negative": "node integration/hubspot-test/test.js --type negative",
|
|
24
|
+
"test:hubspot-wizard:positive": "node integration/hubspot-test/test.js --type positive",
|
|
25
|
+
"test:hubspot-dataplane-down": "node integration/hubspot-test/test-dataplane-down.js",
|
|
20
26
|
"test:manual": "jest --config jest.config.manual.js --runInBand",
|
|
21
27
|
"lint": "eslint . --ext .js",
|
|
22
28
|
"lint:fix": "eslint . --ext .js --fix",
|
|
@@ -28,8 +34,10 @@
|
|
|
28
34
|
"validate": "npm run build",
|
|
29
35
|
"prepublishOnly": "npm run validate",
|
|
30
36
|
"precommit": "npm run lint:fix && npm run test",
|
|
31
|
-
"install:local": "node scripts/install-local.js",
|
|
32
|
-
"uninstall:local": "node scripts/install-local.js uninstall"
|
|
37
|
+
"install:local": "node scripts/install-local.js && which aifabrix && which af",
|
|
38
|
+
"uninstall:local": "node scripts/install-local.js uninstall && which aifabrix && which af",
|
|
39
|
+
"diagnose:cli": "node scripts/diagnose-cli.js",
|
|
40
|
+
"check:schema-sync": "node scripts/check-datasource-test-run-schema-sync.js"
|
|
33
41
|
},
|
|
34
42
|
"keywords": [
|
|
35
43
|
"aifabrix",
|