@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
package/lib/app/show-display.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
const chalk = require('chalk');
|
|
13
13
|
const logger = require('../utils/logger');
|
|
14
|
+
const { truncatePublicKeyPreview } = require('./certification-show-enrich');
|
|
14
15
|
|
|
15
16
|
function logSourceAndHeader(summary) {
|
|
16
17
|
const isOffline = summary.source === 'offline';
|
|
@@ -81,7 +82,7 @@ function logApplicationExternalIntegration(ei, options = {}) {
|
|
|
81
82
|
logger.log(` systems: [${(ei.systems || []).join(', ')}]`);
|
|
82
83
|
logger.log(` dataSources: [${(ei.dataSources || []).join(', ')}]`);
|
|
83
84
|
if (!options.skipHint) {
|
|
84
|
-
logger.log(chalk.gray('\n For external system data as on dataplane, run: aifabrix show <
|
|
85
|
+
logger.log(chalk.gray('\n For external system data as on dataplane, run: aifabrix show <app> --online or aifabrix app show <app>.'));
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
|
|
@@ -261,6 +262,47 @@ function displayExternalAppBlock(summary) {
|
|
|
261
262
|
}
|
|
262
263
|
}
|
|
263
264
|
|
|
265
|
+
/**
|
|
266
|
+
* Local certification + optional verify rows (external integrations).
|
|
267
|
+
* @param {Object} summary
|
|
268
|
+
*/
|
|
269
|
+
function logCertificationSection(summary) {
|
|
270
|
+
if (!summary.isExternal) return;
|
|
271
|
+
logger.log('');
|
|
272
|
+
logger.log('🪪 Certification (local system file)');
|
|
273
|
+
const c = summary.localCertification;
|
|
274
|
+
if (!c || typeof c !== 'object') {
|
|
275
|
+
logger.log(' (none or unreadable)');
|
|
276
|
+
} else {
|
|
277
|
+
logger.log(` enabled: ${c.enabled}`);
|
|
278
|
+
logger.log(` algorithm: ${c.algorithm ?? '—'}`);
|
|
279
|
+
logger.log(` issuer: ${c.issuer ?? '—'}`);
|
|
280
|
+
logger.log(` version: ${c.version ?? '—'}`);
|
|
281
|
+
logger.log(` publicKey: ${truncatePublicKeyPreview(c.publicKey, 64)}`);
|
|
282
|
+
}
|
|
283
|
+
if (summary.certificationVerifyRows && summary.certificationVerifyRows.length > 0) {
|
|
284
|
+
logger.log('');
|
|
285
|
+
logger.log('🪪 Certification verify (dataplane)');
|
|
286
|
+
summary.certificationVerifyRows.forEach((row) => {
|
|
287
|
+
if (row.error) {
|
|
288
|
+
logger.log(` • ${row.datasourceKey}: ${row.error}`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const ok = row.overallValid ? chalk.green('ok') : chalk.yellow('not ok');
|
|
292
|
+
logger.log(
|
|
293
|
+
` • ${row.datasourceKey}: ${ok} signature=${row.validSignature} hash=${row.validHash}`
|
|
294
|
+
);
|
|
295
|
+
if (row.reasons && row.reasons.length) {
|
|
296
|
+
logger.log(chalk.gray(` reasons: ${row.reasons.join('; ')}`));
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
} else if (summary.certificationVerifySkipped) {
|
|
300
|
+
logger.log(chalk.gray('\n Certification verify skipped (not logged in or no controller URL).'));
|
|
301
|
+
} else if (summary.certificationVerifyError) {
|
|
302
|
+
logger.log(chalk.yellow(`\n Certification verify error: ${summary.certificationVerifyError}`));
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
264
306
|
/**
|
|
265
307
|
* Format and print human-readable show output (offline or online).
|
|
266
308
|
* @param {Object} summary - Unified summary (buildOfflineSummaryFromDeployJson or buildOnlineSummary)
|
|
@@ -278,6 +320,7 @@ function display(summary, options = {}) {
|
|
|
278
320
|
}
|
|
279
321
|
logApplicationSection(ctx.a, summary);
|
|
280
322
|
if (summary.isExternal) displayExternalAppBlock(summary);
|
|
323
|
+
if (summary.isExternal) logCertificationSection(summary);
|
|
281
324
|
logRolesSection(ctx.roles);
|
|
282
325
|
logAuthSection(ctx.authentication);
|
|
283
326
|
logConfigurationsSection(ctx.portalInputConfigurations);
|
package/lib/app/show.js
CHANGED
|
@@ -32,6 +32,11 @@ const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
|
|
|
32
32
|
const { formatApiError } = require('../utils/api-error-handler');
|
|
33
33
|
const { formatAuthenticationError } = require('../utils/error-formatters/http-status-errors');
|
|
34
34
|
const { display: displayShow } = require('./show-display');
|
|
35
|
+
const {
|
|
36
|
+
attachLocalCertification,
|
|
37
|
+
attachCertificationVerifyFromDataplane,
|
|
38
|
+
sanitizeCertificationForJson
|
|
39
|
+
} = require('./certification-show-enrich');
|
|
35
40
|
|
|
36
41
|
/** Truncate deployment key for display */
|
|
37
42
|
const DEPLOYMENT_KEY_TRUNCATE_LEN = 12;
|
|
@@ -273,6 +278,69 @@ async function getShowAuthToken(controllerUrl, config) {
|
|
|
273
278
|
throw new Error('Authentication required for --online. Run aifabrix login.');
|
|
274
279
|
}
|
|
275
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Optional dataplane certificate verify rows on the show summary (external only).
|
|
283
|
+
* @param {Object} summary
|
|
284
|
+
* @param {string} appKey
|
|
285
|
+
* @param {boolean} verifyCert
|
|
286
|
+
* @param {{ token: string, controllerUrl: string }|null} [authBundleOptional]
|
|
287
|
+
*/
|
|
288
|
+
async function maybeAttachCertificationVerify(summary, appKey, verifyCert, authBundleOptional) {
|
|
289
|
+
if (!verifyCert || !summary.isExternal) return;
|
|
290
|
+
if (authBundleOptional && authBundleOptional.token && authBundleOptional.controllerUrl) {
|
|
291
|
+
await attachCertificationVerifyFromDataplane(summary, appKey, {
|
|
292
|
+
token: authBundleOptional.token,
|
|
293
|
+
controllerUrl: authBundleOptional.controllerUrl
|
|
294
|
+
});
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
const controllerUrl = await resolveControllerUrl();
|
|
299
|
+
if (!controllerUrl) {
|
|
300
|
+
summary.certificationVerifySkipped = true;
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const config = await getConfig();
|
|
304
|
+
const authResult = await getShowAuthToken(controllerUrl, config);
|
|
305
|
+
await attachCertificationVerifyFromDataplane(summary, appKey, {
|
|
306
|
+
token: authResult.token,
|
|
307
|
+
controllerUrl: authResult.actualControllerUrl
|
|
308
|
+
});
|
|
309
|
+
} catch {
|
|
310
|
+
summary.certificationVerifySkipped = true;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* @param {Object} out - JSON payload (mutated)
|
|
316
|
+
* @param {Object} summary
|
|
317
|
+
*/
|
|
318
|
+
function appendCertificationJsonFields(out, summary) {
|
|
319
|
+
if (!summary.isExternal) return;
|
|
320
|
+
out.localCertification = sanitizeCertificationForJson(summary.localCertification);
|
|
321
|
+
if (summary.certificationVerifyRows) {
|
|
322
|
+
out.certificationVerify = summary.certificationVerifyRows;
|
|
323
|
+
}
|
|
324
|
+
if (summary.certificationVerifySkipped) {
|
|
325
|
+
out.certificationVerifySkipped = true;
|
|
326
|
+
}
|
|
327
|
+
if (summary.certificationVerifyError) {
|
|
328
|
+
out.certificationVerifyError = summary.certificationVerifyError;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* @param {Object} summary
|
|
334
|
+
* @param {string} appKey
|
|
335
|
+
* @param {boolean} verifyCert
|
|
336
|
+
* @param {{ token: string, controllerUrl: string }|null} [authBundleOptional]
|
|
337
|
+
*/
|
|
338
|
+
async function enrichExternalShowSummary(summary, appKey, verifyCert, authBundleOptional) {
|
|
339
|
+
if (!summary.isExternal) return;
|
|
340
|
+
attachLocalCertification(summary, appKey);
|
|
341
|
+
await maybeAttachCertificationVerify(summary, appKey, verifyCert, authBundleOptional);
|
|
342
|
+
}
|
|
343
|
+
|
|
276
344
|
async function fetchOpenApiLists(dataplaneUrl, appKey, authConfig) {
|
|
277
345
|
let openapiFiles = [];
|
|
278
346
|
let openapiEndpoints = [];
|
|
@@ -440,7 +508,7 @@ function formatBuildForDisplay(build) {
|
|
|
440
508
|
if (!build) return '—';
|
|
441
509
|
const parts = [];
|
|
442
510
|
if (build.language) parts.push(build.language);
|
|
443
|
-
const port = build.port
|
|
511
|
+
const port = build.port;
|
|
444
512
|
if (port !== undefined && port !== null) parts.push(`port ${port}`);
|
|
445
513
|
if (build.dockerfile) parts.push('dockerfile');
|
|
446
514
|
if (build.envOutputPath) parts.push(`envOutputPath: ${build.envOutputPath}`);
|
|
@@ -566,22 +634,25 @@ function buildOnlineSummary(apiApp, controllerUrl, externalSystem) {
|
|
|
566
634
|
* @param {string} appKey - Application key
|
|
567
635
|
* @param {boolean} json - Output as JSON
|
|
568
636
|
* @param {boolean} [permissionsOnly] - When true, output only permissions
|
|
637
|
+
* @param {boolean} [verifyCert] - When true, attempt dataplane verify for external apps
|
|
569
638
|
* @throws {Error} If application config not found or invalid
|
|
570
639
|
*/
|
|
571
|
-
async function
|
|
572
|
-
let summary;
|
|
573
|
-
|
|
640
|
+
async function loadOfflineShowSummary(appKey) {
|
|
574
641
|
try {
|
|
575
642
|
const { deployment, appPath } = await generator.buildDeploymentManifestInMemory(appKey);
|
|
576
643
|
const sourcePath = path.relative(process.cwd(), appPath) || appPath;
|
|
577
|
-
|
|
644
|
+
return buildOfflineSummaryFromDeployJson(deployment, sourcePath);
|
|
578
645
|
} catch (_err) {
|
|
579
646
|
const { appPath } = await detectAppType(appKey);
|
|
580
647
|
const configPath = resolveApplicationConfigPath(appPath);
|
|
581
648
|
const variables = loadVariablesFromPath(appPath);
|
|
582
649
|
const sourcePath = path.relative(process.cwd(), configPath) || configPath;
|
|
583
|
-
|
|
650
|
+
return buildOfflineSummary(variables, sourcePath);
|
|
584
651
|
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
async function runOffline(appKey, json, permissionsOnly, verifyCert = false) {
|
|
655
|
+
const summary = await loadOfflineShowSummary(appKey);
|
|
585
656
|
|
|
586
657
|
if (json) {
|
|
587
658
|
if (permissionsOnly) {
|
|
@@ -607,9 +678,14 @@ async function runOffline(appKey, json, permissionsOnly) {
|
|
|
607
678
|
databases: summary.databases
|
|
608
679
|
}
|
|
609
680
|
};
|
|
681
|
+
if (summary.isExternal) {
|
|
682
|
+
await enrichExternalShowSummary(summary, appKey, verifyCert, null);
|
|
683
|
+
appendCertificationJsonFields(out, summary);
|
|
684
|
+
}
|
|
610
685
|
logger.log(JSON.stringify(out, null, 2));
|
|
611
686
|
return;
|
|
612
687
|
}
|
|
688
|
+
await enrichExternalShowSummary(summary, appKey, verifyCert, null);
|
|
613
689
|
displayShow(summary, { permissionsOnly: !!permissionsOnly });
|
|
614
690
|
}
|
|
615
691
|
|
|
@@ -680,6 +756,7 @@ function outputOnlineJson(summary, permissionsOnly) {
|
|
|
680
756
|
? { error: summary.externalSystem.error }
|
|
681
757
|
: summary.externalSystem;
|
|
682
758
|
}
|
|
759
|
+
appendCertificationJsonFields(out, summary);
|
|
683
760
|
logger.log(JSON.stringify(out, null, 2));
|
|
684
761
|
}
|
|
685
762
|
|
|
@@ -688,9 +765,10 @@ function outputOnlineJson(summary, permissionsOnly) {
|
|
|
688
765
|
* @param {string} appKey - Application key
|
|
689
766
|
* @param {boolean} json - Output as JSON
|
|
690
767
|
* @param {boolean} [permissionsOnly] - When true, output only permissions
|
|
768
|
+
* @param {boolean} [verifyCert] - When true, attempt dataplane verify for external apps
|
|
691
769
|
* @throws {Error} On auth failure, 404, or API error
|
|
692
770
|
*/
|
|
693
|
-
async function runOnline(appKey, json, permissionsOnly) {
|
|
771
|
+
async function runOnline(appKey, json, permissionsOnly, verifyCert = false) {
|
|
694
772
|
const controllerUrl = await resolveControllerUrl();
|
|
695
773
|
if (!controllerUrl) {
|
|
696
774
|
throw new Error('Controller URL is required for --online. Run aifabrix login to set the controller URL in config.yaml.');
|
|
@@ -705,6 +783,10 @@ async function runOnline(appKey, json, permissionsOnly) {
|
|
|
705
783
|
? await fetchExternalSystemForOnline(controllerUrl, appKey, authConfig)
|
|
706
784
|
: null;
|
|
707
785
|
const summary = buildOnlineSummary(apiApp, authResult.actualControllerUrl, externalSystem);
|
|
786
|
+
await enrichExternalShowSummary(summary, appKey, verifyCert, {
|
|
787
|
+
token: authConfig.token,
|
|
788
|
+
controllerUrl: authResult.actualControllerUrl
|
|
789
|
+
});
|
|
708
790
|
if (json) {
|
|
709
791
|
outputOnlineJson(summary, permissionsOnly);
|
|
710
792
|
return;
|
|
@@ -720,6 +802,7 @@ async function runOnline(appKey, json, permissionsOnly) {
|
|
|
720
802
|
* @param {boolean} [options.online] - Fetch from controller
|
|
721
803
|
* @param {boolean} [options.json] - Output as JSON
|
|
722
804
|
* @param {boolean} [options.permissions] - When true, output only permissions (app show --permissions)
|
|
805
|
+
* @param {boolean} [options.verifyCert] - When true, attach dataplane certificate verify rows (external)
|
|
723
806
|
* @throws {Error} If file missing/invalid (offline) or API/auth error (online)
|
|
724
807
|
*/
|
|
725
808
|
async function showApp(appKey, options = {}) {
|
|
@@ -730,11 +813,12 @@ async function showApp(appKey, options = {}) {
|
|
|
730
813
|
const online = Boolean(options.online);
|
|
731
814
|
const json = Boolean(options.json);
|
|
732
815
|
const permissions = Boolean(options.permissions);
|
|
816
|
+
const verifyCert = Boolean(options.verifyCert);
|
|
733
817
|
|
|
734
818
|
if (online) {
|
|
735
|
-
await runOnline(appKey, json, permissions);
|
|
819
|
+
await runOnline(appKey, json, permissions, verifyCert);
|
|
736
820
|
} else {
|
|
737
|
-
await runOffline(appKey, json, permissions);
|
|
821
|
+
await runOffline(appKey, json, permissions, verifyCert);
|
|
738
822
|
}
|
|
739
823
|
}
|
|
740
824
|
|
package/lib/build/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatSuccessLine, formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* AI Fabrix Builder Build Functions
|
|
3
4
|
*
|
|
@@ -127,7 +128,9 @@ async function generateDockerfile(appNameOrPath, language, config, buildConfig =
|
|
|
127
128
|
|
|
128
129
|
const template = dockerfileUtils.loadDockerfileTemplate(language);
|
|
129
130
|
const isAppFlag = buildConfig.context === '../..';
|
|
130
|
-
|
|
131
|
+
// Use "./" (not ".") so Dockerfile lines are "COPY ./requirements*.txt" — a bare "."
|
|
132
|
+
// concatenates with "requirements" and becomes ".requirements*.txt", which matches nothing.
|
|
133
|
+
const appSourcePath = isAppFlag ? `apps/${appName}/` : './';
|
|
131
134
|
|
|
132
135
|
const templateVars = {
|
|
133
136
|
port: config.port || 3000,
|
|
@@ -185,11 +188,11 @@ async function generateDockerfile(appNameOrPath, language, config, buildConfig =
|
|
|
185
188
|
async function postBuildTasks(appName, buildConfig) {
|
|
186
189
|
try {
|
|
187
190
|
const envPath = await secrets.generateEnvFile(appName, buildConfig.secrets, 'docker');
|
|
188
|
-
logger.log(
|
|
191
|
+
logger.log(formatSuccessLine(`Generated .env file: ${envPath}`));
|
|
189
192
|
// Note: processEnvVariables is already called by generateEnvFile to generate local .env
|
|
190
193
|
// at the envOutputPath, so we don't need to manually copy the docker .env file
|
|
191
194
|
} catch (error) {
|
|
192
|
-
logger.log(chalk.yellow(
|
|
195
|
+
logger.log(chalk.yellow(`⚠ Warning: Could not generate .env file: ${error.message}`));
|
|
193
196
|
}
|
|
194
197
|
}
|
|
195
198
|
|
|
@@ -229,7 +232,7 @@ async function copyApplicationSourceFiles(appName, devDir) {
|
|
|
229
232
|
const appsPath = path.join(process.cwd(), 'apps', appName);
|
|
230
233
|
if (fsSync.existsSync(appsPath)) {
|
|
231
234
|
await buildCopy.copyAppSourceFiles(appsPath, devDir);
|
|
232
|
-
logger.log(
|
|
235
|
+
logger.log(formatSuccessLine(`Copied application source files from apps/${appName}`));
|
|
233
236
|
return true;
|
|
234
237
|
}
|
|
235
238
|
return false;
|
|
@@ -253,12 +256,12 @@ async function copyTemplateFilesIfNeeded(devDir, language, buildConfig, options)
|
|
|
253
256
|
const projectRoot = getProjectRoot();
|
|
254
257
|
const templatePath = path.join(projectRoot, 'templates', 'typescript');
|
|
255
258
|
await buildCopy.copyTemplateFilesToDevDir(templatePath, devDir, detectedLanguage);
|
|
256
|
-
logger.log(
|
|
259
|
+
logger.log(formatSuccessLine(`Generated application files from ${detectedLanguage} template`));
|
|
257
260
|
} else if (detectedLanguage === 'python' && !fsSync.existsSync(requirementsPath)) {
|
|
258
261
|
const projectRoot = getProjectRoot();
|
|
259
262
|
const templatePath = path.join(projectRoot, 'templates', 'python');
|
|
260
263
|
await buildCopy.copyTemplateFilesToDevDir(templatePath, devDir, detectedLanguage);
|
|
261
|
-
logger.log(
|
|
264
|
+
logger.log(formatSuccessLine(`Generated application files from ${detectedLanguage} template`));
|
|
262
265
|
}
|
|
263
266
|
}
|
|
264
267
|
|
|
@@ -268,7 +271,7 @@ async function prepareDevDirectory(appName, buildConfig, options) {
|
|
|
268
271
|
const directoryName = idNum === 0 ? 'applications' : `dev-${developerId}`;
|
|
269
272
|
logger.log(chalk.blue(`Copying files to developer-specific directory (${directoryName})...`));
|
|
270
273
|
const devDir = await buildCopy.copyBuilderToDevDirectory(appName, developerId);
|
|
271
|
-
logger.log(
|
|
274
|
+
logger.log(formatSuccessLine(`Files copied to: ${devDir}`));
|
|
272
275
|
|
|
273
276
|
const { config: appConfig, imageName } = await buildHelpers.loadAndValidateConfig(appName);
|
|
274
277
|
const effectiveImageName = buildDevImageName(imageName, developerId);
|
|
@@ -294,7 +297,7 @@ function prepareBuildContext(buildConfig, devDir) {
|
|
|
294
297
|
// Check if context is using old format (../appName) - these are incompatible with dev directory structure
|
|
295
298
|
if (buildConfig.context && buildConfig.context.startsWith('../') && buildConfig.context !== '../..') {
|
|
296
299
|
// Old format detected - always use devDir instead
|
|
297
|
-
logger.log(chalk.yellow(
|
|
300
|
+
logger.log(chalk.yellow(`⚠ Warning: Build context uses old format: ${buildConfig.context}`));
|
|
298
301
|
logger.log(chalk.yellow(` Using dev directory instead: ${devDir}`));
|
|
299
302
|
contextPath = devDir;
|
|
300
303
|
} else if (buildConfig.context && buildConfig.context !== '../..') {
|
|
@@ -353,7 +356,7 @@ async function handleDockerfileGeneration(appName, params, options, buildHelpers
|
|
|
353
356
|
language = 'typescript';
|
|
354
357
|
}
|
|
355
358
|
if (!hasExistingDockerfile) {
|
|
356
|
-
logger.log(
|
|
359
|
+
logger.log(formatSuccessLine(`Detected language: ${language}`));
|
|
357
360
|
}
|
|
358
361
|
|
|
359
362
|
// Determine Dockerfile (needs context path to generate in correct location)
|
|
@@ -425,7 +428,7 @@ async function buildApp(appName, options = {}) {
|
|
|
425
428
|
// 7. Post-build tasks
|
|
426
429
|
await postBuildTasks(appName, buildConfig);
|
|
427
430
|
|
|
428
|
-
logger.log(
|
|
431
|
+
logger.log(formatSuccessParagraph('Build completed successfully!'));
|
|
429
432
|
return `${imageName}:${tag}`;
|
|
430
433
|
|
|
431
434
|
} catch (error) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Detect skip-cert-sync from Commander + legacy option shapes.
|
|
3
|
+
* Commander registers `--no-cert-sync` as `certSync` defaulting to true; `--no-cert-sync` sets `certSync: false`.
|
|
4
|
+
* @author AI Fabrix Team
|
|
5
|
+
* @version 2.0.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {Object|null|undefined} options
|
|
12
|
+
* @returns {boolean}
|
|
13
|
+
*/
|
|
14
|
+
function cliOptsSkipCertSync(options) {
|
|
15
|
+
if (!options || typeof options !== 'object') return false;
|
|
16
|
+
if (options.noCertSync === true) return true;
|
|
17
|
+
if (options.certSync === false) return true;
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = { cliOptsSkipCertSync };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Map dataplane certificate artifacts into **certification** (external-system.schema.json).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {unknown} id - certificateId field (string or FK-shaped object)
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
function certificateIdToString(id) {
|
|
14
|
+
if (id === undefined || id === null) return '';
|
|
15
|
+
if (typeof id === 'string') return id.trim();
|
|
16
|
+
if (typeof id === 'object' && id !== null && typeof id.id === 'string') return String(id.id).trim();
|
|
17
|
+
return String(id).trim();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {string|undefined|null} s
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
function trimOrEmpty(s) {
|
|
25
|
+
return s !== undefined && s !== null ? String(s).trim() : '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Prefer an artifact that includes PEM/JWK **publicKey** material for verify-publish.
|
|
30
|
+
* @param {import('../api/types/certificates.types').CertificateArtifactResponse[]} artifacts
|
|
31
|
+
* @returns {import('../api/types/certificates.types').CertificateArtifactResponse|null}
|
|
32
|
+
*/
|
|
33
|
+
function pickArtifactForCertificationMerge(artifacts) {
|
|
34
|
+
const list = Array.isArray(artifacts) ? artifacts.filter((a) => a && typeof a === 'object') : [];
|
|
35
|
+
if (list.length === 0) return null;
|
|
36
|
+
const withKey = list.find((a) => a.publicKey && String(a.publicKey).trim());
|
|
37
|
+
return withKey || list[0];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} algorithmUpper
|
|
42
|
+
* @param {import('../api/types/certificates.types').CertificateArtifactResponse} art
|
|
43
|
+
* @returns {string}
|
|
44
|
+
*/
|
|
45
|
+
function hs256DevPublicKeyPlaceholder(algorithmUpper, art) {
|
|
46
|
+
if (algorithmUpper !== 'HS256') return '';
|
|
47
|
+
const cid = certificateIdToString(art.certificateId);
|
|
48
|
+
return `HS256-DEV-NO-PEM:${cid || 'integration-certificate'}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @param {import('../api/types/certificates.types').CertificateArtifactResponse} art
|
|
53
|
+
* @param {Object} ex
|
|
54
|
+
* @returns {string}
|
|
55
|
+
*/
|
|
56
|
+
function resolvePublicKey(art, ex) {
|
|
57
|
+
const fromArt = trimOrEmpty(art.publicKey);
|
|
58
|
+
if (fromArt) return fromArt;
|
|
59
|
+
const fromExisting = trimOrEmpty(ex.publicKey);
|
|
60
|
+
if (fromExisting) return fromExisting;
|
|
61
|
+
const algorithmUpper = trimOrEmpty(art.algorithm).toUpperCase();
|
|
62
|
+
return hs256DevPublicKeyPlaceholder(algorithmUpper, art);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @param {import('../api/types/certificates.types').CertificateArtifactResponse} art
|
|
67
|
+
* @param {Object} ex
|
|
68
|
+
* @returns {string}
|
|
69
|
+
*/
|
|
70
|
+
function resolveIssuer(art, ex) {
|
|
71
|
+
return (
|
|
72
|
+
trimOrEmpty(art.licenseLevelIssuer) ||
|
|
73
|
+
trimOrEmpty(art.issuedBy) ||
|
|
74
|
+
trimOrEmpty(ex.issuer) ||
|
|
75
|
+
'dataplane'
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {import('../api/types/certificates.types').CertificateArtifactResponse} art
|
|
81
|
+
* @param {Object} ex
|
|
82
|
+
* @returns {string}
|
|
83
|
+
*/
|
|
84
|
+
function resolveVersion(art, ex) {
|
|
85
|
+
return (
|
|
86
|
+
trimOrEmpty(art.version) ||
|
|
87
|
+
trimOrEmpty(art.certificateVersion) ||
|
|
88
|
+
trimOrEmpty(ex.version) ||
|
|
89
|
+
certificateIdToString(art.certificateId)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const CERTIFICATION_LEVELS = new Set(['BRONZE', 'SILVER', 'GOLD', 'PLATINUM']);
|
|
94
|
+
const CERTIFICATION_STATUSES = new Set(['passed', 'not_passed', 'pending']);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {string} raw
|
|
98
|
+
* @returns {string}
|
|
99
|
+
*/
|
|
100
|
+
function normalizeCertificationLevel(raw) {
|
|
101
|
+
const s = trimOrEmpty(raw).toUpperCase();
|
|
102
|
+
return CERTIFICATION_LEVELS.has(s) ? s : '';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @param {string} raw
|
|
107
|
+
* @returns {string}
|
|
108
|
+
*/
|
|
109
|
+
function normalizeCertificationStatus(raw) {
|
|
110
|
+
const s = trimOrEmpty(raw).toLowerCase();
|
|
111
|
+
return CERTIFICATION_STATUSES.has(s) ? s : '';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @param {import('../api/types/certificates.types').CertificateArtifactResponse} art
|
|
116
|
+
* @param {Object} ex
|
|
117
|
+
* @returns {string}
|
|
118
|
+
*/
|
|
119
|
+
function resolveLevel(art, ex) {
|
|
120
|
+
return (
|
|
121
|
+
normalizeCertificationLevel(ex.level) ||
|
|
122
|
+
normalizeCertificationLevel(art.certificationLevel) ||
|
|
123
|
+
''
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Prefer existing file status when valid; otherwise **passed** for an active dataplane artifact.
|
|
129
|
+
*
|
|
130
|
+
* @param {import('../api/types/certificates.types').CertificateArtifactResponse} art
|
|
131
|
+
* @param {Object} ex
|
|
132
|
+
* @returns {string}
|
|
133
|
+
*/
|
|
134
|
+
function resolveStatus(_art, ex) {
|
|
135
|
+
const fromEx = normalizeCertificationStatus(ex.status);
|
|
136
|
+
if (fromEx) return fromEx;
|
|
137
|
+
return 'passed';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Build `certification` object matching **external-system.schema.json** (required: enabled, publicKey, algorithm, issuer, version; optional status, level).
|
|
142
|
+
* Fills gaps from `existingCertification` when the artifact omits publishable fields (common when dataplane redacts `publicKey`).
|
|
143
|
+
* For **HS256** dev certificates with no PEM, uses a non-secret placeholder `publicKey` so the system file stays schema-valid.
|
|
144
|
+
*
|
|
145
|
+
* @param {import('../api/types/certificates.types').CertificateArtifactResponse|null} artifact
|
|
146
|
+
* @param {Object|null|undefined} existingCertification - Current `system.certification`
|
|
147
|
+
* @returns {Object|null} Full certification object, or null if **publicKey** or **version** cannot be satisfied
|
|
148
|
+
*/
|
|
149
|
+
function buildCertificationFromArtifact(artifact, existingCertification) {
|
|
150
|
+
const ex = existingCertification && typeof existingCertification === 'object' ? existingCertification : {};
|
|
151
|
+
const art = artifact && typeof artifact === 'object' ? artifact : null;
|
|
152
|
+
if (!art) return null;
|
|
153
|
+
|
|
154
|
+
const publicKey = resolvePublicKey(art, ex);
|
|
155
|
+
if (!publicKey) return null;
|
|
156
|
+
|
|
157
|
+
const issuer = resolveIssuer(art, ex);
|
|
158
|
+
if (!issuer) return null;
|
|
159
|
+
|
|
160
|
+
const versionStr = resolveVersion(art, ex);
|
|
161
|
+
if (!versionStr) return null;
|
|
162
|
+
|
|
163
|
+
const algorithmUpper = trimOrEmpty(art.algorithm).toUpperCase();
|
|
164
|
+
const algorithm = algorithmUpper === 'HS256' ? 'HS256' : 'RS256';
|
|
165
|
+
|
|
166
|
+
const out = {
|
|
167
|
+
enabled: true,
|
|
168
|
+
publicKey,
|
|
169
|
+
algorithm,
|
|
170
|
+
issuer,
|
|
171
|
+
version: versionStr,
|
|
172
|
+
status: resolveStatus(art, ex)
|
|
173
|
+
};
|
|
174
|
+
const level = resolveLevel(art, ex);
|
|
175
|
+
if (level) {
|
|
176
|
+
out.level = level;
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
module.exports = {
|
|
182
|
+
buildCertificationFromArtifact,
|
|
183
|
+
pickArtifactForCertificationMerge,
|
|
184
|
+
certificateIdToString
|
|
185
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview After successful unified datasource validation, optionally sync system certification.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const logger = require('../utils/logger');
|
|
11
|
+
const { trySyncCertificationFromDataplaneForExternalApp } = require('./sync-after-external-command');
|
|
12
|
+
const { cliOptsSkipCertSync } = require('./cli-cert-sync-skip');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @async
|
|
16
|
+
* @param {number} exitCode
|
|
17
|
+
* @param {string} datasourceKey
|
|
18
|
+
* @param {Object} options - CLI flags (app, noCertSync)
|
|
19
|
+
* @param {string} label - Log label
|
|
20
|
+
* @returns {Promise<void>}
|
|
21
|
+
*/
|
|
22
|
+
async function afterUnifiedValidationCertSync(exitCode, datasourceKey, options, label) {
|
|
23
|
+
if (exitCode !== 0 || cliOptsSkipCertSync(options)) return;
|
|
24
|
+
try {
|
|
25
|
+
const { resolveAppKeyForDatasource } = require('../datasource/resolve-app');
|
|
26
|
+
const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
|
|
27
|
+
await trySyncCertificationFromDataplaneForExternalApp(appKey, label);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
logger.log(chalk.yellow(`⚠ Certification sync (${label}) skipped: ${e.message}`));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = { afterUnifiedValidationCertSync };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Optional certification sync after external flows (validate, tests).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const logger = require('../utils/logger');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* After a successful external integration flow, refresh `certification` on the primary system file from dataplane.
|
|
14
|
+
* Best-effort: skips non-external apps, missing Bearer token, or resolver errors (warn only).
|
|
15
|
+
*
|
|
16
|
+
* @async
|
|
17
|
+
* @param {string} appKey - Integration / system key
|
|
18
|
+
* @param {string} label - Short label for logs (e.g. "validate", "datasource test")
|
|
19
|
+
* @returns {Promise<void>}
|
|
20
|
+
*/
|
|
21
|
+
async function trySyncCertificationFromDataplaneForExternalApp(appKey, label) {
|
|
22
|
+
try {
|
|
23
|
+
const { detectAppType } = require('../utils/paths');
|
|
24
|
+
const t = await detectAppType(appKey).catch(() => null);
|
|
25
|
+
if (!t || !t.isExternal) return;
|
|
26
|
+
|
|
27
|
+
const { resolveDataplaneAndAuth, validateSystemKeyFormat } = require('../commands/upload');
|
|
28
|
+
const { generateControllerManifest } = require('../generator/external-controller-manifest');
|
|
29
|
+
const { maybeSyncSystemCertificationFromDataplane } = require('./sync-system-certification');
|
|
30
|
+
|
|
31
|
+
validateSystemKeyFormat(appKey);
|
|
32
|
+
const { dataplaneUrl, authConfig } = await resolveDataplaneAndAuth(appKey);
|
|
33
|
+
if (!authConfig.token) {
|
|
34
|
+
logger.log(chalk.gray(`Certification sync (${label}) skipped: no Bearer token (run aifabrix login).`));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const manifest = await generateControllerManifest(appKey, { type: 'external' });
|
|
38
|
+
const dsKeys = (manifest.dataSources || []).map((ds) => ds && ds.key).filter(Boolean);
|
|
39
|
+
await maybeSyncSystemCertificationFromDataplane({
|
|
40
|
+
label,
|
|
41
|
+
noCertSync: false,
|
|
42
|
+
systemKey: manifest.key,
|
|
43
|
+
dataplaneUrl,
|
|
44
|
+
authConfig,
|
|
45
|
+
datasourceKeys: dsKeys
|
|
46
|
+
});
|
|
47
|
+
} catch (e) {
|
|
48
|
+
logger.log(chalk.yellow(`⚠ Certification sync (${label}) skipped: ${e.message}`));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = { trySyncCertificationFromDataplaneForExternalApp };
|