@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
@@ -1,12 +1,11 @@
1
1
  /**
2
2
  * Mode handlers for `aifabrix setup`.
3
3
  *
4
- * Five small handlers, one per branch of the setup decision tree:
5
- * - {@link runFreshInstall} — no infra: wizard for admin creds + AI tool, then up-infra + up-platform.
6
- * - {@link runReinstall} — Mode 1: down-infra -v, wipe local secrets, up-infra, up-platform --force.
7
- * - {@link runWipeData} — Mode 2: drop DBs/roles, wipe local secrets, up-infra, up-platform --force.
8
- * - {@link runCleanInstallFiles}— Mode 3: wipe local secrets, up-infra, up-platform --force (templates re-copied).
9
- * - {@link runUpdateImages} — Mode 4: docker pull infra + platform images, up-infra, up-platform.
4
+ * Handlers for the setup decision tree:
5
+ * - {@link runFreshInstall} — no infra running: wipe volumes, wizard, up-infra, image pull, up-platform --force.
6
+ * - {@link runReinstall} — down-infra -v, image pull, up-infra, up-platform --force.
7
+ * - {@link runWipeData} — drop DBs/roles, image pull, up-infra, up-platform --force.
8
+ * - {@link runUpdateImages} — image pull, up-infra, up-platform (no --force).
10
9
  *
11
10
  * Every handler ends with `up-infra` (idempotent, reads flags from
12
11
  * `config.yaml`) followed by `up-platform`. Optional service keys
@@ -25,30 +24,24 @@
25
24
  const fs = require('fs');
26
25
  const path = require('path');
27
26
  const chalk = require('chalk');
28
- const ora = require('ora');
29
27
 
30
28
  const config = require('../core/config');
31
29
  const infra = require('../infrastructure');
32
30
  const pathsUtil = require('../utils/paths');
33
31
  const logger = require('../utils/logger');
34
- const dockerUtils = require('../utils/docker');
35
- const dockerExec = require('../utils/docker-exec');
36
- const {
37
- formatSuccessLine,
38
- formatProgress,
39
- infoLine,
40
- sectionTitle,
41
- formatDatasourceListRow,
42
- successGlyph
43
- } = require('../utils/cli-test-layout-chalk');
32
+ const { successGlyph } = require('../utils/cli-test-layout-chalk');
33
+ const { startSpinner, stopSpinnerSuccess } = require('./setup-spinners');
34
+ const { runSetupImageRefresh } = require('./setup-image-refresh');
35
+ const { beginSetupPlatformFlow, endSetupPlatformFlow } = require('./setup-run-context');
44
36
  const { withMutedLogger } = require('../utils/with-muted-logger');
45
- const infraHelpers = require('../infrastructure/helpers');
46
-
47
37
  const upMiso = require('./up-miso');
48
38
  const upDataplane = require('./up-dataplane');
49
39
  const upCommon = require('./up-common');
50
40
  const postgresWipe = require('../utils/postgres-wipe');
41
+ const postgresBootstrap = require('../utils/postgres-platform-bootstrap');
42
+ const appLib = require('../app');
51
43
  const setupPrompts = require('./setup-prompts');
44
+ const { ensureSetupPlatformAuth, syncPlatformControllerUrlsInConfig } = require('./setup-platform-auth');
52
45
  const { handleLogin } = require('./login');
53
46
  const infraGuided = require('../cli/infra-guided');
54
47
  const {
@@ -167,8 +160,10 @@ function handleBuilderDirAction(action) {
167
160
  return { aborted: false, backedUp: [], skipClean: false };
168
161
  }
169
162
 
170
- async function maybePromptForExistingBuilderDir({ force }) {
171
- if (force !== true) return { aborted: false, backedUp: [], skipClean: false };
163
+ async function maybePromptForExistingBuilderDir({ force, skipBuilderConflictPrompt }) {
164
+ if (force !== true || skipBuilderConflictPrompt === true) {
165
+ return { aborted: false, backedUp: [], skipClean: false };
166
+ }
172
167
  const existing = getBuilderRootEntriesOrNull();
173
168
  const { sysRoot, apps: systemPlatformApps } = getNonEmptySystemPlatformApps();
174
169
  if (!existing && systemPlatformApps.length === 0) {
@@ -186,26 +181,6 @@ async function maybePromptForExistingBuilderDir({ force }) {
186
181
  return handleBuilderDirAction(action);
187
182
  }
188
183
 
189
- function shouldUseSpinner() {
190
- return Boolean(process && process.stdout && process.stdout.isTTY);
191
- }
192
-
193
- function startSpinner(text) {
194
- if (!shouldUseSpinner()) {
195
- logger.log(formatProgress(text));
196
- return null;
197
- }
198
- return ora({ text, spinner: 'dots' }).start();
199
- }
200
-
201
- function stopSpinnerSuccess(spinner, text) {
202
- if (!spinner) {
203
- logger.log(formatSuccessLine(text));
204
- return;
205
- }
206
- spinner.succeed(text);
207
- }
208
-
209
184
  /**
210
185
  * Start infrastructure using the developer's `config.yaml` flags.
211
186
  * Mirrors the relevant slice of `runUpInfraCommand` from `lib/cli/setup-infra.js`
@@ -217,6 +192,7 @@ function stopSpinnerSuccess(spinner, text) {
217
192
  * @param {Object} [overrides] - Optional admin overrides (fresh install only)
218
193
  * @param {string} [overrides.adminEmail] - Override pgAdmin / Keycloak admin email
219
194
  * @param {string} [overrides.adminPassword] - Override Postgres / pgAdmin / Keycloak admin password
195
+ * @param {Object} [overrides.passwordBundle] - Dev/pro bundle from setup wizard
220
196
  * @returns {Promise<void>}
221
197
  */
