@aifabrix/builder 2.45.5 → 2.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) 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/.npmrc.token +1 -0
  5. package/.temp/jest-protection-convert/run-IFN2nv/.protection/hubspot-companies.json +1 -0
  6. package/.temp/jest-protection-convert/run-IvmKLO/.protection/hubspot-companies.yaml +17 -0
  7. package/.temp/jest-protection-convert/run-SdvblF/.protection/hubspot-companies.json +1 -0
  8. package/.temp/jest-protection-convert/run-b51TsW/.protection/hubspot-companies.json +1 -0
  9. package/.temp/jest-protection-convert/run-fiLmb1/.protection/hubspot-companies.json +1 -0
  10. package/.temp/jest-protection-convert/run-qYGHMU/.protection/hubspot-companies.yaml +17 -0
  11. package/.temp/jest-protection-fixtures/hubspot-Mq5re8/hubspot-companies.yaml +17 -0
  12. package/.temp/jest-protection-fixtures/hubspot-f3u4YL/hubspot-companies.yaml +17 -0
  13. package/.temp/jest-protection-fixtures/hubspot-iQtd1O/hubspot-companies.yaml +17 -0
  14. package/.temp/jest-protection-fixtures/hubspot-mdmz5M/hubspot-companies.yaml +17 -0
  15. package/.temp/jest-protection-fixtures/hubspot-qbKYxQ/hubspot-companies.yaml +17 -0
  16. package/.temp/jest-protection-fixtures/hubspot-yzlJy6/hubspot-companies.yaml +17 -0
  17. package/.temp/validation/summary.txt +5 -0
  18. package/README.md +43 -17
  19. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
  20. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
  21. package/jest.config.default.js +2 -1
  22. package/jest.config.isolated.js +2 -1
  23. package/jest.global-live-fabrix-hooks.js +36 -0
  24. package/jest.isolated-projects.js +146 -0
  25. package/jest.projects.js +65 -136
  26. package/lib/api/api-response-errors.js +124 -0
  27. package/lib/api/dataplane-health.api.js +19 -7
  28. package/lib/api/governance-scenario-pack.api.js +159 -0
  29. package/lib/api/index.js +43 -3
  30. package/lib/api/lifecycle.api.js +98 -0
  31. package/lib/api/pipeline.api.js +3 -1
  32. package/lib/api/records-bulk.api.js +14 -1
  33. package/lib/api/resource-types.api.js +107 -0
  34. package/lib/api/runtime-configuration.api.js +72 -0
  35. package/lib/api/types/resource-types.types.js +45 -0
  36. package/lib/api/user-groups.api.js +9 -9
  37. package/lib/api/users.api.js +8 -8
  38. package/lib/api/validation-runner.js +3 -1
  39. package/lib/api/wizard.api.js +10 -2
  40. package/lib/app/deploy-config.js +4 -1
  41. package/lib/app/down.js +78 -27
  42. package/lib/app/index.js +2 -2
  43. package/lib/app/push.js +4 -5
  44. package/lib/app/register.js +7 -4
  45. package/lib/app/run-env-compose.js +84 -30
  46. package/lib/app/run-resolve-image.js +2 -1
  47. package/lib/app/run-stop-containers.js +113 -0
  48. package/lib/app/run.js +1 -31
  49. package/lib/app/show-display.js +35 -0
  50. package/lib/app/show.js +32 -1
  51. package/lib/build/index.js +22 -5
  52. package/lib/build/miso-controller-npm-sdk-guard.js +25 -0
  53. package/lib/certification/sync-system-certification.js +13 -6
  54. package/lib/channels/add-channel.js +348 -0
  55. package/lib/channels/channel-artifact-generator.js +141 -0
  56. package/lib/channels/channel-audit.js +101 -0
  57. package/lib/channels/channel-auth-context.js +37 -0
  58. package/lib/channels/channel-credential.js +200 -0
  59. package/lib/channels/channel-display-name.js +64 -0
  60. package/lib/channels/channel-external-system.js +106 -0
  61. package/lib/channels/channel-integration-generator.js +274 -0
  62. package/lib/channels/channel-probe.js +89 -0
  63. package/lib/channels/channel-runtime-resolver.js +152 -0
  64. package/lib/channels/channel-status-display.js +141 -0
  65. package/lib/channels/channel-targets.js +115 -0
  66. package/lib/cli/index.js +20 -4
  67. package/lib/cli/infra-guided-auth.js +109 -0
  68. package/lib/cli/infra-guided.js +84 -81
  69. package/lib/cli/setup-app.help.js +0 -31
  70. package/lib/cli/setup-app.js +82 -5
  71. package/lib/cli/setup-app.test-commands.js +5 -57
  72. package/lib/cli/setup-auth.js +25 -0
  73. package/lib/cli/setup-certification-commands.js +147 -0
  74. package/lib/cli/setup-certification.help.js +141 -0
  75. package/lib/cli/setup-environment.js +19 -2
  76. package/lib/cli/setup-external-system-help.js +62 -0
  77. package/lib/cli/setup-external-system.js +25 -3
  78. package/lib/cli/setup-infra-up-dataplane-action.js +2 -2
  79. package/lib/cli/setup-infra-up-platform-action.js +2 -1
  80. package/lib/cli/setup-infra.js +9 -1
  81. package/lib/cli/setup-platform.js +6 -1
  82. package/lib/cli/setup-secrets.js +33 -1
  83. package/lib/cli/setup-utility-help-after.js +25 -2
  84. package/lib/cli/setup-utility-repair.js +198 -0
  85. package/lib/cli/setup-utility-resolve.js +44 -5
  86. package/lib/cli/setup-utility-validate.js +197 -0
  87. package/lib/cli/setup-utility.js +4 -239
  88. package/lib/commands/app-logs.js +54 -26
  89. package/lib/commands/app.js +41 -0
  90. package/lib/commands/auth-status-client-tokens.js +214 -0
  91. package/lib/commands/auth-status-dataplane-version.js +142 -68
  92. package/lib/commands/auth-status.js +43 -54
  93. package/lib/commands/channel.js +58 -0
  94. package/lib/commands/datasource-test-trust-cli.js +27 -23
  95. package/lib/commands/datasource-unified-test-cli.js +6 -3
  96. package/lib/commands/datasource-unified-test-cli.options.js +5 -1
  97. package/lib/commands/datasource.js +8 -8
  98. package/lib/commands/dev-show-display.js +8 -1
  99. package/lib/commands/governance-cli-shared.js +94 -0
  100. package/lib/commands/governance-command-action.js +132 -0
  101. package/lib/commands/governance-download-external.js +34 -0
  102. package/lib/commands/governance-generate-external.js +71 -0
  103. package/lib/commands/governance-upload-external.js +36 -0
  104. package/lib/commands/governance-verify-external.js +64 -0
  105. package/lib/commands/governance.js +144 -0
  106. package/lib/commands/identity-apply-sync.js +49 -8
  107. package/lib/commands/identity-group-cli.js +66 -26
  108. package/lib/commands/identity-membership-role-cache.js +58 -37
  109. package/lib/commands/identity-shared.js +22 -1
  110. package/lib/commands/identity-user-cli.js +80 -34
  111. package/lib/commands/lifecycle-command-action.js +123 -0
  112. package/lib/commands/lifecycle-external.js +268 -0
  113. package/lib/commands/login.js +11 -2
  114. package/lib/commands/repair-auth-apply.js +153 -0
  115. package/lib/commands/repair-auth-config.js +8 -13
  116. package/lib/commands/repair-changed-files.js +41 -0
  117. package/lib/commands/repair-datasource-com-v2.js +15 -0
  118. package/lib/commands/repair-datasource-keys.js +4 -1
  119. package/lib/commands/repair-datasource-run.js +59 -0
  120. package/lib/commands/repair-datasource-service-contract.js +206 -0
  121. package/lib/commands/repair-datasource-test-payload.js +259 -0
  122. package/lib/commands/repair-datasource.js +49 -64
  123. package/lib/commands/repair-env-template.js +76 -25
  124. package/lib/commands/repair-external-run.js +216 -0
  125. package/lib/commands/repair-openapi-sync.js +49 -4
  126. package/lib/commands/repair-persist.js +4 -0
  127. package/lib/commands/repair-rbac.js +52 -1
  128. package/lib/commands/repair-steps.js +160 -0
  129. package/lib/commands/repair-system-alignment.js +7 -4
  130. package/lib/commands/repair.js +29 -296
  131. package/lib/commands/resource-type.js +371 -0
  132. package/lib/commands/secrets-get.js +184 -0
  133. package/lib/commands/secrets-remove-all.js +3 -1
  134. package/lib/commands/setup-image-refresh.js +146 -0
  135. package/lib/commands/setup-modes.js +158 -162
  136. package/lib/commands/setup-platform-auth.js +76 -0
  137. package/lib/commands/setup-prompts-admin.js +244 -0
  138. package/lib/commands/setup-prompts-platform-mode.js +70 -0
  139. package/lib/commands/setup-prompts-validators.js +36 -0
  140. package/lib/commands/setup-prompts.js +24 -76
  141. package/lib/commands/setup-run-context.js +45 -0
  142. package/lib/commands/setup-spinners.js +39 -0
  143. package/lib/commands/setup.js +27 -5
  144. package/lib/commands/teardown.js +39 -0
  145. package/lib/commands/test-e2e-external.js +24 -8
  146. package/lib/commands/test-governance-external.js +3 -24
  147. package/lib/commands/test-trust-external.js +48 -100
  148. package/lib/commands/up-common.js +57 -13
  149. package/lib/commands/up-dataplane.js +56 -15
  150. package/lib/commands/upload-publish-context.js +75 -0
  151. package/lib/commands/upload-sidecar-followups.js +89 -0
  152. package/lib/commands/upload.js +113 -110
  153. package/lib/commands/verify-governance-combined-external.js +61 -0
  154. package/lib/commands/verify-governance-command-action.js +64 -0
  155. package/lib/commands/verify-governance-db.js +102 -0
  156. package/lib/commands/verify-governance-external.js +77 -0
  157. package/lib/commands/verify-governance-result-builders.js +71 -0
  158. package/lib/commands/verify-operations-command-action.js +68 -0
  159. package/lib/commands/verify-operations-external.js +268 -0
  160. package/lib/commands/verify-operations-persist.js +75 -0
  161. package/lib/commands/verify-operations-step-plan.js +68 -0
  162. package/lib/commands/verify-operations-steps.js +111 -0
  163. package/lib/commands/verify-trust-command-action.js +73 -0
  164. package/lib/commands/verify-trust-external.js +59 -0
  165. package/lib/commands/wizard-config-normalizer.js +43 -23
  166. package/lib/commands/wizard-core.js +2 -0
  167. package/lib/core/admin-password-generator.js +38 -0
  168. package/lib/core/admin-secrets-bundle.js +111 -0
  169. package/lib/core/admin-secrets-env-overlay.js +62 -0
  170. package/lib/core/admin-secrets.js +32 -4
  171. package/lib/core/config-attach-extensions.js +3 -0
  172. package/lib/core/config-platform-controller.js +44 -0
  173. package/lib/core/config-setup-installation-profile.js +42 -0
  174. package/lib/core/config-setup-platform-mode.js +46 -0
  175. package/lib/core/config.js +46 -36
  176. package/lib/core/secrets-admin-env.js +6 -2
  177. package/lib/core/secrets-ensure.js +4 -0
  178. package/lib/core/secrets-env-content.js +54 -48
  179. package/lib/core/secrets-env-write.js +10 -1
  180. package/lib/core/secrets-infra-placeholder-sync.js +2 -0
  181. package/lib/core/setup-installation-profile.js +43 -0
  182. package/lib/core/setup-platform-mode.js +90 -0
  183. package/lib/datasource/agent-trust-debug-log.js +1 -1
  184. package/lib/datasource/agent-trust-run.js +5 -3
  185. package/lib/datasource/audit-evidence-extract-debug.js +30 -18
  186. package/lib/datasource/audit-evidence-extract.js +7 -4
  187. package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
  188. package/lib/datasource/bulk-loader-run-batches.js +15 -3
  189. package/lib/datasource/capability/capability-diff-slice.js +2 -2
  190. package/lib/datasource/capability/capability-manifest.js +254 -0
  191. package/lib/datasource/capability/capability-resolve.js +3 -4
  192. package/lib/datasource/capability/copy-operations.js +5 -3
  193. package/lib/datasource/capability/remove-operations.js +2 -1
  194. package/lib/datasource/capability/run-capability-copy.js +32 -4
  195. package/lib/datasource/capability/run-capability-diff.js +3 -3
  196. package/lib/datasource/capability/run-capability-dimension.js +2 -4
  197. package/lib/datasource/capability/run-capability-edit.js +4 -7
  198. package/lib/datasource/capability/run-capability-relate.js +2 -4
  199. package/lib/datasource/capability/run-capability-remove.js +2 -4
  200. package/lib/datasource/capability/validate-capability-slice.js +2 -1
  201. package/lib/datasource/datasource-identifier.js +2 -1
  202. package/lib/datasource/datasource-load-export-context.js +3 -0
  203. package/lib/datasource/datasource-validate-display.js +1 -1
  204. package/lib/datasource/field-reference-validator.js +24 -3
  205. package/lib/datasource/log-cleaner.js +2 -2
  206. package/lib/datasource/log-viewer.js +8 -8
  207. package/lib/datasource/orphan-profiles-validator.js +98 -0
  208. package/lib/datasource/test-e2e.js +4 -1
  209. package/lib/datasource/unified-validation-run-body.js +3 -1
  210. package/lib/datasource/unified-validation-run.js +5 -2
  211. package/lib/datasource/validate.js +41 -23
  212. package/lib/deployment/environment-poll-status.js +138 -0
  213. package/lib/deployment/environment.js +42 -34
  214. package/lib/external-system/download-helpers.js +87 -0
  215. package/lib/external-system/download.js +78 -138
  216. package/lib/external-system/generator.js +1 -55
  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.js +16 -21
  220. package/lib/generator/builders.js +11 -1
  221. package/lib/generator/external-controller-manifest.js +18 -0
  222. package/lib/generator/split.js +3 -1
  223. package/lib/generator/wizard.js +1 -28
  224. package/lib/governance/governance-cli-errors.js +96 -0
  225. package/lib/governance/governance-download-display.js +38 -0
  226. package/lib/governance/governance-run-display.js +215 -25
  227. package/lib/identity/fk-reference.js +65 -0
  228. package/lib/identity/identity-apply-core.js +13 -58
  229. package/lib/identity/identity-apply-phases.js +5 -1
  230. package/lib/identity/identity-display.js +243 -0
  231. package/lib/identity/identity-response-helpers.js +52 -0
  232. package/lib/identity/identity-sync-errors.js +62 -0
  233. package/lib/identity/resolve-user-id.js +129 -0
  234. package/lib/identity/username-default.js +31 -0
  235. package/lib/infrastructure/admin-secrets-apply.js +84 -0
  236. package/lib/infrastructure/admin-secrets-ensure.js +130 -0
  237. package/lib/infrastructure/admin-secrets-resolve.js +95 -0
  238. package/lib/infrastructure/admin-secrets-sync.js +91 -0
  239. package/lib/infrastructure/helpers.js +23 -129
  240. package/lib/infrastructure/index.js +5 -6
  241. package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
  242. package/lib/lifecycle/certification-progress.js +231 -0
  243. package/lib/lifecycle/dataplane-ui-url.js +145 -0
  244. package/lib/lifecycle/exit-codes.js +24 -0
  245. package/lib/lifecycle/json-envelope.js +25 -0
  246. package/lib/lifecycle/lifecycle-governance-options.js +51 -0
  247. package/lib/lifecycle/logger-quiet.js +29 -0
  248. package/lib/lifecycle/open-api-published.js +59 -0
  249. package/lib/lifecycle/operations-readiness-metrics.js +101 -0
  250. package/lib/lifecycle/product-model.js +196 -0
  251. package/lib/lifecycle/report-display-trust.js +70 -0
  252. package/lib/lifecycle/report-display.js +472 -0
  253. package/lib/lifecycle/scenario-upload.js +191 -0
  254. package/lib/lifecycle/verify-step-progress.js +87 -0
  255. package/lib/parameters/infra-kv-discovery.js +27 -2
  256. package/lib/protection/auth-context.js +10 -4
  257. package/lib/resolvers/datasource-resolver.js +2 -3
  258. package/lib/resolvers/resource-type-file.js +159 -0
  259. package/lib/schema/application-schema.json +17 -1
  260. package/lib/schema/datasource-test-run.schema.json +89 -6
  261. package/lib/schema/deployment-rules.yaml +2 -1
  262. package/lib/schema/external-datasource.schema.json +2947 -2619
  263. package/lib/schema/external-system.schema.json +1418 -761
  264. package/lib/schema/infra.parameter.yaml +45 -0
  265. package/lib/schema/type/credential-field-registry.json +103 -97
  266. package/lib/schema/type/document-storage.json +9 -5
  267. package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
  268. package/lib/utils/api.js +55 -31
  269. package/lib/utils/app-relative-path-env.js +112 -0
  270. package/lib/utils/app-run-containers.js +25 -2
  271. package/lib/utils/authentication-shape.js +224 -0
  272. package/lib/utils/build-copy.js +36 -5
  273. package/lib/utils/build-resolve-image.js +66 -12
  274. package/lib/utils/celery-companion-apps.js +53 -0
  275. package/lib/utils/cli-secrets-error-format.js +83 -21
  276. package/lib/utils/cli-utils.js +20 -4
  277. package/lib/utils/compose-celery-worker.js +23 -0
  278. package/lib/utils/compose-generate-docker-compose.js +13 -1
  279. package/lib/utils/compose-traefik-ingress-base.js +16 -1
  280. package/lib/utils/config-secrets-path.js +46 -0
  281. package/lib/utils/configuration-env-resolver.js +36 -0
  282. package/lib/utils/controller-url.js +88 -1
  283. package/lib/utils/credential-secrets-env-kv.js +216 -0
  284. package/lib/utils/credential-secrets-env.js +175 -257
  285. package/lib/utils/dataplane-resolver.js +18 -2
  286. package/lib/utils/declarative-url-ports.js +27 -4
  287. package/lib/utils/deployment-auth-mode.js +41 -0
  288. package/lib/utils/developer-volume-id.js +33 -0
  289. package/lib/utils/docker-build.js +1 -4
  290. package/lib/utils/env-copy.js +14 -9
  291. package/lib/utils/env-kv-orphan-lines.js +43 -0
  292. package/lib/utils/error-formatters/network-errors.js +13 -4
  293. package/lib/utils/external-env-template.js +11 -3
  294. package/lib/utils/external-system-readiness-core.js +10 -0
  295. package/lib/utils/external-system-readiness-display.js +80 -23
  296. package/lib/utils/external-system-validators.js +8 -2
  297. package/lib/utils/health-check.js +4 -1
  298. package/lib/utils/help-builder.js +13 -8
  299. package/lib/utils/keycloak-realm-ready.js +101 -0
  300. package/lib/utils/load-cip-capacity-display-config.js +61 -15
  301. package/lib/utils/manifest-source-emit.js +2 -0
  302. package/lib/utils/paths.js +25 -0
  303. package/lib/utils/pipeline-upload-auth-retry.js +82 -0
  304. package/lib/utils/platform-controller-url.js +157 -0
  305. package/lib/utils/platform-kv-ref.js +57 -0
  306. package/lib/utils/postgres-platform-bootstrap.js +199 -0
  307. package/lib/utils/postgres-wipe.js +9 -2
  308. package/lib/utils/resolve-env-mode.js +47 -0
  309. package/lib/utils/runtime-configuration-download.js +189 -0
  310. package/lib/utils/runtime-configuration-values.js +119 -0
  311. package/lib/utils/schema-loader.js +19 -4
  312. package/lib/utils/secrets-generator.js +31 -25
  313. package/lib/utils/secrets-missing-error.js +164 -0
  314. package/lib/utils/service-url-label.js +81 -0
  315. package/lib/utils/setup-quiet-output.js +25 -0
  316. package/lib/utils/template-helpers.js +15 -0
  317. package/lib/utils/token-manager-client-credentials.js +201 -0
  318. package/lib/utils/token-manager-messages.js +8 -0
  319. package/lib/utils/token-manager-refresh.js +12 -2
  320. package/lib/utils/token-manager.js +86 -105
  321. package/lib/utils/upload-pipeline-ui.js +12 -5
  322. package/lib/utils/upload-sync-options.js +42 -0
  323. package/lib/utils/url-declarative-public-base.js +21 -3
  324. package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
  325. package/lib/utils/validation-poll-ui.js +8 -0
  326. package/lib/utils/validation-run-stage.js +45 -0
  327. package/lib/utils/worker-sidecars.js +142 -0
  328. package/lib/validation/external-manifest-validator.js +2 -0
  329. package/lib/validation/runtime-configuration-rules.js +98 -0
  330. package/lib/validation/validate-display-dimensions.js +154 -0
  331. package/lib/validation/validate-display-sections.js +276 -0
  332. package/lib/validation/validate-display-steps.js +67 -0
  333. package/lib/validation/validate-display.js +24 -402
  334. package/package.json +1 -1
  335. package/templates/applications/dataplane/application.yaml +7 -1
  336. package/templates/applications/dataplane/env.template +50 -14
  337. package/templates/applications/dataplane/rbac.yaml +108 -1
  338. package/templates/applications/miso-controller/application.yaml +2 -2
  339. package/templates/applications/miso-controller/env.template +53 -122
  340. package/templates/applications/miso-controller/rbac.yaml +28 -13
  341. package/templates/channels/chatgpt/install.template.md.hbs +49 -0
  342. package/templates/channels/chatgpt/manifest.template.json.hbs +9 -0
  343. package/templates/channels/microsoft-copilot/install.template.md.hbs +49 -0
  344. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +8 -0
  345. package/templates/channels/slack/install.template.md.hbs +49 -0
  346. package/templates/channels/slack/manifest.template.json.hbs +66 -0
  347. package/templates/channels/teams-bot/install.template.md.hbs +49 -0
  348. package/templates/channels/teams-bot/manifest.template.json.hbs +13 -0
  349. package/templates/channels/web-embed/install.template.md.hbs +49 -0
  350. package/templates/channels/web-embed/manifest.template.json.hbs +8 -0
  351. package/templates/external-system/README.md.hbs +74 -17
  352. package/templates/python/docker-compose.hbs +75 -18
  353. package/templates/typescript/docker-compose.hbs +70 -17
  354. package/lib/commands/test-governance-command-action.js +0 -55
  355. package/lib/commands/test-trust-command-action.js +0 -118
