@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
|
@@ -14,9 +14,28 @@ const fs = require('fs').promises;
|
|
|
14
14
|
const fsSync = require('fs');
|
|
15
15
|
const pathsUtil = require('../utils/paths');
|
|
16
16
|
const adminSecrets = require('../core/admin-secrets');
|
|
17
|
+
const config = require('../core/config');
|
|
17
18
|
const secretsEnsure = require('../core/secrets-ensure');
|
|
18
19
|
const secretsEnvWrite = require('../core/secrets-env-write');
|
|
19
20
|
const { getContainerPort } = require('../utils/port-resolver');
|
|
21
|
+
const { applyAdminSecretsPlatformOverlay } = require('../core/admin-secrets-env-overlay');
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Merge app env with admin-secrets; overlay ensures platform keys come from admin file.
|
|
25
|
+
* @param {Object.<string, string>} merged
|
|
26
|
+
* @param {Object.<string, string>} adminObj
|
|
27
|
+
*/
|
|
28
|
+
function mergeRunEnvWithAdminOverlay(merged, adminObj) {
|
|
29
|
+
applyAdminSecretsPlatformOverlay(merged, adminObj);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function applyOnboardingPlatformModeIfNeeded(appName, merged) {
|
|
33
|
+
if (appName !== 'miso-controller') {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const mode = await config.getSetupPlatformMode();
|
|
37
|
+
merged.ONBOARDING_FULL_PLATFORM = mode === 'full' ? 'true' : 'false';
|
|
38
|
+
}
|
|
20
39
|
|
|
21
40
|
/**
|
|
22
41
|
* Backfill only secrets needed for `aifabrix run <app>`: kv:// keys from that app's env.template
|
|
@@ -194,31 +213,72 @@ async function readPasswordFromPgpassFile(pgpassPath) {
|
|
|
194
213
|
}
|
|
195
214
|
|
|
196
215
|
/**
|
|
197
|
-
* Read POSTGRES_PASSWORD from
|
|
198
|
-
*
|
|
199
|
-
*
|
|
216
|
+
* Read POSTGRES_PASSWORD from pgpass-style files beside the active infra compose
|
|
217
|
+
* (`resolveInfraStatePaths()`). Tries legacy `pgpass`, then `.pgpass.bootstrap` written at `up-infra`
|
|
218
|
+
* so db-init matches the password Postgres was started with when admin-secrets later drifted.
|
|
200
219
|
* @param {number|string} developerId - Developer ID
|
|
201
220
|
* @returns {Promise<string|undefined>} Password or undefined
|
|
202
221
|
*/
|
|
203
222
|
async function readPostgresPasswordFromPgpass(developerId) {
|
|
204
|
-
const { resolveInfraStatePaths } = require('../infrastructure/helpers');
|
|
223
|
+
const { resolveInfraStatePaths, PGPASS_BOOTSTRAP_BASENAME } = require('../infrastructure/helpers');
|
|
205
224
|
const { infraDir } = resolveInfraStatePaths(developerId);
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
225
|
+
const candidates = ['pgpass', PGPASS_BOOTSTRAP_BASENAME];
|
|
226
|
+
for (const name of candidates) {
|
|
227
|
+
const pgpassPath = path.join(infraDir, name);
|
|
228
|
+
if (!fsSync.existsSync(pgpassPath)) {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
try {
|
|
232
|
+
const pwd = await readPasswordFromPgpassFile(pgpassPath);
|
|
233
|
+
if (pwd !== undefined && pwd !== '') {
|
|
234
|
+
return pwd;
|
|
235
|
+
}
|
|
236
|
+
} catch {
|
|
237
|
+
// try next candidate
|
|
238
|
+
}
|
|
215
239
|
}
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* @returns {Function}
|
|
245
|
+
*/
|
|
246
|
+
function resolveEnsureAdminSecretsFn() {
|
|
247
|
+
const infra = require('../infrastructure');
|
|
248
|
+
return typeof infra.ensureAdminSecrets === 'function'
|
|
249
|
+
? infra.ensureAdminSecrets
|
|
250
|
+
: require('../infrastructure/helpers').ensureAdminSecrets;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* @param {Object} merged
|
|
255
|
+
* @param {number|string|undefined} developerId
|
|
256
|
+
* @returns {Promise<void>}
|
|
257
|
+
*/
|
|
258
|
+
async function applyPostgresPasswordFromPgpass(merged, developerId) {
|
|
259
|
+
if (developerId === undefined) return;
|
|
260
|
+
const pgpassPwd = await readPostgresPasswordFromPgpass(developerId);
|
|
261
|
+
if (pgpassPwd !== undefined) merged.POSTGRES_PASSWORD = pgpassPwd;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* @param {string} runEnvPath
|
|
266
|
+
* @param {string} runEnvAdminPath
|
|
267
|
+
* @param {Object} appOnly
|
|
268
|
+
* @param {Object} dbInitOnly
|
|
269
|
+
* @returns {Promise<void>}
|
|
270
|
+
*/
|
|
271
|
+
async function writeRunEnvFiles(runEnvPath, runEnvAdminPath, appOnly, dbInitOnly) {
|
|
272
|
+
const toContent = adminSecrets.envObjectToContent;
|
|
273
|
+
await fs.writeFile(runEnvPath, toContent(appOnly), { mode: 0o600 });
|
|
274
|
+
await fs.writeFile(runEnvAdminPath, toContent(dbInitOnly), { mode: 0o600 });
|
|
216
275
|
}
|
|
217
276
|
|
|
218
277
|
/**
|
|
219
278
|
* Build two run env files: .env.run (app-only, no admin secrets) and .env.run.admin (start-only, for db-init).
|
|
220
279
|
* Admin password is never set in the app container; .env.run.admin is used only for start and then deleted.
|
|
221
|
-
* When `pgpass` exists beside the active infra compose, POSTGRES_PASSWORD is taken
|
|
280
|
+
* When `pgpass` or `.pgpass.bootstrap` exists beside the active infra compose, POSTGRES_PASSWORD is taken
|
|
281
|
+
* from it so db-init matches Postgres.
|
|
222
282
|
* @async
|
|
223
283
|
* @param {string} appName - Application name
|
|
224
284
|
* @param {Object} appConfig - Application configuration
|
|
@@ -227,12 +287,8 @@ async function readPostgresPasswordFromPgpass(developerId) {
|
|
|
227
287
|
* @returns {Promise<{ runEnvPath: string, runEnvAdminPath: string }>} Paths to .env.run and .env.run.admin
|
|
228
288
|
*/
|
|
229
289
|
async function buildMergedRunEnvAndWrite(appName, appConfig, devDir, developerId, scopeOpts = null) {
|
|
230
|
-
const infra = require('../infrastructure');
|
|
231
|
-
const ensureAdminSecretsFn = typeof infra.ensureAdminSecrets === 'function'
|
|
232
|
-
? infra.ensureAdminSecrets
|
|
233
|
-
: require('../infrastructure/helpers').ensureAdminSecrets;
|
|
234
290
|
await ensureRunSecretsForApp(appName);
|
|
235
|
-
await
|
|
291
|
+
await resolveEnsureAdminSecretsFn()();
|
|
236
292
|
const adminObj = await adminSecrets.readAndDecryptAdminSecrets();
|
|
237
293
|
const runEnvKey = scopeOpts && scopeOpts.runEnvKey ? String(scopeOpts.runEnvKey).toLowerCase() : 'dev';
|
|
238
294
|
const appObj = await secretsEnvWrite.resolveAndGetEnvMap(appName, {
|
|
@@ -242,22 +298,20 @@ async function buildMergedRunEnvAndWrite(appName, appConfig, devDir, developerId
|
|
|
242
298
|
runEnvKey
|
|
243
299
|
});
|
|
244
300
|
const merged = { ...adminObj, ...appObj };
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
301
|
+
mergeRunEnvWithAdminOverlay(merged, adminObj);
|
|
302
|
+
await applyOnboardingPlatformModeIfNeeded(appName, merged);
|
|
303
|
+
await applyPostgresPasswordFromPgpass(merged, developerId);
|
|
249
304
|
injectDatabaseNamesAndUsers(merged, appConfig, scopeOpts);
|
|
250
305
|
injectContainerPortForRun(merged, appConfig, appName);
|
|
251
306
|
|
|
252
307
|
const runEnvPath = path.join(devDir, '.env.run');
|
|
253
308
|
const runEnvAdminPath = path.join(devDir, '.env.run.admin');
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
309
|
+
await writeRunEnvFiles(
|
|
310
|
+
runEnvPath,
|
|
311
|
+
runEnvAdminPath,
|
|
312
|
+
buildAppOnlyEnv(merged),
|
|
313
|
+
buildDbInitOnlyEnv(merged)
|
|
314
|
+
);
|
|
261
315
|
return { runEnvPath, runEnvAdminPath };
|
|
262
316
|
}
|
|
263
317
|
|
package/lib/build/index.js
CHANGED
|
@@ -401,6 +401,11 @@ async function resolveDockerBuildArgsForApp(appName) {
|
|
|
401
401
|
for (const [k, v] of Object.entries(bashOverlay)) {
|
|
402
402
|
if (v && buildArgs[k] === undefined) buildArgs[k] = v;
|
|
403
403
|
}
|
|
404
|
+
// Exported shell tokens win (local dev: export NPM_TOKEN=... before af build / docker build).
|
|
405
|
+
const shellNpm = typeof process.env.NPM_TOKEN === 'string' ? process.env.NPM_TOKEN.trim() : '';
|
|
406
|
+
const shellPypi = typeof process.env.PYPI_TOKEN === 'string' ? process.env.PYPI_TOKEN.trim() : '';
|
|
407
|
+
if (shellNpm) buildArgs.NPM_TOKEN = shellNpm;
|
|
408
|
+
if (shellPypi) buildArgs.PYPI_TOKEN = shellPypi;
|
|
404
409
|
return buildArgs;
|
|
405
410
|
}
|
|
406
411
|
|
|
@@ -211,7 +211,8 @@ async function maybeSyncSystemCertificationFromDataplane(params) {
|
|
|
211
211
|
authConfig,
|
|
212
212
|
datasourceKeys,
|
|
213
213
|
issuanceFailureHint,
|
|
214
|
-
verboseCertHints
|
|
214
|
+
verboseCertHints,
|
|
215
|
+
silent
|
|
215
216
|
} = params;
|
|
216
217
|
if (noCertSync === true) return;
|
|
217
218
|
try {
|
|
@@ -224,14 +225,20 @@ async function maybeSyncSystemCertificationFromDataplane(params) {
|
|
|
224
225
|
verboseCertHints
|
|
225
226
|
});
|
|
226
227
|
if (r.written) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
if (silent !== true) {
|
|
229
|
+
logger.log(
|
|
230
|
+
chalk.gray(`Updated certification block from dataplane${label ? ` (${label})` : ''} in system file.`)
|
|
231
|
+
);
|
|
232
|
+
}
|
|
230
233
|
} else if (r.reason) {
|
|
231
|
-
|
|
234
|
+
if (silent !== true) {
|
|
235
|
+
logCertificationSyncNotWritten(r, label, verboseCertHints === true);
|
|
236
|
+
}
|
|
232
237
|
}
|
|
233
238
|
} catch (e) {
|
|
234
|
-
|
|
239
|
+
if (silent !== true) {
|
|
240
|
+
logger.log(chalk.yellow(`⚠ Certification sync skipped: ${e.message}`));
|
|
241
|
+
}
|
|
235
242
|
}
|
|
236
243
|
}
|
|
237
244
|
|
package/lib/cli/index.js
CHANGED
|
@@ -27,6 +27,8 @@ const { setupProtectionCommands } = require('../commands/protection');
|
|
|
27
27
|
const { setupCredentialDeploymentCommands } = require('./setup-credential-deployment');
|
|
28
28
|
const { setupIntegrationClientCommands } = require('./setup-integration-client');
|
|
29
29
|
const { setupPlatformCommands } = require('./setup-platform');
|
|
30
|
+
const { setupCertificationCommands } = require('./setup-certification-commands');
|
|
31
|
+
const { setupGovernanceCommands } = require('../commands/governance');
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
34
|
* Sets up all CLI commands on the Commander program instance
|
|
@@ -36,6 +38,8 @@ function setupCommands(program) {
|
|
|
36
38
|
setupInfraCommands(program);
|
|
37
39
|
setupAuthCommands(program);
|
|
38
40
|
setupAppCommands(program);
|
|
41
|
+
setupCertificationCommands(program);
|
|
42
|
+
setupGovernanceCommands(program);
|
|
39
43
|
setupEnvironmentCommands(program);
|
|
40
44
|
setupAppManagementCommands(program);
|
|
41
45
|
setupDatasourceCommands(program);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guided platform install authentication (device login URL + Dataplane recovery).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Auth helpers for infra-guided up-platform / setup
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const logger = require('../utils/logger');
|
|
13
|
+
const config = require('../core/config');
|
|
14
|
+
const { resolvePlatformControllerUrl } = require('../utils/platform-controller-url');
|
|
15
|
+
const { withMutedLogger } = require('../utils/with-muted-logger');
|
|
16
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
17
|
+
const { isAuthenticationError } = require('../utils/cli-utils');
|
|
18
|
+
const { resolveControllerUrl, isPlatformAuthValidForController } = require('../utils/controller-url');
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {Object} authOpts
|
|
22
|
+
* @returns {Promise<string>}
|
|
23
|
+
*/
|
|
24
|
+
async function resolveGuidedAuthControllerUrl(authOpts = {}) {
|
|
25
|
+
return (
|
|
26
|
+
authOpts.platformControllerUrl ||
|
|
27
|
+
(await config.getPlatformControllerUrl()) ||
|
|
28
|
+
(await resolvePlatformControllerUrl())
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @async
|
|
34
|
+
* @param {Function} handleLoginFn
|
|
35
|
+
* @param {string} controllerUrl
|
|
36
|
+
* @param {{ skipDataplaneVersionRefresh?: boolean }} [opts]
|
|
37
|
+
* @returns {Promise<void>}
|
|
38
|
+
*/
|
|
39
|
+
async function runGuidedDeviceLogin(handleLoginFn, controllerUrl, opts = {}) {
|
|
40
|
+
await handleLoginFn({
|
|
41
|
+
method: 'device',
|
|
42
|
+
controller: controllerUrl,
|
|
43
|
+
environment: 'dev',
|
|
44
|
+
compact: true,
|
|
45
|
+
skipDataplaneVersionRefresh: opts.skipDataplaneVersionRefresh === true,
|
|
46
|
+
exitOnFailure: false
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @async
|
|
52
|
+
* @param {Function} handleLoginFn
|
|
53
|
+
* @param {Object} authOpts
|
|
54
|
+
* @param {{ startSpinner: Function, stopSpinnerSuccess: Function }} spinners
|
|
55
|
+
* @returns {Promise<void>}
|
|
56
|
+
*/
|
|
57
|
+
async function runGuidedAuthStep(handleLoginFn, authOpts, spinners) {
|
|
58
|
+
const spin = spinners.startSpinner('Authenticating...');
|
|
59
|
+
const controllerUrl = await resolveGuidedAuthControllerUrl(authOpts);
|
|
60
|
+
const skipLogin =
|
|
61
|
+
authOpts.skipLoginIfAuthenticated === true ||
|
|
62
|
+
(await isPlatformAuthValidForController(controllerUrl));
|
|
63
|
+
try {
|
|
64
|
+
if (skipLogin) {
|
|
65
|
+
spinners.stopSpinnerSuccess(spin, 'Already authenticated');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
await runGuidedDeviceLogin(handleLoginFn, controllerUrl, { skipDataplaneVersionRefresh: true });
|
|
69
|
+
} catch (authErr) {
|
|
70
|
+
if (spin) spin.fail('Authentication required');
|
|
71
|
+
logger.error(formatBlockingError('Authentication required. Complete sign-in in your browser.'));
|
|
72
|
+
await runGuidedDeviceLogin(handleLoginFn, controllerUrl, { skipDataplaneVersionRefresh: true });
|
|
73
|
+
}
|
|
74
|
+
spinners.stopSpinnerSuccess(spin, 'Authenticated');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @async
|
|
79
|
+
* @param {Object} options
|
|
80
|
+
* @param {Function} handleUpDataplane
|
|
81
|
+
* @param {Function} handleLoginFn
|
|
82
|
+
* @param {string} controllerUrl
|
|
83
|
+
* @returns {Promise<void>}
|
|
84
|
+
*/
|
|
85
|
+
async function runGuidedDataplaneWithAuthRecovery(options, handleUpDataplane, handleLoginFn, controllerUrl) {
|
|
86
|
+
try {
|
|
87
|
+
await withMutedLogger(() =>
|
|
88
|
+
handleUpDataplane({ ...options, platformInstall: true, skipInfraCheck: true })
|
|
89
|
+
);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (!isAuthenticationError(error)) {
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
const loginUrl = error.controllerUrl || controllerUrl || (await resolveControllerUrl());
|
|
95
|
+
logger.log('');
|
|
96
|
+
logger.log(chalk.yellow('Device login required to register and deploy Dataplane.'));
|
|
97
|
+
await runGuidedDeviceLogin(handleLoginFn, loginUrl, { skipDataplaneVersionRefresh: false });
|
|
98
|
+
await withMutedLogger(() =>
|
|
99
|
+
handleUpDataplane({ ...options, platformInstall: true, skipInfraCheck: true })
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = {
|
|
105
|
+
resolveGuidedAuthControllerUrl,
|
|
106
|
+
runGuidedDeviceLogin,
|
|
107
|
+
runGuidedAuthStep,
|
|
108
|
+
runGuidedDataplaneWithAuthRecovery
|
|
109
|
+
};
|
package/lib/cli/infra-guided.js
CHANGED
|
@@ -10,16 +10,19 @@ const config = require('../core/config');
|
|
|
10
10
|
const devConfig = require('../utils/dev-config');
|
|
11
11
|
const pathsUtil = require('../utils/paths');
|
|
12
12
|
const { loadConfigFile } = require('../utils/config-format');
|
|
13
|
-
const {
|
|
13
|
+
const { computeAppBaseUrl, resolvePlatformControllerUrl } = require('../utils/platform-controller-url');
|
|
14
14
|
const { withMutedLogger } = require('../utils/with-muted-logger');
|
|
15
|
-
const {
|
|
16
|
-
const { computePublicUrlBaseString } = require('../utils/url-declarative-public-base');
|
|
17
|
-
const { joinUrlPath, normalizeFrontDoorPatternForHealth } = require('../utils/health-check-url');
|
|
15
|
+
const { formatProgress, formatSuccessLine, successGlyph } = require('../utils/cli-test-layout-chalk');
|
|
18
16
|
const ora = require('ora');
|
|
19
17
|
const infra = require('../infrastructure');
|
|
20
18
|
const { execWithDockerEnv } = require('../utils/docker-exec');
|
|
21
19
|
const { getLogLevel, passesLevelFilter } = require('../commands/app-logs');
|
|
22
20
|
const { handleLogin } = require('../commands/login');
|
|
21
|
+
const {
|
|
22
|
+
resolveGuidedAuthControllerUrl,
|
|
23
|
+
runGuidedAuthStep,
|
|
24
|
+
runGuidedDataplaneWithAuthRecovery
|
|
25
|
+
} = require('./infra-guided-auth');
|
|
23
26
|
const healthCheck = require('../utils/health-check');
|
|
24
27
|
const { prepareUrlsLocalRegistryForUpPlatform } = require('../commands/up-common');
|
|
25
28
|
const { assertDevInfraUp } = require('../commands/dev-infra-gate');
|
|
@@ -126,44 +129,17 @@ function resolveInfraHost(remoteServer) {
|
|
|
126
129
|
}
|
|
127
130
|
}
|
|
128
131
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const infraTlsEnabled = Boolean(userCfg && userCfg.tlsEnabled);
|
|
139
|
-
|
|
140
|
-
const fd = variables.frontDoorRouting || null;
|
|
141
|
-
const frontDoorEnabled = Boolean(fd && fd.enabled === true);
|
|
142
|
-
const traefikOn = Boolean(userCfg && userCfg.traefik);
|
|
143
|
-
const pathActive = Boolean(traefikOn && frontDoorEnabled);
|
|
144
|
-
|
|
145
|
-
const publicBase = computePublicUrlBaseString({
|
|
146
|
-
traefik: traefikOn,
|
|
147
|
-
pathActive,
|
|
148
|
-
hostTemplate: fd ? fd.host : null,
|
|
149
|
-
tls: fd ? fd.tls : true,
|
|
150
|
-
developerIdRaw,
|
|
151
|
-
remoteServer,
|
|
152
|
-
// These guided bootstrap commands start services via Docker Compose, so we want the
|
|
153
|
-
// docker-published host port (no workstation +10 offset).
|
|
154
|
-
profile: 'docker',
|
|
155
|
-
listenPort: basePort,
|
|
156
|
-
developerIdNum,
|
|
157
|
-
infraTlsEnabled
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
if (pathActive) {
|
|
161
|
-
const mount = normalizeFrontDoorPatternForHealth(fd.pattern);
|
|
162
|
-
return joinUrlPath(publicBase, mount);
|
|
132
|
+
/**
|
|
133
|
+
* Prefer stored platform controller URL, then compute from routing rules.
|
|
134
|
+
* @async
|
|
135
|
+
* @returns {Promise<string>}
|
|
136
|
+
*/
|
|
137
|
+
async function resolvePlatformControllerUrlForDisplay() {
|
|
138
|
+
const stored = await config.getPlatformControllerUrl();
|
|
139
|
+
if (stored) {
|
|
140
|
+
return stored;
|
|
163
141
|
}
|
|
164
|
-
|
|
165
|
-
// No Traefik front-door routing: publicBase is localhost + published port unless Traefik/proxy opts into remote.
|
|
166
|
-
return String(publicBase).replace(/\/+$/, '');
|
|
142
|
+
return resolvePlatformControllerUrl();
|
|
167
143
|
}
|
|
168
144
|
|
|
169
145
|
function logSection(label, value) {
|
|
@@ -186,7 +162,7 @@ function logFooterEnd() {
|
|
|
186
162
|
|
|
187
163
|
async function logPlatformReadyFooter() {
|
|
188
164
|
const [controllerUrl, dataplaneUrl, keycloakUrl] = await Promise.all([
|
|
189
|
-
|
|
165
|
+
resolvePlatformControllerUrlForDisplay(),
|
|
190
166
|
computeAppBaseUrl('dataplane'),
|
|
191
167
|
computeAppBaseUrl('keycloak')
|
|
192
168
|
]);
|
|
@@ -206,7 +182,7 @@ async function logPlatformReadyFooter() {
|
|
|
206
182
|
|
|
207
183
|
async function logMisoReadyFooter() {
|
|
208
184
|
const [controllerUrl, keycloakUrl] = await Promise.all([
|
|
209
|
-
|
|
185
|
+
resolvePlatformControllerUrlForDisplay(),
|
|
210
186
|
computeAppBaseUrl('keycloak')
|
|
211
187
|
]);
|
|
212
188
|
logFooterStart('Miso Ready');
|
|
@@ -280,6 +256,8 @@ async function runGuidedUpMiso(options, handleUpMiso) {
|
|
|
280
256
|
logger.log(title('AI Fabrix Platform Setup'));
|
|
281
257
|
logger.log(SEPARATOR);
|
|
282
258
|
logger.log('');
|
|
259
|
+
logPlatformSetupDurationHint('platform');
|
|
260
|
+
logger.log('');
|
|
283
261
|
const kcSpin = startSpinner('Starting Keycloak...');
|
|
284
262
|
await withMutedLogger(() => handleUpMiso({ ...options, platformInstall: true }));
|
|
285
263
|
stopSpinnerSuccess(kcSpin, 'Keycloak ready');
|
|
@@ -291,13 +269,11 @@ async function runGuidedUpMiso(options, handleUpMiso) {
|
|
|
291
269
|
await validateAppErrorLogs(['miso-controller']);
|
|
292
270
|
}
|
|
293
271
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
// Infra must be checked before auth: device login talks to the controller, which needs
|
|
300
|
-
// Postgres/Redis when the controller runs locally — a down infra looks like "network error".
|
|
272
|
+
/**
|
|
273
|
+
* Infra must be checked before auth: device login talks to the controller, which needs
|
|
274
|
+
* Postgres/Redis when the controller runs locally — a down infra looks like "network error".
|
|
275
|
+
*/
|
|
276
|
+
async function assertDevInfraForGuidedDataplane() {
|
|
301
277
|
const infraSpin = startSpinner('Checking infrastructure...');
|
|
302
278
|
try {
|
|
303
279
|
await assertDevInfraUp({ quietSuccess: true });
|
|
@@ -307,11 +283,21 @@ async function runGuidedUpDataplane(options, handleUpDataplane) {
|
|
|
307
283
|
if (infraSpin) infraSpin.stop();
|
|
308
284
|
throw infraErr;
|
|
309
285
|
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
async function runGuidedUpDataplane(options, handleUpDataplane) {
|
|
289
|
+
logger.log('');
|
|
290
|
+
logger.log(title('AI Fabrix Dataplane Setup'));
|
|
291
|
+
logger.log(SEPARATOR);
|
|
292
|
+
logger.log('');
|
|
293
|
+
logPlatformSetupDurationHint('dataplane');
|
|
294
|
+
logger.log('');
|
|
295
|
+
await assertDevInfraForGuidedDataplane();
|
|
310
296
|
// Avoid an outer long-running spinner here: up-dataplane has multiple internal
|
|
311
297
|
// phases and may print some output. An outer spinner causes "spinner over spinner"
|
|
312
298
|
// rendering artifacts. Instead, do the same single auth step as up-platform, then
|
|
313
299
|
// show one spinner for the dataplane install/run phase.
|
|
314
|
-
await runGuidedAuthStep(handleLogin);
|
|
300
|
+
await runGuidedAuthStep(handleLogin, {}, { startSpinner, stopSpinnerSuccess });
|
|
315
301
|
|
|
316
302
|
logger.log('');
|
|
317
303
|
emitSystemBuilderAppManifestLineIfTTY(logger, 'dataplane');
|
|
@@ -331,6 +317,8 @@ async function runGuidedUpDataplane(options, handleUpDataplane) {
|
|
|
331
317
|
* @param {string[]} cleanedApps
|
|
332
318
|
*/
|
|
333
319
|
function logUpPlatformForceCleanSummary(forceSummary, cleanedApps) {
|
|
320
|
+
const { isSetupQuietOutput } = require('../utils/setup-quiet-output');
|
|
321
|
+
if (isSetupQuietOutput()) return;
|
|
334
322
|
const check = successGlyph();
|
|
335
323
|
logger.log(chalk.bold('Clean installation files'));
|
|
336
324
|
logger.log(
|
|
@@ -350,40 +338,31 @@ function logUpPlatformForceCleanSummary(forceSummary, cleanedApps) {
|
|
|
350
338
|
logger.log('');
|
|
351
339
|
}
|
|
352
340
|
|
|
341
|
+
/**
|
|
342
|
+
* Yellow notice before long-running platform/dataplane install steps (setup and guided up-*).
|
|
343
|
+
* @param {'platform'|'dataplane'} [scope]
|
|
344
|
+
*/
|
|
345
|
+
function logPlatformSetupDurationHint(scope = 'platform') {
|
|
346
|
+
const line =
|
|
347
|
+
scope === 'dataplane'
|
|
348
|
+
? 'Installation may take a few minutes. Authenticating and starting Dataplane — please wait.'
|
|
349
|
+
: 'Installation may take a few minutes. Keycloak, Miso Controller, and Dataplane are starting — please wait.';
|
|
350
|
+
logger.log(chalk.yellow(`⚠ ${line}`));
|
|
351
|
+
}
|
|
352
|
+
|
|
353
353
|
function logGuidedPlatformSetupHeader() {
|
|
354
354
|
logger.log('');
|
|
355
355
|
logger.log(title('AI Fabrix Platform Setup'));
|
|
356
356
|
logger.log(SEPARATOR);
|
|
357
|
-
logger.log(chalk.gray('This may take a few minutes...'));
|
|
358
357
|
logger.log('');
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
async function runGuidedAuthStep(handleLogin) {
|
|
362
|
-
const spin = startSpinner('Authenticating...');
|
|
363
|
-
try {
|
|
364
|
-
const controllerUrl = await resolveControllerUrl();
|
|
365
|
-
await handleLogin({
|
|
366
|
-
method: 'device',
|
|
367
|
-
controller: controllerUrl,
|
|
368
|
-
environment: 'dev',
|
|
369
|
-
compact: true,
|
|
370
|
-
// Dataplane is not up yet during guided platform/dataplane install; refresh after it starts.
|
|
371
|
-
skipDataplaneVersionRefresh: true
|
|
372
|
-
});
|
|
373
|
-
} catch (authErr) {
|
|
374
|
-
if (spin) spin.fail('Authentication failed');
|
|
375
|
-
logger.error(formatBlockingError('Authentication failed'));
|
|
376
|
-
logger.log(chalk.gray('\nRun:\n af login\n\nThen retry:\n af up-platform\n'));
|
|
377
|
-
throw authErr;
|
|
378
|
-
}
|
|
379
|
-
// Compact device-login prints "Authentication successful"; close the step spinner cleanly.
|
|
380
|
-
stopSpinnerSuccess(spin, 'Authenticated');
|
|
358
|
+
logPlatformSetupDurationHint('platform');
|
|
359
|
+
logger.log('');
|
|
381
360
|
}
|
|
382
361
|
|
|
383
362
|
async function refreshDataplaneVersionAfterPlatformInstall() {
|
|
384
363
|
try {
|
|
385
364
|
const { tryRefreshDataplaneVersionAfterLogin } = require('../commands/auth-status-dataplane-version');
|
|
386
|
-
const controllerUrl = await
|
|
365
|
+
const controllerUrl = await resolvePlatformControllerUrlForDisplay();
|
|
387
366
|
await tryRefreshDataplaneVersionAfterLogin(controllerUrl, {});
|
|
388
367
|
} catch {
|
|
389
368
|
// best-effort only
|
|
@@ -403,13 +382,25 @@ async function runGuidedKeycloakAndMisoControllerPhase(options, handleUpMiso) {
|
|
|
403
382
|
logger.log('');
|
|
404
383
|
}
|
|
405
384
|
|
|
406
|
-
async function runGuidedDataplaneInstallPhase(options, handleUpDataplane) {
|
|
385
|
+
async function runGuidedDataplaneInstallPhase(options, handleUpDataplane, handleLoginFn, controllerUrl) {
|
|
407
386
|
logger.log('');
|
|
408
387
|
emitSystemBuilderAppManifestLineIfTTY(logger, 'dataplane');
|
|
409
388
|
const dpSpin = startSpinner('Starting Dataplane...');
|
|
410
|
-
await
|
|
411
|
-
|
|
412
|
-
|
|
389
|
+
const platformMode = await config.getSetupPlatformMode();
|
|
390
|
+
if (platformMode === 'full') {
|
|
391
|
+
// Full platform: three dataplane containers + per-env registrations.
|
|
392
|
+
const envKeys = ['pro', 'dev', 'tst'];
|
|
393
|
+
for (const envKey of envKeys) {
|
|
394
|
+
await runGuidedDataplaneWithAuthRecovery(
|
|
395
|
+
{ ...options, envKey, runEnvKey: envKey, allowNonDev: true },
|
|
396
|
+
handleUpDataplane,
|
|
397
|
+
handleLoginFn,
|
|
398
|
+
controllerUrl
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
} else {
|
|
402
|
+
await runGuidedDataplaneWithAuthRecovery(options, handleUpDataplane, handleLoginFn, controllerUrl);
|
|
403
|
+
}
|
|
413
404
|
stopSpinnerSuccess(dpSpin, 'Dataplane ready');
|
|
414
405
|
await refreshDataplaneVersionAfterPlatformInstall();
|
|
415
406
|
}
|
|
@@ -420,10 +411,22 @@ async function runGuidedUpPlatform(options, handleUpMiso, handleUpDataplane, han
|
|
|
420
411
|
logUpPlatformForceCleanSummary(forceCleanSummary.forceSummary, forceCleanSummary.cleanedApps);
|
|
421
412
|
}
|
|
422
413
|
|
|
414
|
+
const authOpts = {
|
|
415
|
+
platformControllerUrl: options && options.platformControllerUrl,
|
|
416
|
+
skipLoginIfAuthenticated: options && options.skipLoginIfAuthenticated === true
|
|
417
|
+
};
|
|
418
|
+
|
|
423
419
|
await withMutedLogger(() => prepareUrlsLocalRegistryForUpPlatform());
|
|
424
420
|
await runGuidedKeycloakAndMisoControllerPhase(options, handleUpMiso);
|
|
425
|
-
|
|
426
|
-
|
|
421
|
+
if (options && options.requireKeycloakRealm === true) {
|
|
422
|
+
const { waitForKeycloakRealmReady } = require('../utils/keycloak-realm-ready');
|
|
423
|
+
const realmSpin = startSpinner('Waiting for Keycloak realm (aifabrix)...');
|
|
424
|
+
await waitForKeycloakRealmReady({ timeoutSeconds: 180 });
|
|
425
|
+
stopSpinnerSuccess(realmSpin, 'Keycloak realm ready');
|
|
426
|
+
}
|
|
427
|
+
await runGuidedAuthStep(handleLogin, authOpts, { startSpinner, stopSpinnerSuccess });
|
|
428
|
+
const controllerUrl = await resolveGuidedAuthControllerUrl(authOpts);
|
|
429
|
+
await runGuidedDataplaneInstallPhase(options, handleUpDataplane, handleLogin, controllerUrl);
|
|
427
430
|
await validateAppErrorLogs(['miso-controller', 'dataplane']);
|
|
428
431
|
await logPlatformReadyFooter();
|
|
429
432
|
}
|
|
@@ -75,41 +75,10 @@ Notes:
|
|
|
75
75
|
- Prefer identity apply over SQL in tests/fixtures/protection/optional-dev-identity-dataplane.sql.
|
|
76
76
|
`;
|
|
77
77
|
|
|
78
|
-
const TEST_GOVERNANCE_HELP_AFTER = `
|
|
79
|
-
Examples:
|
|
80
|
-
# External system — ABAC visibility acceptance (governance scenario pack)
|
|
81
|
-
$ aifabrix test-governance test-protection
|
|
82
|
-
$ aifabrix test-governance test-protection --pack scenarios/test-protection-v1.yaml
|
|
83
|
-
$ aifabrix test-governance test-protection -v --no-sync
|
|
84
|
-
$ aifabrix test-governance test-protection --scenario country-isolation-maria-fi --json
|
|
85
|
-
|
|
86
|
-
Notes:
|
|
87
|
-
- Separate from test-e2e (vendor connectivity). Does not call external vendor APIs.
|
|
88
|
-
- Load baseline fixtures first (datasource load, protection upload) — not auto-run by this command.
|
|
89
|
-
- Default pack: integration/<systemKey>/scenarios/default.yaml or <systemKey>-v1.yaml
|
|
90
|
-
- Requires governance:evaluate on the operator token (see permissions.md).
|
|
91
|
-
`;
|
|
92
|
-
|
|
93
|
-
const TEST_TRUST_HELP_AFTER = `
|
|
94
|
-
Examples:
|
|
95
|
-
# External system — semantic trust for every datasource (dataplane 404.5)
|
|
96
|
-
$ aifabrix test-trust hubspot
|
|
97
|
-
$ aifabrix test-trust hubspot -v --revalidate
|
|
98
|
-
$ aifabrix test-trust hubspot --no-sync
|
|
99
|
-
$ aifabrix test-trust hubspot --summary --timeout 120000
|
|
100
|
-
|
|
101
|
-
Notes:
|
|
102
|
-
- For one datasource: aifabrix datasource test-trust <datasourceKey>
|
|
103
|
-
- Does not call external APIs (use test-e2e for live proof).
|
|
104
|
-
- Local integration files are published before run unless --no-sync.
|
|
105
|
-
`;
|
|
106
|
-
|
|
107
78
|
module.exports = {
|
|
108
79
|
TEST_HELP_AFTER,
|
|
109
80
|
TEST_INTEGRATION_HELP_AFTER,
|
|
110
81
|
TEST_E2E_HELP_AFTER,
|
|
111
|
-
TEST_TRUST_HELP_AFTER,
|
|
112
|
-
TEST_GOVERNANCE_HELP_AFTER,
|
|
113
82
|
IDENTITY_HELP_AFTER
|
|
114
83
|
};
|
|
115
84
|
|