@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
@@ -44,6 +44,7 @@ Examples:
44
44
  $ aifabrix datasource test-e2e hubspot-users --app test-e2e-hubspot -v --debug
45
45
  $ aifabrix datasource test-e2e my-documents-ds --min-vector-hits 7 -v --debug
46
46
  $ aifabrix datasource test-e2e hubspot-users -a test-e2e-hubspot --no-async
47
+ $ aifabrix datasource test-e2e hubspot-users --sync --force --verify-audit -v
47
48
  $ aifabrix datasource test-e2e hubspot-users read
48
49
 
49
50
  Notes:
@@ -53,6 +54,7 @@ Notes:
53
54
  aifabrix datasource test-integration <datasourceKey>
54
55
  - For system-level E2E rollup across datasources, use:
55
56
  aifabrix test-e2e <systemKey>
57
+ - To prove governance audit evidence after a green E2E, add --verify-audit (see verify-audit command).
56
58
  `;
57
59
  }
58
60
 
@@ -127,6 +129,10 @@ function attachDatasourceTestCommonOptions(cmd, opts) {
127
129
  '--sync',
128
130
  'Publish local integration config to the dataplane before running the test (same as aifabrix upload <systemKey>; requires login)'
129
131
  )
132
+ .option(
133
+ '--force',
134
+ 'With --sync, pass force to upload (bypass active-datasource schema replacement guards; same as aifabrix upload --force)'
135
+ )
130
136
  .option('--json', 'Print raw DatasourceTestRun JSON to stdout')
131
137
  .option('--summary', 'Print compact summary line')
132
138
  .option('--warnings-as-errors', 'Exit 1 when root status is warn')
@@ -175,11 +181,24 @@ function attachDatasourceTestE2eExclusiveOptions(cmd) {
175
181
  '--primary-key-value <value|@path>',
176
182
  'Primary key value or path to JSON file (e.g. @pk.json) for e2eOptions.primaryKeyValue'
177
183
  )
178
- .option('--capability <key>', 'Capability drill-down (deprecated; use positional [capabilityKey])')
179
184
  .option(
180
185
  '--strict-capability-scope',
181
- 'Exit 1 if a capability drill-down is requested but the report lists more than one capabilities[] row (plan §2.3)'
182
- );
186
+ 'Exit 1 when positional [capabilityKey] is set but the report lists more than one capabilities[] row'
187
+ )
188
+ .option(
189
+ '--verify-audit',
190
+ 'After successful E2E, verify the nine-row audit evidence matrix on the dataplane (requires audit:read)'
191
+ )
192
+ .option(
193
+ '--no-verify-audit',
194
+ 'Skip audit evidence verification even if enabled by default in a future release'
195
+ )
196
+ .option(
197
+ '--audit-poll-ms <ms>',
198
+ 'Max wait for audit rows after E2E when using --verify-audit (default 15000)',
199
+ '15000'
200
+ )
201
+ .option('--audit-poll-interval-ms <ms>', 'Audit poll interval when using --verify-audit (default 2000)', '2000');
183
202
  }
184
203
 
185
204
  module.exports = {
@@ -46,7 +46,7 @@ function exitCodeFromDatasourceTestRunEnvelope(env, options) {
46
46
  warningsAsErrors: options.warningsAsErrors === true,
47
47
  requireCert: options.requireCert === true
48
48
  });
49
- const scope = analyzeCapabilityScope(env, options.capability);
49
+ const scope = analyzeCapabilityScope(env, options.capabilityKey);
50
50
  if (options.strictCapabilityScope === true && scope.violated) {
51
51
  code = Math.max(code, 1);
52
52
  }
@@ -62,10 +62,10 @@ function exitCodeFromDatasourceTestRunEnvelope(env, options) {
62
62
  function finalizeDatasourceTestE2ELegacyPath(data, options) {
63
63
  displayE2EResults(data, options.verbose);
64
64
  logDatasourceTestRunDebugAppendix(data.datasourceTestRun, options.debug);
65
- logE2eCapabilityFocusFromEnvelope(data.datasourceTestRun, options.capability);
65
+ logE2eCapabilityFocusFromEnvelope(data.datasourceTestRun, options.capabilityKey);
66
66
  const env = data.datasourceTestRun;
67
67
  if (env) {
68
- emitCapabilityScopeDiagnostics(env, { requestedCapabilityKey: options.capability });
68
+ emitCapabilityScopeDiagnostics(env, { requestedCapabilityKey: options.capabilityKey });
69
69
  const code = exitCodeFromDatasourceTestRunEnvelope(env, options);
70
70
  return code === null ? 1 : code;
71
71
  }
@@ -91,10 +91,10 @@ function displayDatasourceTestE2EEnvelopeResults(datasourceKey, env, options) {
91
91
  {
92
92
  debug: options.debug,
93
93
  runType: 'e2e',
94
- requestedCapabilityKey: options.capability
94
+ requestedCapabilityKey: options.capabilityKey
95
95
  }
96
96
  );
97
- logE2eCapabilityFocusFromEnvelope(env, options.capability);
97
+ logE2eCapabilityFocusFromEnvelope(env, options.capabilityKey);
98
98
  }
99
99
 
100
100
  module.exports = {
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @fileoverview `aifabrix datasource verify-audit` — re-run 407.1 matrix from last E2E log
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const logger = require('../utils/logger');
10
+ const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
11
+ const { runAuditEvidenceVerification } = require('../datasource/audit-evidence-run');
12
+ const { loadEnvelopeFromLatestE2eLog } = require('../datasource/audit-evidence-extract');
13
+
14
+ const VERIFY_AUDIT_HELP_AFTER = `
15
+ Examples:
16
+ $ aifabrix datasource verify-audit test-e2e-hubspot-companies
17
+ $ aifabrix datasource verify-audit test-e2e-hubspot-companies --app test-e2e-hubspot -v
18
+ $ aifabrix datasource verify-audit test-e2e-hubspot-companies --correlation-id <testRunId>
19
+ $ aifabrix datasource verify-audit test-e2e-hubspot-companies --json
20
+
21
+ Notes:
22
+ - Re-checks audit evidence from the latest test-e2e debug log (or --file) without re-running E2E.
23
+ - Requires audit:read on the dataplane (same login as test-e2e).
24
+ - Pair with: aifabrix datasource test-e2e <datasourceKey> --verify-audit
25
+ `;
26
+
27
+ /**
28
+ * @param {string} datasourceKey
29
+ * @param {Object} options
30
+ */
31
+ async function verifyAuditCommandAction(datasourceKey, options) {
32
+ const envelope = await loadEnvelopeFromLatestE2eLog(datasourceKey, options);
33
+ if (!envelope) {
34
+ logger.error(
35
+ formatBlockingError('verify-audit failed:'),
36
+ 'No test-e2e debug log found (run test-e2e with --debug first)'
37
+ );
38
+ process.exit(3);
39
+ return;
40
+ }
41
+ const pollMs = parseInt(String(options.auditPollMs || '15000'), 10);
42
+ const pollInterval = parseInt(String(options.auditPollIntervalMs || '2000'), 10);
43
+ const { exitCode } = await runAuditEvidenceVerification(datasourceKey, envelope, {
44
+ app: options.app,
45
+ env: options.env,
46
+ verbose: options.verbose,
47
+ json: options.json,
48
+ correlationId: options.correlationId,
49
+ executionId: options.executionId,
50
+ quiet: false,
51
+ auditPollMaxWaitMs: Number.isFinite(pollMs) ? pollMs : 15000,
52
+ auditPollIntervalMs: Number.isFinite(pollInterval) ? pollInterval : 2000
53
+ });
54
+ process.exit(exitCode);
55
+ }
56
+
57
+ /**
58
+ * @param {import('commander').Command} datasource
59
+ */
60
+ function setupDatasourceVerifyAuditCommand(datasource) {
61
+ datasource
62
+ .command('verify-audit <datasourceKey>')
63
+ .description(
64
+ 'Verify audit evidence matrix from latest E2E log (or --file) without re-running E2E'
65
+ )
66
+ .option(
67
+ '-a, --app <app>',
68
+ 'Integration folder name (optional: resolve from cwd or datasource key if single match)'
69
+ )
70
+ .option('-e, --env <env>', 'Environment: dev, tst, or pro')
71
+ .option('-v, --verbose', 'Show matrix row codes and execution id count')
72
+ .option('--json', 'Print auditEvidenceVerification JSON block')
73
+ .option('-f, --file <path>', 'Path to test-e2e debug log JSON')
74
+ .option('--correlation-id <id>', 'Override correlation/testRunId filter')
75
+ .option('--execution-id <id>', 'Include execution id for sub-resource checks')
76
+ .option(
77
+ '--audit-poll-ms <ms>',
78
+ 'Max wait for audit rows to appear (default 15000)',
79
+ '15000'
80
+ )
81
+ .option('--audit-poll-interval-ms <ms>', 'Poll interval (default 2000)', '2000')
82
+ .addHelpText('after', VERIFY_AUDIT_HELP_AFTER)
83
+ .action(async(datasourceKey, options) => {
84
+ try {
85
+ await verifyAuditCommandAction(datasourceKey, options);
86
+ } catch (error) {
87
+ logger.error(formatBlockingError('verify-audit failed:'), error.message);
88
+ process.exit(3);
89
+ }
90
+ });
91
+ }
92
+
93
+ module.exports = {
94
+ setupDatasourceVerifyAuditCommand,
95
+ verifyAuditCommandAction
96
+ };
@@ -2,7 +2,7 @@
2
2
  * AI Fabrix Builder - Datasource Commands
3
3
  *
4
4
  * Handles datasource validation, listing, comparison, deployment, and online validation runs.
5
- * Subcommands `test`, `test-integration`, and `test-e2e` call the dataplane unified validation API; `log-test` / `log-integration` / `log-e2e` read saved debug JSON locally. Permissions are summarized in `docs/commands/permissions.md`.
5
+ * Subcommands `test`, `test-integration`, `test-e2e`, and `verify-trust` call the dataplane; `log-*` read saved debug JSON locally; `clean-logs` removes those files. Permissions are summarized in `docs/commands/permissions.md`.
6
6
  *
7
7
  * @fileoverview Datasource management commands for AI Fabrix Builder
8
8
  * @author AI Fabrix Team
@@ -18,11 +18,15 @@ const { listDatasources } = require('../datasource/list');
18
18
  const { compareDatasources } = require('../datasource/diff');
19
19
  const { deployDatasource } = require('../datasource/deploy');
20
20
  const { runLogViewer } = require('../datasource/log-viewer');
21
+ const { runCleanLogs } = require('../datasource/log-cleaner');
21
22
  const {
22
23
  setupDatasourceTestCommand,
23
24
  setupDatasourceTestIntegrationCommand,
24
25
  setupDatasourceTestE2ECommand
25
26
  } = require('./datasource-unified-test-cli');
27
+ const { setupDatasourceVerifyTrustCommand } = require('./datasource-test-trust-cli');
28
+ const { setupDatasourceVerifyAuditCommand } = require('./datasource-verify-audit-cli');
29
+ const { setupDatasourceLoadExportCommands } = require('./datasource-load-export-cli');
26
30
  const { setupDatasourceCapabilityCommands } = require('./datasource-capability');
27
31
 
28
32
  /**
@@ -38,10 +42,17 @@ Examples:
38
42
  $ af ds upload <datasourceKey> # same as: aifabrix datasource upload …
39
43
  $ af ds test <datasourceKey> --app <integrationFolder> --debug
40
44
  $ af ds test-e2e <datasourceKey> --app <integrationFolder> -v
45
+ $ af ds test-e2e <datasourceKey> --verify-audit
46
+ $ af ds verify-audit <datasourceKey>
47
+ $ af ds verify-trust <datasourceKey> --app <integrationFolder> -v
48
+ $ af ds load <datasourceKey> --app <integrationFolder> --dry-run
49
+ $ af ds export <datasourceKey> --app <integrationFolder> --format ndjson -v
41
50
  $ aifabrix datasource capability copy <file-or-key> --from create --as createBasicTrial --dry-run
42
51
  $ aifabrix datasource capability remove <file-or-key> --capability createTrial --dry-run
43
52
  $ aifabrix datasource capability diff ./a.json ./b.json --capability list
44
53
  $ aifabrix datasource capability edit <file-or-key> --capability create --section openapi
54
+ $ aifabrix datasource clean-logs --app test-e2e-hubspot --dry-run
55
+ $ aifabrix datasource clean-logs --all --type e2e
45
56
 
46
57
  Per-command help: aifabrix datasource <command> --help
47
58
  Shorthand: af ds (alias for datasource)
@@ -220,6 +231,57 @@ function setupDatasourceLogTestCommand(datasource) {
220
231
  });
221
232
  }
222
233
 
234
+ function setupDatasourceCleanLogsCommand(datasource) {
235
+ datasource
236
+ .command('clean-logs')
237
+ .description('Remove saved test debug JSON under integration/<app>/logs/')
238
+ .option('-a, --app <app>', 'Integration folder name (system key)')
239
+ .option('--all', 'Clean logs under every integration/<app>/logs/ folder')
240
+ .option(
241
+ '-t, --type <type>',
242
+ 'Log kind: test, integration, e2e, trust, or all (default: all)',
243
+ 'all'
244
+ )
245
+ .option('--dry-run', 'List files that would be removed without deleting')
246
+ .option('--json', 'Machine-readable summary on stdout')
247
+ .action(async options => {
248
+ try {
249
+ await runCleanLogs({
250
+ app: options.app,
251
+ all: options.all,
252
+ type: options.type,
253
+ dryRun: options.dryRun,
254
+ json: options.json
255
+ });
256
+ } catch (error) {
257
+ logger.error(formatBlockingError('clean-logs failed:'), error.message);
258
+ process.exit(1);
259
+ }
260
+ });
261
+ }
262
+
263
+ function setupDatasourceLogTrustCommand(datasource) {
264
+ datasource.command('log-trust <datasourceKey>')
265
+ .description('Show agent trust log from datasource verify-trust (latest verify-trust-*.json or --file)')
266
+ .option(
267
+ '-a, --app <app>',
268
+ 'Integration folder name (optional: resolve from cwd or datasource key if single match)'
269
+ )
270
+ .option('-f, --file <path>', 'Path to log file (default: latest verify-trust log in app logs folder)')
271
+ .action(async(datasourceKey, options) => {
272
+ try {
273
+ await runLogViewer(datasourceKey, {
274
+ app: options.app,
275
+ file: options.file,
276
+ logType: 'verify-trust'
277
+ });
278
+ } catch (error) {
279
+ logger.error(formatBlockingError('log-trust failed:'), error.message);
280
+ process.exit(1);
281
+ }
282
+ });
283
+ }
284
+
223
285
  /**
224
286
  * Setup datasource management commands
225
287
  * @param {Command} program - Commander program instance
@@ -237,12 +299,17 @@ function setupDatasourceCommands(program) {
237
299
  setupDatasourceListCommand(datasource);
238
300
  setupDatasourceDiffCommand(datasource);
239
301
  setupDatasourceUploadCommand(datasource);
302
+ setupDatasourceLoadExportCommands(datasource);
240
303
  setupDatasourceTestCommand(datasource);
241
304
  setupDatasourceTestIntegrationCommand(datasource);
242
305
  setupDatasourceTestE2ECommand(datasource);
306
+ setupDatasourceVerifyAuditCommand(datasource);
307
+ setupDatasourceVerifyTrustCommand(datasource);
243
308
  setupDatasourceLogE2ECommand(datasource);
244
309
  setupDatasourceLogIntegrationCommand(datasource);
245
310
  setupDatasourceLogTestCommand(datasource);
311
+ setupDatasourceLogTrustCommand(datasource);
312
+ setupDatasourceCleanLogsCommand(datasource);
246
313
  }
247
314
 
248
315
  module.exports = { setupDatasourceCommands };
@@ -336,6 +336,8 @@ function logConfigurationSection(p) {
336
336
  logRow('Environment', p.environment);
337
337
  logRow('Controller', p.controller);
338
338
  logRow('Format', p.formatVal);
339
+ logRow('Platform mode', p.setupPlatformMode);
340
+ logRow('Traefik', p.traefikEnabled ? 'on' : 'off');
339
341
  logRow('Scoped resources', p.scopedResourcesLabel);
340
342
  logRow('URLs registry', p.urlsLocalPath);
341
343
  if (!p.hasRemote) {
@@ -386,11 +388,12 @@ async function loadDevShowData(devIdStr) {
386
388
  const devIdNum = parseInt(devIdStr, 10);
387
389
  const ports = devConfig.getDevPorts(Number.isNaN(devIdNum) ? 0 : devIdNum);
388
390
  const [
389
- environment, tlsEnabled, controller, formatRaw, useScoped, secretsRaw,
391
+ environment, tlsEnabled, controller, formatRaw, useScoped, secretsRaw, setupPlatformMode, traefikEnabled,
390
392
  remoteServer, dockerEndpoint, dockerTlsSkipVerify, mutagenFolder, syncSshUser, syncSshHost
391
393
  ] = await Promise.all([
392
394
  config.getCurrentEnvironment(), config.getTlsEnabled(), config.getControllerUrl(),
393
395
  config.getFormat(), config.getUseEnvironmentScopedResources(), config.getAifabrixSecretsPath(),
396
+ config.getSetupPlatformMode(), config.getTraefikEnabled(),
394
397
  config.getRemoteServer(), config.getDockerEndpoint(), config.getDockerTlsSkipVerify(),
395
398
  config.getUserMutagenFolder(), config.getSyncSshUser(), config.getSyncSshHost()
396
399
  ]);
@@ -410,6 +413,8 @@ async function loadDevShowData(devIdStr) {
410
413
  controller,
411
414
  formatVal: formatRaw ?? null,
412
415
  scopedResourcesLabel,
416
+ setupPlatformMode,
417
+ traefikEnabled,
413
418
  workResolved,
414
419
  homeResolved,
415
420
  secretsMain,
@@ -446,6 +451,8 @@ function renderDevShow(data) {
446
451
  tlsEnabled: data.tlsEnabled,
447
452
  controller: data.controller,
448
453
  formatVal: data.formatVal,
454
+ setupPlatformMode: data.setupPlatformMode,
455
+ traefikEnabled: data.traefikEnabled,
449
456
  scopedResourcesLabel: data.scopedResourcesLabel,
450
457
  urlsLocalPath: data.urlsLocalPath,
451
458
  hasRemote: data.hasRemote,
@@ -2,9 +2,9 @@
2
2
  * Dimension value commands (Controller).
3
3
  *
4
4
  * Commands:
5
- * - aifabrix dimension-value create
6
- * - aifabrix dimension-value list
7
- * - aifabrix dimension-value delete
5
+ * - aifabrix dimension value create
6
+ * - aifabrix dimension value list
7
+ * - aifabrix dimension value delete
8
8
  *
9
9
  * @fileoverview Dimension value CLI commands
10
10
  * @author AI Fabrix Team
@@ -25,29 +25,39 @@ const {
25
25
  deleteDimensionValue
26
26
  } = require('../api/dimension-values.api');
27
27
 
28
+ const DIMENSION_VALUE_HELP_AFTER = `
29
+
30
+ Examples:
31
+ $ aifabrix dimension value create customerRegion --value emea --display-name "EMEA"
32
+ $ aifabrix dimension value list customerRegion
33
+ $ aifabrix dimension value delete clx1234567890abcdef
34
+
35
+ Per-command help: aifabrix dimension value <command> --help
36
+ `;
37
+
28
38
  const DIMENSION_VALUE_CREATE_HELP_AFTER = `
