@aifabrix/builder 2.45.0 → 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 (352) 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/docs-rules.mdc +3 -1
  4. package/.cursor/rules/project-rules.mdc +1 -0
  5. package/README.md +43 -17
  6. package/integration/hubspot-test/wizard-hubspot-e2e.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 +69 -121
  12. package/lib/api/agent-metadata-validation.api.js +93 -0
  13. package/lib/api/api-response-errors.js +124 -0
  14. package/lib/api/audit-api-helpers.js +68 -0
  15. package/lib/api/audit.api.js +119 -0
  16. package/lib/api/auth-cache.api.js +44 -0
  17. package/lib/api/certificates.api.js +4 -4
  18. package/lib/api/credential.api.js +2 -2
  19. package/lib/api/dataplane-health.api.js +137 -0
  20. package/lib/api/dataplane-sync.api.js +27 -0
  21. package/lib/api/datasources-core.api.js +21 -18
  22. package/lib/api/datasources-extended.api.js +22 -22
  23. package/lib/api/dimensions.api.js +3 -0
  24. package/lib/api/external-systems.api.js +13 -13
  25. package/lib/api/governance-scenario-pack.api.js +159 -0
  26. package/lib/api/governance-scenarios.api.js +39 -0
  27. package/lib/api/groups.api.js +79 -0
  28. package/lib/api/index.js +88 -5
  29. package/lib/api/lifecycle.api.js +77 -0
  30. package/lib/api/pipeline.api.js +7 -5
  31. package/lib/api/protection.api.js +157 -0
  32. package/lib/api/records-bulk.api.js +43 -0
  33. package/lib/api/records-search-parse.js +49 -0
  34. package/lib/api/records-search.api.js +29 -0
  35. package/lib/api/types/agent-metadata-validation.types.js +67 -0
  36. package/lib/api/types/audit.types.js +72 -0
  37. package/lib/api/types/dataplane-health.types.js +27 -0
  38. package/lib/api/types/dimensions.types.js +2 -0
  39. package/lib/api/types/governance-scenarios.types.js +39 -0
  40. package/lib/api/types/protection.types.js +69 -0
  41. package/lib/api/types/records-bulk.types.js +35 -0
  42. package/lib/api/types/records-search.types.js +28 -0
  43. package/lib/api/user-groups.api.js +50 -0
  44. package/lib/api/users.api.js +95 -0
  45. package/lib/api/validation-run.api.js +3 -3
  46. package/lib/api/validation-runner.js +5 -3
  47. package/lib/api/wizard-platform.api.js +3 -3
  48. package/lib/api/wizard.api.js +21 -21
  49. package/lib/app/deploy-config.js +4 -1
  50. package/lib/app/deploy.js +34 -19
  51. package/lib/app/down.js +20 -1
  52. package/lib/app/push.js +4 -5
  53. package/lib/app/register.js +7 -4
  54. package/lib/app/run-env-compose.js +84 -30
  55. package/lib/build/index.js +5 -0
  56. package/lib/certification/sync-system-certification.js +13 -6
  57. package/lib/cli/index.js +8 -2
  58. package/lib/cli/infra-guided-auth.js +109 -0
  59. package/lib/cli/infra-guided.js +91 -69
  60. package/lib/cli/setup-app.help.js +19 -2
  61. package/lib/cli/setup-app.js +58 -23
  62. package/lib/cli/setup-app.test-commands.js +28 -21
  63. package/lib/cli/setup-auth.js +55 -3
  64. package/lib/cli/setup-certification-commands.js +147 -0
  65. package/lib/cli/setup-certification.help.js +141 -0
  66. package/lib/cli/setup-environment.js +19 -2
  67. package/lib/cli/setup-external-system-help.js +62 -0
  68. package/lib/cli/setup-external-system.js +62 -6
  69. package/lib/cli/setup-infra.js +9 -1
  70. package/lib/cli/setup-platform.js +6 -1
  71. package/lib/cli/setup-secrets.js +33 -1
  72. package/lib/cli/setup-utility-help-after.js +65 -0
  73. package/lib/cli/setup-utility-repair.js +198 -0
  74. package/lib/cli/setup-utility-resolve.js +42 -6
  75. package/lib/cli/setup-utility-validate.js +197 -0
  76. package/lib/cli/setup-utility.js +41 -258
  77. package/lib/commands/auth-status-client-tokens.js +214 -0
  78. package/lib/commands/auth-status-dataplane-version.js +269 -0
  79. package/lib/commands/auth-status-display.js +94 -0
  80. package/lib/commands/auth-status.js +111 -53
  81. package/lib/commands/credential-push.js +10 -5
  82. package/lib/commands/datasource-load-export-cli.js +178 -0
  83. package/lib/commands/datasource-test-trust-cli.js +118 -0
  84. package/lib/commands/datasource-unified-test-cli.js +31 -20
  85. package/lib/commands/datasource-unified-test-cli.options.js +22 -3
  86. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +5 -5
  87. package/lib/commands/datasource-verify-audit-cli.js +96 -0
  88. package/lib/commands/datasource.js +68 -1
  89. package/lib/commands/dev-show-display.js +8 -1
  90. package/lib/commands/dimension-value.js +43 -13
  91. package/lib/commands/dimension.js +38 -7
  92. package/lib/commands/governance-cli-shared.js +94 -0
  93. package/lib/commands/governance-command-action.js +132 -0
  94. package/lib/commands/governance-download-external.js +34 -0
  95. package/lib/commands/governance-generate-external.js +71 -0
  96. package/lib/commands/governance-upload-external.js +36 -0
  97. package/lib/commands/governance-verify-external.js +64 -0
  98. package/lib/commands/governance.js +144 -0
  99. package/lib/commands/identity-apply-sync.js +131 -0
  100. package/lib/commands/identity-group-cli.js +146 -0
  101. package/lib/commands/identity-membership-role-cache.js +175 -0
  102. package/lib/commands/identity-shared.js +94 -0
  103. package/lib/commands/identity-user-cli.js +158 -0
  104. package/lib/commands/identity.js +43 -0
  105. package/lib/commands/lifecycle-command-action.js +123 -0
  106. package/lib/commands/lifecycle-external.js +268 -0
  107. package/lib/commands/login.js +56 -17
  108. package/lib/commands/protection-cli-leaves.js +286 -0
  109. package/lib/commands/protection.js +50 -0
  110. package/lib/commands/repair-auth-apply.js +127 -0
  111. package/lib/commands/repair-changed-files.js +41 -0
  112. package/lib/commands/repair-datasource-keys.js +4 -1
  113. package/lib/commands/repair-datasource-run.js +59 -0
  114. package/lib/commands/repair-datasource-test-payload.js +259 -0
  115. package/lib/commands/repair-datasource.js +1 -51
  116. package/lib/commands/repair-env-template.js +64 -13
  117. package/lib/commands/repair-external-run.js +216 -0
  118. package/lib/commands/repair-openapi-sync.js +23 -0
  119. package/lib/commands/repair-persist.js +4 -0
  120. package/lib/commands/repair-rbac.js +52 -1
  121. package/lib/commands/repair-steps.js +145 -0
  122. package/lib/commands/repair.js +29 -286
  123. package/lib/commands/secrets-get.js +184 -0
  124. package/lib/commands/secrets-remove-all.js +3 -1
  125. package/lib/commands/setup-image-refresh.js +146 -0
  126. package/lib/commands/setup-modes.js +158 -162
  127. package/lib/commands/setup-platform-auth.js +76 -0
  128. package/lib/commands/setup-prompts-admin.js +244 -0
  129. package/lib/commands/setup-prompts-platform-mode.js +67 -0
  130. package/lib/commands/setup-prompts-validators.js +36 -0
  131. package/lib/commands/setup-prompts.js +24 -76
  132. package/lib/commands/setup-run-context.js +45 -0
  133. package/lib/commands/setup-spinners.js +39 -0
  134. package/lib/commands/setup.js +27 -5
  135. package/lib/commands/teardown.js +39 -0
  136. package/lib/commands/test-e2e-external.js +61 -14
  137. package/lib/commands/test-governance-cli-options.js +47 -0
  138. package/lib/commands/test-governance-external.js +67 -0
  139. package/lib/commands/test-trust-cli-options.js +32 -0
  140. package/lib/commands/test-trust-external.js +126 -0
  141. package/lib/commands/up-common.js +25 -13
  142. package/lib/commands/up-dataplane.js +50 -13
  143. package/lib/commands/upload-publish-context.js +75 -0
  144. package/lib/commands/upload-sidecar-followups.js +89 -0
  145. package/lib/commands/upload.js +108 -105
  146. package/lib/commands/verify-governance-combined-external.js +61 -0
  147. package/lib/commands/verify-governance-command-action.js +64 -0
  148. package/lib/commands/verify-governance-db.js +102 -0
  149. package/lib/commands/verify-governance-external.js +77 -0
  150. package/lib/commands/verify-governance-result-builders.js +71 -0
  151. package/lib/commands/verify-operations-command-action.js +68 -0
  152. package/lib/commands/verify-operations-external.js +268 -0
  153. package/lib/commands/verify-operations-persist.js +75 -0
  154. package/lib/commands/verify-operations-step-plan.js +68 -0
  155. package/lib/commands/verify-operations-steps.js +111 -0
  156. package/lib/commands/verify-trust-command-action.js +70 -0
  157. package/lib/commands/verify-trust-external.js +67 -0
  158. package/lib/commands/wizard-config-normalizer.js +43 -23
  159. package/lib/commands/wizard-core.js +5 -0
  160. package/lib/core/admin-password-generator.js +38 -0
  161. package/lib/core/admin-secrets-bundle.js +111 -0
  162. package/lib/core/admin-secrets-env-overlay.js +62 -0
  163. package/lib/core/admin-secrets.js +32 -4
  164. package/lib/core/config-attach-extensions.js +3 -0
  165. package/lib/core/config-device-dataplane.js +185 -0
  166. package/lib/core/config-platform-controller.js +44 -0
  167. package/lib/core/config-setup-installation-profile.js +42 -0
  168. package/lib/core/config-setup-platform-mode.js +46 -0
  169. package/lib/core/config.js +46 -36
  170. package/lib/core/secrets-admin-env.js +6 -2
  171. package/lib/core/secrets-ensure.js +4 -0
  172. package/lib/core/secrets-env-content.js +54 -48
  173. package/lib/core/secrets-env-write.js +10 -1
  174. package/lib/core/secrets-infra-placeholder-sync.js +2 -0
  175. package/lib/core/setup-installation-profile.js +43 -0
  176. package/lib/core/setup-platform-mode.js +55 -0
  177. package/lib/datasource/agent-trust-debug-log.js +45 -0
  178. package/lib/datasource/agent-trust-fetch.js +115 -0
  179. package/lib/datasource/agent-trust-map.js +101 -0
  180. package/lib/datasource/agent-trust-mock.js +44 -0
  181. package/lib/datasource/agent-trust-run.js +95 -0
  182. package/lib/datasource/agent-trust-timeout.js +25 -0
  183. package/lib/datasource/audit-evidence-display.js +80 -0
  184. package/lib/datasource/audit-evidence-extract-debug.js +115 -0
  185. package/lib/datasource/audit-evidence-extract.js +180 -0
  186. package/lib/datasource/audit-evidence-matrix-rows.js +158 -0
  187. package/lib/datasource/audit-evidence-operation-aliases.js +63 -0
  188. package/lib/datasource/audit-evidence-poll.js +109 -0
  189. package/lib/datasource/audit-evidence-run.js +177 -0
  190. package/lib/datasource/audit-evidence-verify-helpers.js +167 -0
  191. package/lib/datasource/audit-evidence-verify-matrix.js +205 -0
  192. package/lib/datasource/audit-evidence-verify.js +108 -0
  193. package/lib/datasource/bulk-loader-run-batches.js +100 -0
  194. package/lib/datasource/bulk-loader-service-retry.js +52 -0
  195. package/lib/datasource/bulk-loader-service.js +127 -0
  196. package/lib/datasource/capability/run-capability-dimension.js +2 -1
  197. package/lib/datasource/datasource-exporter-resolve.js +82 -0
  198. package/lib/datasource/datasource-exporter-service.js +144 -0
  199. package/lib/datasource/datasource-identifier.js +148 -0
  200. package/lib/datasource/datasource-load-export-context.js +95 -0
  201. package/lib/datasource/integration-context.js +6 -4
  202. package/lib/datasource/local-data-paths.js +145 -0
  203. package/lib/datasource/log-cleaner.js +241 -0
  204. package/lib/datasource/log-viewer.js +111 -6
  205. package/lib/datasource/record-file-parser.js +85 -0
  206. package/lib/datasource/record-mapper.js +129 -0
  207. package/lib/datasource/resolve-app.js +74 -55
  208. package/lib/datasource/test-e2e.js +29 -2
  209. package/lib/datasource/unified-validation-run-body.js +3 -1
  210. package/lib/datasource/unified-validation-run-resolve.js +45 -12
  211. package/lib/datasource/unified-validation-run.js +47 -18
  212. package/lib/datasource/validate.js +37 -20
  213. package/lib/deployment/environment-poll-status.js +138 -0
  214. package/lib/deployment/environment.js +42 -34
  215. package/lib/external-system/download.js +21 -20
  216. package/lib/external-system/generator.js +5 -1
  217. package/lib/external-system/integration-auth-context.js +45 -0
  218. package/lib/external-system/test-auth.js +12 -5
  219. package/lib/external-system/test-system-level.js +25 -4
  220. package/lib/external-system/test.js +9 -7
  221. package/lib/generator/external-controller-manifest.js +15 -0
  222. package/lib/governance/governance-cli-errors.js +96 -0
  223. package/lib/governance/governance-download-display.js +38 -0
  224. package/lib/governance/governance-pack-loader.js +70 -0
  225. package/lib/governance/governance-run-display.js +309 -0
  226. package/lib/identity/identity-apply-core.js +108 -0
  227. package/lib/identity/identity-apply-phases.js +244 -0
  228. package/lib/identity/identity-apply-service.js +77 -0
  229. package/lib/identity/identity-csv-parser.js +114 -0
  230. package/lib/infrastructure/admin-secrets-apply.js +84 -0
  231. package/lib/infrastructure/admin-secrets-ensure.js +130 -0
  232. package/lib/infrastructure/admin-secrets-resolve.js +95 -0
  233. package/lib/infrastructure/admin-secrets-sync.js +91 -0
  234. package/lib/infrastructure/helpers.js +23 -129
  235. package/lib/infrastructure/index.js +5 -6
  236. package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
  237. package/lib/internal/fs-real-sync.js +29 -1
  238. package/lib/lifecycle/certification-progress.js +231 -0
  239. package/lib/lifecycle/dataplane-ui-url.js +145 -0
  240. package/lib/lifecycle/exit-codes.js +24 -0
  241. package/lib/lifecycle/json-envelope.js +25 -0
  242. package/lib/lifecycle/lifecycle-governance-options.js +51 -0
  243. package/lib/lifecycle/logger-quiet.js +29 -0
  244. package/lib/lifecycle/open-api-published.js +59 -0
  245. package/lib/lifecycle/operations-readiness-metrics.js +101 -0
  246. package/lib/lifecycle/product-model.js +196 -0
  247. package/lib/lifecycle/report-display.js +471 -0
  248. package/lib/lifecycle/scenario-upload.js +191 -0
  249. package/lib/lifecycle/verify-step-progress.js +87 -0
  250. package/lib/parameters/infra-kv-discovery.js +27 -2
  251. package/lib/protection/auth-context.js +51 -0
  252. package/lib/protection/convert-batch.js +90 -0
  253. package/lib/protection/load.js +41 -0
  254. package/lib/protection/paths.js +158 -0
  255. package/lib/protection/preflight-datasource-ready.js +46 -0
  256. package/lib/protection/protection-create-probe-lines.js +142 -0
  257. package/lib/protection/protection-create-probes.js +95 -0
  258. package/lib/protection/protection-create-scaffold.js +281 -0
  259. package/lib/protection/protection-display-helpers.js +445 -0
  260. package/lib/protection/protection-display.js +215 -0
  261. package/lib/protection/protection-preset-registry.js +97 -0
  262. package/lib/protection/report-exit.js +62 -0
  263. package/lib/protection/resolve.js +202 -0
  264. package/lib/protection/run-commands-validate.js +130 -0
  265. package/lib/protection/run-commands.js +216 -0
  266. package/lib/protection/run-protection-create-helpers.js +134 -0
  267. package/lib/protection/run-protection-create-probes-flow.js +43 -0
  268. package/lib/protection/run-protection-create.js +191 -0
  269. package/lib/protection/scope.js +22 -0
  270. package/lib/protection/sync-after-upload.js +64 -0
  271. package/lib/protection/upload-batch.js +127 -0
  272. package/lib/protection/validate-batch.js +113 -0
  273. package/lib/protection/validate-local.js +65 -0
  274. package/lib/resolvers/dimension-file.js +29 -4
  275. package/lib/schema/application-schema.json +1 -1
  276. package/lib/schema/datasource-test-run.schema.json +89 -6
  277. package/lib/schema/external-datasource.schema.json +2636 -2588
  278. package/lib/schema/external-system.schema.json +1089 -761
  279. package/lib/schema/flag-map-validation-run.json +2 -2
  280. package/lib/schema/infra.parameter.yaml +45 -0
  281. package/lib/schema/protection.schema.json +374 -0
  282. package/lib/schema/type/credential-field-registry.json +642 -0
  283. package/lib/schema/wizard-config.schema.json +1 -1
  284. package/lib/utils/agent-trust-run-display.js +231 -0
  285. package/lib/utils/agent-trust-run-exit.js +59 -0
  286. package/lib/utils/agent-trust-wait-ui.js +94 -0
  287. package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
  288. package/lib/utils/api.js +55 -31
  289. package/lib/utils/app-relative-path-env.js +112 -0
  290. package/lib/utils/cli-exit-codes.js +30 -0
  291. package/lib/utils/cli-secrets-error-format.js +83 -21
  292. package/lib/utils/cli-sync-options.js +33 -0
  293. package/lib/utils/cli-utils.js +16 -4
  294. package/lib/utils/compose-generate-docker-compose.js +4 -0
  295. package/lib/utils/compose-traefik-ingress-base.js +16 -1
  296. package/lib/utils/config-secrets-path.js +46 -0
  297. package/lib/utils/controller-url.js +88 -1
  298. package/lib/utils/credential-push-ui.js +90 -0
  299. package/lib/utils/credential-secrets-env.js +137 -9
  300. package/lib/utils/dataplane-cli-version-gate.js +202 -0
  301. package/lib/utils/dataplane-cli-version-help.js +74 -0
  302. package/lib/utils/dataplane-resolver.js +129 -2
  303. package/lib/utils/datasource-export-display.js +137 -0
  304. package/lib/utils/datasource-load-display.js +174 -0
  305. package/lib/utils/datasource-load-export-ui.js +120 -0
  306. package/lib/utils/datasource-test-run-capability-scope.js +3 -3
  307. package/lib/utils/datasource-test-run-display.js +3 -3
  308. package/lib/utils/datasource-test-run-tty-log.js +5 -1
  309. package/lib/utils/declarative-url-ports.js +3 -3
  310. package/lib/utils/deployment-auth-mode.js +41 -0
  311. package/lib/utils/developer-volume-id.js +33 -0
  312. package/lib/utils/env-copy.js +14 -9
  313. package/lib/utils/env-kv-orphan-lines.js +43 -0
  314. package/lib/utils/error-formatters/network-errors.js +13 -4
  315. package/lib/utils/external-env-template.js +1 -0
  316. package/lib/utils/external-system-readiness-core.js +10 -0
  317. package/lib/utils/external-system-readiness-display.js +80 -23
  318. package/lib/utils/health-check.js +4 -1
  319. package/lib/utils/help-builder.js +35 -26
  320. package/lib/utils/keycloak-realm-ready.js +101 -0
  321. package/lib/utils/load-cip-capacity-display-config.js +61 -15
  322. package/lib/utils/manifest-source-emit.js +24 -0
  323. package/lib/utils/pipeline-upload-auth-retry.js +82 -0
  324. package/lib/utils/platform-controller-url.js +156 -0
  325. package/lib/utils/postgres-platform-bootstrap.js +199 -0
  326. package/lib/utils/postgres-wipe.js +9 -2
  327. package/lib/utils/resolve-env-mode.js +47 -0
  328. package/lib/utils/secrets-generator.js +31 -25
  329. package/lib/utils/secrets-missing-error.js +164 -0
  330. package/lib/utils/semver-compare.js +127 -0
  331. package/lib/utils/service-url-label.js +81 -0
  332. package/lib/utils/setup-quiet-output.js +25 -0
  333. package/lib/utils/template-helpers.js +15 -0
  334. package/lib/utils/token-manager-client-credentials.js +201 -0
  335. package/lib/utils/token-manager-messages.js +8 -0
  336. package/lib/utils/token-manager-refresh.js +12 -2
  337. package/lib/utils/token-manager.js +86 -105
  338. package/lib/utils/upload-pipeline-ui.js +98 -0
  339. package/lib/utils/upload-sync-options.js +42 -0
  340. package/lib/utils/url-declarative-public-base.js +21 -3
  341. package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
  342. package/lib/utils/validation-poll-ui.js +22 -7
  343. package/lib/utils/validation-run-stage.js +45 -0
  344. package/lib/validation/wizard-config-validator.js +58 -19
  345. package/package.json +1 -1
  346. package/templates/applications/dataplane/application.yaml +2 -1
  347. package/templates/applications/dataplane/env.template +36 -1
  348. package/templates/applications/dataplane/rbac.yaml +4 -0
  349. package/templates/applications/miso-controller/env.template +16 -0
  350. package/templates/external-system/README.md.hbs +116 -11
  351. package/templates/python/docker-compose.hbs +19 -18
  352. package/templates/typescript/docker-compose.hbs +18 -17
