@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
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared verify-governance result builders (breaks governance-verify circular require).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const { verdictFromPassed } = require('../lifecycle/product-model');
|
|
8
|
+
const { primaryDatasourceFromPack } = require('../governance/governance-run-display');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {Array<Object>} rows
|
|
12
|
+
* @returns {{ passed: number, total: number }}
|
|
13
|
+
*/
|
|
14
|
+
function sumEnforcementScenarios(rows) {
|
|
15
|
+
let passed = 0;
|
|
16
|
+
let total = 0;
|
|
17
|
+
for (const row of rows) {
|
|
18
|
+
if (row.scenarios) {
|
|
19
|
+
passed += row.scenarios.passed || 0;
|
|
20
|
+
total += row.scenarios.total || 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return { passed, total };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {Array<Object>} rows
|
|
28
|
+
* @returns {{ policy: number|null, dimension: number|null }}
|
|
29
|
+
*/
|
|
30
|
+
function aggregateCoverage(rows) {
|
|
31
|
+
const policyVals = rows.map(r => r.policyCoveragePercent).filter(v => typeof v === 'number');
|
|
32
|
+
const dimVals = rows.map(r => r.dimensionCoveragePercent).filter(v => typeof v === 'number');
|
|
33
|
+
const minOr100 = vals => (vals.length === 0 ? null : Math.min(...vals));
|
|
34
|
+
return {
|
|
35
|
+
policy: minOr100(policyVals),
|
|
36
|
+
dimension: minOr100(dimVals)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} systemKey
|
|
42
|
+
* @param {{ result: Object, packPath: string, packDocument?: Object }} runPayload
|
|
43
|
+
* @param {string} [commandName]
|
|
44
|
+
* @returns {Object}
|
|
45
|
+
*/
|
|
46
|
+
function buildPackOverrideResult(systemKey, runPayload, commandName = 'verify-governance') {
|
|
47
|
+
const { result, packPath, packDocument } = runPayload;
|
|
48
|
+
const summary = result.summary || {};
|
|
49
|
+
return {
|
|
50
|
+
systemKey,
|
|
51
|
+
command: commandName,
|
|
52
|
+
verdict: verdictFromPassed(summary.failed === 0),
|
|
53
|
+
policyCoveragePercent: 100,
|
|
54
|
+
dimensionCoveragePercent: 100,
|
|
55
|
+
enforcementScenarios: {
|
|
56
|
+
passed: summary.passed || 0,
|
|
57
|
+
total: summary.total || 0
|
|
58
|
+
},
|
|
59
|
+
packPath,
|
|
60
|
+
packDocument,
|
|
61
|
+
packDatasourceKey: primaryDatasourceFromPack(packDocument),
|
|
62
|
+
legacyResult: result,
|
|
63
|
+
datasourceRows: []
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
sumEnforcementScenarios,
|
|
69
|
+
aggregateCoverage,
|
|
70
|
+
buildPackOverrideResult
|
|
71
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CLI action for `aifabrix verify-operations` (plan 150.0).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const logger = require('../utils/logger');
|
|
10
|
+
const { handleCommandError } = require('../utils/cli-utils');
|
|
11
|
+
const { cliOptsSkipSync } = require('../utils/cli-sync-options');
|
|
12
|
+
const { runVerifyOperationsForExternalSystem } = require('./verify-operations-external');
|
|
13
|
+
const { displayVerifyOperationsTTY } = require('../lifecycle/report-display');
|
|
14
|
+
const { exitCodeFromVerdict } = require('../lifecycle/exit-codes');
|
|
15
|
+
const { buildJsonEnvelope } = require('../lifecycle/json-envelope');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {Object} options
|
|
19
|
+
* @param {import('commander').Command} [cmd]
|
|
20
|
+
* @returns {Object}
|
|
21
|
+
*/
|
|
22
|
+
function normalizeVerifyOperationsCliOptions(options, cmd) {
|
|
23
|
+
const raw = cmd && Array.isArray(cmd.rawArgs) ? cmd.rawArgs : [];
|
|
24
|
+
const has = flag => raw.includes(flag);
|
|
25
|
+
return {
|
|
26
|
+
env: options.env || 'dev',
|
|
27
|
+
verbose: options.verbose === true || has('-v') || has('--verbose'),
|
|
28
|
+
debug: options.debug === true || has('-d') || has('--debug'),
|
|
29
|
+
json: options.json === true || has('--json'),
|
|
30
|
+
noSync: cliOptsSkipSync(options, cmd),
|
|
31
|
+
continue: options.continue === true || has('--continue'),
|
|
32
|
+
async: options.async !== false
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function runVerifyOperationsCommandAction(appName, options, cmd) {
|
|
37
|
+
const opts = normalizeVerifyOperationsCliOptions(options, cmd);
|
|
38
|
+
const result = await runVerifyOperationsForExternalSystem(appName, opts);
|
|
39
|
+
|
|
40
|
+
if (opts.json) {
|
|
41
|
+
logger.log(JSON.stringify(buildJsonEnvelope(result, opts.verbose), null, 2));
|
|
42
|
+
} else {
|
|
43
|
+
displayVerifyOperationsTTY(appName, result, {
|
|
44
|
+
details: opts.verbose,
|
|
45
|
+
warnings: result.warnings
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const exitCode = exitCodeFromVerdict(result.verdict);
|
|
50
|
+
if (exitCode !== 0) {
|
|
51
|
+
process.exit(exitCode);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function verifyOperationsCommandHandler(appName, options, cmd) {
|
|
56
|
+
try {
|
|
57
|
+
await runVerifyOperationsCommandAction(appName, options, cmd);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
handleCommandError(error, 'verify-operations');
|
|
60
|
+
process.exit(3);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = {
|
|
65
|
+
normalizeVerifyOperationsCliOptions,
|
|
66
|
+
runVerifyOperationsCommandAction,
|
|
67
|
+
verifyOperationsCommandHandler
|
|
68
|
+
};
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview verify-operations orchestration for external systems (plan 150.0).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { runOperationsVerifySteps } = require('./verify-operations-steps');
|
|
10
|
+
const { persistOperationsForSystem } = require('./verify-operations-persist');
|
|
11
|
+
const {
|
|
12
|
+
VERDICT,
|
|
13
|
+
WARNING_CODES,
|
|
14
|
+
actionHint,
|
|
15
|
+
verdictFromPassed,
|
|
16
|
+
computeOperationalReadinessPercent,
|
|
17
|
+
buildOperationsChecksFromSteps
|
|
18
|
+
} = require('../lifecycle/product-model');
|
|
19
|
+
const { getSystemLifecycleReport } = require('../api/lifecycle.api');
|
|
20
|
+
const {
|
|
21
|
+
extractReadinessMetricsFromLifecycleReport
|
|
22
|
+
} = require('../lifecycle/operations-readiness-metrics');
|
|
23
|
+
const { resolveIntegrationAuth } = require('../external-system/integration-auth-context');
|
|
24
|
+
const { runWithVerifyStepProgress } = require('../lifecycle/verify-step-progress');
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Build grouped details for verbose (-v) output.
|
|
28
|
+
* @param {Record<string, boolean>} checks
|
|
29
|
+
* @returns {Object}
|
|
30
|
+
*/
|
|
31
|
+
function groupOperationsDetails(checks) {
|
|
32
|
+
return {
|
|
33
|
+
connectivity: {
|
|
34
|
+
credentials: checks.credentials,
|
|
35
|
+
authentication: checks.authentication,
|
|
36
|
+
authorization: checks.authorization
|
|
37
|
+
},
|
|
38
|
+
contracts: {
|
|
39
|
+
openApi: checks.openApi,
|
|
40
|
+
mappings: checks.mappings
|
|
41
|
+
},
|
|
42
|
+
runtime: {
|
|
43
|
+
sync: checks.sync,
|
|
44
|
+
crud: checks.crud,
|
|
45
|
+
execution: checks.execution
|
|
46
|
+
},
|
|
47
|
+
reliability: {
|
|
48
|
+
validation: checks.validation,
|
|
49
|
+
unitTests: checks.unitTests,
|
|
50
|
+
integrationTests: checks.integrationTests,
|
|
51
|
+
e2eTests: checks.e2eTests
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @param {string} systemKey
|
|
58
|
+
* @param {Object} authConfig
|
|
59
|
+
* @param {string} dataplaneUrl
|
|
60
|
+
* @returns {Promise<Array>}
|
|
61
|
+
*/
|
|
62
|
+
async function fetchCrossPillarWarnings(systemKey, authConfig, dataplaneUrl) {
|
|
63
|
+
try {
|
|
64
|
+
const report = await getSystemLifecycleReport(dataplaneUrl, authConfig, systemKey, {
|
|
65
|
+
summary: true
|
|
66
|
+
});
|
|
67
|
+
const warnings = [];
|
|
68
|
+
if (report.trust?.verdict !== VERDICT.VERIFIED) {
|
|
69
|
+
warnings.push({
|
|
70
|
+
code: WARNING_CODES.TRUST_NOT_VERIFIED,
|
|
71
|
+
message: 'AI trust not verified',
|
|
72
|
+
action: actionHint(systemKey, 'verify-trust'),
|
|
73
|
+
suggestedCommand: 'verify-trust'
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (report.governance?.verdict !== VERDICT.VERIFIED) {
|
|
77
|
+
warnings.push({
|
|
78
|
+
code: WARNING_CODES.GOVERNANCE_NOT_VERIFIED,
|
|
79
|
+
message: 'Governance not verified',
|
|
80
|
+
action: actionHint(systemKey, 'governance verify'),
|
|
81
|
+
suggestedCommand: 'governance verify'
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return warnings;
|
|
85
|
+
} catch {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @param {Object} params
|
|
92
|
+
* @param {string} params.systemKey
|
|
93
|
+
* @param {Object} params.stepResults
|
|
94
|
+
* @param {Record<string, boolean>} params.checks
|
|
95
|
+
* @param {boolean} params.hardFailure
|
|
96
|
+
* @param {Object} params.options
|
|
97
|
+
* @param {number|null} [params.persistedReadinessPercent]
|
|
98
|
+
* @param {Object|null} [params.readinessMetrics]
|
|
99
|
+
*/
|
|
100
|
+
async function buildOperationsResult({
|
|
101
|
+
systemKey,
|
|
102
|
+
stepResults,
|
|
103
|
+
checks,
|
|
104
|
+
hardFailure,
|
|
105
|
+
options,
|
|
106
|
+
persistedReadinessPercent = null,
|
|
107
|
+
persistedOperationsVerdict = null,
|
|
108
|
+
readinessMetrics = null,
|
|
109
|
+
lifecycleCertification = null
|
|
110
|
+
}) {
|
|
111
|
+
const localPercent = computeOperationalReadinessPercent(checks);
|
|
112
|
+
const localVerdict = verdictFromPassed(!hardFailure);
|
|
113
|
+
// When CLI E2E (or post-sync steps) failed, show step-derived readiness — persisted
|
|
114
|
+
// slices can report 100% ICC/PDS/DTS while runtime verdict is FAILED (422.0-v1).
|
|
115
|
+
const operationalReadinessPercent = hardFailure
|
|
116
|
+
? localPercent
|
|
117
|
+
: typeof persistedReadinessPercent === 'number'
|
|
118
|
+
? persistedReadinessPercent
|
|
119
|
+
: localPercent;
|
|
120
|
+
const verdict = hardFailure
|
|
121
|
+
? localVerdict
|
|
122
|
+
: typeof persistedOperationsVerdict === 'string' && persistedOperationsVerdict.trim()
|
|
123
|
+
? persistedOperationsVerdict.trim()
|
|
124
|
+
: localVerdict;
|
|
125
|
+
const details = groupOperationsDetails(checks);
|
|
126
|
+
|
|
127
|
+
let warnings = [];
|
|
128
|
+
try {
|
|
129
|
+
const { authConfig, dataplaneUrl } = await resolveIntegrationAuth(systemKey, options);
|
|
130
|
+
warnings = await fetchCrossPillarWarnings(systemKey, authConfig, dataplaneUrl);
|
|
131
|
+
} catch {
|
|
132
|
+
warnings = [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const certification =
|
|
136
|
+
lifecycleCertification && lifecycleCertification.level
|
|
137
|
+
? {
|
|
138
|
+
level: lifecycleCertification.level,
|
|
139
|
+
status: lifecycleCertification.status || 'NOT_CERTIFIED'
|
|
140
|
+
}
|
|
141
|
+
: {
|
|
142
|
+
level: verdict === VERDICT.VERIFIED ? 'BRONZE' : 'NONE',
|
|
143
|
+
status: verdict === VERDICT.VERIFIED ? 'TECHNICALLY_READY' : 'NOT_CERTIFIED'
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
systemKey,
|
|
148
|
+
command: 'verify-operations',
|
|
149
|
+
verdict,
|
|
150
|
+
operationalReadinessPercent,
|
|
151
|
+
readinessMetrics: readinessMetrics || null,
|
|
152
|
+
certification,
|
|
153
|
+
warnings,
|
|
154
|
+
details,
|
|
155
|
+
stepResults
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @param {string} systemKey
|
|
161
|
+
* @returns {Promise<void>}
|
|
162
|
+
*/
|
|
163
|
+
async function assertIntegrationExternalSystem(systemKey) {
|
|
164
|
+
const pathsUtil = require('../utils/paths');
|
|
165
|
+
const appType = await pathsUtil.detectAppType(systemKey).catch(() => null);
|
|
166
|
+
if (!appType || appType.baseDir !== 'integration') {
|
|
167
|
+
throw new Error(
|
|
168
|
+
'verify-operations applies to external integration folders only (integration/<systemKey>/).'
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {string} systemKey
|
|
175
|
+
* @param {Object} options
|
|
176
|
+
* @param {Object} stepResults
|
|
177
|
+
* @param {boolean} hardFailure
|
|
178
|
+
* @returns {Promise<Object>}
|
|
179
|
+
*/
|
|
180
|
+
async function loadPersistedOperationsMetrics(
|
|
181
|
+
systemKey,
|
|
182
|
+
options,
|
|
183
|
+
stepResults,
|
|
184
|
+
hardFailure,
|
|
185
|
+
stoppedEarly
|
|
186
|
+
) {
|
|
187
|
+
const empty = {
|
|
188
|
+
persistedReadinessPercent: null,
|
|
189
|
+
persistedOperationsVerdict: null,
|
|
190
|
+
readinessMetrics: null,
|
|
191
|
+
lifecycleCertification: null
|
|
192
|
+
};
|
|
193
|
+
if (options.persist === false) {
|
|
194
|
+
return empty;
|
|
195
|
+
}
|
|
196
|
+
// Persist after upload/sync when integration or E2E ran — partial evidence for Overview (425.9).
|
|
197
|
+
// Skip only when we stopped before post-sync steps (validate/unit hard fail without --continue).
|
|
198
|
+
if (stoppedEarly) {
|
|
199
|
+
return empty;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return runWithVerifyStepProgress(
|
|
203
|
+
'Saving operations results',
|
|
204
|
+
async() => {
|
|
205
|
+
await persistOperationsForSystem(systemKey, options, stepResults);
|
|
206
|
+
try {
|
|
207
|
+
const { authConfig, dataplaneUrl } = await resolveIntegrationAuth(systemKey, options);
|
|
208
|
+
const report = await getSystemLifecycleReport(dataplaneUrl, authConfig, systemKey, {
|
|
209
|
+
details: true
|
|
210
|
+
});
|
|
211
|
+
return {
|
|
212
|
+
persistedReadinessPercent:
|
|
213
|
+
typeof report?.operations?.operationalReadinessPercent === 'number'
|
|
214
|
+
? report.operations.operationalReadinessPercent
|
|
215
|
+
: null,
|
|
216
|
+
persistedOperationsVerdict:
|
|
217
|
+
typeof report?.operations?.verdict === 'string' ? report.operations.verdict : null,
|
|
218
|
+
readinessMetrics: extractReadinessMetricsFromLifecycleReport(report),
|
|
219
|
+
lifecycleCertification: report?.certification || null
|
|
220
|
+
};
|
|
221
|
+
} catch {
|
|
222
|
+
return empty;
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
options
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* @async
|
|
231
|
+
* @param {string} systemKey
|
|
232
|
+
* @param {Object} options
|
|
233
|
+
* @returns {Promise<Object>}
|
|
234
|
+
*/
|
|
235
|
+
async function runVerifyOperationsForExternalSystem(systemKey, options = {}) {
|
|
236
|
+
await assertIntegrationExternalSystem(systemKey);
|
|
237
|
+
|
|
238
|
+
const { stepResults, hardFailure, stoppedEarly } = await runOperationsVerifySteps(
|
|
239
|
+
systemKey,
|
|
240
|
+
options
|
|
241
|
+
);
|
|
242
|
+
const checks = buildOperationsChecksFromSteps(stepResults);
|
|
243
|
+
const persisted = await loadPersistedOperationsMetrics(
|
|
244
|
+
systemKey,
|
|
245
|
+
options,
|
|
246
|
+
stepResults,
|
|
247
|
+
hardFailure,
|
|
248
|
+
stoppedEarly
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
return buildOperationsResult({
|
|
252
|
+
systemKey,
|
|
253
|
+
stepResults,
|
|
254
|
+
checks,
|
|
255
|
+
hardFailure,
|
|
256
|
+
options,
|
|
257
|
+
...persisted
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
module.exports = {
|
|
262
|
+
runVerifyOperationsForExternalSystem,
|
|
263
|
+
groupOperationsDetails,
|
|
264
|
+
fetchCrossPillarWarnings,
|
|
265
|
+
buildOperationsResult,
|
|
266
|
+
assertIntegrationExternalSystem,
|
|
267
|
+
loadPersistedOperationsMetrics
|
|
268
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Persist operations pillar to dataplane lifecycle (plan 150.0 / 419.0).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { resolveExternalIntegrationContext } = require('./test-e2e-external');
|
|
10
|
+
const { resolveIntegrationAuth } = require('../external-system/integration-auth-context');
|
|
11
|
+
const { postValidationRun } = require('../api/validation-run.api');
|
|
12
|
+
const { buildExternalDataSourceValidationRequest } = require('../utils/validation-run-request');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Optional unit rollup stored in operations.details.reliability.unit.
|
|
16
|
+
* @param {Object} stepResults
|
|
17
|
+
* @returns {Object|undefined}
|
|
18
|
+
*/
|
|
19
|
+
function buildUnitTestSummary(stepResults) {
|
|
20
|
+
if (!stepResults || stepResults.unit !== true) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
return { passed: 1, failed: 0, skipped: 0 };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* POST validation/run runType=operations for each active datasource (persists resultOperations).
|
|
28
|
+
* @async
|
|
29
|
+
* @param {string} systemKey
|
|
30
|
+
* @param {Object} options
|
|
31
|
+
* @param {Object} stepResults
|
|
32
|
+
* @returns {Promise<{ persisted: number }>}
|
|
33
|
+
*/
|
|
34
|
+
async function persistOperationsForSystem(systemKey, options, stepResults) {
|
|
35
|
+
const { systemKey: resolvedKey, keys } = resolveExternalIntegrationContext(systemKey);
|
|
36
|
+
if (keys.length === 0) {
|
|
37
|
+
return { persisted: 0 };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const { authConfig, dataplaneUrl } = await resolveIntegrationAuth(systemKey, options);
|
|
41
|
+
|
|
42
|
+
const timeoutMs = parseInt(String(options.timeout || '120000'), 10) || 120000;
|
|
43
|
+
const unitTestSummary = buildUnitTestSummary(stepResults);
|
|
44
|
+
let persisted = 0;
|
|
45
|
+
|
|
46
|
+
for (const dsKey of keys) {
|
|
47
|
+
const body = buildExternalDataSourceValidationRequest({
|
|
48
|
+
systemKey: resolvedKey,
|
|
49
|
+
datasourceKey: dsKey,
|
|
50
|
+
runType: 'operations'
|
|
51
|
+
});
|
|
52
|
+
if (unitTestSummary) {
|
|
53
|
+
body.unitTestSummary = unitTestSummary;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const res = await postValidationRun(dataplaneUrl, authConfig, body, { timeoutMs });
|
|
57
|
+
if (!res || res.success === false) {
|
|
58
|
+
const msg =
|
|
59
|
+
(res &&
|
|
60
|
+
res.error &&
|
|
61
|
+
(res.error.formattedError || res.error.error || res.error.message)) ||
|
|
62
|
+
res?.formattedError ||
|
|
63
|
+
'Operations lifecycle persist failed';
|
|
64
|
+
throw new Error(`${dsKey}: ${msg}`);
|
|
65
|
+
}
|
|
66
|
+
persisted += 1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return { persisted };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
persistOperationsForSystem,
|
|
74
|
+
buildUnitTestSummary
|
|
75
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Step plan for verify-operations (plan 150.0).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const { validateExternalSystemComplete } = require('../validation/validate');
|
|
8
|
+
const { testExternalSystem, testExternalSystemIntegration } = require('../external-system/test');
|
|
9
|
+
const { runTestE2EForExternalSystem } = require('./test-e2e-external');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} systemKey
|
|
13
|
+
* @param {Object} options
|
|
14
|
+
* @returns {{ beforeSync: Array, afterSync: Array, e2e: Object }}
|
|
15
|
+
*/
|
|
16
|
+
function buildOperationsVerifyStepPlan(systemKey, options) {
|
|
17
|
+
return {
|
|
18
|
+
beforeSync: [
|
|
19
|
+
{
|
|
20
|
+
key: 'validation',
|
|
21
|
+
run: () => validateExternalSystemComplete(systemKey, { type: 'external' }),
|
|
22
|
+
ok: (result) => result.valid === true
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
key: 'unit',
|
|
26
|
+
run: () => testExternalSystem(systemKey, { verbose: false }),
|
|
27
|
+
ok: (result) => result.valid === true
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
afterSync: [
|
|
31
|
+
{
|
|
32
|
+
key: 'integration',
|
|
33
|
+
run: () =>
|
|
34
|
+
testExternalSystemIntegration(systemKey, {
|
|
35
|
+
environment: options.env,
|
|
36
|
+
noSync: true,
|
|
37
|
+
verbose: false,
|
|
38
|
+
debug: options.debug === true
|
|
39
|
+
}),
|
|
40
|
+
ok: (result) => result.success === true
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
e2e: {
|
|
44
|
+
key: 'e2e',
|
|
45
|
+
run: (progress) =>
|
|
46
|
+
runTestE2EForExternalSystem(systemKey, {
|
|
47
|
+
env: options.env,
|
|
48
|
+
noSync: true,
|
|
49
|
+
verbose: false,
|
|
50
|
+
debug: options.debug === true,
|
|
51
|
+
async: options.async !== false,
|
|
52
|
+
authConfig: options.authConfig,
|
|
53
|
+
dataplaneUrl: options.dataplaneUrl,
|
|
54
|
+
silentResolve: options.silentResolve === true,
|
|
55
|
+
quietPollUi: true,
|
|
56
|
+
onDatasourceProgress: progress?.setLabel
|
|
57
|
+
? ({ key, index, total }) =>
|
|
58
|
+
progress.setLabel(`Running E2E: ${key} (${index + 1}/${total})`)
|
|
59
|
+
: undefined
|
|
60
|
+
}),
|
|
61
|
+
ok: (result) => result.success === true
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {
|
|
67
|
+
buildOperationsVerifyStepPlan
|
|
68
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview verify-operations step runners (plan 150.0).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const { syncLocalIfRequested } = require('./test-e2e-external');
|
|
8
|
+
const { cliOptsSkipSync } = require('../utils/cli-sync-options');
|
|
9
|
+
const { buildOperationsVerifyStepPlan } = require('./verify-operations-step-plan');
|
|
10
|
+
const { runWithVerifyStepProgress } = require('../lifecycle/verify-step-progress');
|
|
11
|
+
|
|
12
|
+
const STEP_PROGRESS = {
|
|
13
|
+
validation: 'Validating local integration',
|
|
14
|
+
unit: 'Running unit tests',
|
|
15
|
+
integration: 'Running integration tests on dataplane',
|
|
16
|
+
e2e: 'Running E2E tests'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {Object} options
|
|
21
|
+
* @param {Object} uploadCtx
|
|
22
|
+
*/
|
|
23
|
+
function attachUploadAuthToOptions(options, uploadCtx) {
|
|
24
|
+
if (!uploadCtx?.authConfig || !uploadCtx?.dataplaneUrl) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
options.authConfig = uploadCtx.authConfig;
|
|
28
|
+
options.dataplaneUrl = uploadCtx.dataplaneUrl;
|
|
29
|
+
options.silentResolve = true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {Function} runner
|
|
34
|
+
* @param {Function} isSuccess
|
|
35
|
+
* @param {Object} options
|
|
36
|
+
* @returns {Promise<boolean>}
|
|
37
|
+
*/
|
|
38
|
+
async function runVerifyStep(runner, isSuccess) {
|
|
39
|
+
const outcome = await runner();
|
|
40
|
+
return isSuccess(outcome);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {Object} stepResults
|
|
45
|
+
* @param {string} key
|
|
46
|
+
* @param {boolean} passed
|
|
47
|
+
* @param {boolean} continueOnFail
|
|
48
|
+
* @returns {boolean} false when the verify flow should stop early
|
|
49
|
+
*/
|
|
50
|
+
function recordVerifyStep(stepResults, key, passed, continueOnFail) {
|
|
51
|
+
stepResults[key] = passed;
|
|
52
|
+
return passed || continueOnFail;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {Object} stepResults
|
|
57
|
+
* @param {Object} step
|
|
58
|
+
* @param {boolean} continueOnFail
|
|
59
|
+
* @param {Object} options
|
|
60
|
+
* @returns {Promise<boolean>}
|
|
61
|
+
*/
|
|
62
|
+
async function runTrackedVerifyStep(stepResults, step, continueOnFail, options) {
|
|
63
|
+
const label = STEP_PROGRESS[step.key] || step.key;
|
|
64
|
+
const passed = await runWithVerifyStepProgress(
|
|
65
|
+
label,
|
|
66
|
+
async(progress) => runVerifyStep(() => step.run(progress), step.ok),
|
|
67
|
+
options
|
|
68
|
+
);
|
|
69
|
+
return recordVerifyStep(stepResults, step.key, passed, continueOnFail);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @async
|
|
74
|
+
* @param {string} systemKey
|
|
75
|
+
* @param {Object} options
|
|
76
|
+
* @returns {Promise<{ stepResults: Object, hardFailure: boolean, stoppedEarly: boolean }>}
|
|
77
|
+
*/
|
|
78
|
+
async function runOperationsVerifySteps(systemKey, options) {
|
|
79
|
+
const stepResults = { validation: false, unit: false, integration: false, e2e: false };
|
|
80
|
+
const continueOnFail = options.continue === true;
|
|
81
|
+
const plan = buildOperationsVerifyStepPlan(systemKey, options);
|
|
82
|
+
|
|
83
|
+
for (const step of plan.beforeSync) {
|
|
84
|
+
if (!(await runTrackedVerifyStep(stepResults, step, continueOnFail, options))) {
|
|
85
|
+
return { stepResults, hardFailure: true, stoppedEarly: true };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!cliOptsSkipSync(options)) {
|
|
90
|
+
const uploadCtx = await syncLocalIfRequested(systemKey, options);
|
|
91
|
+
attachUploadAuthToOptions(options, uploadCtx);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for (const step of plan.afterSync) {
|
|
95
|
+
if (!(await runTrackedVerifyStep(stepResults, step, continueOnFail, options))) {
|
|
96
|
+
return { stepResults, hardFailure: true, stoppedEarly: true };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const e2eLabel = STEP_PROGRESS.e2e;
|
|
101
|
+
stepResults.e2e = await runWithVerifyStepProgress(
|
|
102
|
+
e2eLabel,
|
|
103
|
+
async(progress) => runVerifyStep(() => plan.e2e.run(progress), plan.e2e.ok),
|
|
104
|
+
options
|
|
105
|
+
);
|
|
106
|
+
return { stepResults, hardFailure: !stepResults.e2e, stoppedEarly: false };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = {
|
|
110
|
+
runOperationsVerifySteps
|
|
111
|
+
};
|