@aifabrix/builder 2.45.5 → 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 (231) 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/README.md +43 -17
  5. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
  6. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.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 +41 -136
  12. package/lib/api/api-response-errors.js +124 -0
  13. package/lib/api/governance-scenario-pack.api.js +159 -0
  14. package/lib/api/index.js +43 -3
  15. package/lib/api/lifecycle.api.js +77 -0
  16. package/lib/api/pipeline.api.js +3 -1
  17. package/lib/api/records-bulk.api.js +14 -1
  18. package/lib/api/validation-runner.js +3 -1
  19. package/lib/app/deploy-config.js +4 -1
  20. package/lib/app/down.js +20 -1
  21. package/lib/app/push.js +4 -5
  22. package/lib/app/register.js +7 -4
  23. package/lib/app/run-env-compose.js +84 -30
  24. package/lib/build/index.js +5 -0
  25. package/lib/certification/sync-system-certification.js +13 -6
  26. package/lib/cli/index.js +4 -0
  27. package/lib/cli/infra-guided-auth.js +109 -0
  28. package/lib/cli/infra-guided.js +84 -81
  29. package/lib/cli/setup-app.help.js +0 -31
  30. package/lib/cli/setup-app.js +28 -2
  31. package/lib/cli/setup-app.test-commands.js +5 -57
  32. package/lib/cli/setup-auth.js +25 -0
  33. package/lib/cli/setup-certification-commands.js +147 -0
  34. package/lib/cli/setup-certification.help.js +141 -0
  35. package/lib/cli/setup-environment.js +19 -2
  36. package/lib/cli/setup-external-system-help.js +62 -0
  37. package/lib/cli/setup-external-system.js +25 -3
  38. package/lib/cli/setup-infra.js +9 -1
  39. package/lib/cli/setup-platform.js +6 -1
  40. package/lib/cli/setup-secrets.js +33 -1
  41. package/lib/cli/setup-utility-help-after.js +22 -2
  42. package/lib/cli/setup-utility-repair.js +198 -0
  43. package/lib/cli/setup-utility-resolve.js +40 -4
  44. package/lib/cli/setup-utility-validate.js +197 -0
  45. package/lib/cli/setup-utility.js +4 -239
  46. package/lib/commands/auth-status-client-tokens.js +214 -0
  47. package/lib/commands/auth-status-dataplane-version.js +58 -20
  48. package/lib/commands/auth-status.js +41 -47
  49. package/lib/commands/datasource-test-trust-cli.js +27 -23
  50. package/lib/commands/datasource-unified-test-cli.js +6 -3
  51. package/lib/commands/datasource-unified-test-cli.options.js +5 -1
  52. package/lib/commands/datasource.js +7 -7
  53. package/lib/commands/dev-show-display.js +8 -1
  54. package/lib/commands/governance-cli-shared.js +94 -0
  55. package/lib/commands/governance-command-action.js +132 -0
  56. package/lib/commands/governance-download-external.js +34 -0
  57. package/lib/commands/governance-generate-external.js +71 -0
  58. package/lib/commands/governance-upload-external.js +36 -0
  59. package/lib/commands/governance-verify-external.js +64 -0
  60. package/lib/commands/governance.js +144 -0
  61. package/lib/commands/lifecycle-command-action.js +123 -0
  62. package/lib/commands/lifecycle-external.js +268 -0
  63. package/lib/commands/login.js +11 -2
  64. package/lib/commands/repair-auth-apply.js +127 -0
  65. package/lib/commands/repair-changed-files.js +41 -0
  66. package/lib/commands/repair-datasource-keys.js +4 -1
  67. package/lib/commands/repair-datasource-run.js +59 -0
  68. package/lib/commands/repair-datasource-test-payload.js +259 -0
  69. package/lib/commands/repair-datasource.js +1 -51
  70. package/lib/commands/repair-env-template.js +64 -13
  71. package/lib/commands/repair-external-run.js +216 -0
  72. package/lib/commands/repair-openapi-sync.js +23 -0
  73. package/lib/commands/repair-persist.js +4 -0
  74. package/lib/commands/repair-rbac.js +52 -1
  75. package/lib/commands/repair-steps.js +145 -0
  76. package/lib/commands/repair.js +29 -296
  77. package/lib/commands/secrets-get.js +184 -0
  78. package/lib/commands/secrets-remove-all.js +3 -1
  79. package/lib/commands/setup-image-refresh.js +146 -0
  80. package/lib/commands/setup-modes.js +158 -162
  81. package/lib/commands/setup-platform-auth.js +76 -0
  82. package/lib/commands/setup-prompts-admin.js +244 -0
  83. package/lib/commands/setup-prompts-platform-mode.js +67 -0
  84. package/lib/commands/setup-prompts-validators.js +36 -0
  85. package/lib/commands/setup-prompts.js +24 -76
  86. package/lib/commands/setup-run-context.js +45 -0
  87. package/lib/commands/setup-spinners.js +39 -0
  88. package/lib/commands/setup.js +27 -5
  89. package/lib/commands/teardown.js +39 -0
  90. package/lib/commands/test-e2e-external.js +24 -8
  91. package/lib/commands/test-governance-external.js +3 -24
  92. package/lib/commands/test-trust-external.js +20 -21
  93. package/lib/commands/up-common.js +25 -13
  94. package/lib/commands/up-dataplane.js +50 -13
  95. package/lib/commands/upload-publish-context.js +75 -0
  96. package/lib/commands/upload-sidecar-followups.js +89 -0
  97. package/lib/commands/upload.js +90 -108
  98. package/lib/commands/verify-governance-combined-external.js +61 -0
  99. package/lib/commands/verify-governance-command-action.js +64 -0
  100. package/lib/commands/verify-governance-db.js +102 -0
  101. package/lib/commands/verify-governance-external.js +77 -0
  102. package/lib/commands/verify-governance-result-builders.js +71 -0
  103. package/lib/commands/verify-operations-command-action.js +68 -0
  104. package/lib/commands/verify-operations-external.js +268 -0
  105. package/lib/commands/verify-operations-persist.js +75 -0
  106. package/lib/commands/verify-operations-step-plan.js +68 -0
  107. package/lib/commands/verify-operations-steps.js +111 -0
  108. package/lib/commands/verify-trust-command-action.js +70 -0
  109. package/lib/commands/verify-trust-external.js +67 -0
  110. package/lib/commands/wizard-config-normalizer.js +43 -23
  111. package/lib/commands/wizard-core.js +2 -0
  112. package/lib/core/admin-password-generator.js +38 -0
  113. package/lib/core/admin-secrets-bundle.js +111 -0
  114. package/lib/core/admin-secrets-env-overlay.js +62 -0
  115. package/lib/core/admin-secrets.js +32 -4
  116. package/lib/core/config-attach-extensions.js +3 -0
  117. package/lib/core/config-platform-controller.js +44 -0
  118. package/lib/core/config-setup-installation-profile.js +42 -0
  119. package/lib/core/config-setup-platform-mode.js +46 -0
  120. package/lib/core/config.js +46 -36
  121. package/lib/core/secrets-admin-env.js +6 -2
  122. package/lib/core/secrets-ensure.js +4 -0
  123. package/lib/core/secrets-env-content.js +54 -48
  124. package/lib/core/secrets-env-write.js +10 -1
  125. package/lib/core/secrets-infra-placeholder-sync.js +2 -0
  126. package/lib/core/setup-installation-profile.js +43 -0
  127. package/lib/core/setup-platform-mode.js +55 -0
  128. package/lib/datasource/agent-trust-debug-log.js +1 -1
  129. package/lib/datasource/agent-trust-run.js +5 -3
  130. package/lib/datasource/audit-evidence-extract-debug.js +30 -18
  131. package/lib/datasource/audit-evidence-extract.js +7 -4
  132. package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
  133. package/lib/datasource/bulk-loader-run-batches.js +15 -3
  134. package/lib/datasource/datasource-load-export-context.js +3 -0
  135. package/lib/datasource/log-cleaner.js +2 -2
  136. package/lib/datasource/log-viewer.js +8 -8
  137. package/lib/datasource/test-e2e.js +4 -1
  138. package/lib/datasource/unified-validation-run-body.js +3 -1
  139. package/lib/datasource/unified-validation-run.js +5 -2
  140. package/lib/deployment/environment-poll-status.js +138 -0
  141. package/lib/deployment/environment.js +42 -34
  142. package/lib/external-system/download.js +21 -20
  143. package/lib/external-system/generator.js +5 -1
  144. package/lib/external-system/integration-auth-context.js +45 -0
  145. package/lib/external-system/test-auth.js +12 -5
  146. package/lib/external-system/test.js +6 -6
  147. package/lib/generator/external-controller-manifest.js +15 -0
  148. package/lib/governance/governance-cli-errors.js +96 -0
  149. package/lib/governance/governance-download-display.js +38 -0
  150. package/lib/governance/governance-run-display.js +215 -25
  151. package/lib/infrastructure/admin-secrets-apply.js +84 -0
  152. package/lib/infrastructure/admin-secrets-ensure.js +130 -0
  153. package/lib/infrastructure/admin-secrets-resolve.js +95 -0
  154. package/lib/infrastructure/admin-secrets-sync.js +91 -0
  155. package/lib/infrastructure/helpers.js +23 -129
  156. package/lib/infrastructure/index.js +5 -6
  157. package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
  158. package/lib/lifecycle/certification-progress.js +231 -0
  159. package/lib/lifecycle/dataplane-ui-url.js +145 -0
  160. package/lib/lifecycle/exit-codes.js +24 -0
  161. package/lib/lifecycle/json-envelope.js +25 -0
  162. package/lib/lifecycle/lifecycle-governance-options.js +51 -0
  163. package/lib/lifecycle/logger-quiet.js +29 -0
  164. package/lib/lifecycle/open-api-published.js +59 -0
  165. package/lib/lifecycle/operations-readiness-metrics.js +101 -0
  166. package/lib/lifecycle/product-model.js +196 -0
  167. package/lib/lifecycle/report-display.js +471 -0
  168. package/lib/lifecycle/scenario-upload.js +191 -0
  169. package/lib/lifecycle/verify-step-progress.js +87 -0
  170. package/lib/parameters/infra-kv-discovery.js +27 -2
  171. package/lib/protection/auth-context.js +10 -4
  172. package/lib/schema/application-schema.json +1 -1
  173. package/lib/schema/datasource-test-run.schema.json +89 -6
  174. package/lib/schema/external-datasource.schema.json +2636 -2622
  175. package/lib/schema/external-system.schema.json +1089 -761
  176. package/lib/schema/infra.parameter.yaml +45 -0
  177. package/lib/schema/type/credential-field-registry.json +103 -97
  178. package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
  179. package/lib/utils/api.js +55 -31
  180. package/lib/utils/app-relative-path-env.js +112 -0
  181. package/lib/utils/cli-secrets-error-format.js +83 -21
  182. package/lib/utils/cli-utils.js +16 -4
  183. package/lib/utils/compose-generate-docker-compose.js +4 -0
  184. package/lib/utils/compose-traefik-ingress-base.js +16 -1
  185. package/lib/utils/config-secrets-path.js +46 -0
  186. package/lib/utils/controller-url.js +88 -1
  187. package/lib/utils/credential-secrets-env.js +137 -9
  188. package/lib/utils/dataplane-resolver.js +129 -2
  189. package/lib/utils/declarative-url-ports.js +3 -3
  190. package/lib/utils/deployment-auth-mode.js +41 -0
  191. package/lib/utils/developer-volume-id.js +33 -0
  192. package/lib/utils/env-copy.js +14 -9
  193. package/lib/utils/env-kv-orphan-lines.js +43 -0
  194. package/lib/utils/error-formatters/network-errors.js +13 -4
  195. package/lib/utils/external-env-template.js +1 -0
  196. package/lib/utils/external-system-readiness-core.js +10 -0
  197. package/lib/utils/external-system-readiness-display.js +80 -23
  198. package/lib/utils/health-check.js +4 -1
  199. package/lib/utils/help-builder.js +11 -8
  200. package/lib/utils/keycloak-realm-ready.js +101 -0
  201. package/lib/utils/load-cip-capacity-display-config.js +61 -15
  202. package/lib/utils/manifest-source-emit.js +2 -0
  203. package/lib/utils/pipeline-upload-auth-retry.js +82 -0
  204. package/lib/utils/platform-controller-url.js +156 -0
  205. package/lib/utils/postgres-platform-bootstrap.js +199 -0
  206. package/lib/utils/postgres-wipe.js +9 -2
  207. package/lib/utils/resolve-env-mode.js +47 -0
  208. package/lib/utils/secrets-generator.js +31 -25
  209. package/lib/utils/secrets-missing-error.js +164 -0
  210. package/lib/utils/service-url-label.js +81 -0
  211. package/lib/utils/setup-quiet-output.js +25 -0
  212. package/lib/utils/template-helpers.js +15 -0
  213. package/lib/utils/token-manager-client-credentials.js +201 -0
  214. package/lib/utils/token-manager-messages.js +8 -0
  215. package/lib/utils/token-manager-refresh.js +12 -2
  216. package/lib/utils/token-manager.js +86 -105
  217. package/lib/utils/upload-pipeline-ui.js +12 -5
  218. package/lib/utils/upload-sync-options.js +42 -0
  219. package/lib/utils/url-declarative-public-base.js +21 -3
  220. package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
  221. package/lib/utils/validation-poll-ui.js +8 -0
  222. package/lib/utils/validation-run-stage.js +45 -0
  223. package/package.json +1 -1
  224. package/templates/applications/dataplane/application.yaml +2 -1
  225. package/templates/applications/dataplane/env.template +24 -1
  226. package/templates/applications/miso-controller/env.template +16 -0
  227. package/templates/external-system/README.md.hbs +74 -17
  228. package/templates/python/docker-compose.hbs +19 -18
  229. package/templates/typescript/docker-compose.hbs +18 -17
  230. package/lib/commands/test-governance-command-action.js +0 -55
  231. package/lib/commands/test-trust-command-action.js +0 -118
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Ensure `admin-secrets.env` exists and reflects CLI / setup password bundles.
3
+ *
4
+ * @fileoverview ensureAdminSecrets for up-infra and setup
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const path = require('path');
12
+ const fsRealSync = require('../internal/fs-real-sync');
13
+ const adminSecrets = require('../core/admin-secrets');
14
+ const logger = require('../utils/logger');
15
+ const paths = require('../utils/paths');
16
+ const {
17
+ loadAdminMergedDefaultsForInfra,
18
+ resolveAdminPasswordAndEmailCli,
19
+ computeAdminSecretsBackfillFlags,
20
+ resolvePasswordForAdminFile
21
+ } = require('./admin-secrets-resolve');
22
+ const { syncAdminKvFromPasswordBundle, syncRequiredKvFromPasswordBundle } = require('./admin-secrets-sync');
23
+ const { applyAdminSecretsFromBundle: applyAdminSecretsFromBundleImpl } = require('./admin-secrets-apply');
24
+
25
+ /**
26
+ * @param {() => object} getCoreSecrets
27
+ * @param {(devId: number|string) => string} getInfraDirName
28
+ * @param {(infraDir: string) => void} logVolumeResetHint
29
+ * @param {Function} applyAdminSecretsUpdate
30
+ * @param {Object} [options]
31
+ * @returns {Promise<string>}
32
+ */
33
+ async function ensureAdminSecrets(
34
+ getCoreSecrets,
35
+ getInfraDirName,
36
+ logVolumeResetHint,
37
+ applyAdminSecretsUpdate,
38
+ options = {}
39
+ ) {
40
+ const { passwordBundleFromCliOptions } = require('../core/admin-secrets-bundle');
41
+ const bundle = options.passwordBundle || passwordBundleFromCliOptions(options);
42
+ const mergedDefaults = loadAdminMergedDefaultsForInfra(options);
43
+ const { adminPwdOverride, passwordToUse, emailOverride, emailToUse } = resolveAdminPasswordAndEmailCli(
44
+ options,
45
+ mergedDefaults
46
+ );
47
+ const adminSecretsPath = path.join(paths.getAifabrixSystemDir(), 'admin-secrets.env');
48
+
49
+ if (!fsRealSync.existsSync(adminSecretsPath)) {
50
+ logger.log('Generating admin-secrets.env...');
51
+ await getCoreSecrets().generateAdminSecretsEnv(undefined);
52
+ }
53
+
54
+ if (bundle) {
55
+ const adminObj = await adminSecrets.readAndDecryptAdminSecrets(adminSecretsPath);
56
+ await applyAdminSecretsFromBundleImpl({
57
+ getCoreSecrets,
58
+ syncAdminKvFromPasswordBundle,
59
+ syncRequiredKvFromPasswordBundle,
60
+ syncAdminKv: options.syncAdminKv === true,
61
+ logVolumeResetHint,
62
+ infraDirForHint: path.join(paths.getAifabrixSystemDir(), getInfraDirName(0)),
63
+ adminSecretsPath,
64
+ adminObj,
65
+ bundle,
66
+ email: emailToUse
67
+ });
68
+ return adminSecretsPath;
69
+ }
70
+
71
+ const adminObj = await adminSecrets.readAndDecryptAdminSecrets(adminSecretsPath);
72
+ return applyLegacyAdminSecretsUpdate(
73
+ applyAdminSecretsUpdate,
74
+ adminSecretsPath,
75
+ adminObj,
76
+ {
77
+ adminPwdOverride,
78
+ passwordToUse,
79
+ emailOverride,
80
+ emailToUse,
81
+ mergedDefaults,
82
+ syncAdminKv: options.syncAdminKv === true
83
+ }
84
+ );
85
+ }
86
+
87
+ /**
88
+ * @param {Function} applyAdminSecretsUpdate
89
+ * @param {string} adminSecretsPath
90
+ * @param {Object} adminObj
91
+ * @param {Object} ctx
92
+ * @returns {Promise<string>}
93
+ */
94
+ async function applyLegacyAdminSecretsUpdate(
95
+ applyAdminSecretsUpdate,
96
+ adminSecretsPath,
97
+ adminObj,
98
+ ctx
99
+ ) {
100
+ const { needsPasswordBackfill, needsEmailBackfill } = computeAdminSecretsBackfillFlags(adminObj);
101
+ const shouldOverwriteWithAdminPwd = ctx.adminPwdOverride !== null;
102
+ const shouldOverwriteEmail = ctx.emailOverride !== null;
103
+ const updateEmail = shouldOverwriteEmail || needsEmailBackfill;
104
+
105
+ if (!shouldOverwriteWithAdminPwd && !needsPasswordBackfill && !updateEmail) {
106
+ return adminSecretsPath;
107
+ }
108
+
109
+ const passwordForFile = resolvePasswordForAdminFile(
110
+ shouldOverwriteWithAdminPwd,
111
+ needsPasswordBackfill,
112
+ ctx.passwordToUse,
113
+ adminObj,
114
+ ctx.mergedDefaults
115
+ );
116
+
117
+ await applyAdminSecretsUpdate(
118
+ adminSecretsPath,
119
+ adminObj,
120
+ passwordForFile,
121
+ shouldOverwriteWithAdminPwd,
122
+ { updateEmail, emailToUse: ctx.emailToUse },
123
+ ctx.syncAdminKv === true
124
+ );
125
+ return adminSecretsPath;
126
+ }
127
+
128
+ module.exports = {
129
+ ensureAdminSecrets
130
+ };
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Resolve admin password/email for ensureAdminSecrets from CLI and catalog defaults.
3
+ *
4
+ * @fileoverview CLI + catalog resolution for admin-secrets.env
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const {
12
+ mergeInfraParameterDefaultsForCli,
13
+ getInfraParameterCatalog,
14
+ readRelaxedCatalogDefaults
15
+ } = require('../parameters/infra-parameter-catalog');
16
+
17
+ /**
18
+ * @param {Object} options
19
+ * @returns {Object}
20
+ */
21
+ function loadAdminMergedDefaultsForInfra(options) {
22
+ try {
23
+ return mergeInfraParameterDefaultsForCli(getInfraParameterCatalog().data, options);
24
+ } catch {
25
+ return mergeInfraParameterDefaultsForCli({}, options);
26
+ }
27
+ }
28
+
29
+ /**
30
+ * @param {Object} options
31
+ * @param {Object} mergedDefaults
32
+ * @returns {{ adminPwdOverride: string|null, passwordToUse: string, emailOverride: string|null, emailToUse: string }}
33
+ */
34
+ function resolveAdminPasswordAndEmailCli(options, mergedDefaults) {
35
+ const infraDefaults = readRelaxedCatalogDefaults();
36
+ const adminPwdCli = String(options.adminPassword || options.adminPwd || '').trim();
37
+ const adminPwdOverride = adminPwdCli !== '' ? adminPwdCli : null;
38
+ const passwordToUse =
39
+ adminPwdOverride !== null
40
+ ? adminPwdOverride
41
+ : mergedDefaults.adminPassword || infraDefaults.adminPassword || '';
42
+ const emailCli = String(options.adminEmail || '').trim();
43
+ const emailOverride = emailCli !== '' ? emailCli : null;
44
+ const emailToUse =
45
+ emailOverride !== null
46
+ ? emailOverride
47
+ : mergedDefaults.adminEmail || infraDefaults.adminEmail || '';
48
+ return { adminPwdOverride, passwordToUse, emailOverride, emailToUse };
49
+ }
50
+
51
+ /**
52
+ * @param {Object} adminObj
53
+ * @returns {{ needsPasswordBackfill: boolean, needsEmailBackfill: boolean }}
54
+ */
55
+ function computeAdminSecretsBackfillFlags(adminObj) {
56
+ const needsPasswordBackfill =
57
+ !(adminObj.POSTGRES_PASSWORD && adminObj.POSTGRES_PASSWORD.trim()) ||
58
+ !(adminObj.PGADMIN_DEFAULT_PASSWORD && adminObj.PGADMIN_DEFAULT_PASSWORD.trim()) ||
59
+ !(adminObj.REDIS_COMMANDER_PASSWORD && adminObj.REDIS_COMMANDER_PASSWORD.trim());
60
+ const needsEmailBackfill = !(adminObj.PGADMIN_DEFAULT_EMAIL && adminObj.PGADMIN_DEFAULT_EMAIL.trim());
61
+ return { needsPasswordBackfill, needsEmailBackfill };
62
+ }
63
+
64
+ /**
65
+ * @param {boolean} shouldOverwriteWithAdminPwd
66
+ * @param {boolean} needsPasswordBackfill
67
+ * @param {string} passwordToUse
68
+ * @param {Object} adminObj
69
+ * @param {Object} mergedDefaults
70
+ * @returns {string}
71
+ */
72
+ function resolvePasswordForAdminFile(
73
+ shouldOverwriteWithAdminPwd,
74
+ needsPasswordBackfill,
75
+ passwordToUse,
76
+ adminObj,
77
+ mergedDefaults
78
+ ) {
79
+ if (shouldOverwriteWithAdminPwd || needsPasswordBackfill) {
80
+ return passwordToUse;
81
+ }
82
+ return (
83
+ String(adminObj.POSTGRES_PASSWORD || '').trim() ||
84
+ mergedDefaults.adminPassword ||
85
+ readRelaxedCatalogDefaults().adminPassword ||
86
+ ''
87
+ );
88
+ }
89
+
90
+ module.exports = {
91
+ loadAdminMergedDefaultsForInfra,
92
+ resolveAdminPasswordAndEmailCli,
93
+ computeAdminSecretsBackfillFlags,
94
+ resolvePasswordForAdminFile
95
+ };
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Sync admin passwords into catalog kv secrets store.
3
+ *
4
+ * @fileoverview {{adminPassword}} placeholder sync for setup / up-infra
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const logger = require('../utils/logger');
12
+ const secretsEnsure = require('../core/secrets-ensure');
13
+
14
+ /**
15
+ * @param {string} password
16
+ * @returns {Promise<void>}
17
+ */
18
+ async function syncAdminPasswordKeysToStore(password) {
19
+ const trimmed = String(password || '').trim();
20
+ if (!trimmed) return;
21
+ try {
22
+ const { syncLiteralKvSecretsFromCliOverrides } = require('../core/secrets-infra-placeholder-sync');
23
+ const { buildInfraPlaceholderContext } = require('../core/secrets-ensure');
24
+ const ipc = require('../parameters/infra-parameter-catalog');
25
+ const placeholderContext = buildInfraPlaceholderContext({
26
+ adminPassword: trimmed,
27
+ adminPwd: trimmed
28
+ });
29
+ await syncLiteralKvSecretsFromCliOverrides(
30
+ { adminPassword: trimmed, adminPwd: trimmed },
31
+ placeholderContext,
32
+ (key, val) => secretsEnsure.setSecretInStore(key, val),
33
+ () => ipc
34
+ );
35
+ } catch (err) {
36
+ logger.warn(`Could not sync admin password keys to secrets store: ${err.message}`);
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Keep kv:// secrets aligned with admin-secrets for platform install (required for pro split bundles).
42
+ * @param {Object|null} bundle
43
+ * @returns {Promise<void>}
44
+ */
45
+ async function syncRequiredKvFromPasswordBundle(bundle) {
46
+ if (!bundle) return;
47
+ const { syncLiteralKvSecretsFromCliOverrides } = require('../core/secrets-infra-placeholder-sync');
48
+ const { buildInfraPlaceholderContext } = require('../core/secrets-ensure');
49
+ const ipc = require('../parameters/infra-parameter-catalog');
50
+
51
+ if (bundle.mode === 'single') {
52
+ const pwd = bundle.password;
53
+ await secretsEnsure.setSecretInStore('keycloak-admin-passwordKeyVault', pwd);
54
+ const ctx = buildInfraPlaceholderContext({ userPassword: pwd });
55
+ await syncLiteralKvSecretsFromCliOverrides(
56
+ { userPassword: pwd },
57
+ ctx,
58
+ (key, val) => secretsEnsure.setSecretInStore(key, val),
59
+ () => ipc
60
+ );
61
+ return;
62
+ }
63
+
64
+ await secretsEnsure.setSecretInStore('keycloak-admin-passwordKeyVault', bundle.keycloak);
65
+ const userCtx = buildInfraPlaceholderContext({ userPassword: bundle.platform });
66
+ await syncLiteralKvSecretsFromCliOverrides(
67
+ { userPassword: bundle.platform },
68
+ userCtx,
69
+ (key, val) => secretsEnsure.setSecretInStore(key, val),
70
+ () => ipc
71
+ );
72
+ }
73
+
74
+ /**
75
+ * @param {Object|null} bundle
76
+ * @returns {Promise<void>}
77
+ */
78
+ async function syncAdminKvFromPasswordBundle(bundle) {
79
+ await syncRequiredKvFromPasswordBundle(bundle);
80
+ if (bundle.mode === 'single') {
81
+ await syncAdminPasswordKeysToStore(bundle.password);
82
+ } else {
83
+ await syncAdminPasswordKeysToStore(bundle.infra);
84
+ }
85
+ }
86
+
87
+ module.exports = {
88
+ syncAdminPasswordKeysToStore,
89
+ syncRequiredKvFromPasswordBundle,
90
+ syncAdminKvFromPasswordBundle
91
+ };
@@ -11,19 +11,13 @@
11
11
 
12
12
  const path = require('path');
13
13
  const fs = require('fs');
14
- const fsRealSync = require('../internal/fs-real-sync');
15
14
  const { nodeFs } = require('../internal/node-fs');
16
15
  const chalk = require('chalk');
17
16
  const handlebars = require('handlebars');
18
17
  const adminSecrets = require('../core/admin-secrets');
19
18
  const logger = require('../utils/logger');
20
19
  const paths = require('../utils/paths');
21
- const secretsEnsure = require('../core/secrets-ensure');
22
- const {
23
- mergeInfraParameterDefaultsForCli,
24
- getInfraParameterCatalog,
25
- readRelaxedCatalogDefaults
26
- } = require('../parameters/infra-parameter-catalog');
20
+ const { readRelaxedCatalogDefaults } = require('../parameters/infra-parameter-catalog');
27
21
  const { checkDockerAvailability } = require('./helpers-docker-check');
28
22
 
29
23
  /**
@@ -77,23 +71,12 @@ function logVolumeResetHint(infraDir) {
77
71
  ));
78
72
  }
79
73
 
80
- /**
81
- * Sync postgres-passwordKeyVault to the main secrets store (file or remote).
82
- * @param {string} password - Password to store
83
- */
84
- async function syncPostgresPasswordToStore(password) {
85
- try {
86
- await secretsEnsure.setSecretInStore('postgres-passwordKeyVault', password);
87
- } catch (err) {
88
- logger.warn(`Could not sync postgres-passwordKeyVault to secrets store: ${err.message}`);
89
- }
90
- }
91
-
92
- /** Non-email defaults for admin-secrets.env merge (email default comes from infra.parameter.yaml `defaults`). */
93
- const DEFAULT_ADMIN_OBJ = {
94
- REDIS_HOST: 'local:redis:6379:0:',
95
- REDIS_COMMANDER_USER: 'admin'
96
- };
74
+ const { syncAdminPasswordKeysToStore } = require('./admin-secrets-sync');
75
+ const {
76
+ DEFAULT_ADMIN_OBJ,
77
+ writeAdminSecretsFile: writeAdminSecretsFileImpl
78
+ } = require('./admin-secrets-apply');
79
+ const { ensureAdminSecrets: ensureAdminSecretsImpl } = require('./admin-secrets-ensure');
97
80
 
98
81
  /**
99
82
  * Writes merged admin secrets to disk and logs/syncs as needed.
@@ -109,20 +92,25 @@ async function applyAdminSecretsUpdate(
109
92
  adminObj,
110
93
  passwordToUse,
111
94
  shouldOverwriteWithAdminPwd,
112
- emailOpts
95
+ emailOpts,
96
+ syncAdminKv = false
113
97
  ) {
114
98
  const merged = { ...DEFAULT_ADMIN_OBJ, ...adminObj };
115
99
  merged.POSTGRES_PASSWORD = passwordToUse;
116
100
  merged.PGADMIN_DEFAULT_PASSWORD = passwordToUse;
117
101
  merged.REDIS_COMMANDER_PASSWORD = passwordToUse;
102
+ merged.KEYCLOAK_ADMIN_USERNAME = merged.KEYCLOAK_ADMIN_USERNAME || 'admin';
103
+ merged.KEYCLOAK_ADMIN_PASSWORD = passwordToUse;
104
+ merged.PLATFORM_ADMIN_PASSWORD = passwordToUse;
118
105
  if (emailOpts && emailOpts.updateEmail && emailOpts.emailToUse) {
119
106
  merged.PGADMIN_DEFAULT_EMAIL = emailOpts.emailToUse;
120
107
  }
121
- const content = await getCoreSecrets().formatAdminSecretsContent(merged);
122
- fsRealSync.writeFileSync(adminSecretsPath, content, { mode: 0o600 });
108
+ await writeAdminSecretsFileImpl(getCoreSecrets, adminSecretsPath, merged, null);
123
109
  if (shouldOverwriteWithAdminPwd) {
124
110
  logger.log('Updated admin password in admin-secrets.env.');
125
- await syncPostgresPasswordToStore(passwordToUse);
111
+ if (syncAdminKv) {
112
+ await syncAdminPasswordKeysToStore(passwordToUse);
113
+ }
126
114
  logVolumeResetHint(path.join(paths.getAifabrixSystemDir(), getInfraDirName(0)));
127
115
  } else if (emailOpts && emailOpts.updateEmail) {
128
116
  logger.log('Updated admin email in admin-secrets.env.');
@@ -131,109 +119,15 @@ async function applyAdminSecretsUpdate(
131
119
  }
132
120
  }
133
121
 
134
- function loadAdminMergedDefaultsForInfra(options) {
135
- try {
136
- return mergeInfraParameterDefaultsForCli(getInfraParameterCatalog().data, options);
137
- } catch {
138
- return mergeInfraParameterDefaultsForCli({}, options);
139
- }
140
- }
141
-
142
- function resolveAdminPasswordAndEmailCli(options, mergedDefaults) {
143
- const infraDefaults = readInfraDefaultScalars();
144
- const adminPwdCli = String(options.adminPassword || options.adminPwd || '').trim();
145
- const adminPwdOverride = adminPwdCli !== '' ? adminPwdCli : null;
146
- const passwordToUse =
147
- adminPwdOverride !== null
148
- ? adminPwdOverride
149
- : mergedDefaults.adminPassword || infraDefaults.adminPassword || '';
150
- const emailCli = String(options.adminEmail || '').trim();
151
- const emailOverride = emailCli !== '' ? emailCli : null;
152
- const emailToUse =
153
- emailOverride !== null
154
- ? emailOverride
155
- : mergedDefaults.adminEmail || infraDefaults.adminEmail || '';
156
- return { adminPwdOverride, passwordToUse, emailOverride, emailToUse };
157
- }
158
-
159
- function computeAdminSecretsBackfillFlags(adminObj) {
160
- const needsPasswordBackfill =
161
- !(adminObj.POSTGRES_PASSWORD && adminObj.POSTGRES_PASSWORD.trim()) ||
162
- !(adminObj.PGADMIN_DEFAULT_PASSWORD && adminObj.PGADMIN_DEFAULT_PASSWORD.trim()) ||
163
- !(adminObj.REDIS_COMMANDER_PASSWORD && adminObj.REDIS_COMMANDER_PASSWORD.trim());
164
- const needsEmailBackfill = !(adminObj.PGADMIN_DEFAULT_EMAIL && adminObj.PGADMIN_DEFAULT_EMAIL.trim());
165
- return { needsPasswordBackfill, needsEmailBackfill };
166
- }
167
-
168
- function resolvePasswordForAdminFile(
169
- shouldOverwriteWithAdminPwd,
170
- needsPasswordBackfill,
171
- passwordToUse,
172
- adminObj,
173
- mergedDefaults
174
- ) {
175
- if (shouldOverwriteWithAdminPwd || needsPasswordBackfill) {
176
- return passwordToUse;
177
- }
178
- return (
179
- String(adminObj.POSTGRES_PASSWORD || '').trim() ||
180
- mergedDefaults.adminPassword ||
181
- readInfraDefaultScalars().adminPassword ||
182
- ''
183
- );
184
- }
185
-
186
- /**
187
- * Ensure admin secrets file exists and set admin password.
188
- * When adminPwd is provided, update POSTGRES_PASSWORD, PGADMIN_DEFAULT_PASSWORD, REDIS_COMMANDER_PASSWORD
189
- * in admin-secrets.env (overwrites existing values). Otherwise only backfill empty fields.
190
- * Reads and writes using decrypted values; writes encrypted when secrets-encryption key is set.
191
- *
192
- * @async
193
- * @param {Object} [options] - Options
194
- * @param {string} [options.adminPassword] - Override admin password (alias: adminPwd)
195
- * @param {string} [options.adminPwd] - Override admin password for Postgres, pgAdmin, Redis Commander
196
- * @param {string} [options.adminEmail] - Override pgAdmin default email (matches {{adminEmail}} defaults)
197
- * @param {string} [options.userPassword] - Reserved for Keycloak user template (secrets use ensureInfraSecrets)
198
- * @returns {Promise<string>} Path to admin secrets file
199
- */
122
+ /** @param {Object} [options] @returns {Promise<string>} */
200
123
  async function ensureAdminSecrets(options = {}) {
201
- const mergedDefaults = loadAdminMergedDefaultsForInfra(options);
202
- const { adminPwdOverride, passwordToUse, emailOverride, emailToUse } = resolveAdminPasswordAndEmailCli(
203
- options,
204
- mergedDefaults
124
+ return ensureAdminSecretsImpl(
125
+ getCoreSecrets,
126
+ getInfraDirName,
127
+ logVolumeResetHint,
128
+ applyAdminSecretsUpdate,
129
+ options
205
130
  );
206
- const adminSecretsPath = path.join(paths.getAifabrixSystemDir(), 'admin-secrets.env');
207
-
208
- if (!fsRealSync.existsSync(adminSecretsPath)) {
209
- logger.log('Generating admin-secrets.env...');
210
- await getCoreSecrets().generateAdminSecretsEnv(undefined);
211
- return adminSecretsPath;
212
- }
213
-
214
- const adminObj = await adminSecrets.readAndDecryptAdminSecrets(adminSecretsPath);
215
- const { needsPasswordBackfill, needsEmailBackfill } = computeAdminSecretsBackfillFlags(adminObj);
216
- const shouldOverwriteWithAdminPwd = adminPwdOverride !== null;
217
- const shouldOverwriteEmail = emailOverride !== null;
218
- const updateEmail = shouldOverwriteEmail || needsEmailBackfill;
219
-
220
- if (!shouldOverwriteWithAdminPwd && !needsPasswordBackfill && !updateEmail) {
221
- return adminSecretsPath;
222
- }
223
-
224
- const passwordForFile = resolvePasswordForAdminFile(
225
- shouldOverwriteWithAdminPwd,
226
- needsPasswordBackfill,
227
- passwordToUse,
228
- adminObj,
229
- mergedDefaults
230
- );
231
-
232
- await applyAdminSecretsUpdate(adminSecretsPath, adminObj, passwordForFile, shouldOverwriteWithAdminPwd, {
233
- updateEmail,
234
- emailToUse
235
- });
236
- return adminSecretsPath;
237
131
  }
238
132
 
239
133
  /** Host-side pgpass for pgAdmin bind mount (must exist before container starts so servers.json import succeeds). */
@@ -85,6 +85,7 @@ async function prepareInfrastructureEnvironment(developerId, options = {}) {
85
85
  adminPwd: adminPass,
86
86
  adminEmail: options.adminEmail,
87
87
  userPassword: options.userPassword,
88
+ passwordBundle: options.passwordBundle,
88
89
  tlsEnabled
89
90
  };
90
91
  await secretsEnsure.ensureInfraSecrets(infraOpts);
@@ -188,12 +189,9 @@ async function stopAllAppContainers(devId) {
188
189
  * @returns {Promise<void>}
189
190
  */
190
191
  async function removeAppVolumes(appNames, devId) {
191
- const { getAppVolumeName } = require('../app/down');
192
- const idNum = typeof devId === 'string' ? parseInt(devId, 10) : devId;
192
+ const { getAppVolumeNameCandidates } = require('../app/down');
193
193
  for (const appName of appNames) {
194
- const primaryName = getAppVolumeName(appName, devId);
195
- const legacyDev0Name = idNum === 0 ? `aifabrix_dev0_${appName}_data` : null;
196
- const candidates = Array.from(new Set([primaryName, legacyDev0Name].filter(Boolean)));
194
+ const candidates = getAppVolumeNameCandidates(appName, devId);
197
195
  for (const volumeName of candidates) {
198
196
  try {
199
197
  await execAsyncWithCwd(`docker volume rm -f ${volumeName}`);
@@ -380,5 +378,6 @@ module.exports = {
380
378
  getInfraStatus,
381
379
  getAppStatus,
382
380
  restartService,
383
- ensureAdminSecrets
381
+ ensureAdminSecrets,
382
+ removeAppVolumes
384
383
  };
@@ -47,16 +47,22 @@ function getInfraServiceContainerNames(devId) {
47
47
  * @param {string|number} devId - Developer ID
48
48
  * @returns {string[]}
49
49
  */
50
+ const { collectDeveloperVolumeIdSuffixes } = require('../utils/developer-volume-id');
51
+
50
52
  function getInfraNamedVolumeCandidates(devId) {
51
53
  const idNum = typeof devId === 'string' ? parseInt(devId, 10) : devId;
52
54
  if (idNum === 0) {
53
55
  return ['infra_postgres_data', 'infra_redis_data', 'infra_pgadmin_data'];
54
56
  }
55
- return [
56
- `infra_dev${devId}_postgres_data`,
57
- `infra_dev${devId}_redis_data`,
58
- `infra_dev${devId}_pgadmin_data`
59
- ];
57
+ const suffixes = collectDeveloperVolumeIdSuffixes(devId);
58
+ const bases = ['postgres_data', 'redis_data', 'pgadmin_data'];
59
+ const names = [];
60
+ for (const suffix of suffixes) {
61
+ for (const base of bases) {
62
+ names.push(`infra_dev${suffix}_${base}`);
63
+ }
64
+ }
65
+ return [...new Set(names)];
60
66
  }
61
67
 
62
68
  /**