@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.
Files changed (231) hide show
  1. package/.cursor/rules/cli-layout.mdc +2 -0
  2. package/.cursor/rules/cli-product-neutral.mdc +43 -0
  3. package/.cursor/rules/project-rules.mdc +1 -0
  4. package/README.md +43 -17
  5. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
  6. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
  7. package/jest.config.default.js +2 -1
  8. package/jest.config.isolated.js +2 -1
  9. package/jest.global-live-fabrix-hooks.js +36 -0
  10. package/jest.isolated-projects.js +130 -0
  11. package/jest.projects.js +41 -136
  12. package/lib/api/api-response-errors.js +124 -0
  13. package/lib/api/governance-scenario-pack.api.js +159 -0
  14. package/lib/api/index.js +43 -3
  15. package/lib/api/lifecycle.api.js +77 -0
  16. package/lib/api/pipeline.api.js +3 -1
  17. package/lib/api/records-bulk.api.js +14 -1
  18. package/lib/api/validation-runner.js +3 -1
  19. package/lib/app/deploy-config.js +4 -1
  20. package/lib/app/down.js +20 -1
  21. package/lib/app/push.js +4 -5
  22. package/lib/app/register.js +7 -4
  23. package/lib/app/run-env-compose.js +84 -30
  24. package/lib/build/index.js +5 -0
  25. package/lib/certification/sync-system-certification.js +13 -6
  26. package/lib/cli/index.js +4 -0
  27. package/lib/cli/infra-guided-auth.js +109 -0
  28. package/lib/cli/infra-guided.js +84 -81
  29. package/lib/cli/setup-app.help.js +0 -31
  30. package/lib/cli/setup-app.js +28 -2
  31. package/lib/cli/setup-app.test-commands.js +5 -57
  32. package/lib/cli/setup-auth.js +25 -0
  33. package/lib/cli/setup-certification-commands.js +147 -0
  34. package/lib/cli/setup-certification.help.js +141 -0
  35. package/lib/cli/setup-environment.js +19 -2
  36. package/lib/cli/setup-external-system-help.js +62 -0
  37. package/lib/cli/setup-external-system.js +25 -3
  38. package/lib/cli/setup-infra.js +9 -1
  39. package/lib/cli/setup-platform.js +6 -1
  40. package/lib/cli/setup-secrets.js +33 -1
  41. package/lib/cli/setup-utility-help-after.js +22 -2
  42. package/lib/cli/setup-utility-repair.js +198 -0
  43. package/lib/cli/setup-utility-resolve.js +40 -4
  44. package/lib/cli/setup-utility-validate.js +197 -0
  45. package/lib/cli/setup-utility.js +4 -239
  46. package/lib/commands/auth-status-client-tokens.js +214 -0
  47. package/lib/commands/auth-status-dataplane-version.js +58 -20
  48. package/lib/commands/auth-status.js +41 -47
  49. package/lib/commands/datasource-test-trust-cli.js +27 -23
  50. package/lib/commands/datasource-unified-test-cli.js +6 -3
  51. package/lib/commands/datasource-unified-test-cli.options.js +5 -1
  52. package/lib/commands/datasource.js +7 -7
  53. package/lib/commands/dev-show-display.js +8 -1
  54. package/lib/commands/governance-cli-shared.js +94 -0
  55. package/lib/commands/governance-command-action.js +132 -0
  56. package/lib/commands/governance-download-external.js +34 -0
  57. package/lib/commands/governance-generate-external.js +71 -0
  58. package/lib/commands/governance-upload-external.js +36 -0
  59. package/lib/commands/governance-verify-external.js +64 -0
  60. package/lib/commands/governance.js +144 -0
  61. package/lib/commands/lifecycle-command-action.js +123 -0
  62. package/lib/commands/lifecycle-external.js +268 -0
  63. package/lib/commands/login.js +11 -2
  64. package/lib/commands/repair-auth-apply.js +127 -0
  65. package/lib/commands/repair-changed-files.js +41 -0
  66. package/lib/commands/repair-datasource-keys.js +4 -1
  67. package/lib/commands/repair-datasource-run.js +59 -0
  68. package/lib/commands/repair-datasource-test-payload.js +259 -0
  69. package/lib/commands/repair-datasource.js +1 -51
  70. package/lib/commands/repair-env-template.js +64 -13
  71. package/lib/commands/repair-external-run.js +216 -0
  72. package/lib/commands/repair-openapi-sync.js +23 -0
  73. package/lib/commands/repair-persist.js +4 -0
  74. package/lib/commands/repair-rbac.js +52 -1
  75. package/lib/commands/repair-steps.js +145 -0
  76. package/lib/commands/repair.js +29 -296
  77. package/lib/commands/secrets-get.js +184 -0
  78. package/lib/commands/secrets-remove-all.js +3 -1
  79. package/lib/commands/setup-image-refresh.js +146 -0
  80. package/lib/commands/setup-modes.js +158 -162
  81. package/lib/commands/setup-platform-auth.js +76 -0
  82. package/lib/commands/setup-prompts-admin.js +244 -0
  83. package/lib/commands/setup-prompts-platform-mode.js +67 -0
  84. package/lib/commands/setup-prompts-validators.js +36 -0
  85. package/lib/commands/setup-prompts.js +24 -76
  86. package/lib/commands/setup-run-context.js +45 -0
  87. package/lib/commands/setup-spinners.js +39 -0
  88. package/lib/commands/setup.js +27 -5
  89. package/lib/commands/teardown.js +39 -0
  90. package/lib/commands/test-e2e-external.js +24 -8
  91. package/lib/commands/test-governance-external.js +3 -24
  92. package/lib/commands/test-trust-external.js +20 -21
  93. package/lib/commands/up-common.js +25 -13
  94. package/lib/commands/up-dataplane.js +50 -13
  95. package/lib/commands/upload-publish-context.js +75 -0
  96. package/lib/commands/upload-sidecar-followups.js +89 -0
  97. package/lib/commands/upload.js +90 -108
  98. package/lib/commands/verify-governance-combined-external.js +61 -0
  99. package/lib/commands/verify-governance-command-action.js +64 -0
  100. package/lib/commands/verify-governance-db.js +102 -0
  101. package/lib/commands/verify-governance-external.js +77 -0
  102. package/lib/commands/verify-governance-result-builders.js +71 -0
  103. package/lib/commands/verify-operations-command-action.js +68 -0
  104. package/lib/commands/verify-operations-external.js +268 -0
  105. package/lib/commands/verify-operations-persist.js +75 -0
  106. package/lib/commands/verify-operations-step-plan.js +68 -0
  107. package/lib/commands/verify-operations-steps.js +111 -0
  108. package/lib/commands/verify-trust-command-action.js +70 -0
  109. package/lib/commands/verify-trust-external.js +67 -0
  110. package/lib/commands/wizard-config-normalizer.js +43 -23
  111. package/lib/commands/wizard-core.js +2 -0
  112. package/lib/core/admin-password-generator.js +38 -0
  113. package/lib/core/admin-secrets-bundle.js +111 -0
  114. package/lib/core/admin-secrets-env-overlay.js +62 -0
  115. package/lib/core/admin-secrets.js +32 -4
  116. package/lib/core/config-attach-extensions.js +3 -0
  117. package/lib/core/config-platform-controller.js +44 -0
  118. package/lib/core/config-setup-installation-profile.js +42 -0
  119. package/lib/core/config-setup-platform-mode.js +46 -0
  120. package/lib/core/config.js +46 -36
  121. package/lib/core/secrets-admin-env.js +6 -2
  122. package/lib/core/secrets-ensure.js +4 -0
  123. package/lib/core/secrets-env-content.js +54 -48
  124. package/lib/core/secrets-env-write.js +10 -1
  125. package/lib/core/secrets-infra-placeholder-sync.js +2 -0
  126. package/lib/core/setup-installation-profile.js +43 -0
  127. package/lib/core/setup-platform-mode.js +55 -0
  128. package/lib/datasource/agent-trust-debug-log.js +1 -1
  129. package/lib/datasource/agent-trust-run.js +5 -3
  130. package/lib/datasource/audit-evidence-extract-debug.js +30 -18
  131. package/lib/datasource/audit-evidence-extract.js +7 -4
  132. package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
  133. package/lib/datasource/bulk-loader-run-batches.js +15 -3
  134. package/lib/datasource/datasource-load-export-context.js +3 -0
  135. package/lib/datasource/log-cleaner.js +2 -2
  136. package/lib/datasource/log-viewer.js +8 -8
  137. package/lib/datasource/test-e2e.js +4 -1
  138. package/lib/datasource/unified-validation-run-body.js +3 -1
  139. package/lib/datasource/unified-validation-run.js +5 -2
  140. package/lib/deployment/environment-poll-status.js +138 -0
  141. package/lib/deployment/environment.js +42 -34
  142. package/lib/external-system/download.js +21 -20
  143. package/lib/external-system/generator.js +5 -1
  144. package/lib/external-system/integration-auth-context.js +45 -0
  145. package/lib/external-system/test-auth.js +12 -5
  146. package/lib/external-system/test.js +6 -6
  147. package/lib/generator/external-controller-manifest.js +15 -0
  148. package/lib/governance/governance-cli-errors.js +96 -0
  149. package/lib/governance/governance-download-display.js +38 -0
  150. package/lib/governance/governance-run-display.js +215 -25
  151. package/lib/infrastructure/admin-secrets-apply.js +84 -0
  152. package/lib/infrastructure/admin-secrets-ensure.js +130 -0
  153. package/lib/infrastructure/admin-secrets-resolve.js +95 -0
  154. package/lib/infrastructure/admin-secrets-sync.js +91 -0
  155. package/lib/infrastructure/helpers.js +23 -129
  156. package/lib/infrastructure/index.js +5 -6
  157. package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
  158. package/lib/lifecycle/certification-progress.js +231 -0
  159. package/lib/lifecycle/dataplane-ui-url.js +145 -0
  160. package/lib/lifecycle/exit-codes.js +24 -0
  161. package/lib/lifecycle/json-envelope.js +25 -0
  162. package/lib/lifecycle/lifecycle-governance-options.js +51 -0
  163. package/lib/lifecycle/logger-quiet.js +29 -0
  164. package/lib/lifecycle/open-api-published.js +59 -0
  165. package/lib/lifecycle/operations-readiness-metrics.js +101 -0
  166. package/lib/lifecycle/product-model.js +196 -0
  167. package/lib/lifecycle/report-display.js +471 -0
  168. package/lib/lifecycle/scenario-upload.js +191 -0
  169. package/lib/lifecycle/verify-step-progress.js +87 -0
  170. package/lib/parameters/infra-kv-discovery.js +27 -2
  171. package/lib/protection/auth-context.js +10 -4
  172. package/lib/schema/application-schema.json +1 -1
  173. package/lib/schema/datasource-test-run.schema.json +89 -6
  174. package/lib/schema/external-datasource.schema.json +2636 -2622
  175. package/lib/schema/external-system.schema.json +1089 -761
  176. package/lib/schema/infra.parameter.yaml +45 -0
  177. package/lib/schema/type/credential-field-registry.json +103 -97
  178. package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
  179. package/lib/utils/api.js +55 -31
  180. package/lib/utils/app-relative-path-env.js +112 -0
  181. package/lib/utils/cli-secrets-error-format.js +83 -21
  182. package/lib/utils/cli-utils.js +16 -4
  183. package/lib/utils/compose-generate-docker-compose.js +4 -0
  184. package/lib/utils/compose-traefik-ingress-base.js +16 -1
  185. package/lib/utils/config-secrets-path.js +46 -0
  186. package/lib/utils/controller-url.js +88 -1
  187. package/lib/utils/credential-secrets-env.js +137 -9
  188. package/lib/utils/dataplane-resolver.js +129 -2
  189. package/lib/utils/declarative-url-ports.js +3 -3
  190. package/lib/utils/deployment-auth-mode.js +41 -0
  191. package/lib/utils/developer-volume-id.js +33 -0
  192. package/lib/utils/env-copy.js +14 -9
  193. package/lib/utils/env-kv-orphan-lines.js +43 -0
  194. package/lib/utils/error-formatters/network-errors.js +13 -4
  195. package/lib/utils/external-env-template.js +1 -0
  196. package/lib/utils/external-system-readiness-core.js +10 -0
  197. package/lib/utils/external-system-readiness-display.js +80 -23
  198. package/lib/utils/health-check.js +4 -1
  199. package/lib/utils/help-builder.js +11 -8
  200. package/lib/utils/keycloak-realm-ready.js +101 -0
  201. package/lib/utils/load-cip-capacity-display-config.js +61 -15
  202. package/lib/utils/manifest-source-emit.js +2 -0
  203. package/lib/utils/pipeline-upload-auth-retry.js +82 -0
  204. package/lib/utils/platform-controller-url.js +156 -0
  205. package/lib/utils/postgres-platform-bootstrap.js +199 -0
  206. package/lib/utils/postgres-wipe.js +9 -2
  207. package/lib/utils/resolve-env-mode.js +47 -0
  208. package/lib/utils/secrets-generator.js +31 -25
  209. package/lib/utils/secrets-missing-error.js +164 -0
  210. package/lib/utils/service-url-label.js +81 -0
  211. package/lib/utils/setup-quiet-output.js +25 -0
  212. package/lib/utils/template-helpers.js +15 -0
  213. package/lib/utils/token-manager-client-credentials.js +201 -0
  214. package/lib/utils/token-manager-messages.js +8 -0
  215. package/lib/utils/token-manager-refresh.js +12 -2
  216. package/lib/utils/token-manager.js +86 -105
  217. package/lib/utils/upload-pipeline-ui.js +12 -5
  218. package/lib/utils/upload-sync-options.js +42 -0
  219. package/lib/utils/url-declarative-public-base.js +21 -3
  220. package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
  221. package/lib/utils/validation-poll-ui.js +8 -0
  222. package/lib/utils/validation-run-stage.js +45 -0
  223. package/package.json +1 -1
  224. package/templates/applications/dataplane/application.yaml +2 -1
  225. package/templates/applications/dataplane/env.template +24 -1
  226. package/templates/applications/miso-controller/env.template +16 -0
  227. package/templates/external-system/README.md.hbs +74 -17
  228. package/templates/python/docker-compose.hbs +19 -18
  229. package/templates/typescript/docker-compose.hbs +18 -17
  230. package/lib/commands/test-governance-command-action.js +0 -55
  231. 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
+ };