29
39
 
30
40
  Examples:
31
- $ aifabrix dimension-value create customerRegion --value emea --display-name "EMEA"
32
- $ aifabrix dimension-value create customerRegion --value na --display-name "North America"
41
+ $ aifabrix dimension value create customerRegion --value emea --display-name "EMEA"
42
+ $ aifabrix dimension value create customerRegion --value na --display-name "North America"
33
43
 
34
44
  `;
35
45
 
36
46
  const DIMENSION_VALUE_LIST_HELP_AFTER = `
37
47
 
38
48
  Examples:
39
- $ aifabrix dimension-value list customerRegion
40
- $ aifabrix dimension-value list customerRegion --page 1 --page-size 50
41
- $ aifabrix dimension-value list customerRegion --search emea
49
+ $ aifabrix dimension value list customerRegion
50
+ $ aifabrix dimension value list customerRegion --page 1 --page-size 50
51
+ $ aifabrix dimension value list customerRegion --search emea
42
52
 
43
53
  `;
44
54
 
45
55
  const DIMENSION_VALUE_DELETE_HELP_AFTER = `
46
56
 
47
57
  Examples:
48
- $ aifabrix dimension-value delete clx1234567890abcdef
58
+ $ aifabrix dimension value delete clx1234567890abcdef
49
59
 
