@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,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Enterprise AI Certification product vocabulary (plan 150.0).
|
|
3
|
+
* Defines verdict enums, tier labels, and operational readiness weights — product model drives API mapping.
|
|
4
|
+
* @author AI Fabrix Team
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
/** @typedef {'VERIFIED'|'FAILED'|'NOT_VERIFIED'} LifecycleVerdict */
|
|
11
|
+
|
|
12
|
+
/** @typedef {'BRONZE'|'SILVER'|'GOLD'|'PLATINUM'|'NONE'} CertificationLevel */
|
|
13
|
+
|
|
14
|
+
/** @typedef {'TECHNICALLY_READY'|'AI_READY'|'ENTERPRISE_AI_READY'|'REGULATED_ENTERPRISE_READY'|'NOT_CERTIFIED'} CertificationStatus */
|
|
15
|
+
|
|
16
|
+
const VERDICT = Object.freeze({
|
|
17
|
+
VERIFIED: 'VERIFIED',
|
|
18
|
+
FAILED: 'FAILED',
|
|
19
|
+
NOT_VERIFIED: 'NOT_VERIFIED'
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const CERTIFICATION_LEVEL = Object.freeze({
|
|
23
|
+
BRONZE: 'BRONZE',
|
|
24
|
+
SILVER: 'SILVER',
|
|
25
|
+
GOLD: 'GOLD',
|
|
26
|
+
PLATINUM: 'PLATINUM',
|
|
27
|
+
NONE: 'NONE'
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const CERTIFICATION_STATUS = Object.freeze({
|
|
31
|
+
TECHNICALLY_READY: 'TECHNICALLY_READY',
|
|
32
|
+
AI_READY: 'AI_READY',
|
|
33
|
+
ENTERPRISE_AI_READY: 'ENTERPRISE_AI_READY',
|
|
34
|
+
REGULATED_ENTERPRISE_READY: 'REGULATED_ENTERPRISE_READY',
|
|
35
|
+
NOT_CERTIFIED: 'NOT_CERTIFIED'
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
/** Display labels for certification status (aligned with dataplane 419 enum). */
|
|
39
|
+
const STATUS_DISPLAY = Object.freeze({
|
|
40
|
+
TECHNICALLY_READY: 'TECHNICALLY READY',
|
|
41
|
+
AI_READY: 'AI READY',
|
|
42
|
+
ENTERPRISE_AI_READY: 'ENTERPRISE AI READY',
|
|
43
|
+
REGULATED_ENTERPRISE_READY: 'REGULATED ENTERPRISE READY',
|
|
44
|
+
NOT_CERTIFIED: 'NOT CERTIFIED'
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* v1 operational readiness weights (sum = 100).
|
|
49
|
+
* connectivity + contracts + runtime + reliability groups from plan 150.
|
|
50
|
+
*/
|
|
51
|
+
const OPERATIONS_WEIGHTS = Object.freeze({
|
|
52
|
+
credentials: 10,
|
|
53
|
+
authentication: 10,
|
|
54
|
+
authorization: 10,
|
|
55
|
+
openApi: 8,
|
|
56
|
+
mappings: 7,
|
|
57
|
+
sync: 5,
|
|
58
|
+
crud: 5,
|
|
59
|
+
execution: 5,
|
|
60
|
+
validation: 10,
|
|
61
|
+
unitTests: 10,
|
|
62
|
+
integrationTests: 10,
|
|
63
|
+
e2eTests: 10
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const WARNING_CODES = Object.freeze({
|
|
67
|
+
TRUST_NOT_VERIFIED: 'TRUST_NOT_VERIFIED',
|
|
68
|
+
GOVERNANCE_NOT_VERIFIED: 'GOVERNANCE_NOT_VERIFIED',
|
|
69
|
+
OPERATIONS_NOT_VERIFIED: 'OPERATIONS_NOT_VERIFIED',
|
|
70
|
+
LIFECYCLE_API_UNAVAILABLE: 'LIFECYCLE_API_UNAVAILABLE'
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const RECOMMENDATION_COMMAND_BY_CODE = Object.freeze({
|
|
74
|
+
OPERATIONS_NOT_VERIFIED: 'verify-operations',
|
|
75
|
+
TRUST_NOT_VERIFIED: 'verify-trust',
|
|
76
|
+
GOVERNANCE_NOT_VERIFIED: 'governance verify'
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {string} systemKey
|
|
81
|
+
* @param {string} command e.g. verify-trust
|
|
82
|
+
* @returns {string}
|
|
83
|
+
*/
|
|
84
|
+
function actionHint(systemKey, command) {
|
|
85
|
+
return `aifabrix ${command} ${systemKey}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Normalize lifecycle recommendation to a copy-pastable CLI command.
|
|
90
|
+
* @param {string} systemKey
|
|
91
|
+
* @param {{ code?: string, action?: string }} rec
|
|
92
|
+
* @returns {string}
|
|
93
|
+
*/
|
|
94
|
+
function formatRecommendationAction(systemKey, rec) {
|
|
95
|
+
const action = String(rec.action || '').trim();
|
|
96
|
+
if (action.startsWith('aifabrix ')) {
|
|
97
|
+
return action;
|
|
98
|
+
}
|
|
99
|
+
const fromCode = RECOMMENDATION_COMMAND_BY_CODE[rec.code];
|
|
100
|
+
if (fromCode && systemKey) {
|
|
101
|
+
return actionHint(systemKey, fromCode);
|
|
102
|
+
}
|
|
103
|
+
const legacy = /^Run\s+(verify-[a-z-]+)$/i.exec(action);
|
|
104
|
+
if (legacy && systemKey) {
|
|
105
|
+
return actionHint(systemKey, legacy[1]);
|
|
106
|
+
}
|
|
107
|
+
return action || rec.code || '';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @param {boolean} passed
|
|
112
|
+
* @returns {LifecycleVerdict}
|
|
113
|
+
*/
|
|
114
|
+
function verdictFromPassed(passed) {
|
|
115
|
+
return passed ? VERDICT.VERIFIED : VERDICT.FAILED;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @param {string} [status]
|
|
120
|
+
* @returns {string}
|
|
121
|
+
*/
|
|
122
|
+
function formatCertificationStatusDisplay(status) {
|
|
123
|
+
if (!status) return STATUS_DISPLAY.NOT_CERTIFIED;
|
|
124
|
+
return STATUS_DISPLAY[status] || String(status).replace(/_/g, ' ');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Compute operational readiness percent from weighted check map.
|
|
129
|
+
* @param {Record<string, boolean>} checks
|
|
130
|
+
* @returns {number}
|
|
131
|
+
*/
|
|
132
|
+
function computeOperationalReadinessPercent(checks) {
|
|
133
|
+
let earned = 0;
|
|
134
|
+
let total = 0;
|
|
135
|
+
for (const [key, weight] of Object.entries(OPERATIONS_WEIGHTS)) {
|
|
136
|
+
total += weight;
|
|
137
|
+
if (checks[key] === true) {
|
|
138
|
+
earned += weight;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (total === 0) return 0;
|
|
142
|
+
return Math.round((earned / total) * 100);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Derive connectivity/runtime checks from step outcomes (v1 inference rules).
|
|
147
|
+
* @param {{ validation?: boolean, unit?: boolean, integration?: boolean, e2e?: boolean }} steps
|
|
148
|
+
* @returns {Record<string, boolean>}
|
|
149
|
+
*/
|
|
150
|
+
function buildOperationsChecksFromSteps(steps) {
|
|
151
|
+
const validation = steps.validation === true;
|
|
152
|
+
const unit = steps.unit === true;
|
|
153
|
+
const integration = steps.integration === true;
|
|
154
|
+
const e2e = steps.e2e === true;
|
|
155
|
+
return {
|
|
156
|
+
credentials: integration || e2e,
|
|
157
|
+
authentication: integration || e2e,
|
|
158
|
+
authorization: integration || e2e,
|
|
159
|
+
openApi: validation,
|
|
160
|
+
mappings: validation,
|
|
161
|
+
sync: e2e,
|
|
162
|
+
crud: e2e,
|
|
163
|
+
execution: e2e,
|
|
164
|
+
validation,
|
|
165
|
+
unitTests: unit,
|
|
166
|
+
integrationTests: integration,
|
|
167
|
+
e2eTests: e2e
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Worst-of rollup for datasource confidence values (0–1).
|
|
173
|
+
* @param {number[]} values
|
|
174
|
+
* @returns {number|null}
|
|
175
|
+
*/
|
|
176
|
+
function worstConfidencePercent(values) {
|
|
177
|
+
const nums = values.filter(v => typeof v === 'number' && !Number.isNaN(v));
|
|
178
|
+
if (nums.length === 0) return null;
|
|
179
|
+
return Math.round(Math.min(...nums) * 100);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
module.exports = {
|
|
183
|
+
VERDICT,
|
|
184
|
+
CERTIFICATION_LEVEL,
|
|
185
|
+
CERTIFICATION_STATUS,
|
|
186
|
+
STATUS_DISPLAY,
|
|
187
|
+
OPERATIONS_WEIGHTS,
|
|
188
|
+
WARNING_CODES,
|
|
189
|
+
actionHint,
|
|
190
|
+
formatRecommendationAction,
|
|
191
|
+
verdictFromPassed,
|
|
192
|
+
formatCertificationStatusDisplay,
|
|
193
|
+
computeOperationalReadinessPercent,
|
|
194
|
+
buildOperationsChecksFromSteps,
|
|
195
|
+
worstConfidencePercent
|
|
196
|
+
};
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TTY display for Enterprise AI Certification verify + lifecycle commands.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const logger = require('../utils/logger');
|
|
11
|
+
const {
|
|
12
|
+
sectionTitle,
|
|
13
|
+
formatSuccessParagraph,
|
|
14
|
+
formatBlockingError,
|
|
15
|
+
formatWarningLine,
|
|
16
|
+
successGlyph,
|
|
17
|
+
failureGlyph,
|
|
18
|
+
metadata: metaGray
|
|
19
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
20
|
+
const {
|
|
21
|
+
VERDICT,
|
|
22
|
+
formatCertificationStatusDisplay,
|
|
23
|
+
actionHint,
|
|
24
|
+
formatRecommendationAction
|
|
25
|
+
} = require('./product-model');
|
|
26
|
+
const {
|
|
27
|
+
METRIC_KEYS,
|
|
28
|
+
OPERATIONS_METRIC_LABELS
|
|
29
|
+
} = require('./operations-readiness-metrics');
|
|
30
|
+
const { displayGovernanceVerboseDetails } = require('../governance/governance-run-display');
|
|
31
|
+
const {
|
|
32
|
+
formatCertificationLevel,
|
|
33
|
+
formatCriterionCurrentHint,
|
|
34
|
+
resolveNextStepCommand,
|
|
35
|
+
formatProgressBar
|
|
36
|
+
} = require('./certification-progress');
|
|
37
|
+
|
|
38
|
+
const SEP = '────────────────────────';
|
|
39
|
+
|
|
40
|
+
function displayPillarHeader(systemKey, pillarLabel) {
|
|
41
|
+
logger.log('');
|
|
42
|
+
logger.log(sectionTitle(`${String(systemKey).toUpperCase()} — ${pillarLabel}`));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function displayHeroMetric(label, percent) {
|
|
46
|
+
logger.log('');
|
|
47
|
+
logger.log(chalk.white(label));
|
|
48
|
+
if (typeof percent === 'number') {
|
|
49
|
+
logger.log(chalk.cyan.bold(`${percent}%`));
|
|
50
|
+
} else {
|
|
51
|
+
logger.log(chalk.gray('—'));
|
|
52
|
+
}
|
|
53
|
+
logger.log('');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function displayVerdictLine(verdict, verifiedLabel, failedLabel) {
|
|
57
|
+
if (verdict === VERDICT.VERIFIED) {
|
|
58
|
+
logger.log(formatSuccessParagraph(verifiedLabel));
|
|
59
|
+
} else {
|
|
60
|
+
logger.log(formatBlockingError(failedLabel));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {string} systemKey
|
|
66
|
+
* @param {Array<{ code: string, action?: string }>} warnings
|
|
67
|
+
*/
|
|
68
|
+
function displayPillarWarnings(systemKey, warnings) {
|
|
69
|
+
if (!warnings || warnings.length === 0) return;
|
|
70
|
+
logger.log('');
|
|
71
|
+
for (const w of warnings) {
|
|
72
|
+
const action = w.action || actionHint(systemKey, w.suggestedCommand || 'verify-trust');
|
|
73
|
+
logger.log(formatWarningLine(`${w.message || w.code}. Run: ${action}`));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {Record<string, number>|null} readinessMetrics
|
|
79
|
+
*/
|
|
80
|
+
function displayOperationsReadinessMetrics(readinessMetrics) {
|
|
81
|
+
if (!readinessMetrics || typeof readinessMetrics !== 'object') {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
logger.log('');
|
|
85
|
+
logger.log(chalk.white('Readiness breakdown'));
|
|
86
|
+
logger.log(chalk.gray(SEP));
|
|
87
|
+
for (const key of METRIC_KEYS) {
|
|
88
|
+
const label = OPERATIONS_METRIC_LABELS[key] || key;
|
|
89
|
+
const pct = readinessMetrics[key];
|
|
90
|
+
const value =
|
|
91
|
+
typeof pct === 'number' ? chalk.cyan.bold(`${pct}%`) : chalk.gray('—');
|
|
92
|
+
logger.log(` ${label.padEnd(34)}${value}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {Record<string, Record<string, boolean>>} detailsGrouped
|
|
98
|
+
*/
|
|
99
|
+
function displayOperationsVerificationSteps(detailsGrouped) {
|
|
100
|
+
logger.log('');
|
|
101
|
+
logger.log(chalk.white('Verification steps'));
|
|
102
|
+
logger.log(chalk.gray(SEP));
|
|
103
|
+
const groups = [
|
|
104
|
+
['Connectivity', ['credentials', 'authentication', 'authorization']],
|
|
105
|
+
['Contracts', ['openApi', 'mappings']],
|
|
106
|
+
['Runtime', ['sync', 'crud', 'execution']],
|
|
107
|
+
['Reliability', ['validation', 'unitTests', 'integrationTests', 'e2eTests']]
|
|
108
|
+
];
|
|
109
|
+
const labels = {
|
|
110
|
+
credentials: 'Credentials',
|
|
111
|
+
authentication: 'Authentication',
|
|
112
|
+
authorization: 'Authorization',
|
|
113
|
+
openApi: 'OpenAPI',
|
|
114
|
+
mappings: 'Mappings',
|
|
115
|
+
sync: 'Sync',
|
|
116
|
+
crud: 'CRUD',
|
|
117
|
+
execution: 'Execution',
|
|
118
|
+
validation: 'Validation',
|
|
119
|
+
unitTests: 'Unit Tests',
|
|
120
|
+
integrationTests: 'Integration Tests',
|
|
121
|
+
e2eTests: 'E2E Tests'
|
|
122
|
+
};
|
|
123
|
+
for (const [groupName, keys] of groups) {
|
|
124
|
+
logger.log(chalk.white(groupName));
|
|
125
|
+
for (const key of keys) {
|
|
126
|
+
const passed = detailsGrouped[groupName.toLowerCase()]?.[key] ?? detailsGrouped[key];
|
|
127
|
+
const glyph = passed ? successGlyph() : failureGlyph();
|
|
128
|
+
logger.log(` ${labels[key] || key}`.padEnd(24) + glyph);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @param {string} systemKey
|
|
135
|
+
* @param {Object} result
|
|
136
|
+
* @param {{ details?: boolean, warnings?: Array }} opts
|
|
137
|
+
*/
|
|
138
|
+
function displayVerifyOperationsTTY(systemKey, result, opts = {}) {
|
|
139
|
+
displayPillarHeader(systemKey, 'OPERATIONS');
|
|
140
|
+
displayHeroMetric('Operational Readiness', result.operationalReadinessPercent);
|
|
141
|
+
displayVerdictLine(
|
|
142
|
+
result.verdict,
|
|
143
|
+
'OPERATIONS VERIFIED',
|
|
144
|
+
'OPERATIONS FAILED'
|
|
145
|
+
);
|
|
146
|
+
displayPillarWarnings(systemKey, result.warnings);
|
|
147
|
+
if (opts.details === true) {
|
|
148
|
+
displayOperationsReadinessMetrics(result.readinessMetrics);
|
|
149
|
+
if (result.details) {
|
|
150
|
+
displayOperationsVerificationSteps(result.details);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @param {string} systemKey
|
|
157
|
+
* @param {Object} result
|
|
158
|
+
* @param {{ details?: boolean }} opts
|
|
159
|
+
*/
|
|
160
|
+
function displayVerifyTrustTTY(systemKey, result, opts = {}) {
|
|
161
|
+
displayPillarHeader(systemKey, 'AI TRUST');
|
|
162
|
+
displayHeroMetric('AI Business Context Confidence', result.businessContextConfidencePercent);
|
|
163
|
+
displayVerdictLine(result.verdict, 'AI TRUST VERIFIED', 'AI TRUST FAILED');
|
|
164
|
+
if (opts.details === true && Array.isArray(result.datasourceRows)) {
|
|
165
|
+
logger.log('');
|
|
166
|
+
logger.log(chalk.white('Datasources'));
|
|
167
|
+
logger.log(chalk.gray(SEP));
|
|
168
|
+
for (const row of result.datasourceRows) {
|
|
169
|
+
const conf =
|
|
170
|
+
typeof row.confidencePercent === 'number' ? `${row.confidencePercent}%` : '—';
|
|
171
|
+
const glyph = row.verdict === VERDICT.VERIFIED ? successGlyph() : failureGlyph();
|
|
172
|
+
logger.log(` ${row.datasourceKey}`.padEnd(36) + `${glyph} ${conf}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @param {string} systemKey
|
|
179
|
+
* @param {Object} result
|
|
180
|
+
* @param {{ details?: boolean }} opts
|
|
181
|
+
*/
|
|
182
|
+
function displayVerifyGovernanceTTY(systemKey, result, opts = {}) {
|
|
183
|
+
displayPillarHeader(systemKey, 'GOVERNANCE');
|
|
184
|
+
displayHeroMetric('Policy Coverage', result.policyCoveragePercent);
|
|
185
|
+
logger.log(chalk.white('Dimension Coverage'));
|
|
186
|
+
logger.log(
|
|
187
|
+
typeof result.dimensionCoveragePercent === 'number'
|
|
188
|
+
? chalk.cyan.bold(`${result.dimensionCoveragePercent}%`)
|
|
189
|
+
: chalk.gray('—')
|
|
190
|
+
);
|
|
191
|
+
logger.log('');
|
|
192
|
+
const scenarios = result.enforcementScenarios || {};
|
|
193
|
+
const total = scenarios.total || 0;
|
|
194
|
+
const passed = scenarios.passed || 0;
|
|
195
|
+
logger.log(chalk.white('Enforcement Scenarios'));
|
|
196
|
+
logger.log(chalk.cyan.bold(`${passed}/${total} Passed`));
|
|
197
|
+
logger.log('');
|
|
198
|
+
displayVerdictLine(result.verdict, 'GOVERNANCE VERIFIED', 'GOVERNANCE FAILED');
|
|
199
|
+
if (opts.details === true) {
|
|
200
|
+
displayGovernanceVerboseDetails(result);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function formatPillarLine(label, verdict) {
|
|
205
|
+
if (verdict === VERDICT.VERIFIED) {
|
|
206
|
+
return `${label.padEnd(24)}${successGlyph()} VERIFIED`;
|
|
207
|
+
}
|
|
208
|
+
if (verdict === VERDICT.FAILED) {
|
|
209
|
+
return `${label.padEnd(24)}${failureGlyph()} FAILED`;
|
|
210
|
+
}
|
|
211
|
+
return `${label.padEnd(24)}— NOT VERIFIED`;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* @param {string} label
|
|
216
|
+
* @param {number|undefined} percent
|
|
217
|
+
* @param {string|undefined} verdict
|
|
218
|
+
* @returns {string}
|
|
219
|
+
*/
|
|
220
|
+
function formatPillarScoreLine(label, percent, verdict) {
|
|
221
|
+
const COL_LABEL = 22;
|
|
222
|
+
const COL_PCT = 10;
|
|
223
|
+
const pctPlain =
|
|
224
|
+
typeof percent === 'number' && Number.isFinite(percent)
|
|
225
|
+
? `${Math.round(percent)}%`
|
|
226
|
+
: '—';
|
|
227
|
+
const pctStr =
|
|
228
|
+
typeof percent === 'number' && Number.isFinite(percent)
|
|
229
|
+
? chalk.cyan.bold(pctPlain)
|
|
230
|
+
: chalk.gray(pctPlain);
|
|
231
|
+
const verdictPart = formatPillarLine('', verdict).trim();
|
|
232
|
+
const pctGap = Math.max(2, COL_PCT - pctPlain.length);
|
|
233
|
+
return `${label.padEnd(COL_LABEL)}${pctStr}${' '.repeat(pctGap)}${verdictPart}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Longest Silver→Gold criterion label ("Operational Readiness ≥ 90%"). */
|
|
237
|
+
const CRITERION_LABEL_COL = 32;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @param {string} glyph
|
|
241
|
+
* @param {string} label
|
|
242
|
+
* @param {string|null|undefined} hintPlain
|
|
243
|
+
* @returns {string}
|
|
244
|
+
*/
|
|
245
|
+
function formatCriterionProgressLine(glyph, label, hintPlain) {
|
|
246
|
+
const prefix = ` ${glyph} `;
|
|
247
|
+
if (!hintPlain) {
|
|
248
|
+
return `${prefix}${label}`;
|
|
249
|
+
}
|
|
250
|
+
const gap = Math.max(2, CRITERION_LABEL_COL - label.length);
|
|
251
|
+
return `${prefix}${label}${' '.repeat(gap)}${metaGray(hintPlain)}`;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* @param {Object} report
|
|
256
|
+
*/
|
|
257
|
+
function displayPillarScores(report) {
|
|
258
|
+
logger.log(chalk.white('Pillar scores'));
|
|
259
|
+
logger.log(chalk.gray(SEP));
|
|
260
|
+
logger.log(
|
|
261
|
+
formatPillarScoreLine(
|
|
262
|
+
'Operations',
|
|
263
|
+
report.operations?.operationalReadinessPercent,
|
|
264
|
+
report.operations?.verdict
|
|
265
|
+
)
|
|
266
|
+
);
|
|
267
|
+
logger.log(
|
|
268
|
+
formatPillarScoreLine(
|
|
269
|
+
'AI Trust',
|
|
270
|
+
report.trust?.businessContextConfidencePercent,
|
|
271
|
+
report.trust?.verdict
|
|
272
|
+
)
|
|
273
|
+
);
|
|
274
|
+
logger.log(
|
|
275
|
+
formatPillarScoreLine(
|
|
276
|
+
'Governance',
|
|
277
|
+
report.governance?.policyCoveragePercent,
|
|
278
|
+
report.governance?.verdict
|
|
279
|
+
)
|
|
280
|
+
);
|
|
281
|
+
logger.log('');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* @param {import('./certification-progress').CertificationProgressViewModel} progress
|
|
286
|
+
*/
|
|
287
|
+
function displayHighestTierAchieved(progress) {
|
|
288
|
+
logger.log(
|
|
289
|
+
metaGray(
|
|
290
|
+
`Current: ${formatCertificationLevel(progress.currentLevel)} — highest tier achieved`
|
|
291
|
+
)
|
|
292
|
+
);
|
|
293
|
+
logger.log('');
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* @param {import('./certification-progress').CertificationProgressViewModel} progress
|
|
298
|
+
*/
|
|
299
|
+
function displayProgressTargetHeader(progress) {
|
|
300
|
+
const targetLabel = formatCertificationLevel(progress.targetLevel);
|
|
301
|
+
const headerSuffix =
|
|
302
|
+
progress.mode === 'progress' && typeof progress.progressPercent === 'number'
|
|
303
|
+
? ` (${progress.progressPercent}%)`
|
|
304
|
+
: '';
|
|
305
|
+
logger.log(
|
|
306
|
+
chalk.white(
|
|
307
|
+
`Current: ${formatCertificationLevel(progress.currentLevel).toUpperCase()} → Progress to ${targetLabel.toUpperCase()}${headerSuffix}`
|
|
308
|
+
)
|
|
309
|
+
);
|
|
310
|
+
logger.log('');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* @param {Object} report
|
|
315
|
+
* @param {import('./certification-progress').CertificationProgressViewModel} progress
|
|
316
|
+
* @param {boolean} openApiPublished
|
|
317
|
+
*/
|
|
318
|
+
function displayProgressCriteriaRows(report, progress, openApiPublished) {
|
|
319
|
+
if (progress.criteria.length === 0) {
|
|
320
|
+
logger.log(
|
|
321
|
+
metaGray(
|
|
322
|
+
`Progress criteria for ${formatCertificationLevel(progress.targetLevel)} are not configured yet.`
|
|
323
|
+
)
|
|
324
|
+
);
|
|
325
|
+
logger.log('');
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
for (const row of progress.criteria) {
|
|
329
|
+
const glyph = row.met ? successGlyph() : failureGlyph();
|
|
330
|
+
const hintPlain = row.met
|
|
331
|
+
? null
|
|
332
|
+
: formatCriterionCurrentHint(row.id, report, openApiPublished);
|
|
333
|
+
logger.log(formatCriterionProgressLine(glyph, row.label, hintPlain));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* @param {import('./certification-progress').CertificationProgressViewModel} progress
|
|
339
|
+
*/
|
|
340
|
+
function displayProgressBarRow(progress) {
|
|
341
|
+
if (progress.mode !== 'progress' || typeof progress.progressPercent !== 'number') {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
logger.log('');
|
|
345
|
+
const targetLabel = formatCertificationLevel(progress.targetLevel);
|
|
346
|
+
const barPlain = formatProgressBar(progress.progressPercent);
|
|
347
|
+
const pctPlain = `${progress.progressPercent}%`;
|
|
348
|
+
const progressLabel = `${targetLabel} progress`;
|
|
349
|
+
logger.log(
|
|
350
|
+
` ${progressLabel.padEnd(18)} ${chalk.cyan(barPlain)} ${chalk.cyan.bold(pctPlain)}`
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* @param {string} systemKey
|
|
356
|
+
* @param {Object} report
|
|
357
|
+
* @param {import('./certification-progress').CertificationProgressViewModel|null} progress
|
|
358
|
+
* @param {boolean} openApiPublished
|
|
359
|
+
* @param {string|null} dataplaneUrl
|
|
360
|
+
* @param {string|null} [dataplaneUiBaseUrl]
|
|
361
|
+
*/
|
|
362
|
+
function displayCertificationProgressBlock(
|
|
363
|
+
systemKey,
|
|
364
|
+
report,
|
|
365
|
+
progress,
|
|
366
|
+
openApiPublished,
|
|
367
|
+
dataplaneUrl,
|
|
368
|
+
dataplaneUiBaseUrl = null
|
|
369
|
+
) {
|
|
370
|
+
if (!progress) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
logger.log(chalk.white('Certification progress'));
|
|
374
|
+
logger.log(chalk.gray(SEP));
|
|
375
|
+
if (progress.highestTierAchieved) {
|
|
376
|
+
displayHighestTierAchieved(progress);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
displayProgressTargetHeader(progress);
|
|
380
|
+
displayProgressCriteriaRows(report, progress, openApiPublished);
|
|
381
|
+
displayProgressBarRow(progress);
|
|
382
|
+
const nextStep = resolveNextStepCommand(systemKey, progress, {
|
|
383
|
+
dataplaneUrl,
|
|
384
|
+
dataplaneUiBaseUrl
|
|
385
|
+
});
|
|
386
|
+
if (nextStep) {
|
|
387
|
+
logger.log('');
|
|
388
|
+
logger.log(chalk.white('Next step:') + ` ${nextStep}`);
|
|
389
|
+
}
|
|
390
|
+
logger.log('');
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function displayCertificationSummary(report) {
|
|
394
|
+
const level = report.certification?.level || 'NONE';
|
|
395
|
+
const status = report.certification?.status || 'NOT_CERTIFIED';
|
|
396
|
+
logger.log(chalk.white('Certification'));
|
|
397
|
+
logger.log(chalk.gray(SEP));
|
|
398
|
+
logger.log(chalk.cyan.bold(level));
|
|
399
|
+
logger.log('');
|
|
400
|
+
logger.log(chalk.white('Status'));
|
|
401
|
+
logger.log(chalk.gray(SEP));
|
|
402
|
+
logger.log(formatCertificationStatusDisplay(status));
|
|
403
|
+
logger.log('');
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* @param {string} systemKey
|
|
408
|
+
* @param {Array<{ code: string, action?: string }>} recs
|
|
409
|
+
*/
|
|
410
|
+
function displayRecommendationsBlock(systemKey, recs) {
|
|
411
|
+
if (recs.length === 0) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
logger.log('');
|
|
415
|
+
logger.log(chalk.white('Recommendations'));
|
|
416
|
+
logger.log(chalk.gray(SEP));
|
|
417
|
+
logger.log(metaGray(`${recs.length} improvement${recs.length === 1 ? '' : 's'} available`));
|
|
418
|
+
for (const rec of recs) {
|
|
419
|
+
logger.log(` • ${formatRecommendationAction(systemKey, rec)}`);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* @param {Array<Object>} datasources
|
|
425
|
+
*/
|
|
426
|
+
function displayDatasourceBreakdown(datasources) {
|
|
427
|
+
logger.log('');
|
|
428
|
+
logger.log(chalk.white('Datasource breakdown'));
|
|
429
|
+
logger.log(chalk.gray(SEP));
|
|
430
|
+
for (const ds of datasources) {
|
|
431
|
+
logger.log(chalk.white(` ${ds.datasourceKey}`));
|
|
432
|
+
logger.log(` ${formatPillarLine('Operations', ds.operations?.verdict).trim()}`);
|
|
433
|
+
logger.log(` ${formatPillarLine('AI Trust', ds.trust?.verdict).trim()}`);
|
|
434
|
+
logger.log(` ${formatPillarLine('Governance', ds.governance?.verdict).trim()}`);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* @param {string} systemKey
|
|
440
|
+
* @param {Object} report - SystemLifecycleReport shape
|
|
441
|
+
* @param {{ details?: boolean, certificationProgress?: Object|null, openApiPublished?: boolean, dataplaneUrl?: string|null, dataplaneUiBaseUrl?: string|null }} opts
|
|
442
|
+
*/
|
|
443
|
+
function displayLifecycleReportTTY(systemKey, report, opts = {}) {
|
|
444
|
+
logger.log('');
|
|
445
|
+
logger.log(sectionTitle(`${String(systemKey).toUpperCase()} CERTIFICATION REPORT`));
|
|
446
|
+
logger.log('');
|
|
447
|
+
displayCertificationSummary(report);
|
|
448
|
+
displayPillarScores(report);
|
|
449
|
+
displayCertificationProgressBlock(
|
|
450
|
+
systemKey,
|
|
451
|
+
report,
|
|
452
|
+
opts.certificationProgress ?? null,
|
|
453
|
+
opts.openApiPublished === true,
|
|
454
|
+
opts.dataplaneUrl ?? null,
|
|
455
|
+
opts.dataplaneUiBaseUrl ?? null
|
|
456
|
+
);
|
|
457
|
+
displayRecommendationsBlock(systemKey, report.recommendations || []);
|
|
458
|
+
if (opts.details === true && Array.isArray(report.datasources) && report.datasources.length > 0) {
|
|
459
|
+
displayDatasourceBreakdown(report.datasources);
|
|
460
|
+
}
|
|
461
|
+
logger.log('');
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
module.exports = {
|
|
465
|
+
displayVerifyOperationsTTY,
|
|
466
|
+
displayVerifyTrustTTY,
|
|
467
|
+
displayVerifyGovernanceTTY,
|
|
468
|
+
displayLifecycleReportTTY,
|
|
469
|
+
displayOperationsReadinessMetrics,
|
|
470
|
+
displayOperationsVerificationSteps
|
|
471
|
+
};
|