@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
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @fileoverview Persist operations pillar to dataplane lifecycle (plan 150.0 / 419.0).
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { resolveExternalIntegrationContext } = require('./test-e2e-external');
10
+ const { resolveIntegrationAuth } = require('../external-system/integration-auth-context');
11
+ const { postValidationRun } = require('../api/validation-run.api');
12
+ const { buildExternalDataSourceValidationRequest } = require('../utils/validation-run-request');
13
+
14
+ /**
15
+ * Optional unit rollup stored in operations.details.reliability.unit.
16
+ * @param {Object} stepResults
17
+ * @returns {Object|undefined}
18
+ */
19
+ function buildUnitTestSummary(stepResults) {
20
+ if (!stepResults || stepResults.unit !== true) {
21
+ return undefined;
22
+ }
23
+ return { passed: 1, failed: 0, skipped: 0 };
24
+ }
25
+
26
+ /**
27
+ * POST validation/run runType=operations for each active datasource (persists resultOperations).
28
+ * @async
29
+ * @param {string} systemKey
30
+ * @param {Object} options
31
+ * @param {Object} stepResults
32
+ * @returns {Promise<{ persisted: number }>}
33
+ */
34
+ async function persistOperationsForSystem(systemKey, options, stepResults) {
35
+ const { systemKey: resolvedKey, keys } = resolveExternalIntegrationContext(systemKey);
36
+ if (keys.length === 0) {
37
+ return { persisted: 0 };
38
+ }
39
+
40
+ const { authConfig, dataplaneUrl } = await resolveIntegrationAuth(systemKey, options);
41
+
42
+ const timeoutMs = parseInt(String(options.timeout || '120000'), 10) || 120000;
43
+ const unitTestSummary = buildUnitTestSummary(stepResults);
44
+ let persisted = 0;
45
+
46
+ for (const dsKey of keys) {
47
+ const body = buildExternalDataSourceValidationRequest({
48
+ systemKey: resolvedKey,
49
+ datasourceKey: dsKey,
50
+ runType: 'operations'
51
+ });
52
+ if (unitTestSummary) {
53
+ body.unitTestSummary = unitTestSummary;
54
+ }
55
+
56
+ const res = await postValidationRun(dataplaneUrl, authConfig, body, { timeoutMs });
57
+ if (!res || res.success === false) {
58
+ const msg =
59
+ (res &&
60
+ res.error &&
61
+ (res.error.formattedError || res.error.error || res.error.message)) ||
62
+ res?.formattedError ||
63
+ 'Operations lifecycle persist failed';
64
+ throw new Error(`${dsKey}: ${msg}`);
65
+ }
66
+ persisted += 1;
67
+ }
68
+
69
+ return { persisted };
70
+ }
71
+
72
+ module.exports = {
73
+ persistOperationsForSystem,
74
+ buildUnitTestSummary
75
+ };
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @fileoverview Step plan for verify-operations (plan 150.0).
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const { validateExternalSystemComplete } = require('../validation/validate');
8
+ const { testExternalSystem, testExternalSystemIntegration } = require('../external-system/test');
9
+ const { runTestE2EForExternalSystem } = require('./test-e2e-external');
10
+
11
+ /**
12
+ * @param {string} systemKey
13
+ * @param {Object} options
14
+ * @returns {{ beforeSync: Array, afterSync: Array, e2e: Object }}
15
+ */
16
+ function buildOperationsVerifyStepPlan(systemKey, options) {
17
+ return {
18
+ beforeSync: [
19
+ {
20
+ key: 'validation',
21
+ run: () => validateExternalSystemComplete(systemKey, { type: 'external' }),
22
+ ok: (result) => result.valid === true
23
+ },
24
+ {
25
+ key: 'unit',
26
+ run: () => testExternalSystem(systemKey, { verbose: false }),
27
+ ok: (result) => result.valid === true
28
+ }
29
+ ],
30
+ afterSync: [
31
+ {
32
+ key: 'integration',
33
+ run: () =>
34
+ testExternalSystemIntegration(systemKey, {
35
+ environment: options.env,
36
+ noSync: true,
37
+ verbose: false,
38
+ debug: options.debug === true
39
+ }),
40
+ ok: (result) => result.success === true
41
+ }
42
+ ],
43
+ e2e: {
44
+ key: 'e2e',
45
+ run: (progress) =>
46
+ runTestE2EForExternalSystem(systemKey, {
47
+ env: options.env,
48
+ noSync: true,
49
+ verbose: false,
50
+ debug: options.debug === true,
51
+ async: options.async !== false,
52
+ authConfig: options.authConfig,
53
+ dataplaneUrl: options.dataplaneUrl,
54
+ silentResolve: options.silentResolve === true,
55
+ quietPollUi: true,
56
+ onDatasourceProgress: progress?.setLabel
57
+ ? ({ key, index, total }) =>
58
+ progress.setLabel(`Running E2E: ${key} (${index + 1}/${total})`)
59
+ : undefined
60
+ }),
61
+ ok: (result) => result.success === true
62
+ }
63
+ };
64
+ }
65
+
66
+ module.exports = {
67
+ buildOperationsVerifyStepPlan
68
+ };
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @fileoverview verify-operations step runners (plan 150.0).
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const { syncLocalIfRequested } = require('./test-e2e-external');
8
+ const { cliOptsSkipSync } = require('../utils/cli-sync-options');
9
+ const { buildOperationsVerifyStepPlan } = require('./verify-operations-step-plan');
10
+ const { runWithVerifyStepProgress } = require('../lifecycle/verify-step-progress');
11
+
12
+ const STEP_PROGRESS = {
13
+ validation: 'Validating local integration',
14
+ unit: 'Running unit tests',
15
+ integration: 'Running integration tests on dataplane',
16
+ e2e: 'Running E2E tests'
17
+ };
18
+
19
+ /**
20
+ * @param {Object} options
21
+ * @param {Object} uploadCtx
22
+ */
23
+ function attachUploadAuthToOptions(options, uploadCtx) {
24
+ if (!uploadCtx?.authConfig || !uploadCtx?.dataplaneUrl) {
25
+ return;
26
+ }
27
+ options.authConfig = uploadCtx.authConfig;
28
+ options.dataplaneUrl = uploadCtx.dataplaneUrl;
29
+ options.silentResolve = true;
30
+ }
31
+
32
+ /**
33
+ * @param {Function} runner
34
+ * @param {Function} isSuccess
35
+ * @param {Object} options
36
+ * @returns {Promise<boolean>}
37
+ */
38
+ async function runVerifyStep(runner, isSuccess) {
39
+ const outcome = await runner();
40
+ return isSuccess(outcome);
41
+ }
42
+
43
+ /**
44
+ * @param {Object} stepResults
45
+ * @param {string} key
46
+ * @param {boolean} passed
47
+ * @param {boolean} continueOnFail
48
+ * @returns {boolean} false when the verify flow should stop early
49
+ */
50
+ function recordVerifyStep(stepResults, key, passed, continueOnFail) {
51
+ stepResults[key] = passed;
52
+ return passed || continueOnFail;
53
+ }
54
+
55
+ /**
56
+ * @param {Object} stepResults
57
+ * @param {Object} step
58
+ * @param {boolean} continueOnFail
59
+ * @param {Object} options
60
+ * @returns {Promise<boolean>}
61
+ */
62
+ async function runTrackedVerifyStep(stepResults, step, continueOnFail, options) {
63
+ const label = STEP_PROGRESS[step.key] || step.key;
64
+ const passed = await runWithVerifyStepProgress(
65
+ label,
66
+ async(progress) => runVerifyStep(() => step.run(progress), step.ok),
67
+ options
68
+ );
69
+ return recordVerifyStep(stepResults, step.key, passed, continueOnFail);
70
+ }
71
+
72
+ /**
73
+ * @async
74
+ * @param {string} systemKey
75
+ * @param {Object} options
76
+ * @returns {Promise<{ stepResults: Object, hardFailure: boolean, stoppedEarly: boolean }>}
77
+ */
78
+ async function runOperationsVerifySteps(systemKey, options) {
79
+ const stepResults = { validation: false, unit: false, integration: false, e2e: false };
80
+ const continueOnFail = options.continue === true;
81
+ const plan = buildOperationsVerifyStepPlan(systemKey, options);
82
+
83
+ for (const step of plan.beforeSync) {
84
+ if (!(await runTrackedVerifyStep(stepResults, step, continueOnFail, options))) {
85
+ return { stepResults, hardFailure: true, stoppedEarly: true };
86
+ }
87
+ }
88
+
89
+ if (!cliOptsSkipSync(options)) {
90
+ const uploadCtx = await syncLocalIfRequested(systemKey, options);
91
+ attachUploadAuthToOptions(options, uploadCtx);
92
+ }
93
+
94
+ for (const step of plan.afterSync) {
95
+ if (!(await runTrackedVerifyStep(stepResults, step, continueOnFail, options))) {
96
+ return { stepResults, hardFailure: true, stoppedEarly: true };
97
+ }
98
+ }
99
+
100
+ const e2eLabel = STEP_PROGRESS.e2e;
101
+ stepResults.e2e = await runWithVerifyStepProgress(
102
+ e2eLabel,
103
+ async(progress) => runVerifyStep(() => plan.e2e.run(progress), plan.e2e.ok),
104
+ options
105
+ );
106
+ return { stepResults, hardFailure: !stepResults.e2e, stoppedEarly: false };
107
+ }
108
+
109
+ module.exports = {
110
+ runOperationsVerifySteps
111
+ };
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @fileoverview CLI action for `aifabrix verify-trust` (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 { runVerifyTrustForExternalSystem } = require('./verify-trust-external');
12
+ const { normalizeTestTrustCliOptions } = require('./test-trust-cli-options');
13
+ const { displayVerifyTrustTTY } = require('../lifecycle/report-display');
14
+ const { exitCodeFromVerdict } = require('../lifecycle/exit-codes');
15
+ const { buildJsonEnvelope } = require('../lifecycle/json-envelope');
16
+
17
+ async function runVerifyTrustCommandAction(appName, options, cmd) {
18
+ const opts = normalizeTestTrustCliOptions(options, cmd);
19
+ const pathsUtil = require('../utils/paths');
20
+ const appType = await pathsUtil.detectAppType(appName).catch(() => null);
21
+ if (!appType || appType.baseDir !== 'integration') {
22
+ throw new Error(
23
+ 'verify-trust applies to external integration folders only (integration/<systemKey>/).'
24
+ );
25
+ }
26
+
27
+ const result = await runVerifyTrustForExternalSystem(appName, {
28
+ env: opts.env,
29
+ verbose: opts.verbose,
30
+ debug: opts.debug,
31
+ noSync: opts.noSync === true,
32
+ revalidate: opts.revalidate === true,
33
+ timeout: opts.timeout
34
+ });
35
+
36
+ if (opts.json) {
37
+ const envelope = buildJsonEnvelope(
38
+ {
39
+ systemKey: result.systemKey,
40
+ command: result.command,
41
+ verdict: result.verdict,
42
+ aiTrustPercent: result.aiTrustPercent,
43
+ accessConfidencePercent: result.accessConfidencePercent,
44
+ businessConfidencePercent: result.businessConfidencePercent,
45
+ findings: result.findings,
46
+ datasourceRows: opts.details ? result.datasourceRows : undefined
47
+ },
48
+ opts.details || opts.verbose
49
+ );
50
+ logger.log(JSON.stringify(envelope, null, 2));
51
+ } else {
52
+ displayVerifyTrustTTY(result.systemKey, result, { details: opts.verbose || opts.details });
53
+ }
54
+
55
+ const exitCode = exitCodeFromVerdict(result.verdict);
56
+ if (exitCode !== 0) {
57
+ process.exit(exitCode);
58
+ }
59
+ }
60
+
61
+ async function verifyTrustCommandHandler(appName, options, cmd) {
62
+ try {
63
+ await runVerifyTrustCommandAction(appName, options, cmd);
64
+ } catch (error) {
65
+ handleCommandError(error, 'verify-trust');
66
+ process.exit(3);
67
+ }
68
+ }
69
+
70
+ module.exports = {
71
+ runVerifyTrustCommandAction,
72
+ verifyTrustCommandHandler
73
+ };
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @fileoverview verify-trust orchestration with dual-confidence report (433.0).
3
+ * @author AI Fabrix Team
4
+ * @version 2.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { runTestTrustForExternalSystem } = require('./test-trust-external');
10
+ const { VERDICT, verdictFromPassed } = require('../lifecycle/product-model');
11
+
12
+ /**
13
+ * @param {Array<Object>} rows
14
+ * @returns {Array<Object>}
15
+ */
16
+ function mapTrustDatasourceRows(rows) {
17
+ return (rows || []).map(row => {
18
+ const tr = row.trustRun;
19
+ const verdict = row.success ? VERDICT.VERIFIED : VERDICT.FAILED;
20
+ return {
21
+ datasourceKey: row.key,
22
+ verdict,
23
+ trustDecision: tr?.trustDecision,
24
+ validationStatus: tr?.validationStatus,
25
+ error: row.error
26
+ };
27
+ });
28
+ }
29
+
30
+ /**
31
+ * @async
32
+ * @param {string} systemKey
33
+ * @param {Object} options
34
+ * @returns {Promise<Object>}
35
+ */
36
+ async function runVerifyTrustForExternalSystem(systemKey, options = {}) {
37
+ const { success, results, systemKey: resolvedKey, trustReport } =
38
+ await runTestTrustForExternalSystem(systemKey, options);
39
+ const datasourceRows = mapTrustDatasourceRows(results);
40
+ const report = trustReport || {};
41
+ const verdict = report.verdict ? report.verdict : verdictFromPassed(success);
42
+
43
+ return {
44
+ systemKey: resolvedKey || systemKey,
45
+ command: 'verify-trust',
46
+ verdict,
47
+ aiTrustPercent: report.aiTrustPercent ?? null,
48
+ accessConfidencePercent: report.accessConfidencePercent ?? null,
49
+ businessConfidencePercent: report.businessConfidencePercent ?? null,
50
+ findings: Array.isArray(report.findings) ? report.findings : [],
51
+ datasourceRows,
52
+ results
53
+ };
54
+ }
55
+
56
+ module.exports = {
57
+ runVerifyTrustForExternalSystem,
58
+ mapTrustDatasourceRows
59
+ };
@@ -17,6 +17,7 @@ const VALID_ENTITY_TYPES = new Set([
17
17
  'none'
18
18
  ]);
19
19
  const VALID_PORTAL_FIELDS = new Set(['text', 'textarea', 'select', 'json', 'boolean', 'number']);
20
+ const { repairTestPayload } = require('./repair-datasource-test-payload');
20
21
 
21
22
  /**
22
23
  * Normalize system config fields to schema constraints
@@ -34,6 +35,45 @@ function normalizeSystemConfig(systemConfig) {
34
35
  return systemConfig;
35
36
  }
36
37
 
38
+ /**
39
+ * @param {Object} datasourceConfig - Datasource config (mutated)
40
+ */
41
+ function normalizePortalInput(datasourceConfig) {
42
+ if (!Array.isArray(datasourceConfig.portalInput)) return;
43
+ datasourceConfig.portalInput = datasourceConfig.portalInput.filter(item => {
44
+ if (!item || typeof item !== 'object') return false;
45
+ if (!item.name || !item.field || !item.label) return false;
46
+ return VALID_PORTAL_FIELDS.has(item.field);
47
+ });
48
+ }
49
+
50
+ /**
51
+ * @param {Object} datasourceConfig - Datasource config (mutated)
52
+ */
53
+ function normalizeCipOutputModes(datasourceConfig) {
54
+ const operations = datasourceConfig.execution?.cip?.operations;
55
+ if (!operations) return;
56
+ for (const operation of Object.values(operations)) {
57
+ if (!operation || !Array.isArray(operation.steps)) continue;
58
+ for (const step of operation.steps) {
59
+ if (step?.output?.mode && step.output.mode !== 'records') {
60
+ step.output.mode = 'records';
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ /**
67
+ * @param {Object} datasourceConfig - Datasource config (mutated)
68
+ */
69
+ function normalizeWizardTestPayload(datasourceConfig) {
70
+ const attrs = datasourceConfig.fieldMappings?.attributes;
71
+ if (!datasourceConfig.metadataSchema || !attrs || Object.keys(attrs).length === 0) {
72
+ return;
73
+ }
74
+ repairTestPayload(datasourceConfig, []);
75
+ }
76
+
37
77
  /**
38
78
  * Normalize datasource config fields to schema constraints
39
79
  * @function normalizeDatasourceConfig
@@ -47,29 +87,9 @@ function normalizeDatasourceConfig(datasourceConfig) {
47
87
  if (datasourceConfig.entityType && !VALID_ENTITY_TYPES.has(datasourceConfig.entityType)) {
48
88
  datasourceConfig.entityType = ENTITY_TYPE_FALLBACK;
49
89
  }
50
- if (Array.isArray(datasourceConfig.portalInput)) {
51
- datasourceConfig.portalInput = datasourceConfig.portalInput.filter(item => {
52
- if (!item || typeof item !== 'object') {
53
- return false;
54
- }
55
- if (!item.name || !item.field || !item.label) {
56
- return false;
57
- }
58
- return VALID_PORTAL_FIELDS.has(item.field);
59
- });
60
- }
61
- if (datasourceConfig.execution?.cip?.operations) {
62
- for (const operation of Object.values(datasourceConfig.execution.cip.operations)) {
63
- if (!operation || !Array.isArray(operation.steps)) {
64
- continue;
65
- }
66
- for (const step of operation.steps) {
67
- if (step?.output?.mode && step.output.mode !== 'records') {
68
- step.output.mode = 'records';
69
- }
70
- }
71
- }
72
- }
90
+ normalizePortalInput(datasourceConfig);
91
+ normalizeCipOutputModes(datasourceConfig);
92
+ normalizeWizardTestPayload(datasourceConfig);
73
93
  return datasourceConfig;
74
94
  }
75
95
 
@@ -512,7 +512,9 @@ async function setupDataplaneAndAuth(options, appName) {
512
512
  } catch (error) {
513
513
  throw new Error(`Authentication failed: ${error.message}`);
514
514
  }
515
+ const { applyLabDataplaneApiKeyBearer } = require('../utils/token-manager');
515
516
  requireBearerForDataplanePipeline(authConfig);
517
+ applyLabDataplaneApiKeyBearer(authConfig);
516
518
  const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
517
519
  let dataplaneUrl;
518
520
  try {
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Cryptographically strong passwords for pro setup autogenerate.
3
+ *
4
+ * @fileoverview Pro installation password generation (show-once in setup wizard)
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const crypto = require('crypto');
12
+
13
+ const PRO_PASSWORD_BYTE_LENGTH = 18;
14
+
15
+ /**
16
+ * One random password suitable for admin roles (URL-safe, no quotes).
17
+ * @returns {string}
18
+ */
19
+ function generateRandomAdminPassword() {
20
+ return crypto.randomBytes(PRO_PASSWORD_BYTE_LENGTH).toString('base64url');
21
+ }
22
+
23
+ /**
24
+ * Distinct passwords for infra, Keycloak install, and platform UI login.
25
+ * @returns {{ infra: string, keycloak: string, platform: string }}
26
+ */
27
+ function generateProAdminPasswords() {
28
+ return {
29
+ infra: generateRandomAdminPassword(),
30
+ keycloak: generateRandomAdminPassword(),
31
+ platform: generateRandomAdminPassword()
32
+ };
33
+ }
34
+
35
+ module.exports = {
36
+ generateRandomAdminPassword,
37
+ generateProAdminPasswords
38
+ };
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Map setup password bundles onto admin-secrets.env keys.
3
+ *
4
+ * @fileoverview Single (dev) vs split (pro) admin credential bundles
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const DEFAULT_REDIS_HOST = 'local:redis:6379:0:';
12
+ const DEFAULT_REDIS_COMMANDER_USER = 'admin';
13
+ const DEFAULT_KEYCLOAK_ADMIN_USERNAME = 'admin';
14
+
15
+ /**
16
+ * @typedef {'single'|'split'} AdminPasswordBundleMode
17
+ */
18
+
19
+ /**
20
+ * @typedef {Object} AdminPasswordBundleSingle
21
+ * @property {'single'} mode
22
+ * @property {string} password
23
+ */
24
+
25
+ /**
26
+ * @typedef {Object} AdminPasswordBundleSplit
27
+ * @property {'split'} mode
28
+ * @property {string} infra
29
+ * @property {string} keycloak
30
+ * @property {string} platform
31
+ */
32
+
33
+ /**
34
+ * @param {string} password
35
+ * @returns {AdminPasswordBundleSingle}
36
+ */
37
+ function singlePasswordBundle(password) {
38
+ return { mode: 'single', password: String(password) };
39
+ }
40
+
41
+ /**
42
+ * @param {{ infra: string, keycloak: string, platform: string }} parts
43
+ * @returns {AdminPasswordBundleSplit}
44
+ */
45
+ function splitPasswordBundle(parts) {
46
+ return {
47
+ mode: 'split',
48
+ infra: String(parts.infra),
49
+ keycloak: String(parts.keycloak),
50
+ platform: String(parts.platform)
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Apply bundle onto a decrypted admin-secrets object (mutates copy).
56
+ * @param {Object.<string, string>} adminObj
57
+ * @param {AdminPasswordBundleSingle|AdminPasswordBundleSplit} bundle
58
+ * @returns {Object.<string, string>}
59
+ */
60
+ function applyPasswordBundleToAdminObj(adminObj, bundle) {
61
+ const merged = { ...(adminObj || {}) };
62
+ merged.REDIS_HOST = merged.REDIS_HOST || DEFAULT_REDIS_HOST;
63
+ merged.REDIS_COMMANDER_USER = merged.REDIS_COMMANDER_USER || DEFAULT_REDIS_COMMANDER_USER;
64
+ merged.KEYCLOAK_ADMIN_USERNAME = DEFAULT_KEYCLOAK_ADMIN_USERNAME;
65
+
66
+ if (bundle.mode === 'single') {
67
+ const p = bundle.password;
68
+ merged.POSTGRES_PASSWORD = p;
69
+ merged.PGADMIN_DEFAULT_PASSWORD = p;
70
+ merged.REDIS_COMMANDER_PASSWORD = p;
71
+ merged.KEYCLOAK_ADMIN_PASSWORD = p;
72
+ merged.PLATFORM_ADMIN_PASSWORD = p;
73
+ return merged;
74
+ }
75
+
76
+ merged.POSTGRES_PASSWORD = bundle.infra;
77
+ merged.PGADMIN_DEFAULT_PASSWORD = bundle.infra;
78
+ merged.REDIS_COMMANDER_PASSWORD = bundle.infra;
79
+ merged.KEYCLOAK_ADMIN_PASSWORD = bundle.keycloak;
80
+ merged.PLATFORM_ADMIN_PASSWORD = bundle.platform;
81
+ return merged;
82
+ }
83
+
84
+ /**
85
+ * Build bundle from setup / up-infra CLI options.
86
+ * @param {Object} [options]
87
+ * @returns {AdminPasswordBundleSingle|AdminPasswordBundleSplit|null}
88
+ */
89
+ function passwordBundleFromCliOptions(options = {}) {
90
+ if (options.passwordBundle && options.passwordBundle.mode) {
91
+ return options.passwordBundle;
92
+ }
93
+ const infra = String(options.infraAdminPassword || '').trim();
94
+ const keycloak = String(options.keycloakAdminPassword || '').trim();
95
+ const platform = String(options.platformAdminPassword || '').trim();
96
+ if (infra && keycloak && platform) {
97
+ return splitPasswordBundle({ infra, keycloak, platform });
98
+ }
99
+ const single = String(options.adminPassword || options.adminPwd || '').trim();
100
+ if (single) {
101
+ return singlePasswordBundle(single);
102
+ }
103
+ return null;
104
+ }
105
+
106
+ module.exports = {
107
+ singlePasswordBundle,
108
+ splitPasswordBundle,
109
+ applyPasswordBundleToAdminObj,
110
+ passwordBundleFromCliOptions
111
+ };
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Map decrypted admin-secrets.env into platform container env keys.
3
+ *
4
+ * @fileoverview Overlay KEYCLOAK_* / ONBOARDING_* from admin-secrets (plan 185 Phase 2)
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /**
12
+ * @param {Object.<string, string>} adminObj
13
+ * @returns {Object.<string, string>}
14
+ */
15
+ function buildPlatformEnvOverlayFromAdminSecrets(adminObj) {
16
+ if (!adminObj || typeof adminObj !== 'object') return {};
17
+ const platformPwd =
18
+ adminObj.PLATFORM_ADMIN_PASSWORD ||
19
+ adminObj.ONBOARDING_ADMIN_PASSWORD ||
20
+ adminObj.MISO_ADMIN_PASSWORD ||
21
+ '';
22
+ const overlay = {};
23
+ if (adminObj.KEYCLOAK_ADMIN_USERNAME) {
24
+ overlay.KEYCLOAK_ADMIN_USERNAME = adminObj.KEYCLOAK_ADMIN_USERNAME;
25
+ }
26
+ if (adminObj.KEYCLOAK_ADMIN_PASSWORD) {
27
+ overlay.KEYCLOAK_ADMIN_PASSWORD = adminObj.KEYCLOAK_ADMIN_PASSWORD;
28
+ // Keycloak image reads KC_BOOTSTRAP_* on first start; keep in sync with admin-secrets (pro split bundles).
29
+ overlay.KC_BOOTSTRAP_ADMIN_PASSWORD = adminObj.KEYCLOAK_ADMIN_PASSWORD;
30
+ overlay.KC_BOOTSTRAP_ADMIN_USERNAME =
31
+ adminObj.KEYCLOAK_ADMIN_USERNAME || adminObj.KC_BOOTSTRAP_ADMIN_USERNAME || 'admin';
32
+ }
33
+ if (platformPwd) {
34
+ overlay.PLATFORM_ADMIN_PASSWORD = platformPwd;
35
+ overlay.ONBOARDING_ADMIN_PASSWORD = platformPwd;
36
+ overlay.MISO_ADMIN_PASSWORD = platformPwd;
37
+ }
38
+ const email = adminObj.PGADMIN_DEFAULT_EMAIL || adminObj.ONBOARDING_ADMIN_EMAIL;
39
+ if (email) {
40
+ overlay.ONBOARDING_ADMIN_EMAIL = email;
41
+ }
42
+ return overlay;
43
+ }
44
+
45
+ /**
46
+ * Apply admin-secrets values over resolved app env (admin-secrets wins for platform keys).
47
+ * @param {Object.<string, string>} envMap
48
+ * @param {Object.<string, string>} adminObj
49
+ */
50
+ function applyAdminSecretsPlatformOverlay(envMap, adminObj) {
51
+ const overlay = buildPlatformEnvOverlayFromAdminSecrets(adminObj);
52
+ for (const [key, value] of Object.entries(overlay)) {
53
+ if (value !== undefined && value !== null && String(value).trim() !== '') {
54
+ envMap[key] = String(value);
55
+ }
56
+ }
57
+ }
58
+
59
+ module.exports = {
60
+ buildPlatformEnvOverlayFromAdminSecrets,
61
+ applyAdminSecretsPlatformOverlay
62
+ };