50
- Tip: Find ids via "aifabrix dimension get <key>" (it prints values) or "aifabrix dimension-value list <key>".
60
+ Tip: Find ids via "aifabrix dimension get <key>" (it prints values) or "aifabrix dimension value list <key>".
51
61
 
52
62
  `;
53
63
 
@@ -62,6 +72,17 @@ function requireNonEmpty(raw, label) {
62
72
  return s;
63
73
  }
64
74
 
75
+ /**
76
+ * @param {Object} response - Controller API response
77
+ * @throws {Error} When response.success === false
78
+ */
79
+ function throwIfApiFailed(response) {
80
+ if (!response || response.success !== false) {
81
+ return;
82
+ }
83
+ throw new Error(response.formattedError || response.error || 'Request failed');
84
+ }
85
+
65
86
  async function resolveControllerAndAuth() {
66
87
  const controllerUrl = await resolveControllerUrl();
67
88
  if (!controllerUrl) {
@@ -100,6 +121,7 @@ function setupDimensionValueCreateCommand(cmd) {
100
121
  displayName: options.displayName,
101
122
  description: options.description
102
123
  });
124
+ throwIfApiFailed(res);
103
125
  const row = unwrapControllerData(res);
104
126
  logger.log(formatSuccessLine(`Dimension value created: ${dimKey}.${row.value}`));
105
127
  } catch (e) {
@@ -126,6 +148,7 @@ function setupDimensionValueListCommand(cmd) {
126
148
  pageSize: options.pageSize,
127
149
  search: options.search
128
150
  });
151
+ throwIfApiFailed(res);
129
152
  const payload = unwrapControllerData(res);
130
153
  const items = payload?.data ?? payload ?? [];
131
154
  logger.log(chalk.bold('\n🏷 Dimension values:\n'));
@@ -157,7 +180,8 @@ function setupDimensionValueDeleteCommand(cmd) {
157
180
  try {
158
181
  const { controllerUrl, authConfig } = await resolveControllerAndAuth();
159
182
  const id = requireNonEmpty(dimensionValueId, 'dimensionValueId');
160
- await deleteDimensionValue(controllerUrl, authConfig, id);
183
+ const res = await deleteDimensionValue(controllerUrl, authConfig, id);
184
+ throwIfApiFailed(res);
161
185
  logger.log(formatSuccessLine(`Dimension value deleted: ${id}`));
162
186
  } catch (e) {
163
187
  logger.error(formatBlockingError(e.message));
@@ -166,8 +190,14 @@ function setupDimensionValueDeleteCommand(cmd) {
166
190
  });
167
191
  }
168
192
 
169
- function setupDimensionValueCommands(program) {
170
- const cmd = program.command('dimension-value').description('Manage dimension values (static dimensions)');
193
+ /**
194
+ * @param {import('commander').Command} dimensionCmd - Parent `dimension` command
195
+ */
196
+ function setupDimensionValueCommands(dimensionCmd) {
197
+ const cmd = dimensionCmd
198
+ .command('value')
199
+ .description('Manage dimension values (static dimensions)')
200
+ .addHelpText('after', DIMENSION_VALUE_HELP_AFTER);
171
201
  setupDimensionValueCreateCommand(cmd);
172
202
  setupDimensionValueListCommand(cmd);
173
203
  setupDimensionValueDeleteCommand(cmd);
@@ -5,6 +5,7 @@
5
5
  * - aifabrix dimension create
6
6
  * - aifabrix dimension get
7
7
  * - aifabrix dimension list
8
+ * - aifabrix dimension value create|list|delete
8
9
  *
9
10
  * @fileoverview Dimension CLI commands
10
11
  * @author AI Fabrix Team
@@ -18,7 +19,7 @@ const logger = require('../utils/logger');
18
19
  const { resolveControllerUrl } = require('../utils/controller-url');
19
20
  const { normalizeControllerUrl, resolveEnvironment } = require('../core/config');
20
21
  const { getOrRefreshDeviceToken } = require('../utils/token-manager');
21
- const { readDimensionCreateFile } = require('../resolvers/dimension-file');
22
+ const { readDimensionCreateFile, normalizeValueType } = require('../resolvers/dimension-file');
22
23
  const {
23
24
  formatBlockingError,
24
25
  formatSuccessLine,
@@ -31,8 +32,23 @@ const {
31
32
  createDimensionIdempotent
32
33
  } = require('../api/dimensions.api');
33
34
  const { createDimensionValue } = require('../api/dimension-values.api');
35
+ const { setupDimensionValueCommands } = require('./dimension-value');
34
36
 
35
37
  const DIMENSION_KEY_PATTERN = /^[a-zA-Z][a-zA-Z0-9-_]*$/;
38
+
39
+ /** Parent help for `aifabrix dimension -h` (leaf commands have their own Examples blocks). */
40
+ const DIMENSION_HELP_AFTER = `
41
+
42
+ Examples:
43
+ $ aifabrix dimension create --key customerRegion --display-name "Customer Region" --data-type string
44
+ $ aifabrix dimension get customerRegion
45
+ $ aifabrix dimension list --search region
46
+ $ aifabrix dimension value create customerRegion --value emea --display-name "EMEA"
47
+ $ aifabrix dimension value list customerRegion
48
+
49
+ Per-command help: aifabrix dimension <command> --help
50
+ `;
51
+
36
52
  const DATA_TYPES = new Set(['string', 'number', 'boolean']);
37
53
 
38
54
  const DIMENSION_CREATE_HELP_AFTER = `
