@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 governance generate — dataplane POST generate per datasource (424.0).
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const { generateDatasourceGovernancePack } = require('../api/governance-scenario-pack.api');
8
+ const {
9
+ buildSubjectsFromOptions,
10
+ resolveGovernanceIntegrationContext
11
+ } = require('./governance-cli-shared');
12
+ const { runWithVerifyStepProgress } = require('../lifecycle/verify-step-progress');
13
+
14
+ /**
15
+ * @async
16
+ * @param {string} systemKey
17
+ * @param {Object} options
18
+ * @returns {Promise<Object>}
19
+ */
20
+ async function runGovernanceGenerateForExternalSystem(systemKey, options = {}) {
21
+ const subjects = buildSubjectsFromOptions(options);
22
+ if (subjects.length === 0) {
23
+ throw new Error(
24
+ 'At least one --subject-user-id or --subject-email is required for governance generate'
25
+ );
26
+ }
27
+
28
+ const { resolvedKey, keys, authConfig, dataplaneUrl } =
29
+ await resolveGovernanceIntegrationContext(systemKey, options);
30
+
31
+ const profile = (options.certificationProfile || 'bronze').trim().toLowerCase();
32
+ const maxSamples = Number(options.maxSamplesPerPartition) || 25;
33
+
34
+ const results = await runWithVerifyStepProgress(
35
+ 'Generating governance scenario packs',
36
+ async progress => {
37
+ const rows = [];
38
+ for (let index = 0; index < keys.length; index += 1) {
39
+ const dsKey = keys[index];
40
+ if (typeof progress.setLabel === 'function') {
41
+ progress.setLabel(`Generating pack: ${dsKey} (${index + 1}/${keys.length})`);
42
+ }
43
+ const row = await generateDatasourceGovernancePack(
44
+ dataplaneUrl,
45
+ authConfig,
46
+ dsKey,
47
+ {
48
+ certificationProfile: profile,
49
+ subjects,
50
+ systemKey: resolvedKey,
51
+ maxSamplesPerPartition: maxSamples
52
+ }
53
+ );
54
+ rows.push({ datasourceKey: dsKey, ...row });
55
+ }
56
+ return rows;
57
+ },
58
+ options
59
+ );
60
+
61
+ return {
62
+ systemKey: resolvedKey,
63
+ command: 'governance generate',
64
+ generated: results.length,
65
+ results
66
+ };
67
+ }
68
+
69
+ module.exports = {
70
+ runGovernanceGenerateForExternalSystem
71
+ };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @fileoverview governance upload — push integration/<systemKey>/scenarios/*.yaml (424.0).
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const { uploadGovernanceScenarioPacks } = require('../lifecycle/scenario-upload');
8
+ const { resolveGovernanceIntegrationContext } = require('./governance-cli-shared');
9
+
10
+ /**
11
+ * @async
12
+ * @param {string} systemKey
13
+ * @param {Object} options
14
+ * @returns {Promise<Object>}
15
+ */
16
+ async function runGovernanceUploadForExternalSystem(systemKey, options = {}) {
17
+ const { resolvedKey, authConfig, dataplaneUrl } = await resolveGovernanceIntegrationContext(
18
+ systemKey,
19
+ options
20
+ );
21
+ const uploaded = await uploadGovernanceScenarioPacks(
22
+ resolvedKey,
23
+ dataplaneUrl,
24
+ authConfig,
25
+ { silent: options.json === true }
26
+ );
27
+ return {
28
+ systemKey: resolvedKey,
29
+ command: 'governance upload',
30
+ uploaded
31
+ };
32
+ }
33
+
34
+ module.exports = {
35
+ runGovernanceUploadForExternalSystem
36
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @fileoverview governance verify — run persisted packs (424.0).
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const { runVerifyGovernanceFromDbPacks } = require('./verify-governance-db');
8
+ const {
9
+ sumEnforcementScenarios,
10
+ aggregateCoverage,
11
+ buildPackOverrideResult
12
+ } = require('./verify-governance-result-builders');
13
+ const { VERDICT, verdictFromPassed } = require('../lifecycle/product-model');
14
+
15
+ /**
16
+ * @async
17
+ * @param {string} systemKey
18
+ * @param {Object} options
19
+ * @returns {Promise<Object>}
20
+ */
21
+ async function runGovernanceVerifyForExternalSystem(systemKey, options = {}) {
22
+ const pathsUtil = require('../utils/paths');
23
+ const appType = await pathsUtil.detectAppType(systemKey).catch(() => null);
24
+ if (!appType || appType.baseDir !== 'integration') {
25
+ throw new Error(
26
+ 'governance verify applies to external integration folders only (integration/<systemKey>/).'
27
+ );
28
+ }
29
+
30
+ if (options.pack) {
31
+ const { runTestGovernanceForExternalSystem } = require('./test-governance-external');
32
+ const runPayload = await runTestGovernanceForExternalSystem(systemKey, options);
33
+ return buildPackOverrideResult(systemKey, runPayload, 'governance verify');
34
+ }
35
+
36
+ const { resolvedKey, datasourceRows } = await runVerifyGovernanceFromDbPacks(systemKey, options);
37
+ if (datasourceRows.length === 0) {
38
+ return {
39
+ systemKey: resolvedKey,
40
+ command: 'governance verify',
41
+ verdict: VERDICT.FAILED,
42
+ policyCoveragePercent: 0,
43
+ dimensionCoveragePercent: 0,
44
+ enforcementScenarios: { passed: 0, total: 0 },
45
+ datasourceRows: []
46
+ };
47
+ }
48
+
49
+ const allVerified = datasourceRows.every(r => r.verdict === VERDICT.VERIFIED);
50
+ const coverage = aggregateCoverage(datasourceRows);
51
+ return {
52
+ systemKey: resolvedKey,
53
+ command: 'governance verify',
54
+ verdict: verdictFromPassed(allVerified),
55
+ policyCoveragePercent: coverage.policy ?? (allVerified ? 100 : 0),
56
+ dimensionCoveragePercent: coverage.dimension ?? (allVerified ? 100 : 0),
57
+ enforcementScenarios: sumEnforcementScenarios(datasourceRows),
58
+ datasourceRows
59
+ };
60
+ }
61
+
62
+ module.exports = {
63
+ runGovernanceVerifyForExternalSystem
64
+ };
@@ -0,0 +1,144 @@
1
+ /**
2
+ * @fileoverview Integration validation scenario packs — governance command family (424.0).
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const {
8
+ collectString,
9
+ governanceGenerateHandler,
10
+ governanceVerifyHandler,
11
+ governanceUploadHandler,
12
+ governanceDownloadHandler
13
+ } = require('./governance-command-action');
14
+ const {
15
+ GOVERNANCE_GENERATE_HELP_AFTER,
16
+ GOVERNANCE_VERIFY_HELP_AFTER,
17
+ GOVERNANCE_UPLOAD_HELP_AFTER,
18
+ GOVERNANCE_DOWNLOAD_HELP_AFTER,
19
+ GOVERNANCE_PARENT_HELP_AFTER
20
+ } = require('../cli/setup-certification.help');
21
+
22
+ const SHARED_OPTS = [
23
+ ['-e, --env <env>', 'Environment: dev, tst, or pro', 'dev'],
24
+ ['--no-sync', 'Skip publishing local integration files before dataplane calls'],
25
+ [
26
+ '--force',
27
+ 'With default sync, pass force to upload (same as aifabrix upload --force)'
28
+ ]
29
+ ];
30
+
31
+ /**
32
+ * @param {import('commander').Command} cmd
33
+ */
34
+ function applySharedGovernanceOpts(cmd) {
35
+ for (const [flags, desc, defaultValue] of SHARED_OPTS) {
36
+ cmd.option(flags, desc, defaultValue);
37
+ }
38
+ }
39
+
40
+ /**
41
+ * @param {import('commander').Command} governance
42
+ */
43
+ function registerGovernanceGenerate(governance) {
44
+ const cmd = governance
45
+ .command('generate <systemKey>')
46
+ .description('Generate integration validation scenario packs on the dataplane')
47
+ .option(
48
+ '--certification-profile <profile>',
49
+ 'Certification profile (bronze, silver, gold, …)',
50
+ 'bronze'
51
+ )
52
+ .option(
53
+ '--subject-user-id <id>',
54
+ 'Subject user id for generated scenarios (repeatable)',
55
+ collectString,
56
+ []
57
+ )
58
+ .option(
59
+ '--subject-email <email>',
60
+ 'Subject email for generated scenarios (repeatable)',
61
+ collectString,
62
+ []
63
+ )
64
+ .option(
65
+ '--max-samples-per-partition <n>',
66
+ 'Max keys per mustInclude/mustExclude partition',
67
+ '25'
68
+ )
69
+ .option('-v, --verbose', 'Verbose output')
70
+ .option('--json', 'Machine-readable envelope')
71
+ .addHelpText('after', GOVERNANCE_GENERATE_HELP_AFTER)
72
+ .action(governanceGenerateHandler);
73
+ applySharedGovernanceOpts(cmd);
74
+ }
75
+
76
+ /**
77
+ * @param {import('commander').Command} governance
78
+ */
79
+ function registerGovernanceVerify(governance) {
80
+ const cmd = governance
81
+ .command('verify <systemKey>')
82
+ .description('Run persisted scenario packs (governance:evaluate)')
83
+ .option(
84
+ '--pack <path>',
85
+ 'Authoring override: local scenario pack YAML instead of dataplane active pack'
86
+ )
87
+ .option('-a, --app <path>', 'Integration folder override (with --pack)')
88
+ .option('--scenario <id>', 'Scenario subset when using --pack (repeatable)', collectString, [])
89
+ .option('-v, --verbose', 'Per-datasource breakdown')
90
+ .option('--json', 'Machine-readable envelope')
91
+ .addHelpText('after', GOVERNANCE_VERIFY_HELP_AFTER)
92
+ .action(governanceVerifyHandler);
93
+ applySharedGovernanceOpts(cmd);
94
+ }
95
+
96
+ /**
97
+ * @param {import('commander').Command} governance
98
+ */
99
+ function registerGovernanceUpload(governance) {
100
+ const cmd = governance
101
+ .command('upload <systemKey>')
102
+ .description('Upload integration/<systemKey>/scenarios/*.yaml to the dataplane')
103
+ .option('--json', 'Machine-readable envelope')
104
+ .addHelpText('after', GOVERNANCE_UPLOAD_HELP_AFTER)
105
+ .action(governanceUploadHandler);
106
+ applySharedGovernanceOpts(cmd);
107
+ }
108
+
109
+ /**
110
+ * @param {import('commander').Command} governance
111
+ */
112
+ function registerGovernanceDownload(governance) {
113
+ const cmd = governance
114
+ .command('download <systemKey>')
115
+ .description('Download active packs to integration/<systemKey>/scenarios/')
116
+ .option('--json', 'Machine-readable envelope')
117
+ .addHelpText('after', GOVERNANCE_DOWNLOAD_HELP_AFTER)
118
+ .action(governanceDownloadHandler);
119
+ applySharedGovernanceOpts(cmd);
120
+ }
121
+
122
+ /**
123
+ * @param {import('commander').Command} program
124
+ */
125
+ function setupGovernanceCommands(program) {
126
+ const governance = program
127
+ .command('governance')
128
+ .description(
129
+ 'Integration validation scenario packs (generate, verify, download, upload)'
130
+ )
131
+ .addHelpText('after', GOVERNANCE_PARENT_HELP_AFTER);
132
+
133
+ applySharedGovernanceOpts(governance);
134
+
135
+ registerGovernanceGenerate(governance);
136
+ registerGovernanceVerify(governance);
137
+ registerGovernanceUpload(governance);
138
+ registerGovernanceDownload(governance);
139
+ }
140
+
141
+ module.exports = {
142
+ setupGovernanceCommands,
143
+ collectString
144
+ };
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @fileoverview CLI action for `aifabrix lifecycle` certification report (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 { runLifecycleForExternalSystem } = require('./lifecycle-external');
13
+ const { displayLifecycleReportTTY } = require('../lifecycle/report-display');
14
+ const { VERDICT } = require('../lifecycle/product-model');
15
+ const { exitCodeFromVerdict } = require('../lifecycle/exit-codes');
16
+ const { lifecycleHasGovernanceSubjects } = require('../lifecycle/lifecycle-governance-options');
17
+
18
+ /**
19
+ * @param {Object} options
20
+ * @param {import('commander').Command} [cmd]
21
+ * @returns {Object}
22
+ */
23
+ function normalizeLifecycleCliOptions(options, cmd) {
24
+ const raw = cmd && Array.isArray(cmd.rawArgs) ? cmd.rawArgs : [];
25
+ const has = flag => raw.includes(flag);
26
+ return {
27
+ env: options.env || 'dev',
28
+ verbose: options.verbose === true || has('-v') || has('--verbose'),
29
+ debug: options.debug === true || has('-d') || has('--debug'),
30
+ json: options.json === true || has('--json'),
31
+ run: options.run === true || has('--run'),
32
+ noSync: cliOptsSkipSync(options, cmd),
33
+ force: options.force === true || has('--force'),
34
+ subjectUserId: options.subjectUserId || [],
35
+ subjectEmail: options.subjectEmail || [],
36
+ certificationProfile: options.certificationProfile || 'bronze'
37
+ };
38
+ }
39
+
40
+ /**
41
+ * @param {Object} report
42
+ * @returns {string}
43
+ */
44
+ function lifecycleVerdictFromReport(report) {
45
+ const ops = report.operations?.verdict;
46
+ const trust = report.trust?.verdict;
47
+ const gov = report.governance?.verdict;
48
+ if (ops === VERDICT.FAILED || trust === VERDICT.FAILED || gov === VERDICT.FAILED) {
49
+ return VERDICT.FAILED;
50
+ }
51
+ if (
52
+ ops === VERDICT.VERIFIED &&
53
+ trust === VERDICT.VERIFIED &&
54
+ gov === VERDICT.VERIFIED
55
+ ) {
56
+ return VERDICT.VERIFIED;
57
+ }
58
+ return VERDICT.NOT_VERIFIED;
59
+ }
60
+
61
+ async function runLifecycleCommandAction(appName, options, cmd) {
62
+ const opts = normalizeLifecycleCliOptions(options, cmd);
63
+ if (lifecycleHasGovernanceSubjects(opts) && !opts.run) {
64
+ throw new Error(
65
+ '--subject-user-id and --subject-email require --run on lifecycle (use verify-governance for governance-only)'
66
+ );
67
+ }
68
+ const result = await runLifecycleForExternalSystem(appName, opts);
69
+ const report = result.report;
70
+
71
+ if (opts.json) {
72
+ const envelope = {
73
+ systemKey: result.systemKey,
74
+ command: 'lifecycle',
75
+ certification: report.certification,
76
+ operations: report.operations,
77
+ trust: report.trust,
78
+ governance: report.governance,
79
+ recommendations: report.recommendations,
80
+ warnings: report.warnings,
81
+ openApiPublished: result.openApiPublished === true,
82
+ certificationProgress: result.certificationProgress ?? null,
83
+ stepsRun: result.stepsRun
84
+ };
85
+ if (opts.verbose) {
86
+ envelope.datasources = report.datasources;
87
+ }
88
+ logger.log(JSON.stringify(envelope, null, 2));
89
+ } else {
90
+ displayLifecycleReportTTY(result.systemKey, report, {
91
+ details: opts.verbose,
92
+ openApiPublished: result.openApiPublished === true,
93
+ certificationProgress: result.certificationProgress ?? null,
94
+ dataplaneUrl: result.dataplaneUrl ?? null,
95
+ dataplaneUiBaseUrl: result.dataplaneUiBaseUrl ?? null
96
+ });
97
+ }
98
+
99
+ const pillarVerdict = lifecycleVerdictFromReport(report);
100
+ const exitCode =
101
+ pillarVerdict === VERDICT.VERIFIED
102
+ ? 0
103
+ : exitCodeFromVerdict(pillarVerdict, { partial: pillarVerdict === VERDICT.NOT_VERIFIED });
104
+ if (exitCode !== 0) {
105
+ process.exit(exitCode);
106
+ }
107
+ }
108
+
109
+ async function lifecycleCommandHandler(appName, options, cmd) {
110
+ try {
111
+ await runLifecycleCommandAction(appName, options, cmd);
112
+ } catch (error) {
113
+ handleCommandError(error, 'lifecycle');
114
+ process.exit(3);
115
+ }
116
+ }
117
+
118
+ module.exports = {
119
+ normalizeLifecycleCliOptions,
120
+ runLifecycleCommandAction,
121
+ lifecycleCommandHandler,
122
+ lifecycleVerdictFromReport
123
+ };
@@ -0,0 +1,268 @@
1
+ /**
2
+ * @fileoverview lifecycle certification report — GET default, --run optional (plan 150.0).
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { getSystemLifecycleReport, runSystemLifecycle } = require('../api/lifecycle.api');
10
+ const { setupIntegrationTestAuth } = require('../external-system/test-auth');
11
+ const { getConfig } = require('../core/config');
12
+ const { cliOptsSkipSync } = require('../utils/cli-sync-options');
13
+ const { syncLocalIfRequested } = require('./test-e2e-external');
14
+ const { runVerifyOperationsForExternalSystem } = require('./verify-operations-external');
15
+ const { runVerifyTrustForExternalSystem } = require('./verify-trust-external');
16
+ const { runGovernanceVerifyForExternalSystem } = require('./governance-verify-external');
17
+ const { VERDICT } = require('../lifecycle/product-model');
18
+ const { buildCertificationProgress } = require('../lifecycle/certification-progress');
19
+ const { resolveOpenApiPublished } = require('../lifecycle/open-api-published');
20
+ const { runWithVerifyStepProgress } = require('../lifecycle/verify-step-progress');
21
+ const { resolveDataplaneUiBaseUrl } = require('../lifecycle/dataplane-ui-url');
22
+ const {
23
+ lifecycleHasGovernanceSubjects,
24
+ lifecycleGovernanceNeedsWork,
25
+ buildGovernanceOptsFromLifecycle
26
+ } = require('../lifecycle/lifecycle-governance-options');
27
+
28
+ /**
29
+ * @async
30
+ * @param {string|null|undefined} dataplaneUrl
31
+ * @returns {Promise<string|null>}
32
+ */
33
+ async function resolveLifecycleDataplaneUiBaseUrl(dataplaneUrl) {
34
+ try {
35
+ return await resolveDataplaneUiBaseUrl(dataplaneUrl);
36
+ } catch {
37
+ return null;
38
+ }
39
+ }
40
+
41
+ /**
42
+ * @async
43
+ * @param {string} systemKey
44
+ * @param {Object} options
45
+ * @returns {Promise<{ authConfig: Object, dataplaneUrl: string }>}
46
+ */
47
+ async function resolveLifecycleAuth(systemKey, options) {
48
+ if (!cliOptsSkipSync(options) && options.run === true) {
49
+ options.lifecycleProgress?.setLabel?.('Checking config on dataplane');
50
+ const uploadCtx = await syncLocalIfRequested(systemKey, {
51
+ ...options,
52
+ suppressPipelineSpinner: true
53
+ });
54
+ if (uploadCtx) {
55
+ options.lifecycleProgress?.setLabel?.('Processing');
56
+ return { authConfig: uploadCtx.authConfig, dataplaneUrl: uploadCtx.dataplaneUrl };
57
+ }
58
+ }
59
+ const configObj = await getConfig();
60
+ return setupIntegrationTestAuth(systemKey, { environment: options.env }, configObj);
61
+ }
62
+
63
+ /**
64
+ * Generate + verify governance when lifecycle --run includes subject selectors.
65
+ * @async
66
+ * @param {string} systemKey
67
+ * @param {Object} report
68
+ * @param {Object} authConfig
69
+ * @param {string} dataplaneUrl
70
+ * @param {Object} options
71
+ */
72
+ async function runLifecycleGovernanceCombinedIfNeeded(
73
+ systemKey,
74
+ report,
75
+ authConfig,
76
+ dataplaneUrl,
77
+ options
78
+ ) {
79
+ if (!lifecycleHasGovernanceSubjects(options)) {
80
+ return;
81
+ }
82
+ if (!lifecycleGovernanceNeedsWork(report)) {
83
+ return;
84
+ }
85
+ const { runVerifyGovernanceCombined } = require('./verify-governance-combined-external');
86
+ await runVerifyGovernanceCombined(
87
+ systemKey,
88
+ buildGovernanceOptsFromLifecycle(options, { authConfig, dataplaneUrl })
89
+ );
90
+ }
91
+
92
+ /**
93
+ * Run missing verify pillars locally when lifecycle/run API unavailable.
94
+ * @async
95
+ * @param {string} systemKey
96
+ * @param {Object} report
97
+ * @param {Object} options
98
+ */
99
+ async function runMissingVerifyStepsLocally(systemKey, report, options) {
100
+ const runOpts = { ...options, noSync: true };
101
+ if (report.operations?.verdict !== VERDICT.VERIFIED) {
102
+ await runVerifyOperationsForExternalSystem(systemKey, runOpts);
103
+ }
104
+ if (report.trust?.verdict !== VERDICT.VERIFIED) {
105
+ await runVerifyTrustForExternalSystem(systemKey, runOpts);
106
+ }
107
+ if (report.governance?.verdict !== VERDICT.VERIFIED) {
108
+ if (lifecycleHasGovernanceSubjects(options)) {
109
+ const { runVerifyGovernanceCombined } = require('./verify-governance-combined-external');
110
+ await runVerifyGovernanceCombined(
111
+ systemKey,
112
+ buildGovernanceOptsFromLifecycle(options, {
113
+ authConfig: options.authConfig,
114
+ dataplaneUrl: options.dataplaneUrl
115
+ })
116
+ );
117
+ } else {
118
+ await runGovernanceVerifyForExternalSystem(systemKey, runOpts);
119
+ }
120
+ }
121
+ }
122
+
123
+ /**
124
+ * @async
125
+ * @param {string} systemKey
126
+ * @param {Object} report
127
+ * @param {string} dataplaneUrl
128
+ * @param {string|null} dataplaneUiBaseUrl
129
+ * @param {Object} authConfig
130
+ * @param {Object} [extra]
131
+ * @returns {Promise<Object>}
132
+ */
133
+ async function buildLifecycleResult(
134
+ systemKey,
135
+ report,
136
+ dataplaneUrl,
137
+ dataplaneUiBaseUrl,
138
+ authConfig,
139
+ extra = {}
140
+ ) {
141
+ const openApiPublished = await resolveOpenApiPublished(dataplaneUrl, authConfig, systemKey);
142
+ return {
143
+ systemKey,
144
+ command: 'lifecycle',
145
+ report,
146
+ dataplaneUrl,
147
+ dataplaneUiBaseUrl,
148
+ openApiPublished,
149
+ certificationProgress: buildCertificationProgress(report, { openApiPublished }),
150
+ ...extra
151
+ };
152
+ }
153
+
154
+ /**
155
+ * @async
156
+ * @param {string} systemKey
157
+ * @param {Object} authConfig
158
+ * @param {string} dataplaneUrl
159
+ * @param {string|null} dataplaneUiBaseUrl
160
+ * @param {Object} options
161
+ * @returns {Promise<Object>}
162
+ */
163
+ async function runLifecycleViaDataplaneApi(
164
+ systemKey,
165
+ authConfig,
166
+ dataplaneUrl,
167
+ dataplaneUiBaseUrl,
168
+ options
169
+ ) {
170
+ if (lifecycleHasGovernanceSubjects(options)) {
171
+ const preReport = await getSystemLifecycleReport(dataplaneUrl, authConfig, systemKey, {
172
+ details: options.verbose === true
173
+ });
174
+ await runLifecycleGovernanceCombinedIfNeeded(
175
+ systemKey,
176
+ preReport,
177
+ authConfig,
178
+ dataplaneUrl,
179
+ options
180
+ );
181
+ }
182
+ const runRes = await runSystemLifecycle(dataplaneUrl, authConfig, systemKey, {});
183
+ return buildLifecycleResult(
184
+ systemKey,
185
+ runRes.report,
186
+ dataplaneUrl,
187
+ dataplaneUiBaseUrl,
188
+ authConfig,
189
+ { stepsRun: runRes.stepsRun || [], source: 'api' }
190
+ );
191
+ }
192
+
193
+ /**
194
+ * @async
195
+ * @param {string} systemKey
196
+ * @param {Object} options
197
+ * @returns {Promise<Object>}
198
+ */
199
+ async function executeLifecycleWork(systemKey, options = {}) {
200
+ const { authConfig, dataplaneUrl } = await resolveLifecycleAuth(systemKey, options);
201
+ const dataplaneUiBaseUrl = await resolveLifecycleDataplaneUiBaseUrl(dataplaneUrl);
202
+
203
+ if (options.run === true) {
204
+ try {
205
+ return await runLifecycleViaDataplaneApi(
206
+ systemKey,
207
+ authConfig,
208
+ dataplaneUrl,
209
+ dataplaneUiBaseUrl,
210
+ options
211
+ );
212
+ } catch {
213
+ const preReport = await getSystemLifecycleReport(dataplaneUrl, authConfig, systemKey, {
214
+ details: options.verbose === true
215
+ });
216
+ await runMissingVerifyStepsLocally(systemKey, preReport, {
217
+ ...options,
218
+ authConfig,
219
+ dataplaneUrl
220
+ });
221
+ }
222
+ }
223
+
224
+ const report = await getSystemLifecycleReport(dataplaneUrl, authConfig, systemKey, {
225
+ details: options.verbose === true
226
+ });
227
+ return buildLifecycleResult(
228
+ systemKey,
229
+ report,
230
+ dataplaneUrl,
231
+ dataplaneUiBaseUrl,
232
+ authConfig,
233
+ { source: options.run ? 'local-fallback' : 'api' }
234
+ );
235
+ }
236
+
237
+ /**
238
+ * @async
239
+ * @param {string} systemKey
240
+ * @param {Object} options
241
+ * @returns {Promise<Object>}
242
+ */
243
+ async function runLifecycleForExternalSystem(systemKey, options = {}) {
244
+ const pathsUtil = require('../utils/paths');
245
+ const appType = await pathsUtil.detectAppType(systemKey).catch(() => null);
246
+ if (!appType || appType.baseDir !== 'integration') {
247
+ throw new Error(
248
+ 'lifecycle applies to external integration folders only (integration/<systemKey>/).'
249
+ );
250
+ }
251
+
252
+ if (options.run === true) {
253
+ return runWithVerifyStepProgress(
254
+ 'Processing',
255
+ async(progress) => executeLifecycleWork(systemKey, { ...options, lifecycleProgress: progress }),
256
+ { json: options.json === true }
257
+ );
258
+ }
259
+
260
+ return executeLifecycleWork(systemKey, options);
261
+ }
262
+
263
+ module.exports = {
264
+ runLifecycleForExternalSystem,
265
+ runMissingVerifyStepsLocally,
266
+ runLifecycleGovernanceCombinedIfNeeded,
267
+ resolveLifecycleAuth
268
+ };