@aifabrix/builder 2.42.1 → 2.44.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 (392) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/README.md +2 -2
  3. package/anchor-docs/README.md +10 -0
  4. package/anchor-docs/_TEMPLATE +24 -0
  5. package/bin/aifabrix.js +13 -4
  6. package/integration/hubspot-test/README.md +157 -0
  7. package/integration/{hubspot → hubspot-test}/application.json +6 -6
  8. package/integration/{hubspot → hubspot-test}/create-hubspot.js +10 -10
  9. package/integration/hubspot-test/env.template +4 -0
  10. package/integration/hubspot-test/hubspot-test-datasource-company.json +138 -0
  11. package/integration/hubspot-test/hubspot-test-datasource-contact.json +146 -0
  12. package/integration/hubspot-test/hubspot-test-datasource-deal.json +146 -0
  13. package/integration/hubspot-test/hubspot-test-datasource-users.json +76 -0
  14. package/integration/{hubspot/hubspot-deploy.json → hubspot-test/hubspot-test-deploy.json} +201 -24
  15. package/integration/{hubspot/hubspot-system.json → hubspot-test/hubspot-test-system.json} +8 -7
  16. package/integration/hubspot-test/rbac.json +166 -0
  17. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-hubspot-credential-real.yaml +3 -3
  18. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-hubspot-env-vars.yaml +2 -2
  19. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-add-datasource.yaml +1 -1
  20. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-credential-create.yaml +1 -1
  21. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-credential-select.yaml +1 -1
  22. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-known-platform.yaml +1 -1
  23. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +2 -0
  24. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-mode.yaml +1 -1
  25. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-openapi-file.yaml +1 -1
  26. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-openapi-url.yaml +1 -1
  27. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-source.yaml +1 -1
  28. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-dimension-array-test.yaml +1 -1
  29. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +5 -0
  30. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +5 -0
  31. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-dimension-test.yaml +1 -1
  32. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-rbac-test.yaml +1 -1
  33. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +1 -1
  34. package/integration/{hubspot → hubspot-test}/test-dataplane-down-tests.js +1 -7
  35. package/integration/{hubspot → hubspot-test}/test-dataplane-down.js +3 -3
  36. package/integration/{hubspot → hubspot-test}/test.js +137 -102
  37. package/integration/{hubspot → hubspot-test}/wizard-hubspot-e2e.yaml +2 -2
  38. package/integration/{hubspot → hubspot-test}/wizard-hubspot-platform.yaml +1 -1
  39. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  40. package/integration/roundtrip-test-local/README.md +144 -0
  41. package/integration/roundtrip-test-local/application.yaml +13 -0
  42. package/integration/roundtrip-test-local/env.template +15 -0
  43. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  44. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  45. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  46. package/integration/roundtrip-test-local2/README.md +144 -0
  47. package/integration/roundtrip-test-local2/application.yaml +13 -0
  48. package/integration/roundtrip-test-local2/env.template +15 -0
  49. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  50. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  51. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  52. package/integration/test/wizard.yaml +8 -0
  53. package/jest.config.default.js +10 -0
  54. package/jest.config.integration.fixtures.js +22 -0
  55. package/jest.config.integration.js +21 -18
  56. package/jest.config.isolated.js +10 -0
  57. package/jest.projects.js +288 -0
  58. package/lib/api/datasources-core.api.js +3 -3
  59. package/lib/api/dev-mtls-request.js +110 -0
  60. package/lib/api/dev-server-https.js +145 -0
  61. package/lib/api/dev.api.js +133 -144
  62. package/lib/api/index.js +0 -1
  63. package/lib/api/pipeline.api.js +67 -20
  64. package/lib/api/service-users.api.js +111 -2
  65. package/lib/api/types/dev.types.js +4 -3
  66. package/lib/api/types/pipeline.types.js +8 -5
  67. package/lib/api/types/service-users.types.js +41 -0
  68. package/lib/api/types/validation-run.types.js +56 -0
  69. package/lib/api/validation-run.api.js +99 -0
  70. package/lib/api/validation-runner.js +99 -0
  71. package/lib/app/config.js +1 -1
  72. package/lib/app/deploy-status-display.js +2 -2
  73. package/lib/app/deploy.js +7 -6
  74. package/lib/app/display.js +2 -1
  75. package/lib/app/dockerfile.js +3 -2
  76. package/lib/app/down.js +2 -1
  77. package/lib/app/helpers.js +6 -5
  78. package/lib/app/index.js +27 -8
  79. package/lib/app/list.js +7 -6
  80. package/lib/app/push.js +4 -3
  81. package/lib/app/register.js +19 -8
  82. package/lib/app/rotate-secret.js +17 -13
  83. package/lib/app/run-container-start.js +184 -0
  84. package/lib/app/run-docker-fallback.js +108 -0
  85. package/lib/app/run-env-compose.js +30 -42
  86. package/lib/app/run-helpers.js +49 -126
  87. package/lib/app/run-infra-requirements.js +30 -0
  88. package/lib/app/run-resolve-image.js +21 -0
  89. package/lib/app/run.js +74 -21
  90. package/lib/app/show-display.js +1 -1
  91. package/lib/app/show.js +1 -1
  92. package/lib/build/index.js +13 -10
  93. package/lib/cli/index.js +2 -0
  94. package/lib/cli/setup-app.help.js +67 -0
  95. package/lib/cli/setup-app.js +59 -123
  96. package/lib/cli/setup-app.test-commands.js +179 -0
  97. package/lib/cli/setup-auth.js +36 -14
  98. package/lib/cli/setup-credential-deployment.js +22 -8
  99. package/lib/cli/setup-dev-path-commands.js +124 -0
  100. package/lib/cli/setup-dev.js +190 -103
  101. package/lib/cli/setup-environment.js +11 -20
  102. package/lib/cli/setup-external-system.js +62 -22
  103. package/lib/cli/setup-infra.js +139 -47
  104. package/lib/cli/setup-parameters.js +32 -0
  105. package/lib/cli/setup-secrets.js +147 -10
  106. package/lib/cli/setup-service-user.js +146 -20
  107. package/lib/cli/setup-utility.js +47 -19
  108. package/lib/commands/app-down.js +5 -7
  109. package/lib/commands/app-install.js +14 -7
  110. package/lib/commands/app-logs.js +13 -10
  111. package/lib/commands/app-shell.js +4 -1
  112. package/lib/commands/app-test.js +25 -19
  113. package/lib/commands/app.js +22 -10
  114. package/lib/commands/auth-config.js +10 -14
  115. package/lib/commands/auth-status.js +4 -3
  116. package/lib/commands/credential-env.js +4 -3
  117. package/lib/commands/credential-list.js +5 -4
  118. package/lib/commands/credential-push.js +4 -3
  119. package/lib/commands/datasource-unified-test-cli.js +495 -0
  120. package/lib/commands/datasource-unified-test-cli.options.js +149 -0
  121. package/lib/commands/datasource-validation-cli.js +129 -0
  122. package/lib/commands/datasource.js +123 -71
  123. package/lib/commands/deployment-list.js +6 -5
  124. package/lib/commands/dev-cli-handlers.js +122 -18
  125. package/lib/commands/dev-down.js +4 -3
  126. package/lib/commands/dev-init.js +231 -116
  127. package/lib/commands/dev-show-display.js +473 -0
  128. package/lib/commands/login-credentials.js +3 -2
  129. package/lib/commands/login-device.js +4 -3
  130. package/lib/commands/login.js +5 -4
  131. package/lib/commands/logout.js +8 -7
  132. package/lib/commands/parameters-validate.js +54 -0
  133. package/lib/commands/repair-datasource.js +314 -68
  134. package/lib/commands/repair-env-template.js +16 -10
  135. package/lib/commands/repair-rbac.js +25 -19
  136. package/lib/commands/repair.js +116 -32
  137. package/lib/commands/secrets-list.js +23 -12
  138. package/lib/commands/secrets-remove-all.js +220 -0
  139. package/lib/commands/secrets-remove.js +22 -13
  140. package/lib/commands/secrets-set.js +21 -12
  141. package/lib/commands/secrets-validate.js +20 -7
  142. package/lib/commands/secure.js +10 -9
  143. package/lib/commands/service-user.js +243 -13
  144. package/lib/commands/test-e2e-external.js +27 -1
  145. package/lib/commands/up-common.js +28 -2
  146. package/lib/commands/up-dataplane.js +31 -18
  147. package/lib/commands/up-miso.js +19 -29
  148. package/lib/commands/upload.js +138 -39
  149. package/lib/commands/wizard-core-helpers.js +1 -1
  150. package/lib/commands/wizard-dataplane.js +4 -3
  151. package/lib/commands/wizard-helpers.js +3 -3
  152. package/lib/commands/wizard.js +2 -2
  153. package/lib/core/admin-secrets.js +16 -5
  154. package/lib/core/audit-logger.js +12 -4
  155. package/lib/core/config-attach-extensions.js +46 -0
  156. package/lib/core/config-runtime-paths.js +29 -0
  157. package/lib/core/config.js +59 -58
  158. package/lib/core/diff.js +3 -2
  159. package/lib/core/ensure-encryption-key.js +2 -4
  160. package/lib/core/secrets-ensure-infra.js +77 -0
  161. package/lib/core/secrets-ensure.js +120 -64
  162. package/lib/core/secrets-env-write.js +35 -7
  163. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  164. package/lib/core/secrets.js +228 -42
  165. package/lib/core/templates-env.js +4 -3
  166. package/lib/core/templates.js +1 -1
  167. package/lib/datasource/abac-validator.js +148 -0
  168. package/lib/datasource/deploy.js +75 -53
  169. package/lib/datasource/field-reference-validator.js +77 -36
  170. package/lib/datasource/integration-context.js +63 -0
  171. package/lib/datasource/list.js +8 -7
  172. package/lib/datasource/log-viewer.js +252 -0
  173. package/lib/datasource/resolve-app.js +109 -0
  174. package/lib/datasource/test-e2e.js +95 -155
  175. package/lib/datasource/test-integration.js +121 -109
  176. package/lib/datasource/unified-validation-run-body.js +65 -0
  177. package/lib/datasource/unified-validation-run-post.js +23 -0
  178. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  179. package/lib/datasource/unified-validation-run.js +92 -0
  180. package/lib/datasource/validate.js +162 -15
  181. package/lib/deployment/deployer.js +4 -3
  182. package/lib/deployment/environment.js +7 -6
  183. package/lib/deployment/push.js +17 -8
  184. package/lib/external-system/delete.js +4 -3
  185. package/lib/external-system/deploy.js +131 -53
  186. package/lib/external-system/download-helpers.js +1 -1
  187. package/lib/external-system/download.js +7 -6
  188. package/lib/external-system/generator.js +104 -14
  189. package/lib/external-system/integration-test-dispatch.js +26 -0
  190. package/lib/external-system/test-execution.js +5 -1
  191. package/lib/external-system/test-helpers.js +0 -4
  192. package/lib/external-system/test-system-level-helpers.js +110 -0
  193. package/lib/external-system/test-system-level.js +83 -44
  194. package/lib/external-system/test.js +59 -8
  195. package/lib/generator/builders.js +23 -11
  196. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  197. package/lib/generator/external-controller-manifest.js +3 -3
  198. package/lib/generator/external.js +23 -11
  199. package/lib/generator/helpers.js +71 -12
  200. package/lib/generator/index.js +8 -4
  201. package/lib/generator/split-readme.js +12 -7
  202. package/lib/generator/split-variables.js +2 -1
  203. package/lib/generator/split.js +46 -11
  204. package/lib/generator/wizard-readme.js +3 -3
  205. package/lib/generator/wizard.js +16 -13
  206. package/lib/infrastructure/compose.js +60 -6
  207. package/lib/infrastructure/helpers.js +238 -51
  208. package/lib/infrastructure/index.js +64 -37
  209. package/lib/infrastructure/services.js +21 -15
  210. package/lib/internal/fs-real-sync.js +104 -0
  211. package/lib/internal/node-fs.js +98 -0
  212. package/lib/parameters/database-secret-values.js +173 -0
  213. package/lib/parameters/infra-kv-discovery.js +121 -0
  214. package/lib/parameters/infra-parameter-catalog.js +458 -0
  215. package/lib/parameters/infra-parameter-validate.js +64 -0
  216. package/lib/schema/application-schema.json +37 -17
  217. package/lib/schema/datasource-test-run.schema.json +493 -0
  218. package/lib/schema/deployment-rules.yaml +102 -63
  219. package/lib/schema/external-datasource.schema.json +1201 -433
  220. package/lib/schema/external-system.schema.json +181 -5
  221. package/lib/schema/flag-map-validation-run.json +31 -0
  222. package/lib/schema/infra-parameter.schema.json +106 -0
  223. package/lib/schema/infra.parameter.yaml +421 -0
  224. package/lib/schema/type/credential-auth-templates.json +40 -0
  225. package/lib/schema/type/document-storage.json +213 -0
  226. package/lib/schema/type/message-service.json +123 -0
  227. package/lib/schema/type/vector-store.json +88 -0
  228. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  229. package/lib/utils/api-error-handler.js +2 -2
  230. package/lib/utils/api.js +49 -14
  231. package/lib/utils/app-config-resolver.js +23 -1
  232. package/lib/utils/app-register-api.js +3 -2
  233. package/lib/utils/app-register-auth.js +1 -1
  234. package/lib/utils/app-register-config.js +4 -4
  235. package/lib/utils/app-register-display.js +3 -2
  236. package/lib/utils/app-register-validator.js +3 -2
  237. package/lib/utils/app-run-containers.js +26 -22
  238. package/lib/utils/app-scoped-config.js +31 -0
  239. package/lib/utils/app-service-env-from-builder.js +164 -0
  240. package/lib/utils/build-copy.js +1 -1
  241. package/lib/utils/build-helpers.js +20 -20
  242. package/lib/utils/build-resolve-image.js +165 -0
  243. package/lib/utils/cli-layout-chalk.js +8 -0
  244. package/lib/utils/cli-test-layout-chalk.js +267 -0
  245. package/lib/utils/cli-utils.js +88 -11
  246. package/lib/utils/compose-db-passwords.js +138 -0
  247. package/lib/utils/compose-generate-docker-compose.js +216 -0
  248. package/lib/utils/compose-generator.js +197 -291
  249. package/lib/utils/compose-miso-env.js +18 -0
  250. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  251. package/lib/utils/config-paths.js +209 -6
  252. package/lib/utils/config-scoped-resources-preference.js +41 -0
  253. package/lib/utils/controller-deployment-outcome.js +68 -0
  254. package/lib/utils/credential-display.js +2 -2
  255. package/lib/utils/credential-secrets-env.js +16 -1
  256. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  257. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  258. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  259. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  260. package/lib/utils/datasource-test-run-display.js +442 -0
  261. package/lib/utils/datasource-test-run-exit.js +58 -0
  262. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  263. package/lib/utils/datasource-test-run-report-version.js +51 -0
  264. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  265. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  266. package/lib/utils/datasource-validation-watch.js +266 -0
  267. package/lib/utils/declarative-url-ports.js +47 -0
  268. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  269. package/lib/utils/dev-ca-install.js +185 -23
  270. package/lib/utils/dev-cert-helper.js +266 -17
  271. package/lib/utils/dev-hosts-helper.js +307 -0
  272. package/lib/utils/dev-init-cert-hints.js +37 -0
  273. package/lib/utils/dev-init-health-messages.js +52 -0
  274. package/lib/utils/dev-init-resolve.js +86 -0
  275. package/lib/utils/dev-init-ssh-merge.js +65 -0
  276. package/lib/utils/dev-ssh-config-helper.js +196 -0
  277. package/lib/utils/dev-user-groups.js +93 -0
  278. package/lib/utils/docker-build.js +42 -17
  279. package/lib/utils/docker-exec.js +28 -0
  280. package/lib/utils/docker-manifest-public-port.js +116 -0
  281. package/lib/utils/docker-not-running-hint.js +52 -0
  282. package/lib/utils/docker.js +98 -11
  283. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  284. package/lib/utils/env-config-loader.js +10 -91
  285. package/lib/utils/env-copy.js +19 -10
  286. package/lib/utils/env-map.js +42 -11
  287. package/lib/utils/env-template.js +2 -2
  288. package/lib/utils/environment-scoped-resources.js +144 -0
  289. package/lib/utils/error-formatter.js +125 -9
  290. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  291. package/lib/utils/error-formatters/network-errors.js +2 -1
  292. package/lib/utils/error-formatters/permission-errors.js +2 -1
  293. package/lib/utils/error-formatters/validation-errors.js +2 -1
  294. package/lib/utils/external-env-template.js +180 -0
  295. package/lib/utils/external-readme.js +8 -1
  296. package/lib/utils/external-system-display.js +277 -136
  297. package/lib/utils/external-system-local-test-tty.js +389 -0
  298. package/lib/utils/external-system-readiness-core.js +377 -0
  299. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  300. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  301. package/lib/utils/external-system-readiness-display.js +186 -0
  302. package/lib/utils/external-system-test-helpers.js +24 -6
  303. package/lib/utils/external-system-validators.js +32 -14
  304. package/lib/utils/health-check-url.js +119 -0
  305. package/lib/utils/health-check.js +59 -25
  306. package/lib/utils/help-builder.js +14 -13
  307. package/lib/utils/image-version.js +4 -8
  308. package/lib/utils/infra-containers.js +4 -7
  309. package/lib/utils/infra-env-defaults.js +162 -0
  310. package/lib/utils/infra-status-display.js +167 -0
  311. package/lib/utils/infra-status.js +16 -8
  312. package/lib/utils/local-secrets.js +29 -7
  313. package/lib/utils/paths.js +136 -48
  314. package/lib/utils/port-resolver.js +10 -23
  315. package/lib/utils/redis-env-scope.js +62 -0
  316. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  317. package/lib/utils/remote-builder-validation.js +99 -0
  318. package/lib/utils/remote-dev-auth.js +117 -21
  319. package/lib/utils/remote-docker-env.js +67 -15
  320. package/lib/utils/remote-secrets-loader.js +13 -4
  321. package/lib/utils/resolve-docker-image-ref.js +124 -0
  322. package/lib/utils/schema-loader.js +22 -9
  323. package/lib/utils/secrets-bash-kv.js +25 -0
  324. package/lib/utils/secrets-generator.js +171 -51
  325. package/lib/utils/secrets-helpers.js +70 -59
  326. package/lib/utils/secrets-kv-scope.js +60 -0
  327. package/lib/utils/secrets-utils.js +35 -37
  328. package/lib/utils/secrets-validation.js +3 -1
  329. package/lib/utils/secrets-yaml-preserve.js +109 -0
  330. package/lib/utils/secure-file-permissions.js +91 -0
  331. package/lib/utils/ssh-key-helper.js +4 -2
  332. package/lib/utils/template-helpers.js +2 -2
  333. package/lib/utils/test-log-writer.js +3 -3
  334. package/lib/utils/token-manager.js +37 -5
  335. package/lib/utils/url-declarative-public-base.js +188 -0
  336. package/lib/utils/url-declarative-resolve-build.js +493 -0
  337. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  338. package/lib/utils/url-declarative-resolve.js +220 -0
  339. package/lib/utils/url-declarative-token-parse.js +74 -0
  340. package/lib/utils/url-declarative-url-flags.js +50 -0
  341. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  342. package/lib/utils/url-public-path-prefix.js +34 -0
  343. package/lib/utils/urls-local-registry.js +220 -0
  344. package/lib/utils/validation-report-tty-kit.js +77 -0
  345. package/lib/utils/validation-run-poll.js +89 -0
  346. package/lib/utils/validation-run-post-retry.js +73 -0
  347. package/lib/utils/validation-run-request.js +98 -0
  348. package/lib/utils/variable-transformer.js +21 -4
  349. package/lib/utils/yaml-preserve.js +78 -1
  350. package/lib/validation/datasource-warnings.js +56 -0
  351. package/lib/validation/env-template-auth.js +50 -2
  352. package/lib/validation/external-manifest-validator.js +35 -7
  353. package/lib/validation/validate-display.js +37 -31
  354. package/lib/validation/validate.js +9 -10
  355. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  356. package/lib/validation/validator.js +32 -78
  357. package/lib/validation/wizard-config-validator.js +2 -1
  358. package/package.json +11 -3
  359. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  360. package/scripts/diagnose-cli.js +150 -0
  361. package/scripts/install-local.js +304 -55
  362. package/templates/README.md +15 -2
  363. package/templates/applications/dataplane/application.yaml +52 -2
  364. package/templates/applications/dataplane/env.template +80 -18
  365. package/templates/applications/dataplane/rbac.yaml +8 -0
  366. package/templates/applications/keycloak/application.yaml +9 -1
  367. package/templates/applications/keycloak/env.template +15 -6
  368. package/templates/applications/miso-controller/application.yaml +10 -2
  369. package/templates/applications/miso-controller/env.template +55 -14
  370. package/templates/applications/miso-controller/rbac.yaml +5 -0
  371. package/templates/external-system/README.md.hbs +20 -7
  372. package/templates/external-system/deploy.js.hbs +5 -5
  373. package/templates/external-system/env.template.hbs +22 -0
  374. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  375. package/templates/infra/compose.yaml.hbs +20 -4
  376. package/templates/python/docker-compose.hbs +16 -0
  377. package/templates/typescript/docker-compose.hbs +16 -0
  378. package/integration/hubspot/README.md +0 -102
  379. package/integration/hubspot/env.template +0 -4
  380. package/integration/hubspot/hubspot-datasource-company.json +0 -541
  381. package/integration/hubspot/hubspot-datasource-contact.json +0 -639
  382. package/integration/hubspot/hubspot-datasource-deal.json +0 -588
  383. package/integration/hubspot/hubspot-datasource-users.json +0 -116
  384. package/integration/hubspot/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
  385. package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
  386. package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
  387. package/lib/api/external-test.api.js +0 -111
  388. package/lib/schema/env-config.yaml +0 -43
  389. /package/integration/{hubspot → hubspot-test}/companies.json +0 -0
  390. /package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-app-name.yaml +0 -0
  391. /package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-missing-app.yaml +0 -0
  392. /package/integration/{hubspot → hubspot-test}/test-dataplane-down-helpers.js +0 -0