@@ -139,6 +155,11 @@ function buildCreatePayload(options) {
139
155
  if (options.displayName) payload.displayName = options.displayName;
140
156
  if (options.description !== undefined) payload.description = options.description;
141
157
  if (options.dataType) payload.dataType = options.dataType;
158
+ if (options.valueType) {
159
+ payload.valueType = normalizeValueType(options.valueType);
160
+ } else if (payload.valueType === undefined) {
161
+ payload.valueType = 'static';
162
+ }
142
163
  if (options.required !== undefined && options.required !== null) {
143
164
  payload.isRequired = Boolean(options.required);
144
165
  }
@@ -197,6 +218,7 @@ function setupDimensionCreateCommand(dim) {
197
218
  .option('--display-name <name>', 'Display name')
198
219
  .option('--description <text>', 'Description')
199
220
  .option('--data-type <type>', 'string | number | boolean')
221
+ .option('--value-type <mode>', 'static | dynamic | both (catalog assignment mode)')
200
222
  .option('--required', 'Mark dimension required (isRequired=true)')
201
223
  .option('--no-required', 'Mark dimension not required (isRequired=false)')
202
224
  .action(async(options) => {
@@ -206,11 +228,12 @@ function setupDimensionCreateCommand(dim) {
206
228
  const out = await createDimensionIdempotent(controllerUrl, authConfig, payload);
207
229
  const dimRow = unwrapControllerData(out.response);
208
230
  await maybeCreateValuesFromFile(controllerUrl, authConfig, payload);
231
+ const vt = dimRow.valueType || payload.valueType || 'static';
209
232
  if (out.created) {
210
- logger.log(formatSuccessLine(`Dimension created: ${dimRow.key}`));
233
+ logger.log(formatSuccessLine(`Dimension created: ${dimRow.key} (valueType: ${vt})`));
211
234
  return;
212
235
  }
213
- logger.log(formatSuccessLine(`Dimension exists: ${dimRow.key}`));
236
+ logger.log(formatSuccessLine(`Dimension exists: ${dimRow.key} (valueType: ${vt})`));
214
237
  logger.log(infoLine('No changes were needed.'));
215
238
  } catch (e) {
216
239
  logger.error(formatBlockingError(e.message));
@@ -236,6 +259,7 @@ function setupDimensionGetCommand(dim) {
236
259
  logger.log(headerKeyValue('Key:', row.key || '—'));
237
260
  logger.log(headerKeyValue('Display:', row.displayName || '—'));
238
261
  logger.log(headerKeyValue('Type:', row.dataType || '—'));
262
+ logger.log(headerKeyValue('Value type:', row.valueType || '—'));
239
263
  logger.log(headerKeyValue('Required:', String(row.isRequired)));
240
264
  if (row.description) {
241
265
  logger.log(headerKeyValue('Description:', row.description));
@@ -268,22 +292,25 @@ function setupDimensionListCommand(dim) {
268
292
  const KEY_WIDTH = 26;
269
293
  const DISPLAY_WIDTH = 34;
270
294
  const TYPE_WIDTH = 10;
295
+ const VTYPE_WIDTH = 8;
271
296
  const REQ_WIDTH = 10;
272
- const SEP_LEN = KEY_WIDTH + DISPLAY_WIDTH + TYPE_WIDTH + REQ_WIDTH;
297
+ const SEP_LEN = KEY_WIDTH + DISPLAY_WIDTH + TYPE_WIDTH + VTYPE_WIDTH + REQ_WIDTH;
273
298
 
274
299
  const keyCol = 'Key'.padEnd(KEY_WIDTH);
275
300
  const displayCol = 'Display'.padEnd(DISPLAY_WIDTH);
276
301
  const typeCol = 'Type'.padEnd(TYPE_WIDTH);
302
+ const vtypeCol = 'VType'.padEnd(VTYPE_WIDTH);
277
303
  const reqCol = 'Required'.padEnd(REQ_WIDTH);
278
- logger.log(chalk.gray(`${keyCol}${displayCol}${typeCol}${reqCol}`));
304
+ logger.log(chalk.gray(`${keyCol}${displayCol}${typeCol}${vtypeCol}${reqCol}`));
279
305
  logger.log(chalk.gray('-'.repeat(SEP_LEN)));
280
306
 
281
307
  items.forEach((d) => {
282
308
  const key = (d?.key ?? '—').toString().padEnd(KEY_WIDTH);
283
309
  const displayName = (d?.displayName ?? '—').toString().padEnd(DISPLAY_WIDTH);
284
310
  const dataType = (d?.dataType ?? '—').toString().padEnd(TYPE_WIDTH);
311
+ const valueType = (d?.valueType ?? '—').toString().padEnd(VTYPE_WIDTH);
285
312
  const required = (d?.isRequired ?? '—').toString().padEnd(REQ_WIDTH);
286
- logger.log(`${key}${displayName}${dataType}${required}`);
313
+ logger.log(`${key}${displayName}${dataType}${valueType}${required}`);
287
314
  });
288
315
  logger.log('');
289
316
  }
@@ -318,10 +345,14 @@ function setupDimensionListCommand(dim) {
318
345
  * @param {import('commander').Command} program
319
346
  */
320
347
  function setupDimensionCommands(program) {
321
- const dim = program.command('dimension').description('Manage the Controller Dimension Catalog');
348
+ const dim = program
349
+ .command('dimension')
350
+ .description('Manage the Controller Dimension Catalog')
351
+ .addHelpText('after', DIMENSION_HELP_AFTER);
322
352
  setupDimensionCreateCommand(dim);
323
353
  setupDimensionGetCommand(dim);
324
354
  setupDimensionListCommand(dim);
355
+ setupDimensionValueCommands(dim);
325
356
  }
326
357
 
327
358
  module.exports = {