@@ -6,9 +6,8 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- const chalk = require('chalk');
10
9
  const logger = require('../utils/logger');
11
- const { formatBlockingError, formatSuccessLine, headerKeyValue } = require('../utils/cli-layout-chalk');
10
+ const { formatBlockingError, formatSuccessLine } = require('../utils/cli-layout-chalk');
12
11
  const {
13
12
  resolveControllerAndAuth,
14
13
  requireNonEmpty,
@@ -21,11 +20,27 @@ const {
21
20
  createUser,
22
21
  listUserGroups
23
22
  } = require('../api/users.api');
23
+ const {
24
+ extractPaginatedList,
25
+ printIdentityEmpty,
26
+ printIdentityListHeader,
27
+ printIdentityNotFound,
28
+ printIdentityTable,
29
+ printListPaginationFooter,
30
+ printUserGroupsTable,
31
+ printUserRecord,
32
+ USER_LIST_COLUMNS
33
+ } = require('../identity/identity-display');
34
+ const { resolveIdentityUsername } = require('../identity/username-default');
24
35
 
25
36
  function printJson(data) {
26
37
  logger.log(JSON.stringify(data, null, 2));
27
38
  }
28
39
 
40
+ function userNotFoundHints() {
41
+ return ['af identity user list --search <text>', 'Check email, username, or id spelling'];
42
+ }
43
+
29
44
  function registerUserCreate(userCmd) {
30
45
  userCmd
31
46
  .command('create')
@@ -38,12 +53,13 @@ function registerUserCreate(userCmd) {
38
53
  .action(async(options) => {
39
54
  try {
40
55
  const { controllerUrl, authConfig } = await resolveControllerAndAuth();
56
+ const email = requireNonEmpty(options.email, 'email');
41
57
  const res = await createUser(controllerUrl, authConfig, {
42
- email: requireNonEmpty(options.email, 'email'),
58
+ email,
43
59
  firstName: options.firstName,
44
60
  lastName: options.lastName,
45
61
  displayName: options.displayName,
46
- username: options.username,
62
+ username: resolveIdentityUsername({ username: options.username, email }),
47
63
  status: 'active'
48
64
  });
49
65
  throwIfApiFailed(res);
@@ -62,26 +78,41 @@ function registerUserList(userCmd) {
62
78
  .description('List users')
63
79
  .option('--page <n>', 'Page', (v) => parseInt(v, 10))
64
80
  .option('--page-size <n>', 'Page size', (v) => parseInt(v, 10))
65
- .option('--search <text>', 'Search users')
81
+ .option('--search <text>', 'Search users (email, username, name)')
82
+ .option('--email <email>', 'Exact email filter')
66
83
  .option('--json', 'JSON output')
67
84
  .action(async(options) => {
68
85
  try {
69
86
  const { controllerUrl, authConfig } = await resolveControllerAndAuth();
70
- const res = await listUsers(controllerUrl, authConfig, {
87
+ const params = {
71
88
  page: options.page,
72
89
  pageSize: options.pageSize,
73
90
  search: options.search
74
- });
91
+ };
92
+ if (options.email) {
93
+ params.filter = `email:eq:${options.email}`;
94
+ delete params.search;
95
+ }
96
+ const res = await listUsers(controllerUrl, authConfig, params);
75
97
  throwIfApiFailed(res);
76
- const data = unwrapControllerData(res);
77
98
  if (options.json) {
78
- printJson(data);
99
+ printJson(res.data ?? res);
79
100
  return;
80
101
  }
81
- const items = Array.isArray(data) ? data : data?.data || [];
82
- logger.log(chalk.bold(`\nUsers (${items.length} shown):\n`));
83
- items.forEach((u) => logger.log(` ${u.id} ${u.email}`));
84
- logger.log('');
102
+ const { items, meta } = extractPaginatedList(res);
103
+ printIdentityListHeader({
104
+ emoji: '👤',
105
+ title: 'Users',
106
+ context: controllerUrl,
107
+ shown: items.length,
108
+ total: meta?.totalItems ?? items.length
109
+ });
110
+ if (items.length === 0) {
111
+ printIdentityEmpty('No users found.', ['Try --search or --email']);
112
+ return;
113
+ }
114
+ printIdentityTable(USER_LIST_COLUMNS, items);
115
+ printListPaginationFooter(meta);
85
116
  } catch (e) {
86
117
  logger.error(formatBlockingError(e.message));
87
118
  process.exit(1);
@@ -91,22 +122,28 @@ function registerUserList(userCmd) {
91
122
 
92
123
  function registerUserGet(userCmd) {
93
124
  userCmd
94
- .command('get <idOrEmail>')
95
- .description('Get user by id or email')
125
+ .command('get <userIdOrEmail>')
126
+ .description('Get user by id, email, or username')
96
127
  .option('--json', 'JSON output')
97
- .action(async(idOrEmail, options) => {
128
+ .action(async(userIdOrEmail, options) => {
98
129
  try {
99
130
  const { controllerUrl, authConfig } = await resolveControllerAndAuth();
100
- const res = await getUser(controllerUrl, authConfig, requireNonEmpty(idOrEmail, 'idOrEmail'));
101
- throwIfApiFailed(res);
131
+ const value = requireNonEmpty(userIdOrEmail, 'userIdOrEmail');
132
+ const res = await getUser(controllerUrl, authConfig, value);
133
+ if (!res || res.success === false) {
134
+ printIdentityNotFound('User', value, userNotFoundHints());
135
+ process.exit(1);
136
+ }
102
137
  const row = unwrapControllerData(res);
138
+ if (!row?.id) {
139
+ printIdentityNotFound('User', value, userNotFoundHints());
140
+ process.exit(1);
141
+ }
103
142
  if (options.json) {
104
143
  printJson(row);
105
144
  return;
106
145
  }
107
- logger.log(headerKeyValue('Id:', row.id));
108
- logger.log(headerKeyValue('Email:', row.email));
109
- logger.log('');
146
+ printUserRecord(row);
110
147
  } catch (e) {
111
148
  logger.error(formatBlockingError(e.message));
112
149
  process.exit(1);
@@ -116,26 +153,35 @@ function registerUserGet(userCmd) {
116
153
 
117
154
  function registerUserGroups(userCmd) {
118
155
  userCmd
119
- .command('groups <idOrEmail>')
120
- .description('List groups for a user')
156
+ .command('groups <userIdOrEmail>')
157
+ .description('List groups for a user (by id, email, or username)')
121
158
  .option('--json', 'JSON output')
122
- .action(async(idOrEmail, options) => {
159
+ .action(async(userIdOrEmail, options) => {
123
160
  try {
124
161
  const { controllerUrl, authConfig } = await resolveControllerAndAuth();
125
- const res = await listUserGroups(
126
- controllerUrl,
127
- authConfig,
128
- requireNonEmpty(idOrEmail, 'idOrEmail')
129
- );
130
- throwIfApiFailed(res);
162
+ const value = requireNonEmpty(userIdOrEmail, 'userIdOrEmail');
163
+ const res = await listUserGroups(controllerUrl, authConfig, value);
164
+ if (!res || res.success === false) {
165
+ printIdentityNotFound('User', value, userNotFoundHints());
166
+ process.exit(1);
167
+ }
131
168
  const data = unwrapControllerData(res);
169
+ const items = Array.isArray(data) ? data : data?.data || [];
132
170
  if (options.json) {
133
- printJson(data);
171
+ printJson(items);
134
172
  return;
135
173
  }
136
- const items = Array.isArray(data) ? data : data?.data || [];
137
- items.forEach((g) => logger.log(` ${g.id || g.groupId} ${g.name || ''}`));
138
- logger.log('');
174
+ printIdentityListHeader({
175
+ emoji: '👥',
176
+ title: `Groups for ${value}`,
177
+ shown: items.length,
178
+ total: items.length
179
+ });
180
+ if (items.length === 0) {
181
+ printIdentityEmpty('No group memberships found.');
182
+ return;
183
+ }
184
+ printUserGroupsTable(items);
139
185
  } catch (e) {
140
186
  logger.error(formatBlockingError(e.message));
141
187
  process.exit(1);
@@ -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
+ };
@@ -85,7 +85,7 @@ async function normalizeControllerUrl(options) {
85
85
  if (!controllerUrl) {
86
86
  controllerUrl = await resolveControllerUrl();
87
87
  }
88
- controllerUrl = String(controllerUrl).replace(/\/+$/, '');
88
+ controllerUrl = String(controllerUrl).trim().replace(/\/+$/, '');
89
89
  // Save controller URL to config
90
90
  await setControllerUrl(controllerUrl);
91
91
  if (!options.compact) {
@@ -170,6 +170,14 @@ async function handleDeviceCodeLoginFlow(controllerUrl, environment, options) {
170
170
  */
171
171
  async function refreshDataplaneVersionIfNeeded(controllerUrl, options, skipRefresh) {
172
172
  if (skipRefresh) return;
173
+ if (!options.compact) {
174
+ const { LOGIN_POST_REFRESH_BUDGET_MS } = require('./auth-status-dataplane-version');
175
+ logger.log(
176
+ chalk.gray(
177
+ `Syncing dataplane version cache (optional, up to ${Math.round(LOGIN_POST_REFRESH_BUDGET_MS / 1000)}s)...`
178
+ )
179
+ );
180
+ }
173
181
  await tryRefreshDataplaneVersionAfterLogin(controllerUrl, options);
174
182
  }
175
183
 
@@ -213,7 +221,8 @@ async function handleLogin(options) {
213
221
  const method = await determineAuthMethod(options.method);
214
222
  validateScopeOptions(method, options);
215
223
 
216
- const skipRefresh = options.skipDataplaneVersionRefresh === true;
224
+ const skipRefresh =
225
+ options.skipDataplaneVersionRefresh === true || options.skipVersionCache === true;
217
226
  const flow = await executeLoginMethod(method, controllerUrl, environment, options, skipRefresh);
218
227
  if (flow === 'device') return;
219
228