@@ -1,3 +1,4 @@
1
+ const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
1
2
  /**
2
3
  * CLI infrastructure command setup (up-infra, up-platform, up-miso, up-dataplane, down-infra, doctor, status, restart).
3
4
  *
@@ -17,6 +18,23 @@ const { resolveControllerUrl } = require('../utils/controller-url');
17
18
  const { handleLogin } = require('../commands/login');
18
19
  const { handleUpMiso } = require('../commands/up-miso');
19
20
  const { handleUpDataplane } = require('../commands/up-dataplane');
21
+ const { cleanBuilderAppDirs } = require('../commands/up-common');
22
+ const {
23
+ loadInfraStatusSummary,
24
+ formatInfraStatusTitleLine,
25
+ logInfraStatusConfigurationSummary,
26
+ logPaddedFieldRow
27
+ } = require('../utils/infra-status-display');
28
+
29
+ const UP_INFRA_HELP_AFTER = `
30
+ Typical sequence:
31
+ $ aifabrix up-infra
32
+ $ aifabrix up-platform
33
+ Or: aifabrix up-miso, then aifabrix up-dataplane (login required for dataplane)
34
+
35
+ Full bootstrap example (Traefik, TLS flag, pgAdmin, catalog overrides — matches shipped defaults in infra.parameter.yaml):
36
+ $ aifabrix up-infra --traefik --tls --adminPassword admin123 --adminEmail admin@aifabrix.dev --userPassword user123 --pgAdmin
37
+ `;
20
38
 
21
39
  /**
22
40
  * Persists optional service flag to config when explicitly set.
@@ -28,7 +46,29 @@ const { handleUpDataplane } = require('../commands/up-dataplane');
28
46
  async function persistOptionalServiceFlag(cfg, key, value, label) {
29
47
  cfg[key] = value;
30
48
  await config.saveConfig(cfg);
31
- logger.log(chalk.green(`✓ ${label} ${value ? 'enabled' : 'disabled'} and saved to config`));
49
+ logger.log(formatSuccessLine(`${label} ${value ? 'enabled' : 'disabled'} and saved to config`));
50
+ }
51
+
52
+ /**
53
+ * Persists TLS mode for ${TLS_ENABLED} / ${HTTP_ENABLED} in application.yaml / deployment manifest interpolation.
54
+ * @param {Object} cfg - Config object (mutated)
55
+ * @param {boolean} value - Whether TLS mode is on
56
+ */
57
+ async function persistTlsEnabledFlag(cfg, value) {
58
+ cfg.tlsEnabled = value;
59
+ await config.saveConfig(cfg);
60
+ const tlsStr = value ? 'true' : 'false';
61
+ const httpStr = value ? 'false' : 'true';
62
+ logger.log(
63
+ chalk.green(
64
+ `✔ TLS mode ${value ? 'enabled' : 'disabled'} and saved to config (` +
65
+ '${TLS_ENABLED}=' +
66
+ tlsStr +
67
+ ', ${HTTP_ENABLED}=' +
68
+ httpStr +
69
+ ' when generating deployment JSON)'
70
+ )
71
+ );
32
72
  }
