@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
@@ -0,0 +1,184 @@
1
+ /**
2
+ * @fileoverview aifabrix secret get – read one secret (local user file or shared-only)
3
+ * @author AI Fabrix Team
4
+ * @version 2.0.0
5
+ */
6
+
7
+ const path = require('path');
8
+ const { getAifabrixSecretsPath } = require('../core/config');
9
+ const { decryptSecretsObject } = require('../core/secrets-load');
10
+ const { loadPrimaryUserSecrets } = require('../utils/secrets-utils');
11
+ const { loadConfiguredSharedSecretsStore } = require('../utils/remote-secrets-loader');
12
+ const remoteDevAuth = require('../utils/remote-dev-auth');
13
+ const devApi = require('../api/dev.api');
14
+ const logger = require('../utils/logger');
15
+
16
+ const REMOTE_NOT_CONFIGURED_MSG =
17
+ 'Remote server is not configured. Set remote-server and run "aifabrix dev init" first.';
18
+
19
+ /**
20
+ * Human-readable label for which store(s) were queried (paths included for file stores).
21
+ * @param {{ shared?: boolean }} options
22
+ * @returns {Promise<string>}
23
+ */
24
+ async function resolveSecretsScopeLabel(options) {
25
+ const useSharedOnly = Boolean(options.shared || options['shared']);
26
+ const generalSecretsPath = await getAifabrixSecretsPath();
27
+
28
+ if (useSharedOnly) {
29
+ if (!generalSecretsPath) {
30
+ return 'shared secrets (aifabrix-secrets not configured; run aifabrix secret set-secrets-file <path>)';
31
+ }
32
+ const target = await remoteDevAuth.resolveSharedSecretsEndpoint(generalSecretsPath);
33
+ if (remoteDevAuth.isRemoteSecretsUrl(target)) {
34
+ const host = remoteDevAuth.getSharedSecretsRemoteHostname(target) || target;
35
+ return `shared secrets API (${host})`;
36
+ }
37
+ const resolved = path.isAbsolute(target) ? target : path.resolve(process.cwd(), target);
38
+ return `shared secrets file ${resolved}`;
39
+ }
40
+
41
+ const pathsUtil = require('../utils/paths');
42
+ const userPath = pathsUtil.getPrimaryUserSecretsLocalPath();
43
+ return `local secrets file ${userPath}`;
44
+ }
45
+
46
+ /**
47
+ * @param {unknown} value
48
+ * @returns {boolean}
49
+ */
50
+ function isSecretPresent(value) {
51
+ if (value === undefined || value === null) {
52
+ return false;
53
+ }
54
+ return String(value).trim() !== '';
55
+ }
56
+
57
+ /**
58
+ * @param {Array<{ name?: string, key?: string, value?: unknown }>} items
59
+ * @returns {Record<string, string>}
60
+ */
61
+ function remoteSecretItemsToMap(items) {
62
+ const raw = {};
63
+ for (const item of items) {
64
+ const name = item?.name || item?.key;
65
+ if (typeof name === 'string' && item.value !== undefined) {
66
+ raw[name] = String(item.value);
67
+ }
68
+ }
69
+ return raw;
70
+ }
71
+
72
+ /**
73
+ * @param {string} target
74
+ * @returns {Promise<Record<string, string>>}
75
+ */
76
+ async function loadRemoteSharedSecretsDecrypted(target) {
77
+ const auth = await remoteDevAuth.getRemoteDevAuth();
78
+ if (!auth) {
79
+ throw new Error(REMOTE_NOT_CONFIGURED_MSG);
80
+ }
81
+ const items = await devApi.listSecrets(
82
+ auth.serverUrl,
83
+ auth.clientCertPem,
84
+ auth.serverCaPem || undefined,
85
+ target
86
+ );
87
+ const label = remoteDevAuth.getSharedSecretsRemoteHostname(target) || 'shared secrets API';
88
+ return decryptSecretsObject(remoteSecretItemsToMap(items), { defaultSourceLabel: label });
89
+ }
90
+
91
+ /**
92
+ * Load shared secrets (file or remote), decrypted.
93
+ * @returns {Promise<Record<string, string>>}
94
+ */
95
+ async function loadSharedSecretsDecrypted() {
96
+ const generalSecretsPath = await getAifabrixSecretsPath();
97
+ if (!generalSecretsPath) {
98
+ throw new Error('Shared secrets not configured. Set aifabrix-secrets in config.yaml.');
99
+ }
100
+
101
+ const target = await remoteDevAuth.resolveSharedSecretsEndpoint(generalSecretsPath);
102
+ if (remoteDevAuth.isRemoteSecretsUrl(target)) {
103
+ return loadRemoteSharedSecretsDecrypted(target);
104
+ }
105
+
106
+ const raw = await loadConfiguredSharedSecretsStore();
107
+ if (!raw || typeof raw !== 'object') {
108
+ return {};
109
+ }
110
+ const resolvedPath = path.isAbsolute(target) ? target : path.resolve(process.cwd(), target);
111
+ return decryptSecretsObject(raw, { defaultSourceLabel: resolvedPath });
112
+ }
113
+
114
+ /**
115
+ * Load and decrypt the primary user secrets file only (not aifabrix-secrets / shared).
116
+ * @returns {Promise<Record<string, string>>}
117
+ */
118
+ async function loadLocalUserSecretsDecrypted() {
119
+ const pathsUtil = require('../utils/paths');
120
+ const userPath = pathsUtil.getPrimaryUserSecretsLocalPath();
121
+ const raw = loadPrimaryUserSecrets();
122
+ return decryptSecretsObject(raw || {}, { defaultSourceLabel: userPath });
123
+ }
124
+
125
+ /**
126
+ * Load secrets for lookup: local user file (default) or shared store only (--shared).
127
+ * @param {{ shared?: boolean }} options
128
+ * @returns {Promise<Record<string, string>>}
129
+ */
130
+ async function loadSecretsForGet(options) {
131
+ if (options.shared || options['shared']) {
132
+ return loadSharedSecretsDecrypted();
133
+ }
134
+ return loadLocalUserSecretsDecrypted();
135
+ }
136
+
137
+ /**
138
+ * Handle secret get command.
139
+ * @param {string} key - Secret key (no kv:// prefix)
140
+ * @param {Object} options
141
+ * @param {boolean} [options.shared] - Shared store only (aifabrix-secrets); default is local user file only
142
+ * @param {boolean} [options.exists] - Exit 0 when present; no stdout (script-friendly)
143
+ * @param {boolean} [options.json] - JSON { key, exists, value }
144
+ * @returns {Promise<{ key: string, exists: boolean, value?: string }>}
145
+ */
146
+ async function handleSecretsGet(key, options = {}) {
147
+ if (!key || typeof key !== 'string') {
148
+ throw new Error('Secret key is required and must be a string');
149
+ }
150
+ if (key.startsWith('kv://')) {
151
+ throw new Error(
152
+ 'Secret key must not start with kv://. Use the key path without the prefix (e.g. hubspot-demo/token).'
153
+ );
154
+ }
155
+
156
+ const secrets = await loadSecretsForGet(options);
157
+ const value = secrets[key];
158
+ const present = isSecretPresent(value);
159
+
160
+ if (!present) {
161
+ const scope = await resolveSecretsScopeLabel(options);
162
+ throw new Error(`Secret '${key}' is missing or empty in ${scope}.`);
163
+ }
164
+
165
+ if (options.exists || options['exists']) {
166
+ return { key, exists: true };
167
+ }
168
+
169
+ if (options.json || options['json']) {
170
+ logger.log(JSON.stringify({ key, exists: true, value: String(value) }));
171
+ return { key, exists: true, value: String(value) };
172
+ }
173
+
174
+ logger.log(String(value));
175
+ return { key, exists: true, value: String(value) };
176
+ }
177
+
178
+ module.exports = {
179
+ handleSecretsGet,
180
+ isSecretPresent,
181
+ loadSecretsForGet,
182
+ loadLocalUserSecretsDecrypted,
183
+ resolveSecretsScopeLabel
184
+ };
@@ -56,6 +56,8 @@ function listKeysFromYamlFile(filePath) {
56
56
  * @param {string} filePath - Absolute path
57
57
  */
58
58
  function writeEmptySecretsFile(filePath) {
59
+ const { assertWritableSecretsPathForTests } = require('../utils/aifabrix-test-runtime-guard');
60
+ assertWritableSecretsPathForTests(filePath);
59
61
  const yamlContent = yaml.dump({}, { indent: 2, lineWidth: -1, noRefs: true, sortKeys: false });
60
62
  fs.writeFileSync(filePath, yamlContent, { mode: 0o600 });
61
63
  }
@@ -217,4 +219,4 @@ async function handleSecretsRemoveAll(options) {
217
219
  await removeAllSharedSecrets(generalSecretsPath, options);
218
220
  }
219
221
 
220
- module.exports = { handleSecretsRemoveAll };
222
+ module.exports = { handleSecretsRemoveAll, writeEmptySecretsFile };
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Template materialization and Docker image pull for `aifabrix setup` modes.
3
+ *
4
+ * @fileoverview Setup image refresh and platform template bootstrap
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const chalk = require('chalk');
14
+
15
+ const config = require('../core/config');
16
+ const pathsUtil = require('../utils/paths');
17
+ const logger = require('../utils/logger');
18
+ const dockerUtils = require('../utils/docker');
19
+ const dockerExec = require('../utils/docker-exec');
20
+ const infraHelpers = require('../infrastructure/helpers');
21
+ const upCommon = require('./up-common');
22
+ const { sectionTitle, formatDatasourceListRow } = require('../utils/cli-test-layout-chalk');
23
+ const { startSpinner, stopSpinnerSuccess } = require('./setup-spinners');
24
+
25
+ const PLATFORM_APPS = ['keycloak', 'miso-controller', 'dataplane'];
26
+
27
+ /**
28
+ * Pull infra-compose images (postgres, redis, optional pgadmin/redis-commander/traefik).
29
+ *
30
+ * @async
31
+ * @param {{ quiet?: boolean }} [opts]
32
+ * @returns {Promise<void>}
33
+ */
34
+ async function pullInfraImages(opts = {}) {
35
+ const quiet = Boolean(opts.quiet);
36
+ const devId = await config.getDeveloperId();
37
+ const infraDir = path.join(pathsUtil.getAifabrixSystemDir(), infraHelpers.getInfraDirName(devId));
38
+ const composePath = path.join(infraDir, 'compose.yaml');
39
+ if (!fs.existsSync(composePath)) {
40
+ if (!quiet) {
41
+ logger.log(chalk.yellow(`No infra compose file at ${composePath}; skipping image pull.`));
42
+ }
43
+ return;
44
+ }
45
+ const project = infraHelpers.getInfraProjectName(devId);
46
+ const composeCmd = await dockerUtils.getComposeCommand();
47
+ if (!quiet) {
48
+ logger.log('');
49
+ logger.log(sectionTitle('Pull images'));
50
+ }
51
+ if (quiet) {
52
+ await dockerExec.execWithDockerEnv(`${composeCmd} -f "${composePath}" -p ${project} pull`, { cwd: infraDir });
53
+ return;
54
+ }
55
+ const spin = startSpinner('Pulling infrastructure images...');
56
+ await dockerExec.execWithDockerEnv(`${composeCmd} -f "${composePath}" -p ${project} pull`, { cwd: infraDir });
57
+ stopSpinnerSuccess(spin, 'Infrastructure images pulled');
58
+ }
59
+
60
+ /**
61
+ * @param {string} appName
62
+ * @returns {string} deploy.image or empty
63
+ */
64
+ function readPlatformDeployImageRef(appName) {
65
+ try {
66
+ const { loadConfigFile } = require('../utils/config-format');
67
+ const builderPath = pathsUtil.getBuilderPath(appName);
68
+ const configPath = pathsUtil.resolveApplicationConfigPath(builderPath);
69
+ const cfg = loadConfigFile(configPath) || {};
70
+ const image = cfg.deploy && cfg.deploy.image;
71
+ return typeof image === 'string' ? image.trim() : '';
72
+ } catch {
73
+ return '';
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Pull one platform app image from `builder/<app>/application.yaml` deploy.image.
79
+ *
80
+ * @async
81
+ * @param {string} appName
82
+ * @param {{ quiet?: boolean }} [opts]
83
+ * @returns {Promise<boolean>} True when a pull was attempted
84
+ */
85
+ async function pullPlatformAppImage(appName, opts = {}) {
86
+ const quiet = Boolean(opts.quiet);
87
+ const imageRef = readPlatformDeployImageRef(appName);
88
+ if (!imageRef) {
89
+ if (!quiet) {
90
+ logger.log(formatDatasourceListRow('skipped', appName, 'no image ref'));
91
+ }
92
+ return false;
93
+ }
94
+ try {
95
+ if (!quiet) {
96
+ const spin = startSpinner(`Pulling ${appName} image...`);
97
+ await dockerExec.execWithDockerEnv(`docker pull ${imageRef}`);
98
+ stopSpinnerSuccess(spin, `Pulled ${appName} image`);
99
+ } else {
100
+ await dockerExec.execWithDockerEnv(`docker pull ${imageRef}`);
101
+ }
102
+ } catch (err) {
103
+ logger.log(chalk.yellow(`Could not pull ${imageRef}: ${err.message}`));
104
+ }
105
+ return true;
106
+ }
107
+
108
+ /**
109
+ * @async
110
+ * @param {{ quiet?: boolean }} [opts]
111
+ * @returns {Promise<number>} Count of images pulled
112
+ */
113
+ async function pullPlatformImages(opts = {}) {
114
+ let pulled = 0;
115
+ for (const appName of PLATFORM_APPS) {
116
+ if (await pullPlatformAppImage(appName, opts)) {
117
+ pulled += 1;
118
+ }
119
+ }
120
+ return pulled;
121
+ }
122
+
123
+ /**
124
+ * Materialize platform templates and pull infra + platform images.
125
+ *
126
+ * @async
127
+ * @param {{ quiet?: boolean }} [opts]
128
+ * @returns {Promise<void>}
129
+ */
130
+ async function runSetupImageRefresh(opts = {}) {
131
+ const quiet = Boolean(opts.quiet);
132
+ const spin = quiet ? startSpinner('Preparing platform configuration...') : null;
133
+ await upCommon.prepareUrlsLocalRegistryForUpPlatform({ silent: quiet });
134
+ await pullInfraImages({ quiet });
135
+ await pullPlatformImages({ quiet });
136
+ if (quiet) {
137
+ stopSpinnerSuccess(spin, 'Platform configuration ready');
138
+ }
139
+ }
140
+
141
+ module.exports = {
142
+ PLATFORM_APPS,
143
+ pullInfraImages,
144
+ pullPlatformImages,
145
+ runSetupImageRefresh
146
+ };