222
198
  async function startInfraFromConfig(overrides = {}) {
@@ -226,14 +202,19 @@ async function startInfraFromConfig(overrides = {}) {
226
202
  const emailFromConfig = typeof cfg.adminEmail === 'string' ? cfg.adminEmail.trim() : '';
227
203
  const adminEmailMerged = emailOverride || emailFromConfig || undefined;
228
204
  const effective = computeEffectiveInfraOptionalFlags(cfg, {});
205
+ const legacyPwd =
206
+ overrides.passwordBundle && overrides.passwordBundle.mode === 'single'
207
+ ? overrides.passwordBundle.password
208
+ : overrides.adminPassword;
229
209
  await withMutedLogger(async() => {
230
210
  await infra.startInfra(null, {
231
211
  traefik: effective.traefik,
232
212
  pgadmin: effective.pgadmin,
233
213
  redisCommander: effective.redisCommander,
234
- adminPassword: overrides.adminPassword,
235
- adminPwd: overrides.adminPassword,
214
+ adminPassword: legacyPwd,
215
+ adminPwd: legacyPwd,
236
216
  adminEmail: adminEmailMerged,
217
+ passwordBundle: overrides.passwordBundle,
237
218
  tlsEnabled: cfg.tlsEnabled === true
238
219
  });
239
220
  });
@@ -245,31 +226,64 @@ async function startInfraFromConfig(overrides = {}) {
245
226
  * builder dirs, then `up-miso` followed by `up-dataplane`.
246
227
  *
247
228
  * @async
248
- * @param {{ force?: boolean }} [opts]
229
+ * @param {{
230
+ * force?: boolean,
231
+ * skipBuilderConflictPrompt?: boolean,
232
+ * skipPrepareTemplates?: boolean,
233
+ * skipForceClean?: boolean,
234
+ * clearTokensAlways?: boolean,
235
+ * requireKeycloakRealm?: boolean
236
+ * }} [opts]
249
237
  * @returns {Promise<void>}
250
238
  */
251
239
  async function runUpPlatform(opts = {}) {
252
- const preflight = await maybePromptForExistingBuilderDir({ force: opts.force === true });
240
+ const preflight = await maybePromptForExistingBuilderDir({
241
+ force: opts.force === true,
242
+ skipBuilderConflictPrompt: opts.skipBuilderConflictPrompt === true
243
+ });
253
244
  if (preflight.aborted) return;
254
245
 
255
- let forceCleanSummary = null;
256
- if (opts.force === true) {
257
- const forceSummary = await upCommon.applyUpPlatformForceConfig({ silent: true });
258
- if (preflight.skipClean !== true) {
259
- const cleanedApps = await upCommon.cleanBuilderAppDirs(PLATFORM_APPS, { silent: true });
260
- forceCleanSummary = { forceSummary, cleanedApps };
261
- } else {
262
- forceCleanSummary = { forceSummary, cleanedApps: [] };
246
+ if (opts.skipPrepareTemplates !== true) {
247
+ await upCommon.prepareUrlsLocalRegistryForUpPlatform({ silent: opts.quiet === true });
248
+ }
249
+ beginSetupPlatformFlow();
250
+ let authCtx;
251
+ try {
252
+ const setupAuthOpts = { applyForceConfig: opts.force === true };
253
+ if (opts.clearTokensAlways === true) {
254
+ setupAuthOpts.clearTokensAlways = true;
263
255
  }
256
+ authCtx = await ensureSetupPlatformAuth(setupAuthOpts);
257
+ } catch (authErr) {
258
+ endSetupPlatformFlow();
259
+ throw authErr;
260
+ }
261
+
262
+ let forceCleanSummary = null;
263
+ if (opts.force === true && opts.skipForceClean !== true) {
264
+ const cleanedApps =
265
+ preflight.skipClean !== true
266
+ ? await upCommon.cleanBuilderAppDirs(PLATFORM_APPS, { silent: true })
267
+ : [];
268
+ forceCleanSummary = { forceSummary: authCtx.forceSummary, cleanedApps };
269
+ }
270
+
271
+ try {
272
+ await infraGuided.runGuidedUpPlatform(
273
+ {
274
+ base: true,
275
+ platformControllerUrl: authCtx.platformControllerUrl,
276
+ skipLoginIfAuthenticated: authCtx.skipLoginIfAuthenticated,
277
+ requireKeycloakRealm: opts.requireKeycloakRealm === true
278
+ },
279
+ upMiso.handleUpMiso,
280
+ upDataplane.handleUpDataplane,
281
+ handleLogin,
282
+ forceCleanSummary
283
+ );
284
+ } finally {
285
+ endSetupPlatformFlow();
264
286
  }
265
- // Reuse the same guided UX as `aifabrix up-platform` (keycloak → miso → auth → dataplane → footer).
266
- await infraGuided.runGuidedUpPlatform(
267
- { base: true },
268
- upMiso.handleUpMiso,
269
- upDataplane.handleUpDataplane,
270
- handleLogin,
271
- forceCleanSummary
272
- );
273
287
  }
274
288
 
275
289
  /**
@@ -280,76 +294,15 @@ async function runUpPlatform(opts = {}) {
280
294
  */
281
295
  function removeUserLocalSecrets() {
282
296
  const target = pathsUtil.getPrimaryUserSecretsLocalPath();
297
+ const { assertWritableSecretsPathForTests } = require('../utils/aifabrix-test-runtime-guard');
298
+ assertWritableSecretsPathForTests(target);
283
299
  if (!fs.existsSync(target)) return false;
284
300
  fs.rmSync(target, { force: true });
285
- logger.log(chalk.gray(` ${successGlyph()} Removed ${target}`));
286
- return true;
287
- }
288
-
289
- /**
290
- * Pull infra-compose images (postgres, redis, optional pgadmin/redis-commander/traefik).
291
- * Best-effort: warns and continues when the compose file is missing.
292
- *
293
- * @async
294
- * @returns {Promise<void>}
295
- */
296
- async function pullInfraImages() {
297
- const devId = await config.getDeveloperId();
298
- const infraDir = path.join(pathsUtil.getAifabrixSystemDir(), infraHelpers.getInfraDirName(devId));
299
- const composePath = path.join(infraDir, 'compose.yaml');
300
- if (!fs.existsSync(composePath)) {
301
- logger.log(chalk.yellow(`No infra compose file at ${composePath}; skipping image pull.`));
302
- return;
303
- }
304
- const project = infraHelpers.getInfraProjectName(devId);
305
- const composeCmd = await dockerUtils.getComposeCommand();
306
- logger.log('');
307
- logger.log(sectionTitle('Pull images'));
308
- const spin = startSpinner('Pulling infrastructure images...');
309
- await dockerExec.execWithDockerEnv(`${composeCmd} -f "${composePath}" -p ${project} pull`, { cwd: infraDir });
310
- stopSpinnerSuccess(spin, 'Infrastructure images pulled');
311
- }
312
-
313
- /**
314
- * Pull a single platform app image based on `builder/<appName>/application.yaml`.
315
- * Tolerates missing config / unresolvable images by warning and continuing.
316
- *
317
- * @async
318
- * @param {string} appName
319
- * @returns {Promise<void>}
320
- */
321
- async function pullPlatformAppImage(appName) {
322
- let imageRef = '';
323
- try {
324
- const { loadConfigFile } = require('../utils/config-format');
325
- const builderPath = pathsUtil.getBuilderPath(appName);
326
- const configPath = pathsUtil.resolveApplicationConfigPath(builderPath);
327
- const cfg = loadConfigFile(configPath) || {};
328
- const deploy = cfg.deploy || {};
329
- if (typeof deploy.image === 'string' && deploy.image.trim()) {
330
- imageRef = deploy.image.trim();
331
- }
332
- } catch {
333
- imageRef = '';
334
- }
335
- if (!imageRef) {
336
- logger.log(formatDatasourceListRow('skipped', appName, 'no image ref'));
337
- return;
338
- }
339
- try {
340
- const spin = startSpinner(`Pulling ${appName} image...`);
341
- await dockerExec.execWithDockerEnv(`docker pull ${imageRef}`);
342
- stopSpinnerSuccess(spin, `Pulled ${appName} image`);
343
- } catch (err) {
344
- logger.log(chalk.yellow(`Could not pull ${imageRef}: ${err.message}`));
345
- }
346
- }
347
-
348
- /** Pull every platform app image. */
349
- async function pullPlatformImages() {
350
- for (const appName of PLATFORM_APPS) {
351
- await pullPlatformAppImage(appName);
301
+ const { isSetupQuietOutput } = require('../utils/setup-quiet-output');
302
+ if (!isSetupQuietOutput()) {
303
+ logger.log(chalk.gray(` ${successGlyph()} Removed ${target}`));
352
304
  }
305
+ return true;
353
306
  }
354
307
 
355
308
  /**
@@ -357,24 +310,42 @@ async function pullPlatformImages() {
357
310
  * then up-infra + up-platform.
358
311
  *
359
312
  * @async
360
- * @param {{ adminEmail: string, adminPassword: string }} adminCreds
313
+ * @param {{ adminEmail: string, adminPassword?: string, passwordBundle?: object }} adminCreds
361
314
  * @returns {Promise<void>}
362
315
  */
363
316
  async function runFreshInstall(adminCreds) {
364
- logger.log(infoLine('Setup: fresh install'));
317
+ removeUserLocalSecrets();
318
+ const resetSpin = startSpinner('Fresh install: clearing previous data...');
319
+ await withMutedLogger(async() => {
320
+ await infra.stopInfraWithVolumes();
321
+ await infra.removeAppVolumes(PLATFORM_APPS, await config.getDeveloperId());
322
+ });
323
+ stopSpinnerSuccess(resetSpin, 'Previous data cleared');
365
324
  const infraSpin = startSpinner('Starting infrastructure...');
366
325
  await startInfraFromConfig({
367
326
  adminEmail: adminCreds.adminEmail,
368
- adminPassword: adminCreds.adminPassword
327
+ adminPassword: adminCreds.adminPassword,
328
+ passwordBundle: adminCreds.passwordBundle
369
329
  });
370
330
  stopSpinnerSuccess(infraSpin, 'Infrastructure ready');
331
+ await runSetupImageRefresh({ quiet: true });
371
332
  // Bring up infra first, then collect optional platform-level secrets (AI tool)
372
333
  // so the flow feels like a product installer: infra → platform configuration → platform services.
373
334
  await setupPrompts.promptAiTool({ silentIfConfigured: true });
374
335
  // Fresh-install should reset dev defaults (env + controller URL) the same way
375
336
  // as other setup recovery paths, otherwise the platform can come up pointed at
376
337
  // stale configuration.
377
- await runUpPlatform({ force: true });
338
+ const dbSpin = startSpinner('Preparing platform databases...');
339
+ await withMutedLogger(() => postgresBootstrap.bootstrapPlatformPostgresDatabases());
340
+ stopSpinnerSuccess(dbSpin, 'Platform databases ready');
341
+ await runUpPlatform({
342
+ force: true,
343
+ skipBuilderConflictPrompt: true,
344
+ skipPrepareTemplates: true,
345
+ skipForceClean: true,
346
+ clearTokensAlways: true,
347
+ requireKeycloakRealm: true
348
+ });
378
349
  }
379
350
 
380
351
  /**
@@ -385,67 +356,94 @@ async function runFreshInstall(adminCreds) {
385
356
  * @returns {Promise<void>}
386
357
  */
387
358
  async function runReinstall() {
388
- logger.log(infoLine('Setup: re-install (volumes will be removed)'));
389
- const downSpin = startSpinner('Stopping infrastructure (down-infra -v)...');
359
+ const downSpin = startSpinner('Re-installing (removing volumes)...');
390
360
  await withMutedLogger(async() => {
391
361
  await infra.stopInfraWithVolumes();
392
362
  });
393
- stopSpinnerSuccess(downSpin, 'Infrastructure stopped and volumes removed');
363
+ stopSpinnerSuccess(downSpin, 'Previous data cleared');
364
+ await syncPlatformControllerUrlsInConfig();
394
365
  removeUserLocalSecrets();
366
+ await runSetupImageRefresh({ quiet: true });
367
+ const adminCreds = await setupPrompts.promptAdminCredentials();
368
+ await config.setAdminEmail(adminCreds.adminEmail);
395
369
  await setupPrompts.promptAiTool({ silentIfConfigured: true });
396
370
  const infraSpin = startSpinner('Starting infrastructure...');
397
- await startInfraFromConfig({});
371
+ await startInfraFromConfig({
372
+ adminEmail: adminCreds.adminEmail,
373
+ adminPassword: adminCreds.adminPassword,
374
+ passwordBundle: adminCreds.passwordBundle
375
+ });
398
376
  stopSpinnerSuccess(infraSpin, 'Infrastructure ready');
399
- await runUpPlatform({ force: true });
377
+ const dbSpin = startSpinner('Preparing platform databases...');
378
+ await withMutedLogger(() => postgresBootstrap.bootstrapPlatformPostgresDatabases());
379
+ stopSpinnerSuccess(dbSpin, 'Platform databases ready');
380
+ await runUpPlatform({
381
+ force: true,
382
+ skipBuilderConflictPrompt: true,
383
+ clearTokensAlways: true,
384
+ requireKeycloakRealm: true
385
+ });
400
386
  }
401
387
 
402
388
  /**
403
- * Mode 2 — Wipe data: drop DBs and DB users, wipe local secrets, then
404
- * up-infra + up-platform --force. Postgres volume + admin password preserved.
389
+ * Stop platform app containers so the next up-platform cycle starts clean after a DB wipe.
405
390
  *
406
391
  * @async
407
392
  * @returns {Promise<void>}
408
393
  */
409
- async function runWipeData() {
410
- logger.log(infoLine('Setup: wipe data (databases and DB users)'));
411
- await postgresWipe.wipePostgresData();
412
- removeUserLocalSecrets();
413
- await setupPrompts.promptAiTool({ silentIfConfigured: true });
414
- const infraSpin = startSpinner('Starting infrastructure...');
415
- await startInfraFromConfig({});
416
- stopSpinnerSuccess(infraSpin, 'Infrastructure ready');
417
- await runUpPlatform({ force: true });
394
+ async function stopPlatformAppContainers() {
395
+ const developerId = await config.getDeveloperId();
396
+ await withMutedLogger(async() => {
397
+ for (const appName of PLATFORM_APPS) {
398
+ try {
399
+ await appLib.stopAndRemoveContainer(appName, developerId, false);
400
+ } catch {
401
+ // Container may already be stopped.
402
+ }
403
+ }
404
+ });
418
405
  }
419
406
 
420
407
  /**
421
- * Mode 3 — Clean install files: wipe local secrets, then up-infra +
422
- * up-platform --force (which removes builder/<keycloak|miso-controller|dataplane>
423
- * and re-fetches from templates).
408
+ * Mode 2 — Wipe data: drop DBs and DB users, wipe local secrets, then
409
+ * up-infra + up-platform --force. Postgres volume + admin password preserved.
424
410
  *
425
411
  * @async
426
412
  * @returns {Promise<void>}
427
413
  */
428
- async function runCleanInstallFiles() {
429
- logger.log(infoLine('Setup: clean installation files and re-install platform services'));
430
- removeUserLocalSecrets();
414
+ async function runWipeData() {
415
+ const wipeSpin = startSpinner('Resetting databases and DB users...');
416
+ await withMutedLogger(async() => {
417
+ await postgresWipe.wipePostgresData();
418
+ removeUserLocalSecrets();
419
+ await stopPlatformAppContainers();
420
+ });
421
+ stopSpinnerSuccess(wipeSpin, 'Databases reset');
422
+ await runSetupImageRefresh({ quiet: true });
431
423
  await setupPrompts.promptAiTool({ silentIfConfigured: true });
432
424
  const infraSpin = startSpinner('Starting infrastructure...');
433
425
  await startInfraFromConfig({});
434
426
  stopSpinnerSuccess(infraSpin, 'Infrastructure ready');
435
- await runUpPlatform({ force: true });
427
+ const dbSpin = startSpinner('Preparing platform databases...');
428
+ await withMutedLogger(() => postgresBootstrap.bootstrapPlatformPostgresDatabases());
429
+ stopSpinnerSuccess(dbSpin, 'Platform databases ready');
430
+ await runUpPlatform({
431
+ force: true,
432
+ skipBuilderConflictPrompt: true,
433
+ clearTokensAlways: true,
434
+ requireKeycloakRealm: true
435
+ });
436
436
  }
437
437
 
438
438
  /**
439
- * Mode 4 — Update images: docker pull infra + platform images, then up-infra +
439
+ * Mode 3 — Update images: docker pull infra + platform images, then up-infra +
440
440
  * up-platform (no force; secrets and data preserved).
441
441
  *
442
442
  * @async
443
443
  * @returns {Promise<void>}
444
444
  */
445
445
  async function runUpdateImages() {
446
- logger.log(infoLine('Setup: update docker images'));
447
- await pullInfraImages();
448
- await pullPlatformImages();
446
+ await runSetupImageRefresh({ quiet: true });
449
447
  await setupPrompts.promptAiTool({ silentIfConfigured: true });
450
448
  const infraSpin = startSpinner('Starting infrastructure...');
451
449
  await startInfraFromConfig({});
@@ -458,11 +456,9 @@ module.exports = {
458
456
  startInfraFromConfig,
459
457
  runUpPlatform,
460
458
  removeUserLocalSecrets,
461
- pullInfraImages,
462
- pullPlatformImages,
459
+ runSetupImageRefresh,
463
460
  runFreshInstall,
464
461
  runReinstall,
465
462
  runWipeData,
466
- runCleanInstallFiles,
467
463
  runUpdateImages
468
464
  };
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Session-aware platform controller URL + auth for `aifabrix setup`.
3
+ *
4
+ * @fileoverview Setup platform-controller persistence and login gate
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const config = require('../core/config');
12
+ const upCommon = require('./up-common');
13
+ const { resolvePlatformControllerUrl } = require('../utils/platform-controller-url');
14
+ const { isPlatformAuthValidForController } = require('../utils/controller-url');
15
+ const { infoLine } = require('../utils/cli-test-layout-chalk');
16
+ const logger = require('../utils/logger');
17
+
18
+ /**
19
+ * Recompute `controller` and `platform-controller` from traefik / setupPlatformMode / front-door config.
20
+ * Call after setup changes platform topology (fresh install, re-install, wipe-data) so a prior
21
+ * full-platform URL (e.g. `http://localhost:3600/miso`) is not reused in single mode.
22
+ *
23
+ * @async
24
+ * @returns {Promise<string>} Normalized platform controller URL
25
+ */
26
+ async function syncPlatformControllerUrlsInConfig() {
27
+ const platformControllerUrl = await resolvePlatformControllerUrl();
28
+ await config.setPlatformControllerUrl(platformControllerUrl);
29
+ await config.setControllerUrl(platformControllerUrl);
30
+ return platformControllerUrl;
31
+ }
32
+
33
+ /**
34
+ * Resolve absolute platform controller URL, persist `platform-controller` and `controller`,
35
+ * and optionally apply `up-platform --force` config (token clear only when not logged in).
36
+ *
37
+ * @async
38
+ * @param {{ applyForceConfig?: boolean, clearTokensAlways?: boolean }} [opts]
39
+ * @returns {Promise<{
40
+ * platformControllerUrl: string,
41
+ * skipLoginIfAuthenticated: boolean,
42
+ * forceSummary: object|null
43
+ * }>}
44
+ */
45
+ async function ensureSetupPlatformAuth(opts = {}) {
46
+ const platformControllerUrl = await syncPlatformControllerUrlsInConfig();
47
+
48
+ let forceSummary = null;
49
+ let skipLoginIfAuthenticated = await isPlatformAuthValidForController(platformControllerUrl);
50
+ const clearTokensAlways = opts.clearTokensAlways === true;
51
+ if (opts.applyForceConfig === true) {
52
+ forceSummary = await upCommon.applyUpPlatformForceConfig({
53
+ silent: true,
54
+ clearTokens: clearTokensAlways || !skipLoginIfAuthenticated,
55
+ defaultControllerUrl: platformControllerUrl
56
+ });
57
+ if (clearTokensAlways || (forceSummary && forceSummary.deviceCleared > 0)) {
58
+ skipLoginIfAuthenticated = false;
59
+ }
60
+ }
61
+
62
+ if (skipLoginIfAuthenticated) {
63
+ logger.log(infoLine(`Already authenticated to ${platformControllerUrl}`));
64
+ }
65
+
66
+ return {
67
+ platformControllerUrl,
68
+ skipLoginIfAuthenticated,
69
+ forceSummary
70
+ };
71
+ }
72
+
73
+ module.exports = {
74
+ syncPlatformControllerUrlsInConfig,
75
+ ensureSetupPlatformAuth
76
+ };