33
73
 
34
74
  /**
@@ -45,24 +85,26 @@ function resolveFlag(optValue, cfgValue, defaultWhenUndef = true) {
45
85
  }
46
86
 
47
87
  /**
48
- * Runs the up-infra command: resolves developer ID, traefik, pgAdmin, redisAdmin, and starts infra.
49
- * @param {Object} options - Commander options (developer, traefik, pgAdmin, redisAdmin)
50
- * @returns {Promise<void>}
88
+ * @param {Object} options - Commander options
89
+ * @returns {Promise<number|null>} Developer ID or null
51
90
  */
52
- async function runUpInfraCommand(options) {
53
- await config.ensureSecretsEncryptionKey();
54
- let developerId = null;
55
- if (options.developer) {
56
- const id = parseInt(options.developer, 10);
57
- if (isNaN(id) || id < 0) {
58
- throw new Error('Developer ID must be a non-negative number (0 = default infra, > 0 = developer-specific)');
59
- }
60
- await config.setDeveloperId(id);
61
- process.env.AIFABRIX_DEVELOPERID = id.toString();
62
- developerId = id;
63
- logger.log(chalk.green(`✓ Developer ID set to ${id}`));
91
+ async function applyDeveloperIdFromUpInfra(options) {
92
+ if (!options.developer) return null;
93
+ const id = parseInt(options.developer, 10);
94
+ if (isNaN(id) || id < 0) {
95
+ throw new Error('Developer ID must be a non-negative number (0 = default infra, > 0 = developer-specific)');
64
96
  }
65
- const cfg = await config.getConfig();
97
+ await config.setDeveloperId(id);
98
+ process.env.AIFABRIX_DEVELOPERID = id.toString();
99
+ logger.log(formatSuccessLine(`Developer ID set to ${id}`));
100
+ return id;
101
+ }
102
+
103
+ /**
104
+ * @param {Object} options
105
+ * @param {Object} cfg - Mutable config from getConfig()
106
+ */
107
+ async function persistOptionalInfraFlagsFromCli(options, cfg) {
66
108
  const flagSpecs = [
67
109
  { opt: options.traefik, key: 'traefik', label: 'Traefik' },
68
110
  { opt: options.pgAdmin, key: 'pgadmin', label: 'pgAdmin' },
@@ -73,25 +115,59 @@ async function runUpInfraCommand(options) {
73
115
  await persistOptionalServiceFlag(cfg, key, opt, label);
74
116
  }
75
117
  }
118
+ }
119
+
120
+ /**
121
+ * @param {Object} options
122
+ * @param {Object} cfg
123
+ */
124
+ async function maybePersistTlsFromUpInfra(options, cfg) {
125
+ // Commander maps --no-tls to options.tls === false (not a separate notls flag).
126
+ if (options.tls === true) await persistTlsEnabledFlag(cfg, true);
127
+ else if (options.tls === false) await persistTlsEnabledFlag(cfg, false);
128
+ }
129
+
130
+ /**
131
+ * Runs the up-infra command: resolves developer ID, traefik, pgAdmin, redisAdmin, and starts infra.
132
+ * @param {Object} options - Commander options (developer, traefik, pgAdmin, redisAdmin)
133
+ * @returns {Promise<void>}
134
+ */
135
+ async function runUpInfraCommand(options) {
136
+ await config.ensureSecretsEncryptionKey();
137
+ const developerId = await applyDeveloperIdFromUpInfra(options);
138
+ const cfg = await config.getConfig();
139
+ await persistOptionalInfraFlagsFromCli(options, cfg);
140
+ await maybePersistTlsFromUpInfra(options, cfg);
141
+ const adminPass = options.adminPassword || options.adminPwd;
142
+ const tlsEnabledEffective = cfg.tlsEnabled === true;
76
143
  await infra.startInfra(developerId, {
77
144
  traefik: resolveFlag(options.traefik, cfg.traefik, false),
78
145
  pgadmin: resolveFlag(options.pgAdmin, cfg.pgadmin, true),
79
146
  redisCommander: resolveFlag(options.redisAdmin, cfg.redisCommander, true),
80
- adminPwd: options.adminPwd
147
+ adminPassword: adminPass,
148
+ adminPwd: adminPass,
149
+ adminEmail: options.adminEmail,
150
+ userPassword: options.userPassword,
151
+ tlsEnabled: tlsEnabledEffective
81
152
  });
82
153
  }
83
154
 
84
155
  function setupUpInfraCommand(program) {
85
156
  program.command('up-infra')
86
- .description('Start local infrastructure: Postgres, Redis, optional pgAdmin, Redis Commander, Traefik')
157
+ .description('Start Postgres, Redis; optional pgAdmin, Redis Commander, Traefik')
158
+ .addHelpText('after', UP_INFRA_HELP_AFTER)
87
159
  .option('-d, --developer <id>', 'Set developer ID and start infrastructure')
88
- .option('--adminPwd <password>', 'Override default admin password for new install (Postgres, pgAdmin, Redis Commander)')
160
+ .option('--adminPassword <password>', 'Override {{adminPassword}} defaults (Postgres, pgAdmin, Redis Commander, catalog literals)')
161
+ .option('--adminEmail <email>', 'Override {{adminEmail}} default (e.g. pgAdmin login email)')
162
+ .option('--userPassword <password>', 'Override {{userPassword}} default (e.g. Keycloak default user password)')
89
163
  .option('--pgAdmin', 'Include pgAdmin web UI and save to config')
90
164
  .option('--no-pgAdmin', 'Exclude pgAdmin and save to config')
91
165
  .option('--redisAdmin', 'Include Redis Commander web UI and save to config')
92
166
  .option('--no-redisAdmin', 'Exclude Redis Commander and save to config')
93
167
  .option('--traefik', 'Include Traefik reverse proxy and save to config')
94
168
  .option('--no-traefik', 'Exclude Traefik and save to config')
169
+ .option('--tls', 'Enable TLS mode; save tlsEnabled (${TLS_ENABLED}=true, ${HTTP_ENABLED}=false in application.yaml)')
170
+ .option('--no-tls', 'Disable TLS mode (${TLS_ENABLED}=false, ${HTTP_ENABLED}=true)')
95
171
  .action(async(options) => {
96
172
  try {
97
173
  await runUpInfraCommand(options);
@@ -104,12 +180,16 @@ function setupUpInfraCommand(program) {
104
180
 
105
181
  function setupUpPlatformCommand(program) {
106
182
  program.command('up-platform')
107
- .description('Start platform (Keycloak, Miso Controller, Dataplane) from community images; infra must be up')
183
+ .description('Start Keycloak, Miso Controller, dataplane from images (needs up-infra)')
108
184
  .option('-r, --registry <url>', 'Override registry for all apps (e.g. myacr.azurecr.io)')
109
185
  .option('--registry-mode <mode>', 'Override registry mode (acr|external)')
110
186
  .option('-i, --image <key>=<value>', 'Override image (e.g. keycloak=myreg/k:v1, miso-controller=myreg/m:v1, dataplane=myreg/d:v1); can be repeated', (v, prev) => (prev || []).concat([v]))
187
+ .option('-f, --force', 'Clean builder/keycloak, builder/miso-controller, builder/dataplane and re-fetch from templates')
111
188
  .action(async(options) => {
112
189
  try {
190
+ if (options.force) {
191
+ await cleanBuilderAppDirs(['keycloak', 'miso-controller', 'dataplane']);
192
+ }
113
193
  await handleUpMiso(options);
114
194
  await handleUpDataplane(options);
115
195
  } catch (error) {
@@ -133,12 +213,16 @@ function setupUpPlatformCommand(program) {
133
213
 
134
214
  function setupUpMisoCommand(program) {
135
215
  program.command('up-miso')
136
- .description('Install keycloak and miso-controller from images (no build). Infra must be up. For dataplane use up-dataplane. Uses auto-generated secrets for testing.')
216
+ .description('Start Keycloak + Miso Controller from images only (no dataplane; needs up-infra)')
137
217
  .option('-r, --registry <url>', 'Override registry for all apps (e.g. myacr.azurecr.io)')
138
218
  .option('--registry-mode <mode>', 'Override registry mode (acr|external)')
139
219
  .option('-i, --image <key>=<value>', 'Override image (e.g. keycloak=myreg/k:v1, miso-controller=myreg/m:v1); can be repeated', (v, prev) => (prev || []).concat([v]))
220
+ .option('-f, --force', 'Clean builder/keycloak and builder/miso-controller and re-fetch from templates')
140
221
  .action(async(options) => {
141
222
  try {
223
+ if (options.force) {
224
+ await cleanBuilderAppDirs(['keycloak', 'miso-controller']);
225
+ }
142
226
  await handleUpMiso(options);
143
227
  } catch (error) {
144
228
  handleCommandError(error, 'up-miso');
@@ -149,12 +233,16 @@ function setupUpMisoCommand(program) {
149
233
 
150
234
  function setupUpDataplaneCommand(program) {
151
235
  program.command('up-dataplane')
152
- .description('Register, deploy, then run dataplane app locally in dev (always local deployment; requires login, environment must be dev)')
236
+ .description('Register, deploy, run dataplane locally (dev env; login required)')
153
237
  .option('-r, --registry <url>', 'Override registry for dataplane image')
154
238
  .option('--registry-mode <mode>', 'Override registry mode (acr|external)')
155
239
  .option('-i, --image <ref>', 'Override dataplane image reference (e.g. myreg/dataplane:latest)')
240
+ .option('-f, --force', 'Clean builder/dataplane and re-fetch from templates')
156
241
  .action(async(options) => {
157
242
  try {
243
+ if (options.force) {
244
+ await cleanBuilderAppDirs(['dataplane']);
245
+ }
158
246
  await handleUpDataplane(options);
159
247
  } catch (error) {
160
248
  if (isAuthenticationError(error)) {
@@ -176,8 +264,8 @@ function setupUpDataplaneCommand(program) {
176
264
  }
177
265
 
178
266
  function setupDownInfraCommand(program) {
179
- program.command('down-infra [app]')
180
- .description('Stop and remove local infrastructure services or a specific application')
267
+ program.command('down-infra [service|app]')
268
+ .description('Stop all infra, or stop one app; use -v to remove volumes')
181
269
  .option('-v, --volumes', 'Remove volumes (deletes all data)')
182
270
  .action(async(appName, options) => {
183
271
  try {
@@ -196,14 +284,14 @@ function setupDownInfraCommand(program) {
196
284
 
197
285
  function setupDoctorCommand(program) {
198
286
  program.command('doctor')
199
- .description('Check environment and configuration')
287
+ .description('Check Docker, ports, secrets, and infra health')
200
288
  .action(async() => {
201
289
  try {
202
290
  const result = await validator.checkEnvironment();
203
291
  logger.log('\n🔍 AI Fabrix Environment Check\n');
204
- logger.log(`Docker: ${result.docker === 'ok' ? ' Running' : ' Not available'}`);
205
- logger.log(`Ports: ${result.ports === 'ok' ? ' Available' : '⚠️ Some ports in use'}`);
206
- logger.log(`Secrets: ${result.secrets === 'ok' ? ' Configured' : ' Missing'}`);
292
+ logger.log(`Docker: ${result.docker === 'ok' ? ' Running' : ' Not available'}`);
293
+ logger.log(`Ports: ${result.ports === 'ok' ? ' Available' : ' Some ports in use'}`);
294
+ logger.log(`Secrets: ${result.secrets === 'ok' ? ' Configured' : ' Missing'}`);
207
295
  if (result.recommendations.length > 0) {
208
296
  logger.log('\n📋 Recommendations:');
209
297
  result.recommendations.forEach(rec => logger.log(` • ${rec}`));
@@ -218,7 +306,7 @@ function setupDoctorCommand(program) {
218
306
  });
219
307
  logger.log('\n🏥 Infrastructure Health:');
220
308
  Object.entries(health).forEach(([service, status]) => {
221
- const icon = status === 'healthy' ? '' : status === 'unknown' ? '❓' : '';
309
+ const icon = status === 'healthy' ? '' : status === 'unknown' ? '❓' : '';
222
310
  logger.log(` ${icon} ${service}: ${status}`);
223
311
  });
224
312
  } catch (error) {
@@ -235,17 +323,21 @@ function setupDoctorCommand(program) {
235
323
 
236
324
  function setupStatusCommand(program) {
237
325
  program.command('status')
238
- .description('Show detailed infrastructure service status and running applications')
326
+ .description('Show infra services and running apps (ports, URLs)')
239
327
  .action(async() => {
240
328
  try {
329
+ const summary = await loadInfraStatusSummary();
241
330
  const status = await infra.getInfraStatus();
242
- logger.log('\n📊 Infrastructure Status\n');
331
+ logger.log('');
332
+ logger.log(formatInfraStatusTitleLine(summary.devIdStr, summary.remoteServer));
333
+ logger.log('');
334
+ logInfraStatusConfigurationSummary(summary);
243
335
  Object.entries(status).forEach(([service, info]) => {
244
- const icon = String(info.status).trim().toLowerCase() === 'running' ? '' : '';
245
- logger.log(`${icon} ${service}:`);
246
- logger.log(` Status: ${info.status}`);
247
- logger.log(` Port: ${info.port}`);
248
- logger.log(` URL: ${info.url}`);
336
+ const icon = String(info.status).trim().toLowerCase() === 'running' ? '' : '';
337
+ logger.log(`${icon} ${service}`);
338
+ logPaddedFieldRow('Status', info.status);
339
+ logPaddedFieldRow('Port', info.port);
340
+ logPaddedFieldRow('URL', info.url);
249
341
  logger.log('');
250
342
  });
251
343
  const apps = await infra.getAppStatus();
@@ -253,12 +345,12 @@ function setupStatusCommand(program) {
253
345
  logger.log('📱 Running Applications\n');
254
346
  apps.forEach((appInfo) => {
255
347
  const s = String(appInfo.status).trim().toLowerCase();
256
- const icon = s.includes('running') || s.includes('up') ? '' : '';
257
- logger.log(`${icon} ${appInfo.name}:`);
258
- logger.log(` Container: ${appInfo.container}`);
259
- logger.log(` Port: ${appInfo.port}`);
260
- logger.log(` Status: ${appInfo.status}`);
261
- logger.log(` URL: ${appInfo.url}`);
348
+ const icon = s.includes('running') || s.includes('up') ? '' : '';
349
+ logger.log(`${icon} ${appInfo.name}`);
350
+ logPaddedFieldRow('Container', appInfo.container);
351
+ logPaddedFieldRow('Port', appInfo.port);
352
+ logPaddedFieldRow('Status', appInfo.status);
353
+ logPaddedFieldRow('URL', appInfo.url);
262
354
  logger.log('');
263
355
  });
264
356
  }
@@ -272,16 +364,16 @@ function setupStatusCommand(program) {
272
364
  const INFRA_SERVICES = ['postgres', 'redis', 'pgadmin', 'redis-commander', 'traefik'];
273
365
 
274
366
  function setupRestartCommand(program) {
275
- program.command('restart <service>')
276
- .description('Restart an infrastructure service or a Docker application (builder/<app>)')
367
+ program.command('restart <service|app>')
368
+ .description('Restart infra service (postgres, redis, …) or a builder/<app> container')
277
369
  .action(async(service) => {
278
370
  try {
279
371
  if (INFRA_SERVICES.includes(service)) {
280
372
  await infra.restartService(service);
281
- logger.log(`✅ ${service} service restarted successfully`);
373
+ logger.log(`✔ ${service} service restarted successfully`);
282
374
  } else {
283
375
  await appLib.restartApp(service);
284
- logger.log(`✅ ${service} restarted successfully`);
376
+ logger.log(`✔ ${service} restarted successfully`);
285
377
  }
286
378
  } catch (error) {
287
379
  handleCommandError(error, 'restart');
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @fileoverview parameters subcommand (validate kv:// catalog coverage)
3
+ * @author AI Fabrix Team
4
+ * @version 2.0.0
5
+ */
6
+
7
+ const { handleCommandError } = require('../utils/cli-utils');
8
+ const { handleParametersValidate } = require('../commands/parameters-validate');
9
+
10
+ /**
11
+ * @param {import('commander').Command} program - Commander program
12
+ */
13
+ function setupParametersCommands(program) {
14
+ const parameters = program
15
+ .command('parameters')
16
+ .description('Infra parameter catalog (kv:// keys, generators, Azure naming hints)');
17
+
18
+ parameters
19
+ .command('validate')
20
+ .description('Check env.template kv:// references against lib/schema/infra.parameter.yaml')
21
+ .option('--catalog <path>', 'Override path to infra.parameter.yaml')
22
+ .action(async(opts) => {
23
+ try {
24
+ const result = await handleParametersValidate({ catalogPath: opts.catalog });
25
+ if (!result.valid) process.exit(1);
26
+ } catch (error) {
27
+ handleCommandError(error, 'parameters validate');
28
+ }
29
+ });
30
+ }
31
+
32
+ module.exports = { setupParametersCommands };
@@ -6,20 +6,115 @@
6
6
  * @version 2.0.0
7
7
  */
8
8
 
9
+ const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
9
10
  const { handleCommandError } = require('../utils/cli-utils');
10
11
  const { handleSecretsSet } = require('../commands/secrets-set');
11
12
  const { handleSecretsList } = require('../commands/secrets-list');
12
13
  const { handleSecretsRemove } = require('../commands/secrets-remove');
13
14
  const { handleSecretsValidate } = require('../commands/secrets-validate');
14
15
  const { handleSecure } = require('../commands/secure');
16
+ const config = require('../core/config');
17
+ const logger = require('../utils/logger');
18
+
19
+ const SECRET_GROUP_HELP_AFTER = `
20
+ Subcommands:
21
+ list, set, remove, remove-all User secrets.local.yaml (add --shared for shared/remote)
22
+ set-secrets-file Point config at a shared secrets file or https URL
23
+ validate YAML structure (+ optional --naming)
24
+
25
+ Also: aifabrix secure Encrypt secrets.local.yaml (ISO 27001)
26
+
27
+ Examples:
28
+ $ aifabrix secret list
29
+ $ aifabrix secret set myapp/clientSecret "your-value"
30
+ $ aifabrix secret remove old-key
31
+ $ aifabrix secret remove-all
32
+ $ aifabrix secret validate
33
+
34
+ Shared over https: key BASH_NPM_TOKEN --shared → NPM_TOKEN available in terminal (exported).
35
+ `;
36
+
37
+ const SECRET_LIST_HELP_AFTER = `
38
+ Examples:
39
+ $ aifabrix secret list
40
+ $ aifabrix secret list --shared
41
+ `;
42
+
43
+ const SECRET_SET_HELP_AFTER = `
44
+ Examples:
45
+ $ aifabrix secret set myapp/clientSecret "your-secret"
46
+ $ aifabrix secret set hubspot/apiKey "$HUBSPOT_KEY"
47
+ $ aifabrix secret set team/shared-token "value" --shared
48
+ $ aifabrix secret set BASH_NPM_TOKEN "$NPM_TOKEN" --shared
49
+
50
+ With https aifabrix-secrets: keys named BASH_<NAME> --shared expose <NAME> in your
51
+ terminal as an exported env var (e.g. BASH_NPM_TOKEN → NPM_TOKEN).
52
+ `;
53
+
54
+ const SECRET_REMOVE_HELP_AFTER = `
55
+ Examples:
56
+ $ aifabrix secret remove deprecated-key
57
+ $ aifabrix secret remove shared-key --shared
58
+ `;
59
+
60
+ const SECRET_REMOVE_ALL_HELP_AFTER = `
61
+ You will be asked to type "yes" to confirm unless you pass --yes.
62
+
63
+ Examples:
64
+ $ aifabrix secret remove-all
65
+ $ aifabrix secret remove-all --yes
66
+ $ aifabrix secret remove-all --shared
67
+ $ aifabrix secret remove-all --shared --yes
68
+ `;
69
+
70
+ const SECRET_SET_SECRETS_FILE_HELP_AFTER = `
71
+ Examples:
72
+ $ aifabrix secret set-secrets-file ./shared-secrets.yaml
73
+ $ aifabrix secret set-secrets-file https://dev.example.com/api/secrets
74
+ $ aifabrix secret set-secrets-file ""
75
+ `;
76
+
77
+ const SECRET_VALIDATE_HELP_AFTER = `
78
+ Examples:
79
+ $ aifabrix secret validate
80
+ $ aifabrix secret validate ./secrets.local.yaml
81
+ $ aifabrix secret validate --naming
82
+ `;
83
+
84
+ const SECURE_HELP_AFTER = `
85
+ Examples:
86
+ $ aifabrix secure
87
+ $ aifabrix secure --secrets-encryption <32-byte-hex-or-base64>
88
+ `;
89
+
90
+ function setupSecretRemoveAllCommand(secretCmd) {
91
+ const { handleSecretsRemoveAll } = require('../commands/secrets-remove-all');
92
+ secretCmd
93
+ .command('remove-all')
94
+ .description('Remove all secret keys (requires typing "yes" unless --yes)')
95
+ .addHelpText('after', SECRET_REMOVE_ALL_HELP_AFTER)
96
+ .option('--shared', 'Remove all from shared secrets (file or remote API)')
97
+ .option('-y, --yes', 'Skip confirmation prompt (non-interactive / scripts)')
98
+ .action(async options => {
99
+ try {
100
+ await config.ensureSecretsEncryptionKey();
101
+ await handleSecretsRemoveAll(options);
102
+ } catch (error) {
103
+ handleCommandError(error, 'secret remove-all');
104
+ process.exit(1);
105
+ }
106
+ });
107
+ }
15
108
 
16
109
  function setupSecretValidateCommand(secretCmd) {
17
110
  secretCmd
18
111
  .command('validate [path]')
19
112
  .description('Validate secrets file (YAML structure and optional naming convention)')
113
+ .addHelpText('after', SECRET_VALIDATE_HELP_AFTER)
20
114
  .option('--naming', 'Check key names against *KeyVault convention')
21
115
  .action(async(pathArg, options) => {
22
116
  try {
117
+ await config.ensureSecretsEncryptionKey();
23
118
  const result = await handleSecretsValidate(pathArg, options);
24
119
  if (!result.valid) process.exit(1);
25
120
  } catch (error) {
@@ -29,6 +124,26 @@ function setupSecretValidateCommand(secretCmd) {
29
124
  });
30
125
  }
31
126
 
127
+ /**
128
+ * Registers the secure command on the program.
129
+ * @param {Command} program - Commander program instance
130
+ */
131
+ function setupSecureCommand(program) {
132
+ program.command('secure')
133
+ .description('Encrypt secrets.local.yaml at rest (ISO 27001)')
134
+ .addHelpText('after', SECURE_HELP_AFTER)
135
+ .option('--secrets-encryption <key>', 'Encryption key (32 bytes, hex or base64)')
136
+ .action(async(options) => {
137
+ try {
138
+ await config.ensureSecretsEncryptionKey();
139
+ await handleSecure(options);
140
+ } catch (error) {
141
+ handleCommandError(error, 'secure');
142
+ process.exit(1);
143
+ }
144
+ });
145
+ }
146
+
32
147
  /**
33
148
  * Sets up secrets and security commands
34
149
  * @param {Command} program - Commander program instance
@@ -36,14 +151,17 @@ function setupSecretValidateCommand(secretCmd) {
36
151
  function setupSecretsCommands(program) {
37
152
  const secretCmd = program
38
153
  .command('secret')
39
- .description('Manage secrets in secrets files');
154
+ .description('User and shared secrets (list, set, remove, remove-all, validate)')
155
+ .addHelpText('after', SECRET_GROUP_HELP_AFTER);
40
156
 
41
157
  secretCmd
42
158
  .command('list')
43
- .description('List secret keys (user or shared; use --shared for shared)')
159
+ .description('List secret keys (--shared for shared/remote)')
160
+ .addHelpText('after', SECRET_LIST_HELP_AFTER)
44
161
  .option('--shared', 'List shared secrets (from config aifabrix-secrets or remote API)')
45
162
  .action(async(options) => {
46
163
  try {
164
+ await config.ensureSecretsEncryptionKey();
47
165
  await handleSecretsList(options);
48
166
  } catch (error) {
49
167
  handleCommandError(error, 'secret list');
@@ -53,10 +171,12 @@ function setupSecretsCommands(program) {
53
171
 
54
172
  secretCmd
55
173
  .command('set <key> <value>')
56
- .description('Set a secret value in secrets file')
174
+ .description('Set a secret value')
175
+ .addHelpText('after', SECRET_SET_HELP_AFTER)
57
176
  .option('--shared', 'Save to general secrets file (from config.yaml aifabrix-secrets) instead of user secrets')
58
177
  .action(async(key, value, options) => {
59
178
  try {
179
+ await config.ensureSecretsEncryptionKey();
60
180
  await handleSecretsSet(key, value, options);
61
181
  } catch (error) {
62
182
  handleCommandError(error, 'secret set');
@@ -66,10 +186,12 @@ function setupSecretsCommands(program) {
66
186
 
67
187
  secretCmd
68
188
  .command('remove <key>')
69
- .description('Remove a secret by key')
189
+ .description('Remove a secret key')
190
+ .addHelpText('after', SECRET_REMOVE_HELP_AFTER)
70
191
  .option('--shared', 'Remove from shared secrets (file or remote API)')
71
192
  .action(async(key, options) => {
72
193
  try {
194
+ await config.ensureSecretsEncryptionKey();
73
195
  await handleSecretsRemove(key, options);
74
196
  } catch (error) {
75
197
  handleCommandError(error, 'secret remove');
@@ -77,16 +199,31 @@ function setupSecretsCommands(program) {
77
199
  }
78
200
  });
79
201
 
202
+ setupSecretRemoveAllCommand(secretCmd);
203
+ setupSecretSetSecretsFileCommand(secretCmd);
80
204
  setupSecretValidateCommand(secretCmd);
205
+ setupSecureCommand(program);
206
+ }
81
207
 
82
- program.command('secure')
83
- .description('Encrypt secrets in secrets.local.yaml files for ISO 27001 compliance')
84
- .option('--secrets-encryption <key>', 'Encryption key (32 bytes, hex or base64)')
85
- .action(async(options) => {
208
+ /**
209
+ * Register secret set-secrets-file command.
210
+ * @param {Command} secretCmd - secret command group
211
+ */
212
+ function setupSecretSetSecretsFileCommand(secretCmd) {
213
+ secretCmd
214
+ .command('set-secrets-file <path>')
215
+ .description('Set shared secrets path in config (file or https; empty clears; not validated)')
216
+ .addHelpText('after', SECRET_SET_SECRETS_FILE_HELP_AFTER)
217
+ .action(async(secretsPath) => {
86
218
  try {
87
- await handleSecure(options);
219
+ const trimmed = (secretsPath || '').trim();
220
+ if (trimmed !== '' && trimmed.startsWith('http://')) {
221
+ throw new Error('Only https URLs are allowed for remote secrets');
222
+ }
223
+ await config.setSecretsPath(trimmed);
224
+ logger.log(trimmed === '' ? formatSuccessLine('Secrets file path cleared') : formatSuccessLine(`Secrets file path set to ${trimmed}`));
88
225
  } catch (error) {
89
- handleCommandError(error, 'secure');
226
+ handleCommandError(error, 'secret set-secrets-file');
90
227
  process.exit(1);
91
228
  }
92
229
  });