@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
|
@@ -113,22 +113,27 @@ async function buildListMatrixRows(ctx, polled, minExpected) {
|
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
115
|
* @param {Object} ctx
|
|
116
|
-
* @param {
|
|
117
|
-
* @
|
|
118
|
-
* @returns {Promise<{ rows: import('../api/types/audit.types').AuditEvidenceMatrixRow[], execIds: string[] }>}
|
|
116
|
+
* @param {string[]} execIds
|
|
117
|
+
* @returns {Promise<import('../api/types/audit.types').AuditEvidenceMatrixRow[]>}
|
|
119
118
|
*/
|
|
120
|
-
async function
|
|
119
|
+
async function buildPerExecutionSubRows(ctx, execIds) {
|
|
121
120
|
const { dataplaneUrl, authConfig } = ctx;
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
const base = { dataplaneUrl, authConfig, executionId: sampleId };
|
|
125
|
-
const rows = await Promise.all([
|
|
121
|
+
const base = { dataplaneUrl, authConfig, executionId: execIds[0] };
|
|
122
|
+
return Promise.all([
|
|
126
123
|
checkPerExecutionSub({ ...base, rowNum: 4, label: 'rbac', fetcher: getExecutionRbac, isValid: isRbacSubResourceValid }),
|
|
127
124
|
checkPerExecutionSub({ ...base, rowNum: 5, label: 'abac', fetcher: getExecutionAbac, isValid: isAbacSubResourceValid }),
|
|
128
125
|
checkPerExecutionSub({ ...base, rowNum: 6, label: 'errors', fetcher: getExecutionErrors, isValid: isErrorsValid }),
|
|
129
126
|
checkPerExecutionSub({ ...base, rowNum: 7, label: 'steps', fetcher: getExecutionSteps, isValid: isStepsValid })
|
|
130
127
|
]);
|
|
128
|
+
}
|
|
131
129
|
|
|
130
|
+
/**
|
|
131
|
+
* @param {Object} ctx
|
|
132
|
+
* @param {Array} executions
|
|
133
|
+
* @returns {Promise<Array>}
|
|
134
|
+
*/
|
|
135
|
+
async function resolveRow8PoolForMatrix(ctx, executions) {
|
|
136
|
+
const { dataplaneUrl, authConfig } = ctx;
|
|
132
137
|
let corrQueryRows = [];
|
|
133
138
|
if (ctx.correlationId) {
|
|
134
139
|
const corr = await queryExecutions(dataplaneUrl, authConfig, {
|
|
@@ -137,28 +142,30 @@ async function buildPerExecutionAndTailRows(ctx, executions, executionIds) {
|
|
|
137
142
|
});
|
|
138
143
|
corrQueryRows = corr.data || [];
|
|
139
144
|
}
|
|
140
|
-
|
|
145
|
+
const row8Pool = corrQueryRows.length ? corrQueryRows : executions;
|
|
141
146
|
const expected = ctx.expectedOperations || [];
|
|
142
|
-
if (expected.length
|
|
143
|
-
|
|
144
|
-
dataplaneUrl,
|
|
145
|
-
authConfig,
|
|
146
|
-
ctx.correlationId,
|
|
147
|
-
expected
|
|
148
|
-
);
|
|
149
|
-
if (byOp.length) row8Pool = byOp;
|
|
147
|
+
if (!expected.length || !ctx.correlationId) {
|
|
148
|
+
return row8Pool;
|
|
150
149
|
}
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
expectedOperations: ctx.expectedOperations
|
|
157
|
-
})
|
|
150
|
+
const byOp = await fetchCorrelationExecutionsByOperation(
|
|
151
|
+
dataplaneUrl,
|
|
152
|
+
authConfig,
|
|
153
|
+
ctx.correlationId,
|
|
154
|
+
expected
|
|
158
155
|
);
|
|
156
|
+
return byOp.length ? byOp : row8Pool;
|
|
157
|
+
}
|
|
159
158
|
|
|
159
|
+
/**
|
|
160
|
+
* @param {Object} ctx
|
|
161
|
+
* @param {string[]} execIds
|
|
162
|
+
* @returns {Promise<Set<string>>}
|
|
163
|
+
*/
|
|
164
|
+
async function collectTraceIdsForRow9(ctx, execIds) {
|
|
165
|
+
const { dataplaneUrl, authConfig } = ctx;
|
|
160
166
|
const traceIds = new Set();
|
|
161
|
-
|
|
167
|
+
const sample = execIds.slice(0, Math.min(execIds.length, 12));
|
|
168
|
+
for (const id of sample) {
|
|
162
169
|
try {
|
|
163
170
|
const tr = await getExecutionTrace(dataplaneUrl, authConfig, id);
|
|
164
171
|
if (tr && tr.executionId) traceIds.add(String(tr.executionId));
|
|
@@ -167,7 +174,28 @@ async function buildPerExecutionAndTailRows(ctx, executions, executionIds) {
|
|
|
167
174
|
/* row 9 may fail */
|
|
168
175
|
}
|
|
169
176
|
}
|
|
170
|
-
|
|
177
|
+
return traceIds;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @param {Object} ctx
|
|
182
|
+
* @param {Array} executions
|
|
183
|
+
* @param {string[]} executionIds
|
|
184
|
+
* @returns {Promise<{ rows: import('../api/types/audit.types').AuditEvidenceMatrixRow[], execIds: string[] }>}
|
|
185
|
+
*/
|
|
186
|
+
async function buildPerExecutionAndTailRows(ctx, executions, executionIds) {
|
|
187
|
+
const execIds = resolveExecutionIdsForChecks(executions, executionIds);
|
|
188
|
+
const rows = await buildPerExecutionSubRows(ctx, execIds);
|
|
189
|
+
const row8Pool = await resolveRow8PoolForMatrix(ctx, executions);
|
|
190
|
+
const row8Executions = resolveRow8Executions(ctx, executions, row8Pool);
|
|
191
|
+
rows.push(
|
|
192
|
+
checkRow8CorrelationGroup({
|
|
193
|
+
correlationId: ctx.correlationId,
|
|
194
|
+
executions: row8Executions,
|
|
195
|
+
expectedOperations: ctx.expectedOperations
|
|
196
|
+
})
|
|
197
|
+
);
|
|
198
|
+
rows.push(checkRow9Traces(await collectTraceIdsForRow9(ctx, execIds), execIds));
|
|
171
199
|
return { rows, execIds };
|
|
172
200
|
}
|
|
173
201
|
|
|
@@ -34,9 +34,21 @@ function recordBatchFailure(state, index, err, batchRecords) {
|
|
|
34
34
|
* @param {Object[]} batchRecords
|
|
35
35
|
*/
|
|
36
36
|
function recordBatchSuccess(state, index, response, batchRecords) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
if (!response || typeof response !== 'object') {
|
|
38
|
+
throw new Error('Bulk sync returned empty response');
|
|
39
|
+
}
|
|
40
|
+
if (response.success === false) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
response.formattedError ||
|
|
43
|
+
response.error ||
|
|
44
|
+
`Bulk sync failed (HTTP ${response.status || 0})`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
const payload =
|
|
48
|
+
response.data !== undefined && response.data !== null ? response.data : response;
|
|
49
|
+
const inserted = payload.insertedCount || 0;
|
|
50
|
+
const updated = payload.updatedCount || 0;
|
|
51
|
+
const processed = payload.totalProcessed || batchRecords.length;
|
|
40
52
|
const failedInBatch = Math.max(0, batchRecords.length - processed);
|
|
41
53
|
|
|
42
54
|
state.batches.push({
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
const { getConfig } = require('../core/config');
|
|
10
10
|
const { setupIntegrationTestAuth } = require('../external-system/test-auth');
|
|
11
|
+
const { applyLabDataplaneApiKeyBearer } = require('../utils/token-manager');
|
|
11
12
|
const { resolveAppKeyForDatasource } = require('./resolve-app');
|
|
12
13
|
const { getSystemKeyFromAppKey } = require('./integration-context');
|
|
13
14
|
const { loadDatasourceForApp } = require('./unified-validation-run-resolve');
|
|
@@ -62,6 +63,8 @@ async function resolveLoadExportContext(datasourceKey, options = {}) {
|
|
|
62
63
|
dataplaneUrl = auth.dataplaneUrl;
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
authConfig = applyLabDataplaneApiKeyBearer(authConfig);
|
|
67
|
+
|
|
65
68
|
return {
|
|
66
69
|
appKey,
|
|
67
70
|
systemKey,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Remove saved datasource test debug JSON under integration/<app>/logs/.
|
|
3
|
-
* @fileoverview Local cleanup for test / test-integration / test-e2e /
|
|
3
|
+
* @fileoverview Local cleanup for test / test-integration / test-e2e / verify-trust logs
|
|
4
4
|
* @author AI Fabrix Team
|
|
5
5
|
* @version 1.0.0
|
|
6
6
|
*/
|
|
@@ -42,7 +42,7 @@ function matchesLogCleanType(fileName, type) {
|
|
|
42
42
|
return fileName.startsWith('test-integration-');
|
|
43
43
|
}
|
|
44
44
|
if (type === 'e2e') return fileName.startsWith('test-e2e-');
|
|
45
|
-
if (type === 'trust') return fileName.startsWith('
|
|
45
|
+
if (type === 'trust') return fileName.startsWith('verify-trust-');
|
|
46
46
|
return false;
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -59,7 +59,7 @@ function isStructuralTestLogFileName(name) {
|
|
|
59
59
|
if (
|
|
60
60
|
name.startsWith('test-e2e-') ||
|
|
61
61
|
name.startsWith('test-integration-') ||
|
|
62
|
-
name.startsWith('
|
|
62
|
+
name.startsWith('verify-trust-')
|
|
63
63
|
) {
|
|
64
64
|
return false;
|
|
65
65
|
}
|
|
@@ -276,7 +276,7 @@ function logTrustFindingsSection(run) {
|
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
/**
|
|
279
|
-
* Format agent trust log (`datasource
|
|
279
|
+
* Format agent trust log (`datasource verify-trust --debug` → `verify-trust-*.json`).
|
|
280
280
|
* @param {Object} data - Parsed JSON { request, response?, error? }
|
|
281
281
|
* @param {string} [fileName] - Log file name for header
|
|
282
282
|
*/
|
|
@@ -356,7 +356,7 @@ function formatStructuralTestLog(data, fileName) {
|
|
|
356
356
|
/**
|
|
357
357
|
* Format log content by type
|
|
358
358
|
* @param {Object} parsed - Parsed JSON log
|
|
359
|
-
* @param {'test'|'test-e2e'|'test-integration'|'
|
|
359
|
+
* @param {'test'|'test-e2e'|'test-integration'|'verify-trust'} logType - Log type
|
|
360
360
|
* @param {string} [fileName] - File name for header
|
|
361
361
|
*/
|
|
362
362
|
function formatLogContent(parsed, logType, fileName) {
|
|
@@ -364,7 +364,7 @@ function formatLogContent(parsed, logType, fileName) {
|
|
|
364
364
|
formatStructuralTestLog(parsed, fileName);
|
|
365
365
|
return;
|
|
366
366
|
}
|
|
367
|
-
if (logType === '
|
|
367
|
+
if (logType === 'verify-trust') {
|
|
368
368
|
formatTrustLog(parsed, fileName);
|
|
369
369
|
return;
|
|
370
370
|
}
|
|
@@ -410,7 +410,7 @@ function parseDatasourceLogJson(content, logPath) {
|
|
|
410
410
|
* @param {Object} options - Options
|
|
411
411
|
* @param {string} [options.app] - App key (optional, resolved from key if omitted)
|
|
412
412
|
* @param {string} [options.file] - Path to log file (overrides app resolution)
|
|
413
|
-
* @param {'test'|'test-e2e'|'test-integration'|'
|
|
413
|
+
* @param {'test'|'test-e2e'|'test-integration'|'verify-trust'} options.logType - Log type
|
|
414
414
|
* @throws {Error} When file not found or invalid JSON
|
|
415
415
|
*/
|
|
416
416
|
/* eslint-disable-next-line max-statements -- Resolve path, read, parse, format */
|
|
@@ -433,11 +433,11 @@ async function runLogViewer(datasourceKey, options) {
|
|
|
433
433
|
`No structural validation log found in ${logsDir}. Run: aifabrix datasource test <key> --debug`
|
|
434
434
|
);
|
|
435
435
|
}
|
|
436
|
-
} else if (logType === '
|
|
437
|
-
logPath = await getLatestLogPath(logsDir, '
|
|
436
|
+
} else if (logType === 'verify-trust') {
|
|
437
|
+
logPath = await getLatestLogPath(logsDir, 'verify-trust-');
|
|
438
438
|
if (!logPath) {
|
|
439
439
|
throw new Error(
|
|
440
|
-
`No
|
|
440
|
+
`No verify-trust log found in ${logsDir}. Run: aifabrix datasource verify-trust <key> --debug`
|
|
441
441
|
);
|
|
442
442
|
}
|
|
443
443
|
} else {
|
|
@@ -42,8 +42,11 @@ function buildUnifiedE2eRunOptions(options, timeoutMs, pk) {
|
|
|
42
42
|
capabilityKey: options.capabilityKey,
|
|
43
43
|
timeout: timeoutMs,
|
|
44
44
|
sync: options.sync === true,
|
|
45
|
+
force: options.force === true,
|
|
45
46
|
authConfig: options.authConfig,
|
|
46
|
-
dataplaneUrl: options.dataplaneUrl || options.dataplane
|
|
47
|
+
dataplaneUrl: options.dataplaneUrl || options.dataplane,
|
|
48
|
+
quietPollUi: options.quietPollUi === true,
|
|
49
|
+
onPollProgress: options.onPollProgress
|
|
47
50
|
};
|
|
48
51
|
}
|
|
49
52
|
|
|
@@ -10,6 +10,7 @@ const {
|
|
|
10
10
|
includeDebugForRequest
|
|
11
11
|
} = require('../utils/validation-run-request');
|
|
12
12
|
const testHelpers = require('../utils/external-system-test-helpers');
|
|
13
|
+
const { withStageOnValidationRunBody } = require('../utils/validation-run-stage');
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* @param {Object} params
|
|
@@ -52,7 +53,7 @@ async function buildUnifiedValidationBody(params) {
|
|
|
52
53
|
})
|
|
53
54
|
: undefined;
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
const body = buildExternalDataSourceValidationRequest({
|
|
56
57
|
systemKey,
|
|
57
58
|
datasourceKey,
|
|
58
59
|
runType,
|
|
@@ -62,6 +63,7 @@ async function buildUnifiedValidationBody(params) {
|
|
|
62
63
|
explain: options.verbose === true,
|
|
63
64
|
e2eOptions: e2eOptions && Object.keys(e2eOptions).length > 0 ? e2eOptions : undefined
|
|
64
65
|
});
|
|
66
|
+
return withStageOnValidationRunBody(body, runType);
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
module.exports = { buildUnifiedValidationBody };
|
|
@@ -18,6 +18,7 @@ const { buildUnifiedValidationBody } = require('./unified-validation-run-body');
|
|
|
18
18
|
const { postValidationRunAndOptionalPoll } = require('./unified-validation-run-post');
|
|
19
19
|
const { requireBearerForDataplanePipeline } = require('../utils/token-manager');
|
|
20
20
|
const logger = require('../utils/logger');
|
|
21
|
+
const { buildMinimalUploadSyncOptions } = require('../utils/upload-sync-options');
|
|
21
22
|
|
|
22
23
|
function _resourceTypeFromDatasource(datasource) {
|
|
23
24
|
return datasource && typeof datasource === 'object' && typeof datasource.resourceType === 'string'
|
|
@@ -59,7 +60,7 @@ async function maybeSyncDatasourceToDataplane({ options, authConfig, systemKey }
|
|
|
59
60
|
// are updated before validation runs. Datasource-only publish can still fail DP-SEC-013 when the
|
|
60
61
|
// dataplane system permissions[] are stale.
|
|
61
62
|
const { uploadExternalSystem } = require('../commands/upload');
|
|
62
|
-
await uploadExternalSystem(systemKey,
|
|
63
|
+
await uploadExternalSystem(systemKey, buildMinimalUploadSyncOptions(options));
|
|
63
64
|
logger.log(formatSuccessLine('Sync complete'));
|
|
64
65
|
}
|
|
65
66
|
|
|
@@ -139,7 +140,9 @@ async function runUnifiedDatasourceValidation(datasourceKey, options) {
|
|
|
139
140
|
useAsync,
|
|
140
141
|
noAsync: options.noAsync === true || options.async === false,
|
|
141
142
|
verbosePoll: options.verbose === true,
|
|
142
|
-
|
|
143
|
+
quietPollUi: options.quietPollUi === true,
|
|
144
|
+
pollSubject: datasourceKey,
|
|
145
|
+
onPollProgress: options.onPollProgress
|
|
143
146
|
});
|
|
144
147
|
|
|
145
148
|
if (result && result.envelope) {
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Poll helpers for environment deploy status (deployment-by-ID).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Parse pipeline/environments deployment poll responses and fail fast on terminal HTTP errors
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const TERMINAL_POLL_HTTP_STATUSES = new Set([400, 401, 403, 404, 410, 422]);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {Object|null|undefined} response - API client response
|
|
13
|
+
* @returns {boolean}
|
|
14
|
+
*/
|
|
15
|
+
function isTerminalPollApiResponse(response) {
|
|
16
|
+
return Boolean(
|
|
17
|
+
response &&
|
|
18
|
+
response.success === false &&
|
|
19
|
+
typeof response.status === 'number' &&
|
|
20
|
+
TERMINAL_POLL_HTTP_STATUSES.has(response.status)
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {Object|null|undefined} response - Successful API client response
|
|
26
|
+
* @returns {Object|null} Deployment record or null
|
|
27
|
+
*/
|
|
28
|
+
function extractDeploymentRecord(response) {
|
|
29
|
+
if (!response || response.success === false) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
if (response?.data?.data) {
|
|
33
|
+
return response.data.data;
|
|
34
|
+
}
|
|
35
|
+
if (response?.data && typeof response.data === 'object' && response.data.status) {
|
|
36
|
+
return response.data;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {Object|null|undefined} pipelineRes
|
|
43
|
+
* @param {Object|null|undefined} envRes
|
|
44
|
+
* @returns {Error}
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* @param {string} requestedEnvKey
|
|
48
|
+
* @param {Error} error
|
|
49
|
+
* @returns {Error}
|
|
50
|
+
*/
|
|
51
|
+
function enrichPollTerminalError(requestedEnvKey, error) {
|
|
52
|
+
if (!error?.pollTerminal || error.status !== 404) {
|
|
53
|
+
return error;
|
|
54
|
+
}
|
|
55
|
+
const base = error.message || '';
|
|
56
|
+
if (!base.includes('Environment with key')) {
|
|
57
|
+
return error;
|
|
58
|
+
}
|
|
59
|
+
error.message =
|
|
60
|
+
`${base}\n\n` +
|
|
61
|
+
'The deployment may have been created under a different environment key ' +
|
|
62
|
+
'(for example evaluation-mode fallback to miso). Check controller logs for ' +
|
|
63
|
+
`effectiveEnvironmentKey, register '${requestedEnvKey}' in the controller, or run ` +
|
|
64
|
+
'aifabrix env deploy miso.';
|
|
65
|
+
return error;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function buildPollStatusError(pipelineRes, envRes) {
|
|
69
|
+
const terminal = [pipelineRes, envRes].filter(isTerminalPollApiResponse);
|
|
70
|
+
const source = terminal[0] || pipelineRes || envRes;
|
|
71
|
+
const message = source?.formattedError || source?.error || 'Unable to retrieve deployment status';
|
|
72
|
+
const err = new Error(message);
|
|
73
|
+
err.pollTerminal = true;
|
|
74
|
+
if (typeof source?.status === 'number') {
|
|
75
|
+
err.status = source.status;
|
|
76
|
+
}
|
|
77
|
+
return err;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Fetches deployment status by ID (pipeline endpoint first, then environments).
|
|
82
|
+
*
|
|
83
|
+
* @async
|
|
84
|
+
* @param {Function} getPipelineDeployment - pipeline.api getPipelineDeployment
|
|
85
|
+
* @param {Function} getDeployment - deployments.api getDeployment
|
|
86
|
+
* @param {string} controllerUrl
|
|
87
|
+
* @param {string} envKey
|
|
88
|
+
* @param {string} deploymentId
|
|
89
|
+
* @param {Object} apiAuthConfig
|
|
90
|
+
* @returns {Promise<Object|null>} Deployment record or null when status is not yet available (retry)
|
|
91
|
+
* @throws {Error} When both endpoints return a terminal HTTP error (e.g. environment not found)
|
|
92
|
+
*/
|
|
93
|
+
async function fetchDeploymentStatusById(
|
|
94
|
+
getPipelineDeployment,
|
|
95
|
+
getDeployment,
|
|
96
|
+
controllerUrl,
|
|
97
|
+
envKey,
|
|
98
|
+
deploymentId,
|
|
99
|
+
apiAuthConfig
|
|
100
|
+
) {
|
|
101
|
+
let pipelineRes;
|
|
102
|
+
let envRes;
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
pipelineRes = await getPipelineDeployment(controllerUrl, envKey, deploymentId, apiAuthConfig);
|
|
106
|
+
const fromPipeline = extractDeploymentRecord(pipelineRes);
|
|
107
|
+
if (fromPipeline) {
|
|
108
|
+
return fromPipeline;
|
|
109
|
+
}
|
|
110
|
+
} catch (err) {
|
|
111
|
+
pipelineRes = { success: false, error: err?.message || String(err) };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
envRes = await getDeployment(controllerUrl, envKey, deploymentId, apiAuthConfig);
|
|
116
|
+
const fromEnv = extractDeploymentRecord(envRes);
|
|
117
|
+
if (fromEnv) {
|
|
118
|
+
return fromEnv;
|
|
119
|
+
}
|
|
120
|
+
} catch (err) {
|
|
121
|
+
envRes = { success: false, error: err?.message || String(err) };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (isTerminalPollApiResponse(pipelineRes) || isTerminalPollApiResponse(envRes)) {
|
|
125
|
+
throw buildPollStatusError(pipelineRes, envRes);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
module.exports = {
|
|
132
|
+
TERMINAL_POLL_HTTP_STATUSES,
|
|
133
|
+
isTerminalPollApiResponse,
|
|
134
|
+
extractDeploymentRecord,
|
|
135
|
+
enrichPollTerminalError,
|
|
136
|
+
buildPollStatusError,
|
|
137
|
+
fetchDeploymentStatusById
|
|
138
|
+
};
|
|
@@ -25,6 +25,7 @@ const {
|
|
|
25
25
|
buildEnvironmentConfigFromPreset,
|
|
26
26
|
loadAndValidateEnvironmentDeployConfig
|
|
27
27
|
} = require('./environment-config');
|
|
28
|
+
const { fetchDeploymentStatusById, enrichPollTerminalError } = require('./environment-poll-status');
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Validates environment deployment prerequisites
|
|
@@ -161,31 +162,24 @@ async function sendEnvironmentDeployment(controllerUrl, envKey, authConfig, opti
|
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
/**
|
|
164
|
-
* Fetches deployment status by ID (pipeline endpoint first, then environments)
|
|
165
|
-
* Mirrors miso-controller manual test: GET pipeline/deployments/:id then GET environments/deployments/:id
|
|
165
|
+
* Fetches deployment status by ID (pipeline endpoint first, then environments).
|
|
166
166
|
* @async
|
|
167
167
|
* @param {string} controllerUrl - Controller URL
|
|
168
168
|
* @param {string} envKey - Environment key
|
|
169
169
|
* @param {string} deploymentId - Deployment ID
|
|
170
170
|
* @param {Object} apiAuthConfig - Auth config { type: 'bearer', token }
|
|
171
|
-
* @returns {Promise<Object|null>} Deployment record
|
|
171
|
+
* @returns {Promise<Object|null>} Deployment record or null when still in progress
|
|
172
|
+
* @throws {Error} On terminal poll errors (e.g. environment or deployment not found)
|
|
172
173
|
*/
|
|
173
174
|
async function getDeploymentStatusById(controllerUrl, envKey, deploymentId, apiAuthConfig) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const envRes = await getDeployment(controllerUrl, envKey, deploymentId, apiAuthConfig);
|
|
183
|
-
if (envRes?.data?.data) return envRes.data.data;
|
|
184
|
-
if (envRes?.data && typeof envRes.data === 'object' && envRes.data.status) return envRes.data;
|
|
185
|
-
} catch {
|
|
186
|
-
// Ignore
|
|
187
|
-
}
|
|
188
|
-
return null;
|
|
175
|
+
return fetchDeploymentStatusById(
|
|
176
|
+
getPipelineDeployment,
|
|
177
|
+
getDeployment,
|
|
178
|
+
controllerUrl,
|
|
179
|
+
envKey,
|
|
180
|
+
deploymentId,
|
|
181
|
+
apiAuthConfig
|
|
182
|
+
);
|
|
189
183
|
}
|
|
190
184
|
|
|
191
185
|
/**
|
|
@@ -218,6 +212,33 @@ function processDeploymentStatusResponse(deployment, validatedEnvKey) {
|
|
|
218
212
|
return null;
|
|
219
213
|
}
|
|
220
214
|
|
|
215
|
+
/**
|
|
216
|
+
* @param {number} attempt
|
|
217
|
+
* @param {number} maxAttempts
|
|
218
|
+
* @param {Object|null} deployment
|
|
219
|
+
*/
|
|
220
|
+
function logPollAttemptProgress(attempt, maxAttempts, deployment) {
|
|
221
|
+
const progress = deployment?.progress ?? 0;
|
|
222
|
+
const statusLabel = deployment?.status ?? 'pending';
|
|
223
|
+
logger.log(chalk.gray(` Attempt ${attempt}/${maxAttempts}... Status: ${statusLabel} (${progress}%)`));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @param {Error} error
|
|
228
|
+
* @param {string} validatedEnvKey
|
|
229
|
+
* @throws {Error}
|
|
230
|
+
*/
|
|
231
|
+
function handlePollIterationError(error, validatedEnvKey) {
|
|
232
|
+
const msg = error?.message || '';
|
|
233
|
+
const isDeploymentFailed =
|
|
234
|
+
msg.includes('Environment deployment failed') ||
|
|
235
|
+
(msg.includes('failed') && !error.pollTerminal);
|
|
236
|
+
if (error.pollTerminal || isDeploymentFailed) {
|
|
237
|
+
throw enrichPollTerminalError(validatedEnvKey, error);
|
|
238
|
+
}
|
|
239
|
+
logger.log(chalk.yellow(` ⚠ Status check failed (will retry): ${msg}`));
|
|
240
|
+
}
|
|
241
|
+
|
|
221
242
|
/**
|
|
222
243
|
* Polls environment deployment status
|
|
223
244
|
* @async
|
|
@@ -231,44 +252,31 @@ function processDeploymentStatusResponse(deployment, validatedEnvKey) {
|
|
|
231
252
|
async function pollEnvironmentStatus(deploymentId, controllerUrl, envKey, authConfig, options = {}) {
|
|
232
253
|
const validatedUrl = validateControllerUrl(controllerUrl);
|
|
233
254
|
const validatedEnvKey = validateEnvironmentKey(envKey);
|
|
234
|
-
|
|
235
255
|
const pollInterval = options.pollInterval || 5000;
|
|
236
256
|
const maxAttempts = options.maxAttempts || 60;
|
|
257
|
+
const apiAuthConfig = { type: 'bearer', token: authConfig.token };
|
|
237
258
|
|
|
238
259
|
logger.log(chalk.blue(`⏳ Polling environment status (${pollInterval}ms intervals)...`));
|
|
239
260
|
|
|
240
|
-
// Use centralized API client
|
|
241
|
-
const apiAuthConfig = { type: 'bearer', token: authConfig.token };
|
|
242
|
-
|
|
243
261
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
244
262
|
try {
|
|
245
263
|
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
246
|
-
|
|
247
264
|
const deployment = await getDeploymentStatusById(
|
|
248
265
|
validatedUrl,
|
|
249
266
|
validatedEnvKey,
|
|
250
267
|
deploymentId,
|
|
251
268
|
apiAuthConfig
|
|
252
269
|
);
|
|
253
|
-
|
|
254
|
-
const statusLabel = deployment?.status ?? 'pending';
|
|
255
|
-
if (attempt <= maxAttempts) {
|
|
256
|
-
logger.log(chalk.gray(` Attempt ${attempt}/${maxAttempts}... Status: ${statusLabel} (${progress}%)`));
|
|
257
|
-
}
|
|
270
|
+
logPollAttemptProgress(attempt, maxAttempts, deployment);
|
|
258
271
|
const statusResult = processDeploymentStatusResponse(deployment, validatedEnvKey);
|
|
259
272
|
if (statusResult) {
|
|
260
273
|
return statusResult;
|
|
261
274
|
}
|
|
262
275
|
} catch (error) {
|
|
263
|
-
|
|
264
|
-
if (error.message && error.message.includes('failed')) {
|
|
265
|
-
throw error;
|
|
266
|
-
}
|
|
267
|
-
// Otherwise, continue polling
|
|
276
|
+
handlePollIterationError(error, validatedEnvKey);
|
|
268
277
|
}
|
|
269
278
|
}
|
|
270
279
|
|
|
271
|
-
// Timeout
|
|
272
280
|
throw new Error(`Environment deployment timeout after ${maxAttempts} attempts. Check controller logs for status.`);
|
|
273
281
|
}
|
|
274
282
|
|
|
@@ -437,30 +437,24 @@ function logDownloadCommandHeader(systemKey) {
|
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
/**
|
|
440
|
-
* Downloads external system from dataplane to local development structure
|
|
440
|
+
* Downloads external system from dataplane to local development structure.
|
|
441
441
|
* @async
|
|
442
|
-
* @
|
|
443
|
-
* @param {
|
|
444
|
-
* @
|
|
445
|
-
* @param {string} [options.format] - Output format: 'yaml' (default) or 'json' (runs convert after split)
|
|
446
|
-
* @param {string} [options.environment] - Environment (dev, tst, pro)
|
|
447
|
-
* @param {string} [options.controller] - Controller URL
|
|
448
|
-
* @param {boolean} [options.dryRun] - Show what would be downloaded without actually downloading
|
|
449
|
-
* @param {boolean} [options.force] - Overwrite existing README.md without prompting
|
|
450
|
-
* @returns {Promise<void>} Resolves when download completes
|
|
451
|
-
* @throws {Error} If download fails
|
|
442
|
+
* @param {string} systemKey
|
|
443
|
+
* @param {Object} [options]
|
|
444
|
+
* @returns {Promise<void>}
|
|
452
445
|
*/
|
|
453
446
|
async function downloadExternalSystem(systemKey, options = {}) {
|
|
454
447
|
validateSystemKeyFormat(systemKey);
|
|
455
|
-
|
|
456
448
|
const format = (options.format || 'yaml').toLowerCase();
|
|
457
449
|
|
|
458
450
|
try {
|
|
459
451
|
logDownloadCommandHeader(systemKey);
|
|
460
|
-
|
|
461
452
|
const config = await getConfig();
|
|
462
|
-
const { authConfig, dataplaneUrl } = await setupAuthenticationAndDataplane(
|
|
463
|
-
|
|
453
|
+
const { authConfig, dataplaneUrl } = await setupAuthenticationAndDataplane(
|
|
454
|
+
systemKey,
|
|
455
|
+
options,
|
|
456
|
+
config
|
|
457
|
+
);
|
|
464
458
|
if (options.dryRun) {
|
|
465
459
|
handleDryRun(systemKey, dataplaneUrl);
|
|
466
460
|
return;
|
|
@@ -468,15 +462,22 @@ async function downloadExternalSystem(systemKey, options = {}) {
|
|
|
468
462
|
|
|
469
463
|
const manifest = await downloadFullManifest(dataplaneUrl, systemKey, authConfig);
|
|
470
464
|
validateAndLogDownloadedData(manifest.application, manifest.dataSources);
|
|
471
|
-
|
|
472
465
|
const finalPath = getIntegrationPath(systemKey);
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
466
|
+
await processDownloadedSystem(
|
|
467
|
+
systemKey,
|
|
468
|
+
manifest,
|
|
469
|
+
await resolveDownloadSplitOptions(finalPath, options)
|
|
470
|
+
);
|
|
471
|
+
const { downloadGovernanceScenarioPacksFromManifest } = require('../lifecycle/scenario-upload');
|
|
472
|
+
await downloadGovernanceScenarioPacksFromManifest(
|
|
473
|
+
systemKey,
|
|
474
|
+
manifest,
|
|
475
|
+
dataplaneUrl,
|
|
476
|
+
authConfig
|
|
477
|
+
);
|
|
476
478
|
if (format === 'json') {
|
|
477
479
|
await runConvertToJsonIfRequested(systemKey);
|
|
478
480
|
}
|
|
479
|
-
|
|
480
481
|
displayDownloadSuccess(systemKey, finalPath, manifest.dataSources.length);
|
|
481
482
|
} catch (error) {
|
|
482
483
|
throw new Error(`Failed to download external system: ${error.message}`);
|
|
@@ -26,7 +26,7 @@ handlebars.registerHelper('json', (obj) => JSON.stringify(obj));
|
|
|
26
26
|
* Build authentication object per schema authenticationVariablesByMethod.
|
|
27
27
|
* Security values use canonical kv://<systemKey>/<segment> paths (segment from getKvPathSegmentForSecurityKey).
|
|
28
28
|
* @param {string} systemKey - External system key
|
|
29
|
-
* @param {string} authType - Auth method (oauth2, aad, apikey, basic, queryParam, oidc, hmac, none)
|
|
29
|
+
* @param {string} authType - Auth method (oauth2, aad, apikey, bearerToken, basic, queryParam, oidc, hmac, none)
|
|
30
30
|
* @returns {{ method: string, variables: Object, security: Object }} Authentication object
|
|
31
31
|
*/
|
|
32
32
|
function buildAuthenticationFromMethod(systemKey, authType) {
|
|
@@ -50,6 +50,10 @@ function buildAuthenticationFromMethod(systemKey, authType) {
|
|
|
50
50
|
variables: { baseUrl: base, headerName: 'X-API-Key' },
|
|
51
51
|
security: { apiKey: kvPath('apiKey') }
|
|
52
52
|
},
|
|
53
|
+
bearerToken: {
|
|
54
|
+
variables: { baseUrl: base, headerName: 'Authorization', prefix: 'Bearer' },
|
|
55
|
+
security: { token: kvPath('token') }
|
|
56
|
+
},
|
|
53
57
|
basic: {
|
|
54
58
|
variables: { baseUrl: base },
|
|
55
59
|
security: { username: kvPath('username'), password: kvPath('password') }
|