@aifabrix/builder 2.45.5 → 2.47.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/.npmrc.token +1 -0
- package/.temp/jest-protection-convert/run-IFN2nv/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-IvmKLO/.protection/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-convert/run-SdvblF/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-b51TsW/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-fiLmb1/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-qYGHMU/.protection/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-Mq5re8/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-f3u4YL/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-iQtd1O/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-mdmz5M/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-qbKYxQ/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-yzlJy6/hubspot-companies.yaml +17 -0
- package/.temp/validation/summary.txt +5 -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 +146 -0
- package/jest.projects.js +65 -136
- package/lib/api/api-response-errors.js +124 -0
- package/lib/api/dataplane-health.api.js +19 -7
- package/lib/api/governance-scenario-pack.api.js +159 -0
- package/lib/api/index.js +43 -3
- package/lib/api/lifecycle.api.js +98 -0
- package/lib/api/pipeline.api.js +3 -1
- package/lib/api/records-bulk.api.js +14 -1
- package/lib/api/resource-types.api.js +107 -0
- package/lib/api/runtime-configuration.api.js +72 -0
- package/lib/api/types/resource-types.types.js +45 -0
- package/lib/api/user-groups.api.js +9 -9
- package/lib/api/users.api.js +8 -8
- package/lib/api/validation-runner.js +3 -1
- package/lib/api/wizard.api.js +10 -2
- package/lib/app/deploy-config.js +4 -1
- package/lib/app/down.js +78 -27
- package/lib/app/index.js +2 -2
- 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/app/run-resolve-image.js +2 -1
- package/lib/app/run-stop-containers.js +113 -0
- package/lib/app/run.js +1 -31
- package/lib/app/show-display.js +35 -0
- package/lib/app/show.js +32 -1
- package/lib/build/index.js +22 -5
- package/lib/build/miso-controller-npm-sdk-guard.js +25 -0
- package/lib/certification/sync-system-certification.js +13 -6
- package/lib/channels/add-channel.js +348 -0
- package/lib/channels/channel-artifact-generator.js +141 -0
- package/lib/channels/channel-audit.js +101 -0
- package/lib/channels/channel-auth-context.js +37 -0
- package/lib/channels/channel-credential.js +200 -0
- package/lib/channels/channel-display-name.js +64 -0
- package/lib/channels/channel-external-system.js +106 -0
- package/lib/channels/channel-integration-generator.js +274 -0
- package/lib/channels/channel-probe.js +89 -0
- package/lib/channels/channel-runtime-resolver.js +152 -0
- package/lib/channels/channel-status-display.js +141 -0
- package/lib/channels/channel-targets.js +115 -0
- package/lib/cli/index.js +20 -4
- 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 +82 -5
- 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-up-dataplane-action.js +2 -2
- package/lib/cli/setup-infra-up-platform-action.js +2 -1
- 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 +25 -2
- package/lib/cli/setup-utility-repair.js +198 -0
- package/lib/cli/setup-utility-resolve.js +44 -5
- package/lib/cli/setup-utility-validate.js +197 -0
- package/lib/cli/setup-utility.js +4 -239
- package/lib/commands/app-logs.js +54 -26
- package/lib/commands/app.js +41 -0
- package/lib/commands/auth-status-client-tokens.js +214 -0
- package/lib/commands/auth-status-dataplane-version.js +142 -68
- package/lib/commands/auth-status.js +43 -54
- package/lib/commands/channel.js +58 -0
- 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 +8 -8
- 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/identity-apply-sync.js +49 -8
- package/lib/commands/identity-group-cli.js +66 -26
- package/lib/commands/identity-membership-role-cache.js +58 -37
- package/lib/commands/identity-shared.js +22 -1
- package/lib/commands/identity-user-cli.js +80 -34
- 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 +153 -0
- package/lib/commands/repair-auth-config.js +8 -13
- package/lib/commands/repair-changed-files.js +41 -0
- package/lib/commands/repair-datasource-com-v2.js +15 -0
- package/lib/commands/repair-datasource-keys.js +4 -1
- package/lib/commands/repair-datasource-run.js +59 -0
- package/lib/commands/repair-datasource-service-contract.js +206 -0
- package/lib/commands/repair-datasource-test-payload.js +259 -0
- package/lib/commands/repair-datasource.js +49 -64
- package/lib/commands/repair-env-template.js +76 -25
- package/lib/commands/repair-external-run.js +216 -0
- package/lib/commands/repair-openapi-sync.js +49 -4
- package/lib/commands/repair-persist.js +4 -0
- package/lib/commands/repair-rbac.js +52 -1
- package/lib/commands/repair-steps.js +160 -0
- package/lib/commands/repair-system-alignment.js +7 -4
- package/lib/commands/repair.js +29 -296
- package/lib/commands/resource-type.js +371 -0
- 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 +70 -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 +48 -100
- package/lib/commands/up-common.js +57 -13
- package/lib/commands/up-dataplane.js +56 -15
- package/lib/commands/upload-publish-context.js +75 -0
- package/lib/commands/upload-sidecar-followups.js +89 -0
- package/lib/commands/upload.js +113 -110
- 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 +73 -0
- package/lib/commands/verify-trust-external.js +59 -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 +90 -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/capability/capability-diff-slice.js +2 -2
- package/lib/datasource/capability/capability-manifest.js +254 -0
- package/lib/datasource/capability/capability-resolve.js +3 -4
- package/lib/datasource/capability/copy-operations.js +5 -3
- package/lib/datasource/capability/remove-operations.js +2 -1
- package/lib/datasource/capability/run-capability-copy.js +32 -4
- package/lib/datasource/capability/run-capability-diff.js +3 -3
- package/lib/datasource/capability/run-capability-dimension.js +2 -4
- package/lib/datasource/capability/run-capability-edit.js +4 -7
- package/lib/datasource/capability/run-capability-relate.js +2 -4
- package/lib/datasource/capability/run-capability-remove.js +2 -4
- package/lib/datasource/capability/validate-capability-slice.js +2 -1
- package/lib/datasource/datasource-identifier.js +2 -1
- package/lib/datasource/datasource-load-export-context.js +3 -0
- package/lib/datasource/datasource-validate-display.js +1 -1
- package/lib/datasource/field-reference-validator.js +24 -3
- package/lib/datasource/log-cleaner.js +2 -2
- package/lib/datasource/log-viewer.js +8 -8
- package/lib/datasource/orphan-profiles-validator.js +98 -0
- 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/datasource/validate.js +41 -23
- package/lib/deployment/environment-poll-status.js +138 -0
- package/lib/deployment/environment.js +42 -34
- package/lib/external-system/download-helpers.js +87 -0
- package/lib/external-system/download.js +78 -138
- package/lib/external-system/generator.js +1 -55
- 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 +16 -21
- package/lib/generator/builders.js +11 -1
- package/lib/generator/external-controller-manifest.js +18 -0
- package/lib/generator/split.js +3 -1
- package/lib/generator/wizard.js +1 -28
- 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/identity/fk-reference.js +65 -0
- package/lib/identity/identity-apply-core.js +13 -58
- package/lib/identity/identity-apply-phases.js +5 -1
- package/lib/identity/identity-display.js +243 -0
- package/lib/identity/identity-response-helpers.js +52 -0
- package/lib/identity/identity-sync-errors.js +62 -0
- package/lib/identity/resolve-user-id.js +129 -0
- package/lib/identity/username-default.js +31 -0
- 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-trust.js +70 -0
- package/lib/lifecycle/report-display.js +472 -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/resolvers/datasource-resolver.js +2 -3
- package/lib/resolvers/resource-type-file.js +159 -0
- package/lib/schema/application-schema.json +17 -1
- package/lib/schema/datasource-test-run.schema.json +89 -6
- package/lib/schema/deployment-rules.yaml +2 -1
- package/lib/schema/external-datasource.schema.json +2947 -2619
- package/lib/schema/external-system.schema.json +1418 -761
- package/lib/schema/infra.parameter.yaml +45 -0
- package/lib/schema/type/credential-field-registry.json +103 -97
- package/lib/schema/type/document-storage.json +9 -5
- 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/app-run-containers.js +25 -2
- package/lib/utils/authentication-shape.js +224 -0
- package/lib/utils/build-copy.js +36 -5
- package/lib/utils/build-resolve-image.js +66 -12
- package/lib/utils/celery-companion-apps.js +53 -0
- package/lib/utils/cli-secrets-error-format.js +83 -21
- package/lib/utils/cli-utils.js +20 -4
- package/lib/utils/compose-celery-worker.js +23 -0
- package/lib/utils/compose-generate-docker-compose.js +13 -1
- package/lib/utils/compose-traefik-ingress-base.js +16 -1
- package/lib/utils/config-secrets-path.js +46 -0
- package/lib/utils/configuration-env-resolver.js +36 -0
- package/lib/utils/controller-url.js +88 -1
- package/lib/utils/credential-secrets-env-kv.js +216 -0
- package/lib/utils/credential-secrets-env.js +175 -257
- package/lib/utils/dataplane-resolver.js +18 -2
- package/lib/utils/declarative-url-ports.js +27 -4
- package/lib/utils/deployment-auth-mode.js +41 -0
- package/lib/utils/developer-volume-id.js +33 -0
- package/lib/utils/docker-build.js +1 -4
- 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 +11 -3
- package/lib/utils/external-system-readiness-core.js +10 -0
- package/lib/utils/external-system-readiness-display.js +80 -23
- package/lib/utils/external-system-validators.js +8 -2
- package/lib/utils/health-check.js +4 -1
- package/lib/utils/help-builder.js +13 -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/paths.js +25 -0
- package/lib/utils/pipeline-upload-auth-retry.js +82 -0
- package/lib/utils/platform-controller-url.js +157 -0
- package/lib/utils/platform-kv-ref.js +57 -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/runtime-configuration-download.js +189 -0
- package/lib/utils/runtime-configuration-values.js +119 -0
- package/lib/utils/schema-loader.js +19 -4
- 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/lib/utils/worker-sidecars.js +142 -0
- package/lib/validation/external-manifest-validator.js +2 -0
- package/lib/validation/runtime-configuration-rules.js +98 -0
- package/lib/validation/validate-display-dimensions.js +154 -0
- package/lib/validation/validate-display-sections.js +276 -0
- package/lib/validation/validate-display-steps.js +67 -0
- package/lib/validation/validate-display.js +24 -402
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +7 -1
- package/templates/applications/dataplane/env.template +50 -14
- package/templates/applications/dataplane/rbac.yaml +108 -1
- package/templates/applications/miso-controller/application.yaml +2 -2
- package/templates/applications/miso-controller/env.template +53 -122
- package/templates/applications/miso-controller/rbac.yaml +28 -13
- package/templates/channels/chatgpt/install.template.md.hbs +49 -0
- package/templates/channels/chatgpt/manifest.template.json.hbs +9 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +49 -0
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +8 -0
- package/templates/channels/slack/install.template.md.hbs +49 -0
- package/templates/channels/slack/manifest.template.json.hbs +66 -0
- package/templates/channels/teams-bot/install.template.md.hbs +49 -0
- package/templates/channels/teams-bot/manifest.template.json.hbs +13 -0
- package/templates/channels/web-embed/install.template.md.hbs +49 -0
- package/templates/channels/web-embed/manifest.template.json.hbs +8 -0
- package/templates/external-system/README.md.hbs +74 -17
- package/templates/python/docker-compose.hbs +75 -18
- package/templates/typescript/docker-compose.hbs +70 -17
- package/lib/commands/test-governance-command-action.js +0 -55
- package/lib/commands/test-trust-command-action.js +0 -118
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview UX certification progress for lifecycle CLI (aligned with dataplane overview / app-ui).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { VERDICT } = require('./product-model');
|
|
10
|
+
const { formatOpenApiPublishNextStep } = require('./dataplane-ui-url');
|
|
11
|
+
|
|
12
|
+
/** @typedef {'governanceCoverage'|'operationalReadiness'|'openApiPublished'|'aiTrust'|'activeWarnings'} CertificationCriterionId */
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} CertificationCriterionRow
|
|
16
|
+
* @property {CertificationCriterionId} id
|
|
17
|
+
* @property {string} label
|
|
18
|
+
* @property {boolean} met
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {Object} CertificationProgressViewModel
|
|
23
|
+
* @property {'progress'|'gaps'} mode
|
|
24
|
+
* @property {string} currentLevel
|
|
25
|
+
* @property {string} targetLevel
|
|
26
|
+
* @property {CertificationCriterionRow[]} criteria
|
|
27
|
+
* @property {number|null} progressPercent
|
|
28
|
+
* @property {boolean} highestTierAchieved
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const SILVER_TO_GOLD_CRITERIA = [
|
|
32
|
+
{
|
|
33
|
+
id: 'governanceCoverage',
|
|
34
|
+
label: 'Governance Coverage ≥ 95%',
|
|
35
|
+
evaluate: ctx =>
|
|
36
|
+
(ctx.report.governance?.policyCoveragePercent ?? 0) >= 95 &&
|
|
37
|
+
ctx.report.governance?.verdict === VERDICT.VERIFIED
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 'operationalReadiness',
|
|
41
|
+
label: 'Operational Readiness ≥ 90%',
|
|
42
|
+
evaluate: ctx => (ctx.report.operations?.operationalReadinessPercent ?? 0) >= 90
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: 'openApiPublished',
|
|
46
|
+
label: 'OpenAPI Published',
|
|
47
|
+
evaluate: ctx => ctx.openApiPublished === true
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: 'aiTrust',
|
|
51
|
+
label: 'AI Trust ≥ 95%',
|
|
52
|
+
evaluate: ctx => (ctx.report.trust?.aiTrustPercent ?? 0) >= 95
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'activeWarnings',
|
|
56
|
+
label: '0 Active Warnings',
|
|
57
|
+
evaluate: ctx => ctx.activeWarningCount === 0
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
/** @type {Record<CertificationCriterionId, string>} */
|
|
62
|
+
const NEXT_COMMAND_BY_CRITERION = {
|
|
63
|
+
governanceCoverage: 'governance verify',
|
|
64
|
+
operationalReadiness: 'verify-operations',
|
|
65
|
+
openApiPublished: '',
|
|
66
|
+
aiTrust: 'verify-trust',
|
|
67
|
+
activeWarnings: ''
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {string} level
|
|
72
|
+
* @returns {string}
|
|
73
|
+
*/
|
|
74
|
+
function formatCertificationLevel(level) {
|
|
75
|
+
if (!level || level === 'NONE') return 'Uncertified';
|
|
76
|
+
return level.charAt(0) + level.slice(1).toLowerCase();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {string} current
|
|
81
|
+
* @returns {string|null}
|
|
82
|
+
*/
|
|
83
|
+
function resolveTargetLevel(current) {
|
|
84
|
+
if (current === 'NONE' || current === 'BRONZE') return 'SILVER';
|
|
85
|
+
if (current === 'SILVER') return 'GOLD';
|
|
86
|
+
if (current === 'GOLD') return 'PLATINUM';
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @param {string} current
|
|
92
|
+
* @param {string} target
|
|
93
|
+
* @param {{ report: Object, openApiPublished?: boolean, activeWarningCount: number }} ctx
|
|
94
|
+
* @returns {CertificationCriterionRow[]}
|
|
95
|
+
*/
|
|
96
|
+
function buildCriteriaForTarget(current, target, ctx) {
|
|
97
|
+
if (current === 'SILVER' && target === 'GOLD') {
|
|
98
|
+
return SILVER_TO_GOLD_CRITERIA.map(def => ({
|
|
99
|
+
id: def.id,
|
|
100
|
+
label: def.label,
|
|
101
|
+
met: def.evaluate(ctx)
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @param {Object|null|undefined} report - SystemLifecycleReport
|
|
109
|
+
* @param {{ openApiPublished?: boolean }} [options]
|
|
110
|
+
* @returns {CertificationProgressViewModel|null}
|
|
111
|
+
*/
|
|
112
|
+
function buildCertificationProgress(report, options = {}) {
|
|
113
|
+
if (!report?.certification?.level) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const currentLevel = report.certification.level;
|
|
117
|
+
const targetLevel = resolveTargetLevel(currentLevel);
|
|
118
|
+
if (!targetLevel) {
|
|
119
|
+
return {
|
|
120
|
+
mode: 'gaps',
|
|
121
|
+
currentLevel,
|
|
122
|
+
targetLevel: currentLevel,
|
|
123
|
+
criteria: [],
|
|
124
|
+
progressPercent: 100,
|
|
125
|
+
highestTierAchieved: true
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const activeWarningCount = Array.isArray(report.warnings) ? report.warnings.length : 0;
|
|
130
|
+
const ctx = {
|
|
131
|
+
report,
|
|
132
|
+
openApiPublished: options.openApiPublished === true,
|
|
133
|
+
activeWarningCount
|
|
134
|
+
};
|
|
135
|
+
const criteria = buildCriteriaForTarget(currentLevel, targetLevel, ctx);
|
|
136
|
+
if (criteria.length === 0) {
|
|
137
|
+
return {
|
|
138
|
+
mode: 'gaps',
|
|
139
|
+
currentLevel,
|
|
140
|
+
targetLevel,
|
|
141
|
+
criteria: [],
|
|
142
|
+
progressPercent: null,
|
|
143
|
+
highestTierAchieved: false
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const metCount = criteria.filter(c => c.met).length;
|
|
148
|
+
const progressPercent = Math.round((metCount / criteria.length) * 100);
|
|
149
|
+
return {
|
|
150
|
+
mode: 'progress',
|
|
151
|
+
currentLevel,
|
|
152
|
+
targetLevel,
|
|
153
|
+
criteria,
|
|
154
|
+
progressPercent,
|
|
155
|
+
highestTierAchieved: false
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @param {CertificationCriterionId} id
|
|
161
|
+
* @param {Object} report
|
|
162
|
+
* @param {boolean} openApiPublished
|
|
163
|
+
* @returns {string|null}
|
|
164
|
+
*/
|
|
165
|
+
function formatCriterionCurrentHint(id, report, openApiPublished) {
|
|
166
|
+
if (id === 'aiTrust') {
|
|
167
|
+
const p = report.trust?.aiTrustPercent;
|
|
168
|
+
return typeof p === 'number' ? `(current: ${p}%)` : null;
|
|
169
|
+
}
|
|
170
|
+
if (id === 'operationalReadiness') {
|
|
171
|
+
const p = report.operations?.operationalReadinessPercent;
|
|
172
|
+
return typeof p === 'number' ? `(current: ${p}%)` : null;
|
|
173
|
+
}
|
|
174
|
+
if (id === 'governanceCoverage') {
|
|
175
|
+
const p = report.governance?.policyCoveragePercent;
|
|
176
|
+
return typeof p === 'number' ? `(current: ${p}%)` : null;
|
|
177
|
+
}
|
|
178
|
+
if (id === 'openApiPublished' && !openApiPublished) {
|
|
179
|
+
return '(not published)';
|
|
180
|
+
}
|
|
181
|
+
if (id === 'activeWarnings') {
|
|
182
|
+
const n = Array.isArray(report.warnings) ? report.warnings.length : 0;
|
|
183
|
+
return n > 0 ? `(current: ${n})` : null;
|
|
184
|
+
}
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @param {string} systemKey
|
|
190
|
+
* @param {CertificationProgressViewModel} progress
|
|
191
|
+
* @param {{ dataplaneUrl?: string|null }} [options]
|
|
192
|
+
* @returns {string|null}
|
|
193
|
+
*/
|
|
194
|
+
function resolveNextStepCommand(systemKey, progress, options = {}) {
|
|
195
|
+
const firstUnmet = progress.criteria.find(c => !c.met);
|
|
196
|
+
if (!firstUnmet) return null;
|
|
197
|
+
const cmd = NEXT_COMMAND_BY_CRITERION[firstUnmet.id];
|
|
198
|
+
if (firstUnmet.id === 'openApiPublished') {
|
|
199
|
+
return formatOpenApiPublishNextStep(systemKey, {
|
|
200
|
+
dataplaneUrl: options.dataplaneUrl,
|
|
201
|
+
dataplaneUiBaseUrl: options.dataplaneUiBaseUrl
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
if (firstUnmet.id === 'activeWarnings') {
|
|
205
|
+
return 'Resolve lifecycle warnings, then re-run lifecycle';
|
|
206
|
+
}
|
|
207
|
+
if (!cmd) return null;
|
|
208
|
+
return `aifabrix ${cmd} ${systemKey} -v`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @param {number|null} percent
|
|
213
|
+
* @param {number} [width]
|
|
214
|
+
* @returns {string}
|
|
215
|
+
*/
|
|
216
|
+
function formatProgressBar(percent, width = 10) {
|
|
217
|
+
if (typeof percent !== 'number' || Number.isNaN(percent)) {
|
|
218
|
+
return '—'.repeat(width);
|
|
219
|
+
}
|
|
220
|
+
const filled = Math.round((Math.max(0, Math.min(100, percent)) / 100) * width);
|
|
221
|
+
return `${'█'.repeat(filled)}${'░'.repeat(width - filled)}`;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
module.exports = {
|
|
225
|
+
buildCertificationProgress,
|
|
226
|
+
formatCertificationLevel,
|
|
227
|
+
formatCriterionCurrentHint,
|
|
228
|
+
resolveNextStepCommand,
|
|
229
|
+
formatProgressBar,
|
|
230
|
+
NEXT_COMMAND_BY_CRITERION
|
|
231
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Resolve dataplane app-ui base URL for lifecycle CLI hints.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.1.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { getConfig } = require('../core/config');
|
|
10
|
+
const {
|
|
11
|
+
expandDeclarativeUrlsInEnvContent,
|
|
12
|
+
parseSimpleEnvMap
|
|
13
|
+
} = require('../utils/url-declarative-resolve');
|
|
14
|
+
|
|
15
|
+
const EXTERNAL_SYSTEMS_UI_PATH = '/external-systems';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {string} url
|
|
19
|
+
* @returns {number|null}
|
|
20
|
+
*/
|
|
21
|
+
function portFromUrl(url) {
|
|
22
|
+
try {
|
|
23
|
+
const u = new URL(url);
|
|
24
|
+
if (u.port) {
|
|
25
|
+
const port = parseInt(u.port, 10);
|
|
26
|
+
return Number.isFinite(port) ? port : null;
|
|
27
|
+
}
|
|
28
|
+
return u.protocol === 'https:' ? 443 : 80;
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} hostname
|
|
36
|
+
* @returns {boolean}
|
|
37
|
+
*/
|
|
38
|
+
function isLoopbackHost(hostname) {
|
|
39
|
+
const h = String(hostname || '').toLowerCase();
|
|
40
|
+
return h === 'localhost' || h === '127.0.0.1' || h === '[::1]';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Browser-reachable origin from the resolved dataplane API base URL (same host/port).
|
|
45
|
+
* @param {string|null|undefined} dataplaneUrl
|
|
46
|
+
* @returns {string|null}
|
|
47
|
+
*/
|
|
48
|
+
function resolveDataplaneUiBaseUrlFromApiOrigin(dataplaneUrl) {
|
|
49
|
+
if (!dataplaneUrl || typeof dataplaneUrl !== 'string') {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const u = new URL(dataplaneUrl.replace(/\/$/, ''));
|
|
54
|
+
return `${u.protocol}//${u.host}`;
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Resolve `url://dataplane-host-public` from builder registry + user config.
|
|
62
|
+
* @async
|
|
63
|
+
* @returns {Promise<string|null>}
|
|
64
|
+
*/
|
|
65
|
+
async function resolveDataplaneUiBaseUrlFromRegistry() {
|
|
66
|
+
try {
|
|
67
|
+
const userCfg = await getConfig();
|
|
68
|
+
const content = 'DATAPLANE_UI=url://dataplane-host-public';
|
|
69
|
+
const expanded = await expandDeclarativeUrlsInEnvContent(content, {
|
|
70
|
+
profile: 'local',
|
|
71
|
+
currentAppKey: 'dataplane',
|
|
72
|
+
useEnvironmentScopedResources: userCfg.useEnvironmentScopedResources === true,
|
|
73
|
+
appEnvironmentScopedResources: false,
|
|
74
|
+
remoteServer: userCfg['remote-server'] || userCfg.remoteServer || null,
|
|
75
|
+
developerIdRaw: userCfg['developer-id'] ?? userCfg.developerId ?? null,
|
|
76
|
+
traefik: userCfg.traefik === true,
|
|
77
|
+
userCfg
|
|
78
|
+
});
|
|
79
|
+
const map = parseSimpleEnvMap(expanded);
|
|
80
|
+
const url = map.DATAPLANE_UI;
|
|
81
|
+
if (url && typeof url === 'string' && !url.startsWith('url://')) {
|
|
82
|
+
return url.replace(/\/$/, '');
|
|
83
|
+
}
|
|
84
|
+
} catch {
|
|
85
|
+
// Fall back to API origin below.
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @async
|
|
92
|
+
* @param {string|null|undefined} dataplaneUrl - Resolved dataplane API base URL
|
|
93
|
+
* @returns {Promise<string|null>}
|
|
94
|
+
*/
|
|
95
|
+
async function resolveDataplaneUiBaseUrl(dataplaneUrl) {
|
|
96
|
+
const fromRegistry = await resolveDataplaneUiBaseUrlFromRegistry();
|
|
97
|
+
if (fromRegistry) {
|
|
98
|
+
return fromRegistry;
|
|
99
|
+
}
|
|
100
|
+
return resolveDataplaneUiBaseUrlFromApiOrigin(dataplaneUrl);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @param {string|null|undefined} dataplaneUiBaseUrl
|
|
105
|
+
* @param {string} systemKey
|
|
106
|
+
* @returns {string|null}
|
|
107
|
+
*/
|
|
108
|
+
function buildExternalSystemUiUrl(dataplaneUiBaseUrl, systemKey) {
|
|
109
|
+
if (!dataplaneUiBaseUrl || !systemKey) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const base = String(dataplaneUiBaseUrl).replace(/\/$/, '');
|
|
113
|
+
const key = encodeURIComponent(String(systemKey).trim());
|
|
114
|
+
if (!key) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
return `${base}${EXTERNAL_SYSTEMS_UI_PATH}/${key}`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {string} systemKey
|
|
122
|
+
* @param {{ dataplaneUrl?: string|null, dataplaneUiBaseUrl?: string|null }} [options]
|
|
123
|
+
* @returns {string}
|
|
124
|
+
*/
|
|
125
|
+
function formatOpenApiPublishNextStep(systemKey, options = {}) {
|
|
126
|
+
const uiBase =
|
|
127
|
+
options.dataplaneUiBaseUrl ||
|
|
128
|
+
resolveDataplaneUiBaseUrlFromApiOrigin(options.dataplaneUrl);
|
|
129
|
+
const uiUrl = buildExternalSystemUiUrl(uiBase, systemKey);
|
|
130
|
+
if (uiUrl) {
|
|
131
|
+
return `Publish OpenAPI in dataplane UI: ${uiUrl}`;
|
|
132
|
+
}
|
|
133
|
+
return `Publish OpenAPI in dataplane UI — open external system "${systemKey}"`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = {
|
|
137
|
+
EXTERNAL_SYSTEMS_UI_PATH,
|
|
138
|
+
portFromUrl,
|
|
139
|
+
isLoopbackHost,
|
|
140
|
+
resolveDataplaneUiBaseUrlFromApiOrigin,
|
|
141
|
+
resolveDataplaneUiBaseUrlFromRegistry,
|
|
142
|
+
resolveDataplaneUiBaseUrl,
|
|
143
|
+
buildExternalSystemUiUrl,
|
|
144
|
+
formatOpenApiPublishNextStep
|
|
145
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Exit codes for Enterprise AI Certification verify commands.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { VERDICT } = require('./product-model');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} verdict
|
|
13
|
+
* @param {{ partial?: boolean }} [opts]
|
|
14
|
+
* @returns {number}
|
|
15
|
+
*/
|
|
16
|
+
function exitCodeFromVerdict(verdict, opts = {}) {
|
|
17
|
+
if (opts.partial === true) return 2;
|
|
18
|
+
if (verdict === VERDICT.VERIFIED) return 0;
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
exitCodeFromVerdict
|
|
24
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Machine-readable --json envelopes for verify + lifecycle commands.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {Object} base
|
|
11
|
+
* @param {boolean} includeDetails
|
|
12
|
+
* @returns {Object}
|
|
13
|
+
*/
|
|
14
|
+
function buildJsonEnvelope(base, includeDetails) {
|
|
15
|
+
const out = { ...base };
|
|
16
|
+
if (!includeDetails) {
|
|
17
|
+
delete out.details;
|
|
18
|
+
delete out.readinessMetrics;
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = {
|
|
24
|
+
buildJsonEnvelope
|
|
25
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Map lifecycle CLI flags to governance verify/generate options.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const { VERDICT } = require('./product-model');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {Object} options
|
|
11
|
+
* @returns {boolean}
|
|
12
|
+
*/
|
|
13
|
+
function lifecycleHasGovernanceSubjects(options) {
|
|
14
|
+
const emails = options.subjectEmail || options.subjectEmails || [];
|
|
15
|
+
const ids = options.subjectUserId || options.subjectUserIds || [];
|
|
16
|
+
return [...emails, ...ids].some(value => String(value || '').trim());
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {Object} report
|
|
21
|
+
* @returns {boolean}
|
|
22
|
+
*/
|
|
23
|
+
function lifecycleGovernanceNeedsWork(report) {
|
|
24
|
+
return report?.governance?.verdict !== VERDICT.VERIFIED;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {Object} options
|
|
29
|
+
* @param {{ authConfig?: Object, dataplaneUrl?: string }} [context]
|
|
30
|
+
* @returns {Object}
|
|
31
|
+
*/
|
|
32
|
+
function buildGovernanceOptsFromLifecycle(options, context = {}) {
|
|
33
|
+
return {
|
|
34
|
+
env: options.env || 'dev',
|
|
35
|
+
verbose: options.verbose === true,
|
|
36
|
+
debug: options.debug === true,
|
|
37
|
+
noSync: true,
|
|
38
|
+
force: options.force === true,
|
|
39
|
+
certificationProfile: options.certificationProfile || 'bronze',
|
|
40
|
+
subjectEmails: options.subjectEmail || options.subjectEmails || [],
|
|
41
|
+
subjectUserIds: options.subjectUserId || options.subjectUserIds || [],
|
|
42
|
+
authConfig: context.authConfig,
|
|
43
|
+
dataplaneUrl: context.dataplaneUrl
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = {
|
|
48
|
+
lifecycleHasGovernanceSubjects,
|
|
49
|
+
lifecycleGovernanceNeedsWork,
|
|
50
|
+
buildGovernanceOptsFromLifecycle
|
|
51
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Suppress CLI logger output during orchestration (verify-operations).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const logger = require('../utils/logger');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Run async fn with logger.log temporarily disabled.
|
|
13
|
+
* @template T
|
|
14
|
+
* @param {() => Promise<T>} fn
|
|
15
|
+
* @returns {Promise<T>}
|
|
16
|
+
*/
|
|
17
|
+
async function withQuietLogs(fn) {
|
|
18
|
+
const prev = logger.log;
|
|
19
|
+
logger.log = () => {};
|
|
20
|
+
try {
|
|
21
|
+
return await fn();
|
|
22
|
+
} finally {
|
|
23
|
+
logger.log = prev;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
withQuietLogs
|
|
29
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Resolve OpenAPI published flag for lifecycle certification progress.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { getExternalSystem } = require('../api/external-systems.api');
|
|
10
|
+
const { unwrapApiData } = require('../utils/external-system-readiness-core');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Dataplane ExternalSystemStatus serializes as lowercase (e.g. "published").
|
|
14
|
+
* @param {string|undefined} status
|
|
15
|
+
* @returns {boolean}
|
|
16
|
+
*/
|
|
17
|
+
function isExternalSystemPublishedStatus(status) {
|
|
18
|
+
return String(status || '')
|
|
19
|
+
.trim()
|
|
20
|
+
.toLowerCase() === 'published';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Mirrors dataplane SystemOverviewService openApiPublished logic.
|
|
25
|
+
* @param {Object|null|undefined} system - ExternalSystemResponse body
|
|
26
|
+
* @returns {boolean}
|
|
27
|
+
*/
|
|
28
|
+
function evaluateOpenApiPublished(system) {
|
|
29
|
+
if (!system || typeof system !== 'object') {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
const published = isExternalSystemPublishedStatus(system.status);
|
|
33
|
+
const showDocs = system.showOpenApiDocs === true;
|
|
34
|
+
const hasUrl = !!(system.openApiDocsPageUrl || system.apiDocumentUrl);
|
|
35
|
+
return published && showDocs && hasUrl;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @async
|
|
40
|
+
* @param {string} dataplaneUrl
|
|
41
|
+
* @param {Object} authConfig
|
|
42
|
+
* @param {string} systemKey
|
|
43
|
+
* @returns {Promise<boolean>}
|
|
44
|
+
*/
|
|
45
|
+
async function resolveOpenApiPublished(dataplaneUrl, authConfig, systemKey) {
|
|
46
|
+
try {
|
|
47
|
+
const res = await getExternalSystem(dataplaneUrl, systemKey, authConfig);
|
|
48
|
+
const system = unwrapApiData(res);
|
|
49
|
+
return evaluateOpenApiPublished(system);
|
|
50
|
+
} catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = {
|
|
56
|
+
isExternalSystemPublishedStatus,
|
|
57
|
+
evaluateOpenApiPublished,
|
|
58
|
+
resolveOpenApiPublished
|
|
59
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Operational readiness metric rollup for verify-operations (422.0).
|
|
3
|
+
* Human-facing labels for ICC/PDS/DTS; extraction from lifecycle reliability envelopes.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
/** @type {readonly string[]} */
|
|
9
|
+
const METRIC_KEYS = Object.freeze(['icc', 'pds', 'dts']);
|
|
10
|
+
|
|
11
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
12
|
+
const OPERATIONS_METRIC_LABELS = Object.freeze({
|
|
13
|
+
icc: 'Integration contract coverage',
|
|
14
|
+
pds: 'Pipeline determinism',
|
|
15
|
+
dts: 'Data trust'
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {unknown} raw
|
|
20
|
+
* @returns {number|null}
|
|
21
|
+
*/
|
|
22
|
+
function metricScorePercent(raw) {
|
|
23
|
+
if (!raw || typeof raw !== 'object') {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const score = raw.score;
|
|
27
|
+
if (typeof score === 'number' && Number.isFinite(score)) {
|
|
28
|
+
return Math.max(0, Math.min(100, Math.round(score * 100)));
|
|
29
|
+
}
|
|
30
|
+
const pct = raw.percentage;
|
|
31
|
+
if (typeof pct === 'number' && Number.isFinite(pct)) {
|
|
32
|
+
return Math.max(0, Math.min(100, Math.round(pct)));
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {unknown} envelope
|
|
39
|
+
* @returns {Record<string, number>|null}
|
|
40
|
+
*/
|
|
41
|
+
function metricsFromEnvelope(envelope) {
|
|
42
|
+
if (!envelope || typeof envelope !== 'object') {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
let metrics = envelope.metricsOutput;
|
|
46
|
+
if (!metrics && envelope.validation && typeof envelope.validation === 'object') {
|
|
47
|
+
metrics = envelope.validation.metricsOutput;
|
|
48
|
+
}
|
|
49
|
+
if (!metrics || typeof metrics !== 'object') {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const out = {};
|
|
53
|
+
for (const key of METRIC_KEYS) {
|
|
54
|
+
const pct = metricScorePercent(metrics[key]);
|
|
55
|
+
if (pct !== null) {
|
|
56
|
+
out[key] = pct;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return Object.keys(out).length > 0 ? out : null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Conservative rollup: min(ICC,PDS,DTS) per leg across validation + integration envelopes.
|
|
64
|
+
* E2E legs without metrics are ignored (runtime gate only).
|
|
65
|
+
* @param {unknown} reliability
|
|
66
|
+
* @returns {Record<string, number>|null}
|
|
67
|
+
*/
|
|
68
|
+
function rollupReadinessMetrics(reliability) {
|
|
69
|
+
if (!reliability || typeof reliability !== 'object') {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const legs = [reliability.validation, reliability.integration].filter(Boolean);
|
|
73
|
+
const rolled = {};
|
|
74
|
+
for (const key of METRIC_KEYS) {
|
|
75
|
+
const values = legs
|
|
76
|
+
.map(leg => metricsFromEnvelope(leg)?.[key])
|
|
77
|
+
.filter(v => typeof v === 'number');
|
|
78
|
+
if (values.length > 0) {
|
|
79
|
+
rolled[key] = Math.min(...values);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return Object.keys(rolled).length > 0 ? rolled : null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {Object|null} lifecycleReport
|
|
87
|
+
* @returns {Record<string, number>|null}
|
|
88
|
+
*/
|
|
89
|
+
function extractReadinessMetricsFromLifecycleReport(lifecycleReport) {
|
|
90
|
+
const reliability = lifecycleReport?.operations?.details?.reliability;
|
|
91
|
+
return rollupReadinessMetrics(reliability);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = {
|
|
95
|
+
METRIC_KEYS,
|
|
96
|
+
OPERATIONS_METRIC_LABELS,
|
|
97
|
+
metricScorePercent,
|
|
98
|
+
metricsFromEnvelope,
|
|
99
|
+
rollupReadinessMetrics,
|
|
100
|
+
extractReadinessMetricsFromLifecycleReport
|
|
101
|
+
};
|