@aifabrix/builder 2.45.0 → 2.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/cli-layout.mdc +2 -0
- package/.cursor/rules/cli-product-neutral.mdc +43 -0
- package/.cursor/rules/docs-rules.mdc +3 -1
- package/.cursor/rules/project-rules.mdc +1 -0
- package/README.md +43 -17
- package/integration/hubspot-test/wizard-hubspot-e2e.yaml +1 -1
- package/jest.config.default.js +2 -1
- package/jest.config.isolated.js +2 -1
- package/jest.global-live-fabrix-hooks.js +36 -0
- package/jest.isolated-projects.js +130 -0
- package/jest.projects.js +69 -121
- package/lib/api/agent-metadata-validation.api.js +93 -0
- package/lib/api/api-response-errors.js +124 -0
- package/lib/api/audit-api-helpers.js +68 -0
- package/lib/api/audit.api.js +119 -0
- package/lib/api/auth-cache.api.js +44 -0
- package/lib/api/certificates.api.js +4 -4
- package/lib/api/credential.api.js +2 -2
- package/lib/api/dataplane-health.api.js +137 -0
- package/lib/api/dataplane-sync.api.js +27 -0
- package/lib/api/datasources-core.api.js +21 -18
- package/lib/api/datasources-extended.api.js +22 -22
- package/lib/api/dimensions.api.js +3 -0
- package/lib/api/external-systems.api.js +13 -13
- package/lib/api/governance-scenario-pack.api.js +159 -0
- package/lib/api/governance-scenarios.api.js +39 -0
- package/lib/api/groups.api.js +79 -0
- package/lib/api/index.js +88 -5
- package/lib/api/lifecycle.api.js +77 -0
- package/lib/api/pipeline.api.js +7 -5
- package/lib/api/protection.api.js +157 -0
- package/lib/api/records-bulk.api.js +43 -0
- package/lib/api/records-search-parse.js +49 -0
- package/lib/api/records-search.api.js +29 -0
- package/lib/api/types/agent-metadata-validation.types.js +67 -0
- package/lib/api/types/audit.types.js +72 -0
- package/lib/api/types/dataplane-health.types.js +27 -0
- package/lib/api/types/dimensions.types.js +2 -0
- package/lib/api/types/governance-scenarios.types.js +39 -0
- package/lib/api/types/protection.types.js +69 -0
- package/lib/api/types/records-bulk.types.js +35 -0
- package/lib/api/types/records-search.types.js +28 -0
- package/lib/api/user-groups.api.js +50 -0
- package/lib/api/users.api.js +95 -0
- package/lib/api/validation-run.api.js +3 -3
- package/lib/api/validation-runner.js +5 -3
- package/lib/api/wizard-platform.api.js +3 -3
- package/lib/api/wizard.api.js +21 -21
- package/lib/app/deploy-config.js +4 -1
- package/lib/app/deploy.js +34 -19
- package/lib/app/down.js +20 -1
- package/lib/app/push.js +4 -5
- package/lib/app/register.js +7 -4
- package/lib/app/run-env-compose.js +84 -30
- package/lib/build/index.js +5 -0
- package/lib/certification/sync-system-certification.js +13 -6
- package/lib/cli/index.js +8 -2
- package/lib/cli/infra-guided-auth.js +109 -0
- package/lib/cli/infra-guided.js +91 -69
- package/lib/cli/setup-app.help.js +19 -2
- package/lib/cli/setup-app.js +58 -23
- package/lib/cli/setup-app.test-commands.js +28 -21
- package/lib/cli/setup-auth.js +55 -3
- package/lib/cli/setup-certification-commands.js +147 -0
- package/lib/cli/setup-certification.help.js +141 -0
- package/lib/cli/setup-environment.js +19 -2
- package/lib/cli/setup-external-system-help.js +62 -0
- package/lib/cli/setup-external-system.js +62 -6
- package/lib/cli/setup-infra.js +9 -1
- package/lib/cli/setup-platform.js +6 -1
- package/lib/cli/setup-secrets.js +33 -1
- package/lib/cli/setup-utility-help-after.js +65 -0
- package/lib/cli/setup-utility-repair.js +198 -0
- package/lib/cli/setup-utility-resolve.js +42 -6
- package/lib/cli/setup-utility-validate.js +197 -0
- package/lib/cli/setup-utility.js +41 -258
- package/lib/commands/auth-status-client-tokens.js +214 -0
- package/lib/commands/auth-status-dataplane-version.js +269 -0
- package/lib/commands/auth-status-display.js +94 -0
- package/lib/commands/auth-status.js +111 -53
- package/lib/commands/credential-push.js +10 -5
- package/lib/commands/datasource-load-export-cli.js +178 -0
- package/lib/commands/datasource-test-trust-cli.js +118 -0
- package/lib/commands/datasource-unified-test-cli.js +31 -20
- package/lib/commands/datasource-unified-test-cli.options.js +22 -3
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +5 -5
- package/lib/commands/datasource-verify-audit-cli.js +96 -0
- package/lib/commands/datasource.js +68 -1
- package/lib/commands/dev-show-display.js +8 -1
- package/lib/commands/dimension-value.js +43 -13
- package/lib/commands/dimension.js +38 -7
- package/lib/commands/governance-cli-shared.js +94 -0
- package/lib/commands/governance-command-action.js +132 -0
- package/lib/commands/governance-download-external.js +34 -0
- package/lib/commands/governance-generate-external.js +71 -0
- package/lib/commands/governance-upload-external.js +36 -0
- package/lib/commands/governance-verify-external.js +64 -0
- package/lib/commands/governance.js +144 -0
- package/lib/commands/identity-apply-sync.js +131 -0
- package/lib/commands/identity-group-cli.js +146 -0
- package/lib/commands/identity-membership-role-cache.js +175 -0
- package/lib/commands/identity-shared.js +94 -0
- package/lib/commands/identity-user-cli.js +158 -0
- package/lib/commands/identity.js +43 -0
- package/lib/commands/lifecycle-command-action.js +123 -0
- package/lib/commands/lifecycle-external.js +268 -0
- package/lib/commands/login.js +56 -17
- package/lib/commands/protection-cli-leaves.js +286 -0
- package/lib/commands/protection.js +50 -0
- package/lib/commands/repair-auth-apply.js +127 -0
- package/lib/commands/repair-changed-files.js +41 -0
- package/lib/commands/repair-datasource-keys.js +4 -1
- package/lib/commands/repair-datasource-run.js +59 -0
- package/lib/commands/repair-datasource-test-payload.js +259 -0
- package/lib/commands/repair-datasource.js +1 -51
- package/lib/commands/repair-env-template.js +64 -13
- package/lib/commands/repair-external-run.js +216 -0
- package/lib/commands/repair-openapi-sync.js +23 -0
- package/lib/commands/repair-persist.js +4 -0
- package/lib/commands/repair-rbac.js +52 -1
- package/lib/commands/repair-steps.js +145 -0
- package/lib/commands/repair.js +29 -286
- package/lib/commands/secrets-get.js +184 -0
- package/lib/commands/secrets-remove-all.js +3 -1
- package/lib/commands/setup-image-refresh.js +146 -0
- package/lib/commands/setup-modes.js +158 -162
- package/lib/commands/setup-platform-auth.js +76 -0
- package/lib/commands/setup-prompts-admin.js +244 -0
- package/lib/commands/setup-prompts-platform-mode.js +67 -0
- package/lib/commands/setup-prompts-validators.js +36 -0
- package/lib/commands/setup-prompts.js +24 -76
- package/lib/commands/setup-run-context.js +45 -0
- package/lib/commands/setup-spinners.js +39 -0
- package/lib/commands/setup.js +27 -5
- package/lib/commands/teardown.js +39 -0
- package/lib/commands/test-e2e-external.js +61 -14
- package/lib/commands/test-governance-cli-options.js +47 -0
- package/lib/commands/test-governance-external.js +67 -0
- package/lib/commands/test-trust-cli-options.js +32 -0
- package/lib/commands/test-trust-external.js +126 -0
- package/lib/commands/up-common.js +25 -13
- package/lib/commands/up-dataplane.js +50 -13
- package/lib/commands/upload-publish-context.js +75 -0
- package/lib/commands/upload-sidecar-followups.js +89 -0
- package/lib/commands/upload.js +108 -105
- package/lib/commands/verify-governance-combined-external.js +61 -0
- package/lib/commands/verify-governance-command-action.js +64 -0
- package/lib/commands/verify-governance-db.js +102 -0
- package/lib/commands/verify-governance-external.js +77 -0
- package/lib/commands/verify-governance-result-builders.js +71 -0
- package/lib/commands/verify-operations-command-action.js +68 -0
- package/lib/commands/verify-operations-external.js +268 -0
- package/lib/commands/verify-operations-persist.js +75 -0
- package/lib/commands/verify-operations-step-plan.js +68 -0
- package/lib/commands/verify-operations-steps.js +111 -0
- package/lib/commands/verify-trust-command-action.js +70 -0
- package/lib/commands/verify-trust-external.js +67 -0
- package/lib/commands/wizard-config-normalizer.js +43 -23
- package/lib/commands/wizard-core.js +5 -0
- package/lib/core/admin-password-generator.js +38 -0
- package/lib/core/admin-secrets-bundle.js +111 -0
- package/lib/core/admin-secrets-env-overlay.js +62 -0
- package/lib/core/admin-secrets.js +32 -4
- package/lib/core/config-attach-extensions.js +3 -0
- package/lib/core/config-device-dataplane.js +185 -0
- package/lib/core/config-platform-controller.js +44 -0
- package/lib/core/config-setup-installation-profile.js +42 -0
- package/lib/core/config-setup-platform-mode.js +46 -0
- package/lib/core/config.js +46 -36
- package/lib/core/secrets-admin-env.js +6 -2
- package/lib/core/secrets-ensure.js +4 -0
- package/lib/core/secrets-env-content.js +54 -48
- package/lib/core/secrets-env-write.js +10 -1
- package/lib/core/secrets-infra-placeholder-sync.js +2 -0
- package/lib/core/setup-installation-profile.js +43 -0
- package/lib/core/setup-platform-mode.js +55 -0
- package/lib/datasource/agent-trust-debug-log.js +45 -0
- package/lib/datasource/agent-trust-fetch.js +115 -0
- package/lib/datasource/agent-trust-map.js +101 -0
- package/lib/datasource/agent-trust-mock.js +44 -0
- package/lib/datasource/agent-trust-run.js +95 -0
- package/lib/datasource/agent-trust-timeout.js +25 -0
- package/lib/datasource/audit-evidence-display.js +80 -0
- package/lib/datasource/audit-evidence-extract-debug.js +115 -0
- package/lib/datasource/audit-evidence-extract.js +180 -0
- package/lib/datasource/audit-evidence-matrix-rows.js +158 -0
- package/lib/datasource/audit-evidence-operation-aliases.js +63 -0
- package/lib/datasource/audit-evidence-poll.js +109 -0
- package/lib/datasource/audit-evidence-run.js +177 -0
- package/lib/datasource/audit-evidence-verify-helpers.js +167 -0
- package/lib/datasource/audit-evidence-verify-matrix.js +205 -0
- package/lib/datasource/audit-evidence-verify.js +108 -0
- package/lib/datasource/bulk-loader-run-batches.js +100 -0
- package/lib/datasource/bulk-loader-service-retry.js +52 -0
- package/lib/datasource/bulk-loader-service.js +127 -0
- package/lib/datasource/capability/run-capability-dimension.js +2 -1
- package/lib/datasource/datasource-exporter-resolve.js +82 -0
- package/lib/datasource/datasource-exporter-service.js +144 -0
- package/lib/datasource/datasource-identifier.js +148 -0
- package/lib/datasource/datasource-load-export-context.js +95 -0
- package/lib/datasource/integration-context.js +6 -4
- package/lib/datasource/local-data-paths.js +145 -0
- package/lib/datasource/log-cleaner.js +241 -0
- package/lib/datasource/log-viewer.js +111 -6
- package/lib/datasource/record-file-parser.js +85 -0
- package/lib/datasource/record-mapper.js +129 -0
- package/lib/datasource/resolve-app.js +74 -55
- package/lib/datasource/test-e2e.js +29 -2
- package/lib/datasource/unified-validation-run-body.js +3 -1
- package/lib/datasource/unified-validation-run-resolve.js +45 -12
- package/lib/datasource/unified-validation-run.js +47 -18
- package/lib/datasource/validate.js +37 -20
- package/lib/deployment/environment-poll-status.js +138 -0
- package/lib/deployment/environment.js +42 -34
- package/lib/external-system/download.js +21 -20
- package/lib/external-system/generator.js +5 -1
- package/lib/external-system/integration-auth-context.js +45 -0
- package/lib/external-system/test-auth.js +12 -5
- package/lib/external-system/test-system-level.js +25 -4
- package/lib/external-system/test.js +9 -7
- package/lib/generator/external-controller-manifest.js +15 -0
- package/lib/governance/governance-cli-errors.js +96 -0
- package/lib/governance/governance-download-display.js +38 -0
- package/lib/governance/governance-pack-loader.js +70 -0
- package/lib/governance/governance-run-display.js +309 -0
- package/lib/identity/identity-apply-core.js +108 -0
- package/lib/identity/identity-apply-phases.js +244 -0
- package/lib/identity/identity-apply-service.js +77 -0
- package/lib/identity/identity-csv-parser.js +114 -0
- package/lib/infrastructure/admin-secrets-apply.js +84 -0
- package/lib/infrastructure/admin-secrets-ensure.js +130 -0
- package/lib/infrastructure/admin-secrets-resolve.js +95 -0
- package/lib/infrastructure/admin-secrets-sync.js +91 -0
- package/lib/infrastructure/helpers.js +23 -129
- package/lib/infrastructure/index.js +5 -6
- package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
- package/lib/internal/fs-real-sync.js +29 -1
- package/lib/lifecycle/certification-progress.js +231 -0
- package/lib/lifecycle/dataplane-ui-url.js +145 -0
- package/lib/lifecycle/exit-codes.js +24 -0
- package/lib/lifecycle/json-envelope.js +25 -0
- package/lib/lifecycle/lifecycle-governance-options.js +51 -0
- package/lib/lifecycle/logger-quiet.js +29 -0
- package/lib/lifecycle/open-api-published.js +59 -0
- package/lib/lifecycle/operations-readiness-metrics.js +101 -0
- package/lib/lifecycle/product-model.js +196 -0
- package/lib/lifecycle/report-display.js +471 -0
- package/lib/lifecycle/scenario-upload.js +191 -0
- package/lib/lifecycle/verify-step-progress.js +87 -0
- package/lib/parameters/infra-kv-discovery.js +27 -2
- package/lib/protection/auth-context.js +51 -0
- package/lib/protection/convert-batch.js +90 -0
- package/lib/protection/load.js +41 -0
- package/lib/protection/paths.js +158 -0
- package/lib/protection/preflight-datasource-ready.js +46 -0
- package/lib/protection/protection-create-probe-lines.js +142 -0
- package/lib/protection/protection-create-probes.js +95 -0
- package/lib/protection/protection-create-scaffold.js +281 -0
- package/lib/protection/protection-display-helpers.js +445 -0
- package/lib/protection/protection-display.js +215 -0
- package/lib/protection/protection-preset-registry.js +97 -0
- package/lib/protection/report-exit.js +62 -0
- package/lib/protection/resolve.js +202 -0
- package/lib/protection/run-commands-validate.js +130 -0
- package/lib/protection/run-commands.js +216 -0
- package/lib/protection/run-protection-create-helpers.js +134 -0
- package/lib/protection/run-protection-create-probes-flow.js +43 -0
- package/lib/protection/run-protection-create.js +191 -0
- package/lib/protection/scope.js +22 -0
- package/lib/protection/sync-after-upload.js +64 -0
- package/lib/protection/upload-batch.js +127 -0
- package/lib/protection/validate-batch.js +113 -0
- package/lib/protection/validate-local.js +65 -0
- package/lib/resolvers/dimension-file.js +29 -4
- package/lib/schema/application-schema.json +1 -1
- package/lib/schema/datasource-test-run.schema.json +89 -6
- package/lib/schema/external-datasource.schema.json +2636 -2588
- package/lib/schema/external-system.schema.json +1089 -761
- package/lib/schema/flag-map-validation-run.json +2 -2
- package/lib/schema/infra.parameter.yaml +45 -0
- package/lib/schema/protection.schema.json +374 -0
- package/lib/schema/type/credential-field-registry.json +642 -0
- package/lib/schema/wizard-config.schema.json +1 -1
- package/lib/utils/agent-trust-run-display.js +231 -0
- package/lib/utils/agent-trust-run-exit.js +59 -0
- package/lib/utils/agent-trust-wait-ui.js +94 -0
- package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
- package/lib/utils/api.js +55 -31
- package/lib/utils/app-relative-path-env.js +112 -0
- package/lib/utils/cli-exit-codes.js +30 -0
- package/lib/utils/cli-secrets-error-format.js +83 -21
- package/lib/utils/cli-sync-options.js +33 -0
- package/lib/utils/cli-utils.js +16 -4
- package/lib/utils/compose-generate-docker-compose.js +4 -0
- package/lib/utils/compose-traefik-ingress-base.js +16 -1
- package/lib/utils/config-secrets-path.js +46 -0
- package/lib/utils/controller-url.js +88 -1
- package/lib/utils/credential-push-ui.js +90 -0
- package/lib/utils/credential-secrets-env.js +137 -9
- package/lib/utils/dataplane-cli-version-gate.js +202 -0
- package/lib/utils/dataplane-cli-version-help.js +74 -0
- package/lib/utils/dataplane-resolver.js +129 -2
- package/lib/utils/datasource-export-display.js +137 -0
- package/lib/utils/datasource-load-display.js +174 -0
- package/lib/utils/datasource-load-export-ui.js +120 -0
- package/lib/utils/datasource-test-run-capability-scope.js +3 -3
- package/lib/utils/datasource-test-run-display.js +3 -3
- package/lib/utils/datasource-test-run-tty-log.js +5 -1
- package/lib/utils/declarative-url-ports.js +3 -3
- package/lib/utils/deployment-auth-mode.js +41 -0
- package/lib/utils/developer-volume-id.js +33 -0
- package/lib/utils/env-copy.js +14 -9
- package/lib/utils/env-kv-orphan-lines.js +43 -0
- package/lib/utils/error-formatters/network-errors.js +13 -4
- package/lib/utils/external-env-template.js +1 -0
- package/lib/utils/external-system-readiness-core.js +10 -0
- package/lib/utils/external-system-readiness-display.js +80 -23
- package/lib/utils/health-check.js +4 -1
- package/lib/utils/help-builder.js +35 -26
- package/lib/utils/keycloak-realm-ready.js +101 -0
- package/lib/utils/load-cip-capacity-display-config.js +61 -15
- package/lib/utils/manifest-source-emit.js +24 -0
- package/lib/utils/pipeline-upload-auth-retry.js +82 -0
- package/lib/utils/platform-controller-url.js +156 -0
- package/lib/utils/postgres-platform-bootstrap.js +199 -0
- package/lib/utils/postgres-wipe.js +9 -2
- package/lib/utils/resolve-env-mode.js +47 -0
- package/lib/utils/secrets-generator.js +31 -25
- package/lib/utils/secrets-missing-error.js +164 -0
- package/lib/utils/semver-compare.js +127 -0
- package/lib/utils/service-url-label.js +81 -0
- package/lib/utils/setup-quiet-output.js +25 -0
- package/lib/utils/template-helpers.js +15 -0
- package/lib/utils/token-manager-client-credentials.js +201 -0
- package/lib/utils/token-manager-messages.js +8 -0
- package/lib/utils/token-manager-refresh.js +12 -2
- package/lib/utils/token-manager.js +86 -105
- package/lib/utils/upload-pipeline-ui.js +98 -0
- package/lib/utils/upload-sync-options.js +42 -0
- package/lib/utils/url-declarative-public-base.js +21 -3
- package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
- package/lib/utils/validation-poll-ui.js +22 -7
- package/lib/utils/validation-run-stage.js +45 -0
- package/lib/validation/wizard-config-validator.js +58 -19
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +2 -1
- package/templates/applications/dataplane/env.template +36 -1
- package/templates/applications/dataplane/rbac.yaml +4 -0
- package/templates/applications/miso-controller/env.template +16 -0
- package/templates/external-system/README.md.hbs +116 -11
- package/templates/python/docker-compose.hbs +19 -18
- package/templates/typescript/docker-compose.hbs +18 -17
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client token listing and proactive refresh for auth status.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Stored app tokens, auto-refresh when credentials exist
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const config = require('../core/config');
|
|
13
|
+
const logger = require('../utils/logger');
|
|
14
|
+
const { successGlyph, failureGlyph } = require('../utils/cli-test-layout-chalk');
|
|
15
|
+
const {
|
|
16
|
+
getOrRefreshClientToken,
|
|
17
|
+
loadClientCredentials,
|
|
18
|
+
refreshClientToken,
|
|
19
|
+
isTokenExpired
|
|
20
|
+
} = require('../utils/token-manager');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} controllerUrl
|
|
24
|
+
* @param {string} storedController
|
|
25
|
+
* @returns {boolean}
|
|
26
|
+
*/
|
|
27
|
+
function controllersMatch(controllerUrl, storedController) {
|
|
28
|
+
if (!storedController) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return config.normalizeControllerUrl(storedController) === config.normalizeControllerUrl(controllerUrl);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} environment
|
|
36
|
+
* @param {string} controllerUrl
|
|
37
|
+
* @returns {Promise<Record<string, { controller?: string, token?: string, expiresAt?: string }>>}
|
|
38
|
+
*/
|
|
39
|
+
async function getClientEntriesForController(environment, controllerUrl) {
|
|
40
|
+
const configData = await config.getConfig();
|
|
41
|
+
const clients = configData.environments?.[environment]?.clients || {};
|
|
42
|
+
const out = {};
|
|
43
|
+
for (const [appName, tokenData] of Object.entries(clients)) {
|
|
44
|
+
if (controllersMatch(controllerUrl, tokenData?.controller)) {
|
|
45
|
+
out[appName] = tokenData;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Refresh expired client tokens when secrets.local.yaml (or env) has client id/secret.
|
|
53
|
+
*
|
|
54
|
+
* @async
|
|
55
|
+
* @param {string} environment
|
|
56
|
+
* @param {string} controllerUrl
|
|
57
|
+
* @returns {Promise<number>} Count refreshed
|
|
58
|
+
*/
|
|
59
|
+
async function refreshExpiredClientTokensWherePossible(environment, controllerUrl) {
|
|
60
|
+
const entries = await getClientEntriesForController(environment, controllerUrl);
|
|
61
|
+
let refreshed = 0;
|
|
62
|
+
for (const appName of Object.keys(entries)) {
|
|
63
|
+
const tokenData = entries[appName];
|
|
64
|
+
if (!tokenData?.token || !isTokenExpired(tokenData.expiresAt)) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const credentials = await loadClientCredentials(appName);
|
|
68
|
+
if (!credentials?.clientId || !credentials?.clientSecret) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
await refreshClientToken(environment, appName, controllerUrl);
|
|
73
|
+
refreshed += 1;
|
|
74
|
+
} catch {
|
|
75
|
+
// Skip apps without valid credentials or controller errors
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return refreshed;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {string} expiresAt
|
|
83
|
+
* @returns {'valid'|'expired'|'unknown'}
|
|
84
|
+
*/
|
|
85
|
+
function tokenExpiryState(expiresAt) {
|
|
86
|
+
if (!expiresAt) {
|
|
87
|
+
return 'unknown';
|
|
88
|
+
}
|
|
89
|
+
return isTokenExpired(expiresAt) ? 'expired' : 'valid';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Build rows for stored client tokens table.
|
|
94
|
+
*
|
|
95
|
+
* @async
|
|
96
|
+
* @param {string} environment
|
|
97
|
+
* @param {string} controllerUrl
|
|
98
|
+
* @returns {Promise<Array<{ appName: string, expiresAt: string, state: string, logoutCmd: string }>>}
|
|
99
|
+
*/
|
|
100
|
+
async function listClientTokenRows(environment, controllerUrl) {
|
|
101
|
+
const entries = await getClientEntriesForController(environment, controllerUrl);
|
|
102
|
+
const rows = [];
|
|
103
|
+
for (const appName of Object.keys(entries).sort()) {
|
|
104
|
+
const tokenData = entries[appName];
|
|
105
|
+
const state = tokenExpiryState(tokenData.expiresAt);
|
|
106
|
+
const credentials = await loadClientCredentials(appName);
|
|
107
|
+
const canRefresh = !!(credentials?.clientId && credentials?.clientSecret);
|
|
108
|
+
let stateLabel = state;
|
|
109
|
+
if (state === 'expired' && canRefresh) {
|
|
110
|
+
stateLabel = 'expired (credentials available — refreshed on status if possible)';
|
|
111
|
+
} else if (state === 'expired' && !canRefresh) {
|
|
112
|
+
stateLabel = 'expired (no client id/secret in secrets — logout or login)';
|
|
113
|
+
}
|
|
114
|
+
rows.push({
|
|
115
|
+
appName,
|
|
116
|
+
expiresAt: tokenData.expiresAt || '—',
|
|
117
|
+
state: stateLabel,
|
|
118
|
+
logoutCmd: `aifabrix logout -e ${environment} -a ${appName}`
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return rows;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Print stored application client tokens and logout commands.
|
|
126
|
+
*
|
|
127
|
+
* @async
|
|
128
|
+
* @param {string} environment
|
|
129
|
+
* @param {string} controllerUrl
|
|
130
|
+
* @param {number} [refreshedCount]
|
|
131
|
+
* @returns {Promise<void>}
|
|
132
|
+
*/
|
|
133
|
+
async function displayStoredClientTokensSection(environment, controllerUrl, refreshedCount = 0) {
|
|
134
|
+
const rows = await listClientTokenRows(environment, controllerUrl);
|
|
135
|
+
if (rows.length === 0) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
logger.log('');
|
|
140
|
+
logger.log(chalk.bold('Stored application client tokens:'));
|
|
141
|
+
if (refreshedCount > 0) {
|
|
142
|
+
logger.log(
|
|
143
|
+
chalk.gray(
|
|
144
|
+
` Refreshed ${refreshedCount} expired token(s) using client id/secret from secrets.local.yaml or env.`
|
|
145
|
+
)
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
logger.log(chalk.gray(` Environment: ${environment} · Controller: ${controllerUrl}`));
|
|
149
|
+
logger.log('');
|
|
150
|
+
for (const row of rows) {
|
|
151
|
+
const icon = row.state.startsWith('valid') ? successGlyph() : failureGlyph();
|
|
152
|
+
logger.log(` ${icon} ${chalk.cyan(row.appName)}`);
|
|
153
|
+
logger.log(` Expires: ${chalk.gray(row.expiresAt)}`);
|
|
154
|
+
logger.log(` Status: ${row.state}`);
|
|
155
|
+
logger.log(` Clear: ${chalk.gray(row.logoutCmd)}`);
|
|
156
|
+
}
|
|
157
|
+
logger.log('');
|
|
158
|
+
logger.log(chalk.gray(' Clear all client tokens for this environment:'), chalk.gray(`aifabrix logout -e ${environment}`));
|
|
159
|
+
logger.log(chalk.gray(' Clear device login for this controller:'), chalk.gray(`aifabrix logout -c ${controllerUrl}`));
|
|
160
|
+
logger.log('');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Resolve a working client token (refresh when expired if credentials exist).
|
|
165
|
+
*
|
|
166
|
+
* @async
|
|
167
|
+
* @param {string} controllerUrl
|
|
168
|
+
* @param {string} environment
|
|
169
|
+
* @param {function(string, string, string, string, string): Promise<Object>} validateClientTokenFn
|
|
170
|
+
* @returns {Promise<Object|null>}
|
|
171
|
+
*/
|
|
172
|
+
async function tryResolveClientTokenAuth(controllerUrl, environment, validateClientTokenFn) {
|
|
173
|
+
const entries = await getClientEntriesForController(environment, controllerUrl);
|
|
174
|
+
const appNames = Object.keys(entries);
|
|
175
|
+
if (appNames.length === 0) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const ordered = ['dataplane', ...appNames.filter(a => a !== 'dataplane').sort()];
|
|
180
|
+
let lastFailure = null;
|
|
181
|
+
|
|
182
|
+
for (const appName of ordered) {
|
|
183
|
+
try {
|
|
184
|
+
const refreshed = await getOrRefreshClientToken(environment, appName, controllerUrl);
|
|
185
|
+
if (!refreshed?.token) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const stored = await config.getClientToken(environment, appName);
|
|
189
|
+
const result = await validateClientTokenFn(
|
|
190
|
+
refreshed.token,
|
|
191
|
+
controllerUrl,
|
|
192
|
+
environment,
|
|
193
|
+
appName,
|
|
194
|
+
stored?.expiresAt
|
|
195
|
+
);
|
|
196
|
+
if (result.authenticated) {
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
lastFailure = result;
|
|
200
|
+
} catch {
|
|
201
|
+
// Try next app
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return lastFailure;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
module.exports = {
|
|
209
|
+
refreshExpiredClientTokensWherePossible,
|
|
210
|
+
displayStoredClientTokensSection,
|
|
211
|
+
tryResolveClientTokenAuth,
|
|
212
|
+
listClientTokenRows,
|
|
213
|
+
getClientEntriesForController
|
|
214
|
+
};
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth-status dataplane version refresh + compatibility resolution (plan 142.0).
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `auth-status.js` to keep that file under the 500-line limit
|
|
5
|
+
* (`.cursor/rules/project-rules.mdc → File and Function Size Limits`). The
|
|
6
|
+
* helpers here are pure-ish (only depend on the dataplane health API and the
|
|
7
|
+
* `device.<controllerUrl>` cache module) so they are easy to mock in unit
|
|
8
|
+
* tests.
|
|
9
|
+
*
|
|
10
|
+
* @fileoverview Resolve dataplane version + Builder CLI compatibility for auth status
|
|
11
|
+
* @author AI Fabrix Team
|
|
12
|
+
* @version 2.0.0
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const { fetchDataplaneGeneralHealth } = require('../api/dataplane-health.api');
|
|
18
|
+
const {
|
|
19
|
+
updateDeviceDataplaneVersions,
|
|
20
|
+
getDeviceDataplaneVersions
|
|
21
|
+
} = require('../core/config-device-dataplane');
|
|
22
|
+
const {
|
|
23
|
+
getInstalledCliVersion
|
|
24
|
+
} = require('../utils/dataplane-cli-version-gate');
|
|
25
|
+
const { isAtLeast, isValidSemver } = require('../utils/semver-compare');
|
|
26
|
+
|
|
27
|
+
/** Max wall time for post-login version cache refresh (silent after success banner). */
|
|
28
|
+
const LOGIN_POST_REFRESH_BUDGET_MS = 12000;
|
|
29
|
+
|
|
30
|
+
/** Per health probe during login refresh (two endpoints may be tried). */
|
|
31
|
+
const LOGIN_HEALTH_PROBE_TIMEOUT_MS = 6000;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Resolve when `promise` settles or when `timeoutMs` elapses (returns undefined).
|
|
35
|
+
* @template T
|
|
36
|
+
* @param {Promise<T>} promise
|
|
37
|
+
* @param {number} timeoutMs
|
|
38
|
+
* @returns {Promise<T|undefined>}
|
|
39
|
+
*/
|
|
40
|
+
function raceWithTimeout(promise, timeoutMs) {
|
|
41
|
+
return Promise.race([
|
|
42
|
+
promise,
|
|
43
|
+
new Promise((resolve) => {
|
|
44
|
+
setTimeout(() => resolve(undefined), timeoutMs);
|
|
45
|
+
})
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Per plan 142.0: invalid semver from the dataplane is logged but does **not**
|
|
51
|
+
* block the CLI; missing min version means no enforcement.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} cliVersion
|
|
54
|
+
* @param {string|undefined} minBuilderCliVersion
|
|
55
|
+
* @returns {boolean}
|
|
56
|
+
*/
|
|
57
|
+
function computeCompatibility(cliVersion, minBuilderCliVersion) {
|
|
58
|
+
if (!minBuilderCliVersion) return true;
|
|
59
|
+
if (!isValidSemver(minBuilderCliVersion) || !isValidSemver(cliVersion)) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return isAtLeast(cliVersion, minBuilderCliVersion);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Read `device.<controllerUrl>` cache without throwing.
|
|
67
|
+
* @private
|
|
68
|
+
* @async
|
|
69
|
+
* @param {string} controllerUrl
|
|
70
|
+
* @returns {Promise<Object|null>}
|
|
71
|
+
*/
|
|
72
|
+
async function safeReadCache(controllerUrl) {
|
|
73
|
+
if (!controllerUrl) return null;
|
|
74
|
+
try {
|
|
75
|
+
return await getDeviceDataplaneVersions(controllerUrl);
|
|
76
|
+
} catch (_error) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Refresh dataplane health, persist `device.<controllerUrl>` version cache,
|
|
83
|
+
* and derive the compatibility verdict against the installed Builder CLI.
|
|
84
|
+
* Falls back to the cached entry when the live probe fails so `auth status`
|
|
85
|
+
* still shows the last-known values offline.
|
|
86
|
+
*
|
|
87
|
+
* @async
|
|
88
|
+
* @param {string} controllerUrl - Controller URL (cache key)
|
|
89
|
+
* @param {string} dataplaneUrl - Dataplane base URL for the health probe
|
|
90
|
+
* @returns {Promise<{
|
|
91
|
+
* dataplaneVersion: string|undefined,
|
|
92
|
+
* minBuilderCliVersion: string|undefined,
|
|
93
|
+
* cliVersion: string,
|
|
94
|
+
* compatible: boolean
|
|
95
|
+
* }>}
|
|
96
|
+
*/
|
|
97
|
+
async function refreshDataplaneVersionInfo(controllerUrl, dataplaneUrl, options = {}) {
|
|
98
|
+
const cliVersion = getInstalledCliVersion();
|
|
99
|
+
let dataplaneVersion;
|
|
100
|
+
let minBuilderCliVersion;
|
|
101
|
+
const healthOpts = {};
|
|
102
|
+
if (options.healthTimeoutMs !== undefined && options.healthTimeoutMs !== null) {
|
|
103
|
+
healthOpts.timeoutMs = options.healthTimeoutMs;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
const snapshot = await fetchDataplaneGeneralHealth(dataplaneUrl, healthOpts);
|
|
108
|
+
if (snapshot) {
|
|
109
|
+
dataplaneVersion = snapshot.version;
|
|
110
|
+
minBuilderCliVersion = snapshot.minBuilderCliVersion;
|
|
111
|
+
try {
|
|
112
|
+
await updateDeviceDataplaneVersions(controllerUrl, {
|
|
113
|
+
version: dataplaneVersion,
|
|
114
|
+
minBuilderCliVersion: minBuilderCliVersion || null
|
|
115
|
+
});
|
|
116
|
+
} catch (_persistError) {
|
|
117
|
+
// cache write failure must not break the display
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} catch (_fetchError) {
|
|
121
|
+
// ignore — fall through to cached values
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!dataplaneVersion && !minBuilderCliVersion) {
|
|
125
|
+
const cached = await safeReadCache(controllerUrl);
|
|
126
|
+
if (cached) {
|
|
127
|
+
dataplaneVersion = cached.version;
|
|
128
|
+
minBuilderCliVersion = cached.minBuilderCliVersion;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const compatible = computeCompatibility(cliVersion, minBuilderCliVersion);
|
|
133
|
+
return { dataplaneVersion, minBuilderCliVersion, cliVersion, compatible };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Load cached versions only (no live probe). Used when the dataplane is
|
|
138
|
+
* unreachable so `auth status` can still surface a known compatibility floor.
|
|
139
|
+
*
|
|
140
|
+
* @async
|
|
141
|
+
* @param {string} controllerUrl
|
|
142
|
+
* @returns {Promise<{
|
|
143
|
+
* dataplaneVersion: string|undefined,
|
|
144
|
+
* minBuilderCliVersion: string|undefined,
|
|
145
|
+
* cliVersion: string,
|
|
146
|
+
* compatible: boolean
|
|
147
|
+
* }>}
|
|
148
|
+
*/
|
|
149
|
+
async function loadCachedVersionInfo(controllerUrl) {
|
|
150
|
+
const cliVersion = getInstalledCliVersion();
|
|
151
|
+
const cached = await safeReadCache(controllerUrl);
|
|
152
|
+
const dataplaneVersion = cached ? cached.version : undefined;
|
|
153
|
+
const minBuilderCliVersion = cached ? cached.minBuilderCliVersion : undefined;
|
|
154
|
+
return {
|
|
155
|
+
dataplaneVersion,
|
|
156
|
+
minBuilderCliVersion,
|
|
157
|
+
cliVersion,
|
|
158
|
+
compatible: computeCompatibility(cliVersion, minBuilderCliVersion)
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Resolve bearer auth after login (device token preferred, else client app token).
|
|
164
|
+
* @private
|
|
165
|
+
* @async
|
|
166
|
+
* @param {string} controllerUrl
|
|
167
|
+
* @param {string} environment
|
|
168
|
+
* @param {Object} loginOptions
|
|
169
|
+
* @returns {Promise<Object|null>}
|
|
170
|
+
*/
|
|
171
|
+
async function resolveAuthConfigAfterLogin(controllerUrl, environment, loginOptions) {
|
|
172
|
+
const { getOrRefreshDeviceToken, getDeploymentAuth } = require('../utils/token-manager');
|
|
173
|
+
const device = await getOrRefreshDeviceToken(controllerUrl);
|
|
174
|
+
if (device && device.token) {
|
|
175
|
+
return { type: 'bearer', token: device.token };
|
|
176
|
+
}
|
|
177
|
+
if (!loginOptions.app) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
return await getDeploymentAuth(controllerUrl, environment, loginOptions.app);
|
|
182
|
+
} catch (_authError) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Resolve dataplane URL after login (mirrors auth-status silent resolver).
|
|
189
|
+
* @private
|
|
190
|
+
* @async
|
|
191
|
+
* @param {string} controllerUrl
|
|
192
|
+
* @param {string} environment
|
|
193
|
+
* @param {Object} authConfig
|
|
194
|
+
* @returns {Promise<string|null>}
|
|
195
|
+
*/
|
|
196
|
+
async function resolveDataplaneUrlAfterLogin(controllerUrl, environment, authConfig) {
|
|
197
|
+
const { findDataplaneServiceAppKey } = require('./wizard-dataplane');
|
|
198
|
+
const { getDataplaneUrl } = require('../datasource/deploy');
|
|
199
|
+
try {
|
|
200
|
+
const dataplaneAppKey = await findDataplaneServiceAppKey(
|
|
201
|
+
controllerUrl,
|
|
202
|
+
environment,
|
|
203
|
+
authConfig
|
|
204
|
+
);
|
|
205
|
+
if (dataplaneAppKey) {
|
|
206
|
+
return await getDataplaneUrl(controllerUrl, dataplaneAppKey, environment, authConfig);
|
|
207
|
+
}
|
|
208
|
+
return await getDataplaneUrl(controllerUrl, 'dataplane', environment, authConfig);
|
|
209
|
+
} catch (_resolveError) {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Best-effort health refresh after login when dataplane URL is discoverable.
|
|
216
|
+
* Never throws — cache failures must not block login success.
|
|
217
|
+
*
|
|
218
|
+
* @async
|
|
219
|
+
* @param {string} controllerUrl - Controller URL (device cache key)
|
|
220
|
+
* @param {Object} [loginOptions]
|
|
221
|
+
* @param {string} [loginOptions.app] - App name (credentials login) for client-token auth
|
|
222
|
+
* @returns {Promise<void>}
|
|
223
|
+
*/
|
|
224
|
+
async function tryRefreshDataplaneVersionAfterLoginWork(controllerUrl, loginOptions = {}) {
|
|
225
|
+
const { resolveEnvironment } = require('../core/config');
|
|
226
|
+
const environment = await resolveEnvironment();
|
|
227
|
+
const authConfig = await resolveAuthConfigAfterLogin(
|
|
228
|
+
controllerUrl,
|
|
229
|
+
environment,
|
|
230
|
+
loginOptions
|
|
231
|
+
);
|
|
232
|
+
if (!authConfig) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const dataplaneUrl = await resolveDataplaneUrlAfterLogin(
|
|
236
|
+
controllerUrl,
|
|
237
|
+
environment,
|
|
238
|
+
authConfig
|
|
239
|
+
);
|
|
240
|
+
if (dataplaneUrl) {
|
|
241
|
+
await refreshDataplaneVersionInfo(controllerUrl, dataplaneUrl, {
|
|
242
|
+
healthTimeoutMs: LOGIN_HEALTH_PROBE_TIMEOUT_MS
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async function tryRefreshDataplaneVersionAfterLogin(controllerUrl, loginOptions = {}) {
|
|
248
|
+
if (!controllerUrl || typeof controllerUrl !== 'string') {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
await raceWithTimeout(
|
|
253
|
+
tryRefreshDataplaneVersionAfterLoginWork(controllerUrl, loginOptions),
|
|
254
|
+
LOGIN_POST_REFRESH_BUDGET_MS
|
|
255
|
+
);
|
|
256
|
+
} catch (_error) {
|
|
257
|
+
// best-effort only
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
module.exports = {
|
|
262
|
+
refreshDataplaneVersionInfo,
|
|
263
|
+
loadCachedVersionInfo,
|
|
264
|
+
computeCompatibility,
|
|
265
|
+
tryRefreshDataplaneVersionAfterLogin,
|
|
266
|
+
LOGIN_POST_REFRESH_BUDGET_MS,
|
|
267
|
+
LOGIN_HEALTH_PROBE_TIMEOUT_MS,
|
|
268
|
+
raceWithTimeout
|
|
269
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth-status dataplane version block + blocking upgrade UX (plan 142.0).
|
|
3
|
+
*
|
|
4
|
+
* Kept in a separate module so `auth-status.js` stays under the 500-line
|
|
5
|
+
* limit and so the same display helpers can be reused by future dataplane
|
|
6
|
+
* gate surfaces (`upload`, `wizard`, `deploy`, …).
|
|
7
|
+
*
|
|
8
|
+
* @fileoverview TTY rendering for dataplane / Builder CLI compatibility
|
|
9
|
+
* @author AI Fabrix Team
|
|
10
|
+
* @version 2.0.0
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
const chalk = require('chalk');
|
|
16
|
+
const logger = require('../utils/logger');
|
|
17
|
+
const {
|
|
18
|
+
successGlyph,
|
|
19
|
+
failureGlyph
|
|
20
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
21
|
+
const {
|
|
22
|
+
formatCliVersionGateError
|
|
23
|
+
} = require('../utils/dataplane-cli-version-help');
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Format a single key/value version line indented under the dataplane block.
|
|
27
|
+
* @private
|
|
28
|
+
* @param {string} label
|
|
29
|
+
* @param {string|undefined|null} value
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
function versionLine(label, value) {
|
|
33
|
+
const display = value && String(value).trim() ? chalk.cyan(value) : chalk.gray('—');
|
|
34
|
+
return ` ${label}: ${display}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Render the dataplane version subsection on `aifabrix auth status`.
|
|
39
|
+
*
|
|
40
|
+
* Designed to be called immediately after the existing connection/status line,
|
|
41
|
+
* so the output reads as a single grouped block per layout.md §HEADER BLOCK.
|
|
42
|
+
*
|
|
43
|
+
* @param {Object} params
|
|
44
|
+
* @param {boolean} params.connected - Whether dataplane reachability probe passed
|
|
45
|
+
* @param {string|undefined} params.dataplaneVersion - From `device.<controllerUrl>.dataplane-version`
|
|
46
|
+
* @param {string|undefined} params.minBuilderCliVersion - From `device.<controllerUrl>.dataplane-min-cli-version`
|
|
47
|
+
* @param {string} params.cliVersion - Installed Builder CLI version
|
|
48
|
+
* @param {boolean} params.compatible - true when CLI ≥ minimum (or no minimum enforced)
|
|
49
|
+
* @returns {void}
|
|
50
|
+
*/
|
|
51
|
+
function displayDataplaneVersionSection({
|
|
52
|
+
connected,
|
|
53
|
+
dataplaneVersion,
|
|
54
|
+
minBuilderCliVersion,
|
|
55
|
+
cliVersion,
|
|
56
|
+
compatible
|
|
57
|
+
}) {
|
|
58
|
+
if (!connected && !dataplaneVersion) {
|
|
59
|
+
// Nothing to add — keep auth status quiet when the dataplane probe failed
|
|
60
|
+
// and no cached version is known (the reachability line already told the user).
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
logger.log(versionLine('Dataplane version', dataplaneVersion));
|
|
64
|
+
logger.log(versionLine('Min Builder CLI', minBuilderCliVersion));
|
|
65
|
+
logger.log(versionLine('This CLI', cliVersion));
|
|
66
|
+
if (!minBuilderCliVersion) {
|
|
67
|
+
logger.log(` Compatibility: ${chalk.gray('Not enforced')}`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (compatible) {
|
|
71
|
+
logger.log(` Compatibility: ${successGlyph()} ${chalk.green('OK')}`);
|
|
72
|
+
} else {
|
|
73
|
+
logger.log(` Compatibility: ${failureGlyph()} ${chalk.red('Upgrade required')}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Render the blocking upgrade block (red ✖ + Next actions) under the
|
|
79
|
+
* dataplane subsection when the CLI is incompatible.
|
|
80
|
+
*
|
|
81
|
+
* @param {Object} params
|
|
82
|
+
* @param {string} params.required - Required minimum semver
|
|
83
|
+
* @param {string} params.installed - Currently installed semver
|
|
84
|
+
* @returns {void}
|
|
85
|
+
*/
|
|
86
|
+
function displayCliUpgradeRequired({ required, installed }) {
|
|
87
|
+
logger.log('');
|
|
88
|
+
logger.log(formatCliVersionGateError(required, installed));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = {
|
|
92
|
+
displayDataplaneVersionSection,
|
|
93
|
+
displayCliUpgradeRequired
|
|
94
|
+
};
|