@aifabrix/builder 2.45.5 → 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/project-rules.mdc +1 -0
- package/README.md +43 -17
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
- package/jest.config.default.js +2 -1
- package/jest.config.isolated.js +2 -1
- package/jest.global-live-fabrix-hooks.js +36 -0
- package/jest.isolated-projects.js +130 -0
- package/jest.projects.js +41 -136
- package/lib/api/api-response-errors.js +124 -0
- package/lib/api/governance-scenario-pack.api.js +159 -0
- package/lib/api/index.js +43 -3
- package/lib/api/lifecycle.api.js +77 -0
- package/lib/api/pipeline.api.js +3 -1
- package/lib/api/records-bulk.api.js +14 -1
- package/lib/api/validation-runner.js +3 -1
- package/lib/app/deploy-config.js +4 -1
- 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 +4 -0
- package/lib/cli/infra-guided-auth.js +109 -0
- package/lib/cli/infra-guided.js +84 -81
- package/lib/cli/setup-app.help.js +0 -31
- package/lib/cli/setup-app.js +28 -2
- package/lib/cli/setup-app.test-commands.js +5 -57
- package/lib/cli/setup-auth.js +25 -0
- package/lib/cli/setup-certification-commands.js +147 -0
- package/lib/cli/setup-certification.help.js +141 -0
- package/lib/cli/setup-environment.js +19 -2
- package/lib/cli/setup-external-system-help.js +62 -0
- package/lib/cli/setup-external-system.js +25 -3
- package/lib/cli/setup-infra.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 +22 -2
- package/lib/cli/setup-utility-repair.js +198 -0
- package/lib/cli/setup-utility-resolve.js +40 -4
- package/lib/cli/setup-utility-validate.js +197 -0
- package/lib/cli/setup-utility.js +4 -239
- package/lib/commands/auth-status-client-tokens.js +214 -0
- package/lib/commands/auth-status-dataplane-version.js +58 -20
- package/lib/commands/auth-status.js +41 -47
- package/lib/commands/datasource-test-trust-cli.js +27 -23
- package/lib/commands/datasource-unified-test-cli.js +6 -3
- package/lib/commands/datasource-unified-test-cli.options.js +5 -1
- package/lib/commands/datasource.js +7 -7
- package/lib/commands/dev-show-display.js +8 -1
- package/lib/commands/governance-cli-shared.js +94 -0
- package/lib/commands/governance-command-action.js +132 -0
- package/lib/commands/governance-download-external.js +34 -0
- package/lib/commands/governance-generate-external.js +71 -0
- package/lib/commands/governance-upload-external.js +36 -0
- package/lib/commands/governance-verify-external.js +64 -0
- package/lib/commands/governance.js +144 -0
- package/lib/commands/lifecycle-command-action.js +123 -0
- package/lib/commands/lifecycle-external.js +268 -0
- package/lib/commands/login.js +11 -2
- package/lib/commands/repair-auth-apply.js +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 -296
- 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 +24 -8
- package/lib/commands/test-governance-external.js +3 -24
- package/lib/commands/test-trust-external.js +20 -21
- 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 +90 -108
- 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 +2 -0
- package/lib/core/admin-password-generator.js +38 -0
- package/lib/core/admin-secrets-bundle.js +111 -0
- package/lib/core/admin-secrets-env-overlay.js +62 -0
- package/lib/core/admin-secrets.js +32 -4
- package/lib/core/config-attach-extensions.js +3 -0
- package/lib/core/config-platform-controller.js +44 -0
- package/lib/core/config-setup-installation-profile.js +42 -0
- package/lib/core/config-setup-platform-mode.js +46 -0
- package/lib/core/config.js +46 -36
- package/lib/core/secrets-admin-env.js +6 -2
- package/lib/core/secrets-ensure.js +4 -0
- package/lib/core/secrets-env-content.js +54 -48
- package/lib/core/secrets-env-write.js +10 -1
- package/lib/core/secrets-infra-placeholder-sync.js +2 -0
- package/lib/core/setup-installation-profile.js +43 -0
- package/lib/core/setup-platform-mode.js +55 -0
- package/lib/datasource/agent-trust-debug-log.js +1 -1
- package/lib/datasource/agent-trust-run.js +5 -3
- package/lib/datasource/audit-evidence-extract-debug.js +30 -18
- package/lib/datasource/audit-evidence-extract.js +7 -4
- package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
- package/lib/datasource/bulk-loader-run-batches.js +15 -3
- package/lib/datasource/datasource-load-export-context.js +3 -0
- package/lib/datasource/log-cleaner.js +2 -2
- package/lib/datasource/log-viewer.js +8 -8
- package/lib/datasource/test-e2e.js +4 -1
- package/lib/datasource/unified-validation-run-body.js +3 -1
- package/lib/datasource/unified-validation-run.js +5 -2
- package/lib/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.js +6 -6
- 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-run-display.js +215 -25
- package/lib/infrastructure/admin-secrets-apply.js +84 -0
- package/lib/infrastructure/admin-secrets-ensure.js +130 -0
- package/lib/infrastructure/admin-secrets-resolve.js +95 -0
- package/lib/infrastructure/admin-secrets-sync.js +91 -0
- package/lib/infrastructure/helpers.js +23 -129
- package/lib/infrastructure/index.js +5 -6
- package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
- package/lib/lifecycle/certification-progress.js +231 -0
- package/lib/lifecycle/dataplane-ui-url.js +145 -0
- package/lib/lifecycle/exit-codes.js +24 -0
- package/lib/lifecycle/json-envelope.js +25 -0
- package/lib/lifecycle/lifecycle-governance-options.js +51 -0
- package/lib/lifecycle/logger-quiet.js +29 -0
- package/lib/lifecycle/open-api-published.js +59 -0
- package/lib/lifecycle/operations-readiness-metrics.js +101 -0
- package/lib/lifecycle/product-model.js +196 -0
- package/lib/lifecycle/report-display.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 +10 -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 -2622
- package/lib/schema/external-system.schema.json +1089 -761
- package/lib/schema/infra.parameter.yaml +45 -0
- package/lib/schema/type/credential-field-registry.json +103 -97
- 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-secrets-error-format.js +83 -21
- 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-secrets-env.js +137 -9
- package/lib/utils/dataplane-resolver.js +129 -2
- 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 +11 -8
- package/lib/utils/keycloak-realm-ready.js +101 -0
- package/lib/utils/load-cip-capacity-display-config.js +61 -15
- package/lib/utils/manifest-source-emit.js +2 -0
- package/lib/utils/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/service-url-label.js +81 -0
- package/lib/utils/setup-quiet-output.js +25 -0
- package/lib/utils/template-helpers.js +15 -0
- package/lib/utils/token-manager-client-credentials.js +201 -0
- package/lib/utils/token-manager-messages.js +8 -0
- package/lib/utils/token-manager-refresh.js +12 -2
- package/lib/utils/token-manager.js +86 -105
- package/lib/utils/upload-pipeline-ui.js +12 -5
- package/lib/utils/upload-sync-options.js +42 -0
- package/lib/utils/url-declarative-public-base.js +21 -3
- package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
- package/lib/utils/validation-poll-ui.js +8 -0
- package/lib/utils/validation-run-stage.js +45 -0
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +2 -1
- package/templates/applications/dataplane/env.template +24 -1
- package/templates/applications/miso-controller/env.template +16 -0
- package/templates/external-system/README.md.hbs +74 -17
- package/templates/python/docker-compose.hbs +19 -18
- package/templates/typescript/docker-compose.hbs +18 -17
- package/lib/commands/test-governance-command-action.js +0 -55
- package/lib/commands/test-trust-command-action.js +0 -118
|
@@ -11,8 +11,6 @@
|
|
|
11
11
|
const chalk = require('chalk');
|
|
12
12
|
const { failureGlyph, successGlyph } = require('../utils/cli-test-layout-chalk');
|
|
13
13
|
const logger = require('../utils/logger');
|
|
14
|
-
const config = require('../core/config');
|
|
15
|
-
const { getConfig } = config;
|
|
16
14
|
const { getOrRefreshDeviceToken } = require('../utils/token-manager');
|
|
17
15
|
const { getAuthUser } = require('../api/auth.api');
|
|
18
16
|
const { resolveControllerUrl } = require('../utils/controller-url');
|
|
@@ -32,6 +30,11 @@ const {
|
|
|
32
30
|
EXIT_CLI_VERSION_INCOMPATIBLE,
|
|
33
31
|
EXIT_OK
|
|
34
32
|
} = require('../utils/cli-exit-codes');
|
|
33
|
+
const {
|
|
34
|
+
refreshExpiredClientTokensWherePossible,
|
|
35
|
+
displayStoredClientTokensSection,
|
|
36
|
+
tryResolveClientTokenAuth
|
|
37
|
+
} = require('./auth-status-client-tokens');
|
|
35
38
|
|
|
36
39
|
/**
|
|
37
40
|
* Format expiration date for display
|
|
@@ -94,22 +97,6 @@ async function checkDeviceToken(controllerUrl) {
|
|
|
94
97
|
}
|
|
95
98
|
}
|
|
96
99
|
|
|
97
|
-
/**
|
|
98
|
-
* Decrypt token if encrypted
|
|
99
|
-
* @async
|
|
100
|
-
* @param {string} token - Token to decrypt
|
|
101
|
-
* @returns {Promise<string>} Decrypted token
|
|
102
|
-
*/
|
|
103
|
-
async function decryptTokenIfNeeded(token) {
|
|
104
|
-
const { decryptToken, isTokenEncrypted } = require('../utils/token-encryption');
|
|
105
|
-
const encryptionKey = await config.getSecretsEncryptionKey();
|
|
106
|
-
|
|
107
|
-
if (encryptionKey && isTokenEncrypted(token)) {
|
|
108
|
-
return await decryptToken(token, encryptionKey);
|
|
109
|
-
}
|
|
110
|
-
return token;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
100
|
/**
|
|
114
101
|
* Validate client token and return result
|
|
115
102
|
* @async
|
|
@@ -156,29 +143,14 @@ async function validateClientToken(token, controllerUrl, environment, appName, e
|
|
|
156
143
|
}
|
|
157
144
|
|
|
158
145
|
/**
|
|
159
|
-
* Check and validate client token
|
|
146
|
+
* Check and validate client token (refreshes when expired if client credentials exist).
|
|
160
147
|
* @async
|
|
161
148
|
* @param {string} controllerUrl - Controller URL
|
|
162
149
|
* @param {string} environment - Environment key
|
|
163
150
|
* @returns {Promise<Object|null>} Token validation result or null
|
|
164
151
|
*/
|
|
165
152
|
async function checkClientToken(controllerUrl, environment) {
|
|
166
|
-
|
|
167
|
-
const environments = configData.environments || {};
|
|
168
|
-
const envConfig = environments[environment];
|
|
169
|
-
|
|
170
|
-
if (!envConfig || !envConfig.clients) {
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
for (const [appName, tokenData] of Object.entries(envConfig.clients)) {
|
|
175
|
-
if (tokenData.controller === controllerUrl && tokenData.token) {
|
|
176
|
-
const token = await decryptTokenIfNeeded(tokenData.token);
|
|
177
|
-
return await validateClientToken(token, controllerUrl, environment, appName, tokenData.expiresAt);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return null;
|
|
153
|
+
return tryResolveClientTokenAuth(controllerUrl, environment, validateClientToken);
|
|
182
154
|
}
|
|
183
155
|
|
|
184
156
|
/**
|
|
@@ -382,18 +354,34 @@ async function buildDataplaneInfo(controllerUrl, environment, authConfig) {
|
|
|
382
354
|
* @param {boolean} [options.validate] - If true, exit with code 1 when not authenticated, or code 3 when CLI is older than dataplane minimum
|
|
383
355
|
* @returns {Promise<void>} Resolves when status is displayed
|
|
384
356
|
*/
|
|
357
|
+
/**
|
|
358
|
+
* Prefer a working device token; fall back to environment client credentials when the
|
|
359
|
+
* stored device token is expired or rejected (common in long-lived dev VMs).
|
|
360
|
+
*
|
|
361
|
+
* @async
|
|
362
|
+
* @param {string} controllerUrl
|
|
363
|
+
* @param {string} environment
|
|
364
|
+
* @returns {Promise<Object|null>}
|
|
365
|
+
*/
|
|
366
|
+
async function resolveAuthenticatedTokenInfo(controllerUrl, environment) {
|
|
367
|
+
const deviceResult = await checkDeviceToken(controllerUrl);
|
|
368
|
+
if (deviceResult && deviceResult.authenticated) {
|
|
369
|
+
return deviceResult;
|
|
370
|
+
}
|
|
371
|
+
const clientResult = await checkClientToken(controllerUrl, environment);
|
|
372
|
+
if (clientResult && clientResult.authenticated) {
|
|
373
|
+
return clientResult;
|
|
374
|
+
}
|
|
375
|
+
return deviceResult || clientResult || null;
|
|
376
|
+
}
|
|
377
|
+
|
|
385
378
|
async function handleAuthStatus(options = {}) {
|
|
386
379
|
const { resolveEnvironment } = require('../core/config');
|
|
387
380
|
const controllerUrl = await resolveControllerUrl();
|
|
388
381
|
const environment = await resolveEnvironment();
|
|
389
382
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
// If no device token, check client token
|
|
394
|
-
if (!tokenInfo) {
|
|
395
|
-
tokenInfo = await checkClientToken(controllerUrl, environment);
|
|
396
|
-
}
|
|
383
|
+
const refreshedCount = await refreshExpiredClientTokensWherePossible(environment, controllerUrl);
|
|
384
|
+
const tokenInfo = await resolveAuthenticatedTokenInfo(controllerUrl, environment);
|
|
397
385
|
|
|
398
386
|
let dataplaneInfo = null;
|
|
399
387
|
if (tokenInfo && tokenInfo.authenticated && tokenInfo.token) {
|
|
@@ -402,6 +390,7 @@ async function handleAuthStatus(options = {}) {
|
|
|
402
390
|
}
|
|
403
391
|
|
|
404
392
|
displayStatus(controllerUrl, environment, tokenInfo, dataplaneInfo);
|
|
393
|
+
await displayStoredClientTokensSection(environment, controllerUrl, refreshedCount);
|
|
405
394
|
|
|
406
395
|
if (options.validate) {
|
|
407
396
|
if (!tokenInfo || !tokenInfo.authenticated) {
|
|
@@ -427,10 +416,7 @@ async function getValidatedAuthContext() {
|
|
|
427
416
|
const controllerUrl = await resolveControllerUrl();
|
|
428
417
|
const environment = await resolveEnvironment();
|
|
429
418
|
|
|
430
|
-
|
|
431
|
-
if (!tokenInfo) {
|
|
432
|
-
tokenInfo = await checkClientToken(controllerUrl, environment);
|
|
433
|
-
}
|
|
419
|
+
const tokenInfo = await resolveAuthenticatedTokenInfo(controllerUrl, environment);
|
|
434
420
|
|
|
435
421
|
if (!tokenInfo || !tokenInfo.authenticated || !tokenInfo.token) {
|
|
436
422
|
throw new Error('Not authenticated. Run "aifabrix login" or configure client credentials.');
|
|
@@ -442,4 +428,12 @@ async function getValidatedAuthContext() {
|
|
|
442
428
|
return { controllerUrl, environment, authConfig, dataplaneUrl };
|
|
443
429
|
}
|
|
444
430
|
|
|
445
|
-
module.exports = {
|
|
431
|
+
module.exports = {
|
|
432
|
+
handleAuthStatus,
|
|
433
|
+
getValidatedAuthContext,
|
|
434
|
+
resolveAuthenticatedTokenInfo,
|
|
435
|
+
checkDeviceToken,
|
|
436
|
+
checkClientToken,
|
|
437
|
+
refreshExpiredClientTokensWherePossible,
|
|
438
|
+
displayStoredClientTokensSection
|
|
439
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview CLI wiring for `datasource
|
|
2
|
+
* @fileoverview CLI wiring for `datasource verify-trust` (404.5 / plan 143).
|
|
3
3
|
* @author AI Fabrix Team
|
|
4
4
|
* @version 1.0.0
|
|
5
5
|
*/
|
|
@@ -15,26 +15,27 @@ const { computeExitCodeFromTrustRun } = require('../utils/agent-trust-run-exit')
|
|
|
15
15
|
const { attachDatasourceTestCommonOptions } = require('./datasource-unified-test-cli.options');
|
|
16
16
|
const { cliOptsSkipSync } = require('../utils/cli-sync-options');
|
|
17
17
|
|
|
18
|
-
function
|
|
18
|
+
function datasourceVerifyTrustHelpAfter() {
|
|
19
19
|
return `
|
|
20
20
|
Examples:
|
|
21
|
-
$ aifabrix datasource
|
|
22
|
-
$ aifabrix datasource
|
|
23
|
-
$ aifabrix datasource
|
|
24
|
-
$ aifabrix
|
|
21
|
+
$ aifabrix datasource verify-trust hubspot-companies
|
|
22
|
+
$ aifabrix datasource verify-trust hubspot-companies --app test-e2e-hubspot -v
|
|
23
|
+
$ aifabrix datasource verify-trust hubspot-companies --revalidate --strict
|
|
24
|
+
$ aifabrix verify-trust test-e2e-hubspot
|
|
25
25
|
|
|
26
26
|
Notes:
|
|
27
27
|
- Semantic trust only (agent metadata validation). For live API proof use test-e2e.
|
|
28
28
|
- Local files are published before run unless --no-sync.
|
|
29
|
-
- With --debug, JSON is saved under integration/<app>/logs/ (
|
|
29
|
+
- With --debug, JSON is saved under integration/<app>/logs/ (verify-trust-<key>-*.json). View with: aifabrix datasource log-trust <key>
|
|
30
30
|
`;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
async function
|
|
33
|
+
async function runDatasourceVerifyTrustOnce(datasourceKey, options) {
|
|
34
34
|
const { trustRun, apiError } = await runDatasourceAgentTrust(datasourceKey, {
|
|
35
35
|
app: options.app,
|
|
36
36
|
environment: options.env,
|
|
37
37
|
noSync: options.noSync === true,
|
|
38
|
+
force: options.force === true,
|
|
38
39
|
revalidate: options.revalidate === true,
|
|
39
40
|
summary: options.summary === true,
|
|
40
41
|
timeout: options.timeout
|
|
@@ -42,7 +43,7 @@ async function runDatasourceTestTrustOnce(datasourceKey, options) {
|
|
|
42
43
|
return { trustRun, apiError };
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
async function
|
|
46
|
+
async function finalizeDatasourceVerifyTrust(datasourceKey, options, result) {
|
|
46
47
|
const displayOpts = {
|
|
47
48
|
json: options.json,
|
|
48
49
|
verbose: options.verbose,
|
|
@@ -67,10 +68,10 @@ async function finalizeDatasourceTestTrust(datasourceKey, options, result) {
|
|
|
67
68
|
return computeExitCodeFromTrustRun(result.trustRun, exitOpts);
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
async function
|
|
71
|
+
async function datasourceVerifyTrustAction(datasourceKey, options, cmd) {
|
|
71
72
|
try {
|
|
72
73
|
const merged = { ...options, noSync: cliOptsSkipSync(options, cmd) };
|
|
73
|
-
const result = await
|
|
74
|
+
const result = await runDatasourceVerifyTrustOnce(datasourceKey, merged);
|
|
74
75
|
const { resolveAppKeyForDatasource } = require('../datasource/resolve-app');
|
|
75
76
|
const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
|
|
76
77
|
if (options.debug) {
|
|
@@ -80,7 +81,7 @@ async function datasourceTestTrustAction(datasourceKey, options, cmd) {
|
|
|
80
81
|
error: result.apiError ? result.apiError.message : null
|
|
81
82
|
});
|
|
82
83
|
}
|
|
83
|
-
const exitCode = await
|
|
84
|
+
const exitCode = await finalizeDatasourceVerifyTrust(datasourceKey, merged, result);
|
|
84
85
|
process.exit(exitCode);
|
|
85
86
|
} catch (err) {
|
|
86
87
|
logger.error(formatBlockingError('Agent trust validation failed:'), err.message);
|
|
@@ -88,10 +89,7 @@ async function datasourceTestTrustAction(datasourceKey, options, cmd) {
|
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
function
|
|
92
|
-
const cmd = datasource
|
|
93
|
-
.command('test-trust <datasourceKey>')
|
|
94
|
-
.description('Semantic agent metadata validation for one datasource (dataplane 404.5)');
|
|
92
|
+
function attachDatasourceTrustOptions(cmd) {
|
|
95
93
|
attachDatasourceTestCommonOptions(cmd, {
|
|
96
94
|
includeNoAsync: false,
|
|
97
95
|
includePayload: false,
|
|
@@ -101,14 +99,20 @@ function setupDatasourceTestTrustCommand(datasource) {
|
|
|
101
99
|
cmd
|
|
102
100
|
.option('--no-sync', 'Skip publishing local integration files before validate')
|
|
103
101
|
.option('--revalidate', 'Force new validation (ignore inputHash cache)')
|
|
104
|
-
.option('--strict', 'Exit 1 unless trustDecision is trusted')
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
.option('--strict', 'Exit 1 unless trustDecision is trusted');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function setupDatasourceVerifyTrustCommand(datasource) {
|
|
106
|
+
const cmd = datasource
|
|
107
|
+
.command('verify-trust <datasourceKey>')
|
|
108
|
+
.description('Semantic agent metadata validation for one datasource');
|
|
109
|
+
attachDatasourceTrustOptions(cmd);
|
|
110
|
+
cmd.addHelpText('after', datasourceVerifyTrustHelpAfter()).action(datasourceVerifyTrustAction);
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
module.exports = {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
setupDatasourceVerifyTrustCommand,
|
|
115
|
+
runDatasourceVerifyTrustOnce,
|
|
116
|
+
finalizeDatasourceVerifyTrust,
|
|
117
|
+
datasourceVerifyTrustAction
|
|
114
118
|
};
|
|
@@ -77,7 +77,8 @@ function buildDatasourceTestRunOpts(options) {
|
|
|
77
77
|
timeout: options.timeout,
|
|
78
78
|
async: options.async !== false,
|
|
79
79
|
noAsync: options.async === false,
|
|
80
|
-
sync: options.sync === true
|
|
80
|
+
sync: options.sync === true,
|
|
81
|
+
force: options.force === true
|
|
81
82
|
};
|
|
82
83
|
}
|
|
83
84
|
|
|
@@ -174,7 +175,8 @@ function buildIntegrationTestOpts(options) {
|
|
|
174
175
|
debug: options.debug,
|
|
175
176
|
verbose: options.verbose,
|
|
176
177
|
timeout: options.timeout,
|
|
177
|
-
sync: options.sync === true
|
|
178
|
+
sync: options.sync === true,
|
|
179
|
+
force: options.force === true
|
|
178
180
|
};
|
|
179
181
|
}
|
|
180
182
|
|
|
@@ -335,7 +337,8 @@ async function runDatasourceTestE2ECliOnce(datasourceKey, options) {
|
|
|
335
337
|
minRecordCount: options.minRecordCount,
|
|
336
338
|
timeout: options.timeout,
|
|
337
339
|
capabilityKey: options.capabilityKey,
|
|
338
|
-
sync: options.sync === true
|
|
340
|
+
sync: options.sync === true,
|
|
341
|
+
force: options.force === true
|
|
339
342
|
});
|
|
340
343
|
const unifiedModes =
|
|
341
344
|
options.json || options.summary || options.warningsAsErrors || options.requireCert;
|
|
@@ -44,7 +44,7 @@ Examples:
|
|
|
44
44
|
$ aifabrix datasource test-e2e hubspot-users --app test-e2e-hubspot -v --debug
|
|
45
45
|
$ aifabrix datasource test-e2e my-documents-ds --min-vector-hits 7 -v --debug
|
|
46
46
|
$ aifabrix datasource test-e2e hubspot-users -a test-e2e-hubspot --no-async
|
|
47
|
-
$ aifabrix datasource test-e2e hubspot-users --sync --verify-audit -v
|
|
47
|
+
$ aifabrix datasource test-e2e hubspot-users --sync --force --verify-audit -v
|
|
48
48
|
$ aifabrix datasource test-e2e hubspot-users read
|
|
49
49
|
|
|
50
50
|
Notes:
|
|
@@ -129,6 +129,10 @@ function attachDatasourceTestCommonOptions(cmd, opts) {
|
|
|
129
129
|
'--sync',
|
|
130
130
|
'Publish local integration config to the dataplane before running the test (same as aifabrix upload <systemKey>; requires login)'
|
|
131
131
|
)
|
|
132
|
+
.option(
|
|
133
|
+
'--force',
|
|
134
|
+
'With --sync, pass force to upload (bypass active-datasource schema replacement guards; same as aifabrix upload --force)'
|
|
135
|
+
)
|
|
132
136
|
.option('--json', 'Print raw DatasourceTestRun JSON to stdout')
|
|
133
137
|
.option('--summary', 'Print compact summary line')
|
|
134
138
|
.option('--warnings-as-errors', 'Exit 1 when root status is warn')
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* AI Fabrix Builder - Datasource Commands
|
|
3
3
|
*
|
|
4
4
|
* Handles datasource validation, listing, comparison, deployment, and online validation runs.
|
|
5
|
-
* Subcommands `test`, `test-integration`, `test-e2e`, and `
|
|
5
|
+
* Subcommands `test`, `test-integration`, `test-e2e`, and `verify-trust` call the dataplane; `log-*` read saved debug JSON locally; `clean-logs` removes those files. Permissions are summarized in `docs/commands/permissions.md`.
|
|
6
6
|
*
|
|
7
7
|
* @fileoverview Datasource management commands for AI Fabrix Builder
|
|
8
8
|
* @author AI Fabrix Team
|
|
@@ -24,7 +24,7 @@ const {
|
|
|
24
24
|
setupDatasourceTestIntegrationCommand,
|
|
25
25
|
setupDatasourceTestE2ECommand
|
|
26
26
|
} = require('./datasource-unified-test-cli');
|
|
27
|
-
const {
|
|
27
|
+
const { setupDatasourceVerifyTrustCommand } = require('./datasource-test-trust-cli');
|
|
28
28
|
const { setupDatasourceVerifyAuditCommand } = require('./datasource-verify-audit-cli');
|
|
29
29
|
const { setupDatasourceLoadExportCommands } = require('./datasource-load-export-cli');
|
|
30
30
|
const { setupDatasourceCapabilityCommands } = require('./datasource-capability');
|
|
@@ -44,7 +44,7 @@ Examples:
|
|
|
44
44
|
$ af ds test-e2e <datasourceKey> --app <integrationFolder> -v
|
|
45
45
|
$ af ds test-e2e <datasourceKey> --verify-audit
|
|
46
46
|
$ af ds verify-audit <datasourceKey>
|
|
47
|
-
$ af ds
|
|
47
|
+
$ af ds verify-trust <datasourceKey> --app <integrationFolder> -v
|
|
48
48
|
$ af ds load <datasourceKey> --app <integrationFolder> --dry-run
|
|
49
49
|
$ af ds export <datasourceKey> --app <integrationFolder> --format ndjson -v
|
|
50
50
|
$ aifabrix datasource capability copy <file-or-key> --from create --as createBasicTrial --dry-run
|
|
@@ -262,18 +262,18 @@ function setupDatasourceCleanLogsCommand(datasource) {
|
|
|
262
262
|
|
|
263
263
|
function setupDatasourceLogTrustCommand(datasource) {
|
|
264
264
|
datasource.command('log-trust <datasourceKey>')
|
|
265
|
-
.description('Show agent trust log from datasource
|
|
265
|
+
.description('Show agent trust log from datasource verify-trust (latest verify-trust-*.json or --file)')
|
|
266
266
|
.option(
|
|
267
267
|
'-a, --app <app>',
|
|
268
268
|
'Integration folder name (optional: resolve from cwd or datasource key if single match)'
|
|
269
269
|
)
|
|
270
|
-
.option('-f, --file <path>', 'Path to log file (default: latest
|
|
270
|
+
.option('-f, --file <path>', 'Path to log file (default: latest verify-trust log in app logs folder)')
|
|
271
271
|
.action(async(datasourceKey, options) => {
|
|
272
272
|
try {
|
|
273
273
|
await runLogViewer(datasourceKey, {
|
|
274
274
|
app: options.app,
|
|
275
275
|
file: options.file,
|
|
276
|
-
logType: '
|
|
276
|
+
logType: 'verify-trust'
|
|
277
277
|
});
|
|
278
278
|
} catch (error) {
|
|
279
279
|
logger.error(formatBlockingError('log-trust failed:'), error.message);
|
|
@@ -304,7 +304,7 @@ function setupDatasourceCommands(program) {
|
|
|
304
304
|
setupDatasourceTestIntegrationCommand(datasource);
|
|
305
305
|
setupDatasourceTestE2ECommand(datasource);
|
|
306
306
|
setupDatasourceVerifyAuditCommand(datasource);
|
|
307
|
-
|
|
307
|
+
setupDatasourceVerifyTrustCommand(datasource);
|
|
308
308
|
setupDatasourceLogE2ECommand(datasource);
|
|
309
309
|
setupDatasourceLogIntegrationCommand(datasource);
|
|
310
310
|
setupDatasourceLogTestCommand(datasource);
|
|
@@ -336,6 +336,8 @@ function logConfigurationSection(p) {
|
|
|
336
336
|
logRow('Environment', p.environment);
|
|
337
337
|
logRow('Controller', p.controller);
|
|
338
338
|
logRow('Format', p.formatVal);
|
|
339
|
+
logRow('Platform mode', p.setupPlatformMode);
|
|
340
|
+
logRow('Traefik', p.traefikEnabled ? 'on' : 'off');
|
|
339
341
|
logRow('Scoped resources', p.scopedResourcesLabel);
|
|
340
342
|
logRow('URLs registry', p.urlsLocalPath);
|
|
341
343
|
if (!p.hasRemote) {
|
|
@@ -386,11 +388,12 @@ async function loadDevShowData(devIdStr) {
|
|
|
386
388
|
const devIdNum = parseInt(devIdStr, 10);
|
|
387
389
|
const ports = devConfig.getDevPorts(Number.isNaN(devIdNum) ? 0 : devIdNum);
|
|
388
390
|
const [
|
|
389
|
-
environment, tlsEnabled, controller, formatRaw, useScoped, secretsRaw,
|
|
391
|
+
environment, tlsEnabled, controller, formatRaw, useScoped, secretsRaw, setupPlatformMode, traefikEnabled,
|
|
390
392
|
remoteServer, dockerEndpoint, dockerTlsSkipVerify, mutagenFolder, syncSshUser, syncSshHost
|
|
391
393
|
] = await Promise.all([
|
|
392
394
|
config.getCurrentEnvironment(), config.getTlsEnabled(), config.getControllerUrl(),
|
|
393
395
|
config.getFormat(), config.getUseEnvironmentScopedResources(), config.getAifabrixSecretsPath(),
|
|
396
|
+
config.getSetupPlatformMode(), config.getTraefikEnabled(),
|
|
394
397
|
config.getRemoteServer(), config.getDockerEndpoint(), config.getDockerTlsSkipVerify(),
|
|
395
398
|
config.getUserMutagenFolder(), config.getSyncSshUser(), config.getSyncSshHost()
|
|
396
399
|
]);
|
|
@@ -410,6 +413,8 @@ async function loadDevShowData(devIdStr) {
|
|
|
410
413
|
controller,
|
|
411
414
|
formatVal: formatRaw ?? null,
|
|
412
415
|
scopedResourcesLabel,
|
|
416
|
+
setupPlatformMode,
|
|
417
|
+
traefikEnabled,
|
|
413
418
|
workResolved,
|
|
414
419
|
homeResolved,
|
|
415
420
|
secretsMain,
|
|
@@ -446,6 +451,8 @@ function renderDevShow(data) {
|
|
|
446
451
|
tlsEnabled: data.tlsEnabled,
|
|
447
452
|
controller: data.controller,
|
|
448
453
|
formatVal: data.formatVal,
|
|
454
|
+
setupPlatformMode: data.setupPlatformMode,
|
|
455
|
+
traefikEnabled: data.traefikEnabled,
|
|
449
456
|
scopedResourcesLabel: data.scopedResourcesLabel,
|
|
450
457
|
urlsLocalPath: data.urlsLocalPath,
|
|
451
458
|
hasRemote: data.hasRemote,
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared helpers for governance * CLI commands (424.0).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
resolveExternalIntegrationContext,
|
|
9
|
+
syncLocalIfRequested
|
|
10
|
+
} = require('./test-e2e-external');
|
|
11
|
+
const { resolveIntegrationAuth } = require('../external-system/integration-auth-context');
|
|
12
|
+
const { cliOptsSkipSync } = require('../utils/cli-sync-options');
|
|
13
|
+
const { fetchDataplaneGeneralHealth } = require('../api/dataplane-health.api');
|
|
14
|
+
const { formatNetworkError } = require('../utils/api-error-handler');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {Object} options
|
|
18
|
+
* @param {string[]} [options.subjectUserIds]
|
|
19
|
+
* @param {string[]} [options.subjectEmails]
|
|
20
|
+
* @returns {Array<{ subjectUserId?: string, subjectEmail?: string }>}
|
|
21
|
+
*/
|
|
22
|
+
function buildSubjectsFromOptions(options) {
|
|
23
|
+
const subjects = [];
|
|
24
|
+
const userIds = options.subjectUserIds || [];
|
|
25
|
+
const emails = options.subjectEmails || [];
|
|
26
|
+
for (const subjectUserId of userIds) {
|
|
27
|
+
const id = String(subjectUserId || '').trim();
|
|
28
|
+
if (id) subjects.push({ subjectUserId: id });
|
|
29
|
+
}
|
|
30
|
+
for (const subjectEmail of emails) {
|
|
31
|
+
const email = String(subjectEmail || '').trim();
|
|
32
|
+
if (email) subjects.push({ subjectEmail: email });
|
|
33
|
+
}
|
|
34
|
+
return subjects;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Fail fast when dataplane health is unreachable (avoids misleading API validation errors).
|
|
39
|
+
* @async
|
|
40
|
+
* @param {string} dataplaneUrl
|
|
41
|
+
* @returns {Promise<void>}
|
|
42
|
+
*/
|
|
43
|
+
async function assertDataplaneReachable(dataplaneUrl) {
|
|
44
|
+
const base = String(dataplaneUrl || '').replace(/\/$/, '');
|
|
45
|
+
const snapshot = await fetchDataplaneGeneralHealth(base, { timeoutMs: 8000 });
|
|
46
|
+
if (snapshot) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const endpointUrl = `${base}/api/v1/health`;
|
|
50
|
+
const err = new Error(`Cannot reach dataplane at ${base}`);
|
|
51
|
+
err.network = true;
|
|
52
|
+
err.serviceLabel = 'dataplane';
|
|
53
|
+
err.endpointUrl = endpointUrl;
|
|
54
|
+
err.formatted = formatNetworkError(err.message, {
|
|
55
|
+
endpointUrl,
|
|
56
|
+
serviceLabel: 'dataplane'
|
|
57
|
+
});
|
|
58
|
+
throw err;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @async
|
|
63
|
+
* @param {string} systemKey
|
|
64
|
+
* @param {Object} options
|
|
65
|
+
* @returns {Promise<{ resolvedKey: string, keys: string[], authConfig: Object, dataplaneUrl: string }>}
|
|
66
|
+
*/
|
|
67
|
+
async function resolveGovernanceIntegrationContext(systemKey, options) {
|
|
68
|
+
const { systemKey: resolvedKey, keys } = resolveExternalIntegrationContext(systemKey);
|
|
69
|
+
if (options.authConfig && options.dataplaneUrl) {
|
|
70
|
+
return {
|
|
71
|
+
resolvedKey,
|
|
72
|
+
keys,
|
|
73
|
+
authConfig: options.authConfig,
|
|
74
|
+
dataplaneUrl: options.dataplaneUrl
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
if (!cliOptsSkipSync(options)) {
|
|
78
|
+
const uploadCtx = await syncLocalIfRequested(resolvedKey, options);
|
|
79
|
+
if (uploadCtx?.authConfig && uploadCtx?.dataplaneUrl) {
|
|
80
|
+
options.authConfig = uploadCtx.authConfig;
|
|
81
|
+
options.dataplaneUrl = uploadCtx.dataplaneUrl;
|
|
82
|
+
options.silentResolve = true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const { authConfig, dataplaneUrl } = await resolveIntegrationAuth(resolvedKey, options);
|
|
86
|
+
await assertDataplaneReachable(dataplaneUrl);
|
|
87
|
+
return { resolvedKey, keys, authConfig, dataplaneUrl };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
module.exports = {
|
|
91
|
+
buildSubjectsFromOptions,
|
|
92
|
+
assertDataplaneReachable,
|
|
93
|
+
resolveGovernanceIntegrationContext
|
|
94
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CLI actions for `aifabrix governance *` (424.0).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const logger = require('../utils/logger');
|
|
8
|
+
const { handleCommandError } = require('../utils/cli-utils');
|
|
9
|
+
const { runGovernanceGenerateForExternalSystem } = require('./governance-generate-external');
|
|
10
|
+
const { runGovernanceVerifyForExternalSystem } = require('./governance-verify-external');
|
|
11
|
+
const { runGovernanceUploadForExternalSystem } = require('./governance-upload-external');
|
|
12
|
+
const { runGovernanceDownloadForExternalSystem } = require('./governance-download-external');
|
|
13
|
+
const { displayVerifyGovernanceTTY } = require('../lifecycle/report-display');
|
|
14
|
+
const { exitCodeFromVerdict } = require('../lifecycle/exit-codes');
|
|
15
|
+
const { buildJsonEnvelope } = require('../lifecycle/json-envelope');
|
|
16
|
+
const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Commander repeatable-option collector. Splits comma-separated values so both
|
|
20
|
+
* `--flag a --flag b` and `--flag a,b` work.
|
|
21
|
+
* @param {string} value
|
|
22
|
+
* @param {string[]} previous
|
|
23
|
+
* @returns {string[]}
|
|
24
|
+
*/
|
|
25
|
+
function collectString(value, previous) {
|
|
26
|
+
const parts = String(value)
|
|
27
|
+
.split(',')
|
|
28
|
+
.map(entry => entry.trim())
|
|
29
|
+
.filter(Boolean);
|
|
30
|
+
return previous.concat(parts.length > 0 ? parts : [String(value).trim()].filter(Boolean));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function normalizeGovernanceOptions(options, cmd) {
|
|
34
|
+
const parent = cmd && cmd.parent ? cmd.parent.opts() : {};
|
|
35
|
+
return {
|
|
36
|
+
env: options.env || parent.env || 'dev',
|
|
37
|
+
verbose: options.verbose === true || parent.verbose === true,
|
|
38
|
+
noSync: options.noSync === true || parent.noSync === true,
|
|
39
|
+
force: options.force === true || parent.force === true,
|
|
40
|
+
json: options.json === true || parent.json === true,
|
|
41
|
+
pack: options.pack,
|
|
42
|
+
app: options.app,
|
|
43
|
+
scenarioIds: options.scenario || [],
|
|
44
|
+
certificationProfile: options.certificationProfile || 'bronze',
|
|
45
|
+
subjectUserIds: options.subjectUserId || [],
|
|
46
|
+
subjectEmails: options.subjectEmail || [],
|
|
47
|
+
maxSamplesPerPartition: options.maxSamplesPerPartition
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function governanceGenerateHandler(systemKey, options, cmd) {
|
|
52
|
+
try {
|
|
53
|
+
const opts = normalizeGovernanceOptions(options, cmd);
|
|
54
|
+
const result = await runGovernanceGenerateForExternalSystem(systemKey, opts);
|
|
55
|
+
if (opts.json) {
|
|
56
|
+
logger.log(JSON.stringify(buildJsonEnvelope(result, opts.verbose), null, 2));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
for (const row of result.results || []) {
|
|
60
|
+
logger.log(
|
|
61
|
+
formatSuccessLine(
|
|
62
|
+
`${row.datasourceKey}: pack v${row.packVersion} (${row.scenarioCount} scenarios)`
|
|
63
|
+
)
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
} catch (error) {
|
|
67
|
+
handleCommandError(error, 'governance generate');
|
|
68
|
+
process.exit(3);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function governanceVerifyHandler(systemKey, options, cmd) {
|
|
73
|
+
try {
|
|
74
|
+
const opts = normalizeGovernanceOptions(options, cmd);
|
|
75
|
+
const result = await runGovernanceVerifyForExternalSystem(systemKey, opts);
|
|
76
|
+
if (opts.json) {
|
|
77
|
+
logger.log(JSON.stringify(buildJsonEnvelope(result, opts.verbose), null, 2));
|
|
78
|
+
} else {
|
|
79
|
+
displayVerifyGovernanceTTY(result.systemKey, result, { details: opts.verbose });
|
|
80
|
+
}
|
|
81
|
+
const exitCode = exitCodeFromVerdict(result.verdict);
|
|
82
|
+
if (exitCode !== 0) {
|
|
83
|
+
process.exit(exitCode);
|
|
84
|
+
}
|
|
85
|
+
} catch (error) {
|
|
86
|
+
handleCommandError(error, 'governance verify');
|
|
87
|
+
process.exit(3);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function governanceUploadHandler(systemKey, options, cmd) {
|
|
92
|
+
try {
|
|
93
|
+
const opts = normalizeGovernanceOptions(options, cmd);
|
|
94
|
+
const result = await runGovernanceUploadForExternalSystem(systemKey, opts);
|
|
95
|
+
if (opts.json) {
|
|
96
|
+
logger.log(JSON.stringify(buildJsonEnvelope(result, opts.verbose), null, 2));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
logger.log(formatSuccessLine(`Uploaded ${result.uploaded} scenario pack(s)`));
|
|
100
|
+
} catch (error) {
|
|
101
|
+
if (error.friendlyHint) {
|
|
102
|
+
logger.log(error.friendlyHint);
|
|
103
|
+
}
|
|
104
|
+
handleCommandError(error, 'governance upload');
|
|
105
|
+
process.exit(3);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function governanceDownloadHandler(systemKey, options, cmd) {
|
|
110
|
+
try {
|
|
111
|
+
const opts = normalizeGovernanceOptions(options, cmd);
|
|
112
|
+
opts.noSync = true;
|
|
113
|
+
const result = await runGovernanceDownloadForExternalSystem(systemKey, opts);
|
|
114
|
+
if (opts.json) {
|
|
115
|
+
logger.log(JSON.stringify(buildJsonEnvelope(result, opts.verbose), null, 2));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
logger.log(formatSuccessLine(`Downloaded ${result.written} scenario pack(s)`));
|
|
119
|
+
} catch (error) {
|
|
120
|
+
handleCommandError(error, 'governance download');
|
|
121
|
+
process.exit(3);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = {
|
|
126
|
+
collectString,
|
|
127
|
+
normalizeGovernanceOptions,
|
|
128
|
+
governanceGenerateHandler,
|
|
129
|
+
governanceVerifyHandler,
|
|
130
|
+
governanceUploadHandler,
|
|
131
|
+
governanceDownloadHandler
|
|
132
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview governance download — pull packs to integration/<systemKey>/scenarios/ (424.0).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const { downloadGovernanceScenarioPacks } = require('../lifecycle/scenario-upload');
|
|
8
|
+
const { resolveGovernanceIntegrationContext } = require('./governance-cli-shared');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @async
|
|
12
|
+
* @param {string} systemKey
|
|
13
|
+
* @param {Object} options
|
|
14
|
+
* @returns {Promise<Object>}
|
|
15
|
+
*/
|
|
16
|
+
async function runGovernanceDownloadForExternalSystem(systemKey, options = {}) {
|
|
17
|
+
const { resolvedKey, keys, authConfig, dataplaneUrl } =
|
|
18
|
+
await resolveGovernanceIntegrationContext(systemKey, options);
|
|
19
|
+
const written = await downloadGovernanceScenarioPacks(
|
|
20
|
+
resolvedKey,
|
|
21
|
+
keys,
|
|
22
|
+
dataplaneUrl,
|
|
23
|
+
authConfig
|
|
24
|
+
);
|
|
25
|
+
return {
|
|
26
|
+
systemKey: resolvedKey,
|
|
27
|
+
command: 'governance download',
|
|
28
|
+
written
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
runGovernanceDownloadForExternalSystem
|
|
34
|
+
};
|