@@ -0,0 +1,197 @@
1
+ /**
2
+ * `aifabrix validate` and `diff` command wiring (split from setup-utility for size limits).
3
+ *
4
+ * @fileoverview Validate and diff CLI commands
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const chalk = require('chalk');
13
+ const logger = require('../utils/logger');
14
+ const { handleCommandError } = require('../utils/cli-utils');
15
+ const { VALIDATE_HELP_AFTER } = require('./setup-utility-help-after');
16
+
17
+ /**
18
+ * @param {string} appOrFile
19
+ * @param {object} result
20
+ * @param {string} outFormat
21
+ */
22
+ function emitManifestAfterValidateIfApplicable(appOrFile, result, outFormat) {
23
+ if (outFormat === 'json' || !result?.appPath || !appOrFile || typeof appOrFile !== 'string') {
24
+ return;
25
+ }
26
+ try {
27
+ if (fs.existsSync(appOrFile) && fs.statSync(appOrFile).isFile()) {
28
+ return;
29
+ }
30
+ const { emitManifestMetadataLineIfTTY } = require('../utils/manifest-source-emit');
31
+ emitManifestMetadataLineIfTTY(logger, {
32
+ appKey: appOrFile,
33
+ appPath: result.appPath,
34
+ envOnly: false,
35
+ json: false
36
+ });
37
+ } catch {
38
+ /* ignore emit failures */
39
+ }
40
+ }
41
+
42
+ /**
43
+ * @param {object} validate
44
+ * @param {object} opts
45
+ * @returns {Promise<boolean>}
46
+ */
47
+ async function runValidateBatchBranch(validate, opts) {
48
+ const integration = opts.integration === true;
49
+ const builder = opts.builder === true;
50
+ if (!integration && !builder) {
51
+ return false;
52
+ }
53
+ const outFormat = (opts.format || 'default').toLowerCase();
54
+ const batchResult = integration && builder
55
+ ? await validate.validateAll(opts)
56
+ : integration
57
+ ? await validate.validateAllIntegrations(opts)
58
+ : await validate.validateAllBuilderApps(opts);
59
+ if (outFormat === 'json') {
60
+ logger.log(JSON.stringify(batchResult, null, 2));
61
+ } else {
62
+ validate.displayBatchValidationResults(batchResult);
63
+ }
64
+ if (!batchResult.valid) process.exit(1);
65
+ return true;
66
+ }
67
+
68
+ /**
69
+ * @param {string} appOrFile
70
+ * @param {object} opts
71
+ * @returns {Promise<void>}
72
+ */
73
+ async function runProtectionValidateBranch(appOrFile, opts) {
74
+ const { validateProtectionBatchCommand } = require('../protection/validate-batch');
75
+ const code = await validateProtectionBatchCommand(
76
+ {
77
+ env: opts.env,
78
+ json: (opts.format || '').toLowerCase() === 'json',
79
+ warningsAsErrors: opts.warningsAsErrors === true,
80
+ simulate: opts.simulate === true,
81
+ verbose: opts.verbose === true
82
+ },
83
+ logger
84
+ );
85
+ if (code !== 0) {
86
+ process.exit(code);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * @param {object} result
92
+ * @param {string} appOrFile
93
+ * @returns {object}
94
+ */
95
+ function buildValidateJsonPayload(result, appOrFile) {
96
+ let payload = result;
97
+ try {
98
+ if (result?.appPath && appOrFile && typeof appOrFile === 'string') {
99
+ if (!(fs.existsSync(appOrFile) && fs.statSync(appOrFile).isFile())) {
100
+ const { getManifestSourcePayload } = require('../utils/manifest-source-emit');
101
+ payload = { ...result, manifestSource: getManifestSourcePayload(appOrFile, result.appPath) };
102
+ }
103
+ }
104
+ } catch {
105
+ /* keep plain result */
106
+ }
107
+ return payload;
108
+ }
109
+
110
+ /**
111
+ * @param {string} appOrFile
112
+ * @param {object} result
113
+ * @param {string} outFormat
114
+ * @param {object} validate
115
+ */
116
+ function displaySingleValidateResult(appOrFile, result, outFormat, validate) {
117
+ emitManifestAfterValidateIfApplicable(appOrFile, result, outFormat);
118
+ if (outFormat === 'json') {
119
+ logger.log(JSON.stringify(buildValidateJsonPayload(result, appOrFile), null, 2));
120
+ return;
121
+ }
122
+ validate.displayValidationResults(result);
123
+ }
124
+
125
+ /**
126
+ * @param {string} appOrFile
127
+ * @param {object} options
128
+ * @returns {Promise<void>}
129
+ */
130
+ async function runValidateCommand(appOrFile, options) {
131
+ const validate = require('../validation/validate');
132
+ const opts = options.opts ? options.opts() : options;
133
+ const { isProtectionScope } = require('../protection/scope');
134
+ if (isProtectionScope(appOrFile)) {
135
+ await runProtectionValidateBranch(appOrFile, opts);
136
+ return;
137
+ }
138
+ if (await runValidateBatchBranch(validate, opts)) {
139
+ return;
140
+ }
141
+ const outFormat = (opts.format || 'default').toLowerCase();
142
+ if (!appOrFile || typeof appOrFile !== 'string') {
143
+ logger.log(chalk.red('App name or file path is required, or use --integration / --builder'));
144
+ process.exit(1);
145
+ }
146
+ const result = await validate.validateAppOrFile(appOrFile, {
147
+ ...opts,
148
+ certSync: opts.certSync === true
149
+ });
150
+ displaySingleValidateResult(appOrFile, result, outFormat, validate);
151
+ if (!result.valid) process.exit(1);
152
+ }
153
+
154
+ /**
155
+ * @param {import('commander').Command} program
156
+ */
157
+ function setupValidateDiffCommands(program) {
158
+ program.command('validate [appKey|systemKey|file]')
159
+ .description('Validate appKey, systemKey, file path, .protection batch, or all under integration/ and builder/')
160
+ .addHelpText('after', VALIDATE_HELP_AFTER)
161
+ .option('--format <format>', 'Output format: json | default (human-readable)')
162
+ .option('--integration', 'Validate all applications under integration/')
163
+ .option('--builder', 'Validate all applications under builder/')
164
+ .option('--warnings-as-errors', 'For .protection: pass strict=true to dataplane validate')
165
+ .option('--simulate', 'For .protection: run simulate after validate')
166
+ .option(
167
+ '--cert-sync',
168
+ 'After successful validation of an external integration, refresh the system file certification block from the dataplane (requires login)'
169
+ )
170
+ .action((appOrFile, options) => {
171
+ runValidateCommand(appOrFile, options).catch((error) => {
172
+ handleCommandError(error, 'validate');
173
+ process.exit(1);
174
+ });
175
+ });
176
+
177
+ program.command('diff <file1> <file2>')
178
+ .description('Diff two config files (optional schema validate)')
179
+ .option('--no-validate', 'Skip schema validation (type check still applied)')
180
+ .action(async(file1, file2, cmd) => {
181
+ try {
182
+ const diff = require('../core/diff');
183
+ const opts = cmd.opts();
184
+ const result = await diff.compareFiles(file1, file2, { validate: opts.validate !== false });
185
+ diff.formatDiffOutput(result);
186
+ if (!result.identical) process.exit(1);
187
+ } catch (error) {
188
+ handleCommandError(error, 'diff');
189
+ process.exit(1);
190
+ }
191
+ });
192
+ }
193
+
194
+ module.exports = {
195
+ setupValidateDiffCommands,
196
+ runValidateCommand
197
+ };
@@ -1,4 +1,3 @@
1
- const { formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
2
1
  /**
3
2
  * CLI utility command setup (resolve, json, split-json, show, validate, diff).
4
3
  *
@@ -10,45 +9,15 @@ const { formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
10
9
  const path = require('path');
11
10
  const fs = require('fs');
12
11
  const chalk = require('chalk');
12
+ const { formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
13
13
  const generator = require('../generator');
14
14
  const logger = require('../utils/logger');
15
15
  const { handleCommandError, logOfflinePathWhenType } = require('../utils/cli-utils');
16
16
  const { detectAppType, getDeployJsonPath, getResolveAppPath } = require('../utils/paths');
17
17
  const { setupResolveCommand } = require('./setup-utility-resolve');
18
-
19
- const JSON_HELP_AFTER = `
20
- Example:
21
- $ aifabrix json myapp
22
- Generates *-deploy.json (or application-schema.json) for commit before deploy.
23
- `;
24
-
25
- const VALIDATE_HELP_AFTER = `
26
- Examples:
27
- $ aifabrix validate myapp
28
- $ aifabrix validate myapp --cert-sync
29
- $ aifabrix validate --integration
30
- $ aifabrix validate --builder
31
- `;
32
-
33
- const REPAIR_HELP_AFTER = `
34
- Examples:
35
- $ aifabrix repair hubspot-demo
36
- Align manifest, system/datasource files, RBAC extract, env.template, and deploy JSON under integration/<systemKey>/.
37
-
38
- $ aifabrix repair hubspot-demo --dry-run
39
- Show what would change without writing files.
40
-
41
- $ aifabrix repair hubspot-demo --auth oauth2
42
- Set authentication method; updates the system file and env.template (oauth2, aad, apikey, basic, …).
43
-
44
- $ aifabrix repair hubspot-demo --rbac --expose --sync --test
45
- Optional datasource fixes: RBAC roles/permissions, exposed.schema from attributes, default sync block, testPayload stubs.
46
-
47
- $ aifabrix repair hubspot-demo --doc
48
- Regenerate README.md from the current deployment manifest only (other drift fixes unchanged).
49
-
50
- Before overwriting files, repair writes timestamped backups under integration/<systemKey>/backup/ (same as datasource capability copy). Use --no-backup to skip.
51
- `;
18
+ const { setupRepairCommand } = require('./setup-utility-repair');
19
+ const { setupValidateDiffCommands } = require('./setup-utility-validate');
20
+ const { JSON_HELP_AFTER } = require('./setup-utility-help-after');
52
21
 
53
22
  /**
54
23
  * Resolve app path and type for split-json (integration first, then builder).
@@ -122,7 +91,7 @@ function logSplitJsonResult(result) {
122
91
  }
123
92
 
124
93
  function setupJsonCommand(program) {
125
- program.command('json <app>')
94
+ program.command('json <appKey|systemKey>')
126
95
  .description('Write deployment JSON to disk for version control')
127
96
  .addHelpText('after', JSON_HELP_AFTER)
128
97
  .action(async(appName, options) => {
@@ -156,7 +125,7 @@ function setupJsonCommand(program) {
156
125
  }
157
126
 
158
127
  function setupSplitJsonCommand(program) {
159
- program.command('split-json <app>')
128
+ program.command('split-json <appKey|systemKey>')
160
129
  .description('Split deploy JSON into env.template, application.yaml, rbac, README, …')
161
130
  .option('-o, --output <dir>', 'Output directory for component files (defaults to same directory as JSON)')
162
131
  .action(async(appName, options) => {
@@ -169,126 +138,54 @@ function setupSplitJsonCommand(program) {
169
138
  });
170
139
  }
171
140
 
172
- function buildRepairExternalIntegrationOptions(appName, options, format) {
173
- const all = options.all === true;
174
- return {
175
- auth: options.auth,
176
- doc: options.doc || all,
177
- dryRun: options.dryRun,
178
- format,
179
- rbac: options.rbac || all,
180
- expose: options.expose || all,
181
- sync: options.sync || all,
182
- api: options.api || all,
183
- test: options.test || all,
184
- backup: options.backup,
185
- noBackup: options.noBackup
186
- };
187
- }
188
-
189
- function logRepairResult(options, result) {
190
- if (options.dryRun && result.updated && result.changes.length > 0) {
191
- logger.log(chalk.yellow('\nWould apply:'));
192
- result.changes.forEach(c => logger.log(chalk.gray(` ${c}`)));
193
- return;
194
- }
195
- if (Array.isArray(result.backupPaths) && result.backupPaths.length > 0) {
196
- result.backupPaths.forEach((p) => logger.log(chalk.gray(`Backup: ${p}`)));
197
- }
198
- if (result.updated) {
199
- logger.log(formatSuccessParagraph('Repaired external integration config.'));
200
- return;
201
- }
202
- if (Array.isArray(result.changes) && result.changes.length > 0) {
203
- logger.log(formatSuccessParagraph('Repair actions completed.'));
204
- result.changes.forEach(c => logger.log(chalk.gray(` ${c}`)));
205
- return;
141
+ async function resolveConvertTargetFormat(options) {
142
+ const config = require('../core/config');
143
+ const effectiveFormat = options.format || (await config.getFormat());
144
+ if (!effectiveFormat) {
145
+ throw new Error(
146
+ 'Option --format is required and must be \'json\' or \'yaml\' (or set default with aifabrix dev set-format)'
147
+ );
206
148
  }
207
- if (result.readmeRegenerated) {
208
- logger.log(formatSuccessParagraph('Regenerated README.md from deployment manifest.'));
209
- return;
149
+ const normalized = effectiveFormat.trim().toLowerCase();
150
+ if (normalized !== 'json' && normalized !== 'yaml') {
151
+ throw new Error('Option --format must be \'json\' or \'yaml\'');
210
152
  }
211
- logger.log(chalk.gray('No changes needed; config already matches files on disk.'));
153
+ return normalized;
212
154
  }
213
155
 
214
- /**
215
- * Handler for `aifabrix repair <systemKey>`.
216
- * @param {string} appName
217
- * @param {object} options - Commander options
218
- * @returns {Promise<void>}
219
- */
220
- async function handleRepairCommand(appName, options) {
221
- const { repairExternalIntegration } = require('../commands/repair');
222
- const { detectAppType } = require('../utils/paths');
223
- const { appPath } = await detectAppType(appName);
224
- logOfflinePathWhenType(appPath);
225
- let format = 'yaml';
226
- try {
227
- const config = require('../core/config');
228
- format = (await config.getFormat()) || format;
229
- } catch (_) {
230
- /* default yaml when config unavailable */
156
+ function logConvertCommandResults(converted, deleted) {
157
+ logger.log(formatSuccessParagraph('Convert complete.'));
158
+ converted.forEach((p) => logger.log(` • ${p}`));
159
+ if (deleted.length > 0) {
160
+ logger.log(chalk.gray(' Removed old files:'));
161
+ deleted.forEach((p) => logger.log(chalk.gray(` ${p}`)));
231
162
  }
232
- const result = await repairExternalIntegration(
233
- appName,
234
- buildRepairExternalIntegrationOptions(appName, options, format)
235
- );
236
- logRepairResult(options, result);
237
163
  }
238
164
 
239
- function setupRepairCommand(program) {
240
- program.command('repair <systemKey>')
241
- .description('Fix external integration drift (files, RBAC, manifest, …)')
242
- .option('--all', 'Run all repair actions (api, doc, expose, rbac, sync, test)')
243
- .option(
244
- '--api',
245
- 'Validate and sync API contracts needed for OpenAPI/MCP (uses local OpenAPI specs at integration/<systemKey>/openapi/*.json when present)'
246
- )
247
- .option('--auth <method>', 'Set authentication method (oauth2, aad, apikey, basic, queryParam, oidc, hmac, none); updates system file and env.template')
248
- .option('--doc', 'Regenerate README.md from deployment manifest')
249
- .option('--expose', 'Set exposed.schema on each datasource from all fieldMappings.attributes keys (metadata.<key>); removes deprecated exposed.attributes if present')
250
- .option('--rbac', 'Ensure RBAC permissions per datasource and add default Admin/Reader roles if none exist')
251
- .option('--sync', 'Add default sync section to datasources that lack it')
252
- .option('--test', 'Generate testPayload.payloadTemplate and testPayload.expectedResult from attributes')
253
- .option('--no-backup', 'Skip timestamped copies under integration/<systemKey>/backup/')
254
- .option('--dry-run', 'Report changes only; do not write')
255
- .addHelpText('after', REPAIR_HELP_AFTER)
256
- .action(async(appName, options) => {
257
- try {
258
- await handleRepairCommand(appName, options);
259
- } catch (error) {
260
- handleCommandError(error, 'repair');
261
- process.exit(1);
262
- }
165
+ async function runConvertCommandForApp(appName, options) {
166
+ const normalized = await resolveConvertTargetFormat(options);
167
+ const { isProtectionScope } = require('../protection/scope');
168
+ if (isProtectionScope(appName)) {
169
+ const { runConvertProtectionBatch } = require('../protection/convert-batch');
170
+ const { converted, deleted } = await runConvertProtectionBatch(normalized, {
171
+ force: options.force
263
172
  });
173
+ logConvertCommandResults(converted, deleted);
174
+ return;
175
+ }
176
+ const { runConvert } = require('../commands/convert');
177
+ const { converted, deleted } = await runConvert(appName, { format: normalized, force: options.force });
178
+ logConvertCommandResults(converted, deleted);
264
179
  }
265
180
 
266
181
  function setupConvertCommand(program) {
267
- program.command('convert <app>')
268
- .description('Convert integration config files between JSON and YAML')
182
+ program.command('convert <appKey|systemKey>')
183
+ .description('Convert config files between JSON and YAML (builder/<appKey>/ or integration/<systemKey>/)')
269
184
  .option('--format <format>', 'Target format: json | yaml (required unless config format is set)')
270
185
  .option('-f, --force', 'Skip confirmation prompt')
271
186
  .action(async(appName, options) => {
272
187
  try {
273
- const config = require('../core/config');
274
- const effectiveFormat = options.format || (await config.getFormat());
275
- if (!effectiveFormat) {
276
- throw new Error(
277
- 'Option --format is required and must be \'json\' or \'yaml\' (or set default with aifabrix dev set-format)'
278
- );
279
- }
280
- const normalized = effectiveFormat.trim().toLowerCase();
281
- if (normalized !== 'json' && normalized !== 'yaml') {
282
- throw new Error('Option --format must be \'json\' or \'yaml\'');
283
- }
284
- const { runConvert } = require('../commands/convert');
285
- const { converted, deleted } = await runConvert(appName, { format: normalized, force: options.force });
286
- logger.log(formatSuccessParagraph('Convert complete.'));
287
- converted.forEach(p => logger.log(` • ${p}`));
288
- if (deleted.length > 0) {
289
- logger.log(chalk.gray(' Removed old files:'));
290
- deleted.forEach(p => logger.log(chalk.gray(` ${p}`)));
291
- }
188
+ await runConvertCommandForApp(appName, options);
292
189
  } catch (error) {
293
190
  handleCommandError(error, 'convert');
294
191
  process.exit(1);
@@ -297,8 +194,8 @@ function setupConvertCommand(program) {
297
194
  }
298
195
 
299
196
  function setupShowCommand(program) {
300
- program.command('show <app>')
301
- .description('Show app from local tree (default) or controller (--online)')
197
+ program.command('show <appKey|systemKey>')
198
+ .description('Show builder app or external system from local tree (default) or controller (--online)')
302
199
  .option('--online', 'Fetch application data from the controller')
303
200
  .option('--json', 'Output as JSON')
304
201
  .option(
@@ -327,120 +224,6 @@ function setupSplitJsonConvertShowCommands(program) {
327
224
  setupShowCommand(program);
328
225
  }
329
226
 
330
- function emitManifestAfterValidateIfApplicable(appOrFile, result, outFormat) {
331
- if (outFormat === 'json' || !result?.appPath || !appOrFile || typeof appOrFile !== 'string') {
332
- return;
333
- }
334
- try {
335
- if (fs.existsSync(appOrFile) && fs.statSync(appOrFile).isFile()) {
336
- return;
337
- }
338
- const { emitManifestMetadataLineIfTTY } = require('../utils/manifest-source-emit');
339
- emitManifestMetadataLineIfTTY(logger, {
340
- appKey: appOrFile,
341
- appPath: result.appPath,
342
- envOnly: false,
343
- json: false
344
- });
345
- } catch {
346
- /* ignore emit failures */
347
- }
348
- }
349
-
350
- async function runValidateBatchBranch(validate, opts) {
351
- const integration = opts.integration === true;
352
- const builder = opts.builder === true;
353
- if (!integration && !builder) {
354
- return false;
355
- }
356
- const outFormat = (opts.format || 'default').toLowerCase();
357
- const batchResult = integration && builder
358
- ? await validate.validateAll(opts)
359
- : integration
360
- ? await validate.validateAllIntegrations(opts)
361
- : await validate.validateAllBuilderApps(opts);
362
- if (outFormat === 'json') {
363
- logger.log(JSON.stringify(batchResult, null, 2));
364
- } else {
365
- validate.displayBatchValidationResults(batchResult);
366
- }
367
- if (!batchResult.valid) process.exit(1);
368
- return true;
369
- }
370
-
371
- async function runValidateCommand(appOrFile, options) {
372
- const validate = require('../validation/validate');
373
- const opts = options.opts ? options.opts() : options;
374
- if (await runValidateBatchBranch(validate, opts)) {
375
- return;
376
- }
377
-
378
- const outFormat = (opts.format || 'default').toLowerCase();
379
-
380
- if (!appOrFile || typeof appOrFile !== 'string') {
381
- logger.log(chalk.red('App name or file path is required, or use --integration / --builder'));
382
- process.exit(1);
383
- }
384
-
385
- const result = await validate.validateAppOrFile(appOrFile, {
386
- ...opts,
387
- certSync: opts.certSync === true
388
- });
389
- emitManifestAfterValidateIfApplicable(appOrFile, result, outFormat);
390
- if (outFormat === 'json') {
391
- let payload = result;
392
- try {
393
- if (result?.appPath && appOrFile && typeof appOrFile === 'string') {
394
- if (!(fs.existsSync(appOrFile) && fs.statSync(appOrFile).isFile())) {
395
- const { getManifestSourcePayload } = require('../utils/manifest-source-emit');
396
- payload = { ...result, manifestSource: getManifestSourcePayload(appOrFile, result.appPath) };
397
- }
398
- }
399
- } catch {
400
- /* keep plain result */
401
- }
402
- logger.log(JSON.stringify(payload, null, 2));
403
- } else {
404
- validate.displayValidationResults(result);
405
- }
406
- if (!result.valid) process.exit(1);
407
- }
408
-
409
- function setupValidateDiffCommands(program) {
410
- program.command('validate [appOrFile]')
411
- .description('Validate one app/file or all under integration/ or builder/')
412
- .addHelpText('after', VALIDATE_HELP_AFTER)
413
- .option('--format <format>', 'Output format: json | default (human-readable)')
414
- .option('--integration', 'Validate all applications under integration/')
415
- .option('--builder', 'Validate all applications under builder/')
416
- .option(
417
- '--cert-sync',
418
- 'After successful validation of an external integration, refresh the system file certification block from the dataplane (requires login)'
419
- )
420
- .action((appOrFile, options) => {
421
- runValidateCommand(appOrFile, options).catch((error) => {
422
- handleCommandError(error, 'validate');
423
- process.exit(1);
424
- });
425
- });
426
-
427
- program.command('diff <file1> <file2>')
428
- .description('Diff two config files (optional schema validate)')
429
- .option('--no-validate', 'Skip schema validation (type check still applied)')
430
- .action(async(file1, file2, cmd) => {
431
- try {
432
- const diff = require('../core/diff');
433
- const opts = cmd.opts();
434
- const result = await diff.compareFiles(file1, file2, { validate: opts.validate !== false });
435
- diff.formatDiffOutput(result);
436
- if (!result.identical) process.exit(1);
437
- } catch (error) {
438
- handleCommandError(error, 'diff');
439
- process.exit(1);
440
- }
441
- });
442
- }
443
-
444
227
  /**
445
228
  * Sets up utility commands
446
229
  * @param {Command} program - Commander program instance