@aifabrix/builder 2.43.0 → 2.44.1

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 (371) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/.cursor/rules/cli-layout.mdc +75 -0
  3. package/.cursor/rules/project-rules.mdc +8 -0
  4. package/.npmrc.token +1 -0
  5. package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  6. package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  7. package/.nyc_output/processinfo/index.json +1 -0
  8. package/README.md +1 -1
  9. package/anchor-docs/README.md +10 -0
  10. package/anchor-docs/_TEMPLATE +24 -0
  11. package/bin/aifabrix.js +13 -4
  12. package/integration/hubspot-test/README.md +31 -0
  13. package/integration/hubspot-test/create-hubspot.js +5 -5
  14. package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
  15. package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
  16. package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
  17. package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
  18. package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
  19. package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
  20. package/integration/hubspot-test/test-dataplane-down.js +3 -3
  21. package/integration/hubspot-test/test.js +35 -43
  22. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  23. package/integration/roundtrip-test-local/README.md +144 -0
  24. package/integration/roundtrip-test-local/application.yaml +13 -0
  25. package/integration/roundtrip-test-local/env.template +15 -0
  26. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  27. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  28. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  29. package/integration/roundtrip-test-local2/README.md +144 -0
  30. package/integration/roundtrip-test-local2/application.yaml +13 -0
  31. package/integration/roundtrip-test-local2/env.template +15 -0
  32. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  33. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  34. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  35. package/integration/test/wizard.yaml +8 -0
  36. package/jest.config.default.js +10 -0
  37. package/jest.config.integration.fixtures.js +22 -0
  38. package/jest.config.integration.js +21 -18
  39. package/jest.config.isolated.js +10 -0
  40. package/jest.projects.js +301 -0
  41. package/lib/api/certificates.api.js +62 -0
  42. package/lib/api/datasources-core.api.js +3 -3
  43. package/lib/api/dev-mtls-request.js +110 -0
  44. package/lib/api/dev-server-https.js +145 -0
  45. package/lib/api/dev.api.js +133 -144
  46. package/lib/api/index.js +11 -3
  47. package/lib/api/pipeline.api.js +67 -20
  48. package/lib/api/types/certificates.types.js +48 -0
  49. package/lib/api/types/dev.types.js +4 -3
  50. package/lib/api/types/pipeline.types.js +8 -5
  51. package/lib/api/types/validation-run.types.js +56 -0
  52. package/lib/api/validation-run.api.js +111 -0
  53. package/lib/api/validation-runner.js +109 -0
  54. package/lib/app/certification-show-enrich.js +129 -0
  55. package/lib/app/certification-verify-rows.js +60 -0
  56. package/lib/app/config.js +1 -1
  57. package/lib/app/deploy-status-display.js +2 -2
  58. package/lib/app/deploy.js +7 -6
  59. package/lib/app/display.js +2 -1
  60. package/lib/app/dockerfile.js +3 -2
  61. package/lib/app/down.js +2 -1
  62. package/lib/app/helpers.js +6 -5
  63. package/lib/app/index.js +27 -8
  64. package/lib/app/list.js +7 -6
  65. package/lib/app/push.js +4 -3
  66. package/lib/app/register.js +16 -7
  67. package/lib/app/rotate-secret.js +14 -13
  68. package/lib/app/run-container-start.js +184 -0
  69. package/lib/app/run-docker-fallback.js +108 -0
  70. package/lib/app/run-env-compose.js +30 -42
  71. package/lib/app/run-helpers.js +49 -126
  72. package/lib/app/run-infra-requirements.js +30 -0
  73. package/lib/app/run-resolve-image.js +21 -0
  74. package/lib/app/run.js +74 -21
  75. package/lib/app/show-display.js +44 -1
  76. package/lib/app/show.js +93 -9
  77. package/lib/build/index.js +13 -10
  78. package/lib/certification/cli-cert-sync-skip.js +21 -0
  79. package/lib/certification/merge-certification-from-artifact.js +185 -0
  80. package/lib/certification/post-unified-cert-sync.js +33 -0
  81. package/lib/certification/sync-after-external-command.js +52 -0
  82. package/lib/certification/sync-system-certification.js +197 -0
  83. package/lib/cli/index.js +2 -0
  84. package/lib/cli/setup-app.help.js +67 -0
  85. package/lib/cli/setup-app.js +61 -121
  86. package/lib/cli/setup-app.test-commands.js +195 -0
  87. package/lib/cli/setup-auth.js +19 -5
  88. package/lib/cli/setup-credential-deployment.js +22 -8
  89. package/lib/cli/setup-dev-path-commands.js +124 -0
  90. package/lib/cli/setup-dev.js +170 -113
  91. package/lib/cli/setup-environment.js +7 -1
  92. package/lib/cli/setup-external-system.js +84 -23
  93. package/lib/cli/setup-infra.js +126 -47
  94. package/lib/cli/setup-parameters.js +32 -0
  95. package/lib/cli/setup-secrets.js +137 -18
  96. package/lib/cli/setup-service-user.js +1 -1
  97. package/lib/cli/setup-utility.js +54 -22
  98. package/lib/commands/app-down.js +5 -7
  99. package/lib/commands/app-install.js +14 -7
  100. package/lib/commands/app-logs.js +13 -10
  101. package/lib/commands/app-shell.js +4 -1
  102. package/lib/commands/app-test.js +25 -19
  103. package/lib/commands/app.js +32 -11
  104. package/lib/commands/auth-config.js +6 -6
  105. package/lib/commands/auth-status.js +4 -3
  106. package/lib/commands/credential-env.js +4 -3
  107. package/lib/commands/credential-list.js +5 -4
  108. package/lib/commands/credential-push.js +4 -3
  109. package/lib/commands/datasource-unified-test-cli.js +428 -0
  110. package/lib/commands/datasource-unified-test-cli.options.js +191 -0
  111. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
  112. package/lib/commands/datasource-validation-cli.js +143 -0
  113. package/lib/commands/datasource.js +125 -95
  114. package/lib/commands/deployment-list.js +6 -5
  115. package/lib/commands/dev-cli-handlers.js +122 -18
  116. package/lib/commands/dev-down.js +4 -3
  117. package/lib/commands/dev-init.js +231 -116
  118. package/lib/commands/dev-show-display.js +473 -0
  119. package/lib/commands/login-credentials.js +3 -2
  120. package/lib/commands/login-device.js +4 -3
  121. package/lib/commands/login.js +5 -4
  122. package/lib/commands/logout.js +8 -7
  123. package/lib/commands/parameters-validate.js +54 -0
  124. package/lib/commands/repair-datasource.js +314 -68
  125. package/lib/commands/repair-env-template.js +2 -2
  126. package/lib/commands/repair.js +21 -3
  127. package/lib/commands/secrets-list.js +23 -12
  128. package/lib/commands/secrets-remove-all.js +220 -0
  129. package/lib/commands/secrets-remove.js +21 -12
  130. package/lib/commands/secrets-set.js +21 -12
  131. package/lib/commands/secrets-validate.js +4 -4
  132. package/lib/commands/secure.js +10 -9
  133. package/lib/commands/service-user.js +26 -25
  134. package/lib/commands/test-e2e-external.js +27 -1
  135. package/lib/commands/up-common.js +3 -2
  136. package/lib/commands/up-dataplane.js +29 -16
  137. package/lib/commands/up-miso.js +19 -29
  138. package/lib/commands/upload.js +149 -39
  139. package/lib/commands/wizard-core-helpers.js +1 -1
  140. package/lib/commands/wizard-dataplane.js +4 -3
  141. package/lib/commands/wizard-helpers.js +3 -3
  142. package/lib/commands/wizard.js +2 -2
  143. package/lib/core/admin-secrets.js +14 -5
  144. package/lib/core/audit-logger.js +12 -4
  145. package/lib/core/config-attach-extensions.js +46 -0
  146. package/lib/core/config-runtime-paths.js +29 -0
  147. package/lib/core/config.js +55 -56
  148. package/lib/core/diff.js +3 -2
  149. package/lib/core/ensure-encryption-key.js +1 -1
  150. package/lib/core/secrets-ensure-infra.js +77 -0
  151. package/lib/core/secrets-ensure.js +120 -64
  152. package/lib/core/secrets-env-write.js +35 -7
  153. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  154. package/lib/core/secrets.js +200 -37
  155. package/lib/core/templates-env.js +4 -3
  156. package/lib/datasource/abac-validator.js +1 -10
  157. package/lib/datasource/deploy.js +75 -53
  158. package/lib/datasource/field-reference-validator.js +9 -6
  159. package/lib/datasource/integration-context.js +63 -0
  160. package/lib/datasource/list.js +8 -7
  161. package/lib/datasource/log-viewer.js +189 -67
  162. package/lib/datasource/resolve-app.js +4 -4
  163. package/lib/datasource/test-e2e.js +113 -146
  164. package/lib/datasource/test-integration.js +114 -122
  165. package/lib/datasource/unified-validation-run-body.js +68 -0
  166. package/lib/datasource/unified-validation-run-post.js +23 -0
  167. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  168. package/lib/datasource/unified-validation-run.js +93 -0
  169. package/lib/datasource/validate.js +157 -13
  170. package/lib/deployment/deployer.js +4 -3
  171. package/lib/deployment/environment.js +7 -6
  172. package/lib/deployment/push.js +17 -8
  173. package/lib/external-system/delete.js +4 -3
  174. package/lib/external-system/deploy.js +166 -53
  175. package/lib/external-system/download-helpers.js +1 -1
  176. package/lib/external-system/download.js +7 -6
  177. package/lib/external-system/generator.js +92 -6
  178. package/lib/external-system/integration-test-dispatch.js +26 -0
  179. package/lib/external-system/test-execution.js +5 -1
  180. package/lib/external-system/test-helpers.js +0 -4
  181. package/lib/external-system/test-system-level-helpers.js +110 -0
  182. package/lib/external-system/test-system-level.js +83 -44
  183. package/lib/external-system/test.js +59 -8
  184. package/lib/generator/builders.js +23 -11
  185. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  186. package/lib/generator/external.js +16 -4
  187. package/lib/generator/helpers.js +58 -3
  188. package/lib/generator/index.js +4 -0
  189. package/lib/generator/split-readme.js +12 -7
  190. package/lib/generator/split-variables.js +2 -1
  191. package/lib/generator/split.js +1 -1
  192. package/lib/generator/wizard-readme.js +3 -3
  193. package/lib/generator/wizard.js +8 -8
  194. package/lib/infrastructure/compose.js +70 -7
  195. package/lib/infrastructure/helpers-docker-check.js +67 -0
  196. package/lib/infrastructure/helpers.js +203 -42
  197. package/lib/infrastructure/index.js +31 -18
  198. package/lib/infrastructure/services.js +21 -67
  199. package/lib/internal/fs-real-sync.js +104 -0
  200. package/lib/internal/node-fs.js +98 -0
  201. package/lib/parameters/database-secret-values.js +173 -0
  202. package/lib/parameters/infra-kv-discovery.js +121 -0
  203. package/lib/parameters/infra-parameter-catalog.js +458 -0
  204. package/lib/parameters/infra-parameter-validate.js +64 -0
  205. package/lib/schema/application-schema.json +37 -17
  206. package/lib/schema/datasource-test-run.schema.json +493 -0
  207. package/lib/schema/deployment-rules.yaml +102 -63
  208. package/lib/schema/external-datasource.schema.json +1200 -442
  209. package/lib/schema/external-system.schema.json +203 -5
  210. package/lib/schema/flag-map-validation-run.json +31 -0
  211. package/lib/schema/infra-parameter.schema.json +106 -0
  212. package/lib/schema/infra.parameter.yaml +421 -0
  213. package/lib/schema/type/credential-auth-templates.json +40 -0
  214. package/lib/schema/type/document-storage.json +226 -0
  215. package/lib/schema/type/message-service.json +123 -0
  216. package/lib/schema/type/vector-store.json +88 -0
  217. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  218. package/lib/utils/api-error-handler.js +2 -2
  219. package/lib/utils/api.js +77 -17
  220. package/lib/utils/app-register-api.js +3 -2
  221. package/lib/utils/app-register-auth.js +1 -1
  222. package/lib/utils/app-register-config.js +4 -4
  223. package/lib/utils/app-register-display.js +3 -2
  224. package/lib/utils/app-register-validator.js +3 -2
  225. package/lib/utils/app-run-containers.js +26 -22
  226. package/lib/utils/app-scoped-config.js +31 -0
  227. package/lib/utils/app-service-env-from-builder.js +164 -0
  228. package/lib/utils/build-copy.js +1 -1
  229. package/lib/utils/build-helpers.js +20 -20
  230. package/lib/utils/build-resolve-image.js +165 -0
  231. package/lib/utils/cli-layout-chalk.js +8 -0
  232. package/lib/utils/cli-test-layout-chalk.js +267 -0
  233. package/lib/utils/cli-utils.js +88 -11
  234. package/lib/utils/compose-db-passwords.js +138 -0
  235. package/lib/utils/compose-generate-docker-compose.js +216 -0
  236. package/lib/utils/compose-generator.js +197 -291
  237. package/lib/utils/compose-miso-env.js +18 -0
  238. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  239. package/lib/utils/config-paths.js +166 -7
  240. package/lib/utils/config-scoped-resources-preference.js +41 -0
  241. package/lib/utils/configuration-env-resolver.js +11 -8
  242. package/lib/utils/controller-deployment-outcome.js +68 -0
  243. package/lib/utils/credential-display.js +2 -2
  244. package/lib/utils/credential-secrets-env.js +5 -5
  245. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  246. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  247. package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
  248. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  249. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  250. package/lib/utils/datasource-test-run-display.js +459 -0
  251. package/lib/utils/datasource-test-run-exit.js +83 -0
  252. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  253. package/lib/utils/datasource-test-run-report-version.js +51 -0
  254. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  255. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  256. package/lib/utils/datasource-validation-watch.js +266 -0
  257. package/lib/utils/declarative-url-ports.js +47 -0
  258. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  259. package/lib/utils/dev-ca-install.js +185 -23
  260. package/lib/utils/dev-cert-helper.js +266 -17
  261. package/lib/utils/dev-hosts-helper.js +307 -0
  262. package/lib/utils/dev-init-cert-hints.js +37 -0
  263. package/lib/utils/dev-init-health-messages.js +52 -0
  264. package/lib/utils/dev-init-resolve.js +86 -0
  265. package/lib/utils/dev-init-ssh-merge.js +65 -0
  266. package/lib/utils/dev-ssh-config-helper.js +196 -0
  267. package/lib/utils/dev-user-groups.js +93 -0
  268. package/lib/utils/docker-build.js +42 -17
  269. package/lib/utils/docker-exec.js +28 -0
  270. package/lib/utils/docker-manifest-public-port.js +116 -0
  271. package/lib/utils/docker-not-running-hint.js +52 -0
  272. package/lib/utils/docker.js +98 -11
  273. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  274. package/lib/utils/env-config-loader.js +10 -91
  275. package/lib/utils/env-copy.js +19 -10
  276. package/lib/utils/env-map.js +35 -8
  277. package/lib/utils/env-template.js +2 -2
  278. package/lib/utils/environment-scoped-resources.js +144 -0
  279. package/lib/utils/error-formatter.js +92 -13
  280. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  281. package/lib/utils/error-formatters/network-errors.js +2 -1
  282. package/lib/utils/error-formatters/permission-errors.js +2 -1
  283. package/lib/utils/error-formatters/validation-errors.js +2 -1
  284. package/lib/utils/external-readme.js +8 -1
  285. package/lib/utils/external-system-display.js +242 -136
  286. package/lib/utils/external-system-local-test-tty.js +389 -0
  287. package/lib/utils/external-system-readiness-core.js +377 -0
  288. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  289. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  290. package/lib/utils/external-system-readiness-display.js +186 -0
  291. package/lib/utils/external-system-system-test-tty-overview.js +120 -0
  292. package/lib/utils/external-system-system-test-tty.js +417 -0
  293. package/lib/utils/external-system-test-helpers.js +24 -6
  294. package/lib/utils/external-system-validators.js +30 -12
  295. package/lib/utils/health-check-url.js +119 -0
  296. package/lib/utils/health-check.js +59 -25
  297. package/lib/utils/help-builder.js +11 -8
  298. package/lib/utils/image-version.js +4 -8
  299. package/lib/utils/infra-containers.js +4 -7
  300. package/lib/utils/infra-env-defaults.js +162 -0
  301. package/lib/utils/infra-status-display.js +167 -0
  302. package/lib/utils/infra-status.js +16 -8
  303. package/lib/utils/local-secrets.js +3 -4
  304. package/lib/utils/paths.js +148 -47
  305. package/lib/utils/port-resolver.js +10 -23
  306. package/lib/utils/redis-env-scope.js +62 -0
  307. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  308. package/lib/utils/remote-builder-validation.js +99 -0
  309. package/lib/utils/remote-dev-auth.js +117 -21
  310. package/lib/utils/remote-docker-env.js +67 -15
  311. package/lib/utils/remote-secrets-loader.js +13 -4
  312. package/lib/utils/resolve-docker-image-ref.js +124 -0
  313. package/lib/utils/schema-loader.js +22 -9
  314. package/lib/utils/secrets-bash-kv.js +25 -0
  315. package/lib/utils/secrets-generator.js +169 -49
  316. package/lib/utils/secrets-helpers.js +70 -59
  317. package/lib/utils/secrets-kv-scope.js +60 -0
  318. package/lib/utils/secrets-utils.js +32 -38
  319. package/lib/utils/secrets-validation.js +3 -1
  320. package/lib/utils/secrets-yaml-preserve.js +109 -0
  321. package/lib/utils/ssh-key-helper.js +4 -2
  322. package/lib/utils/template-helpers.js +2 -2
  323. package/lib/utils/test-log-writer.js +3 -3
  324. package/lib/utils/token-manager.js +1 -2
  325. package/lib/utils/url-declarative-public-base.js +188 -0
  326. package/lib/utils/url-declarative-resolve-build.js +493 -0
  327. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  328. package/lib/utils/url-declarative-resolve.js +220 -0
  329. package/lib/utils/url-declarative-token-parse.js +74 -0
  330. package/lib/utils/url-declarative-url-flags.js +50 -0
  331. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  332. package/lib/utils/url-public-path-prefix.js +34 -0
  333. package/lib/utils/urls-local-registry.js +220 -0
  334. package/lib/utils/validation-report-tty-kit.js +77 -0
  335. package/lib/utils/validation-run-poll.js +112 -0
  336. package/lib/utils/validation-run-post-retry.js +85 -0
  337. package/lib/utils/validation-run-request.js +116 -0
  338. package/lib/utils/variable-transformer.js +21 -4
  339. package/lib/utils/yaml-preserve.js +33 -14
  340. package/lib/validation/datasource-warnings.js +56 -0
  341. package/lib/validation/env-template-auth.js +1 -1
  342. package/lib/validation/external-manifest-validator.js +27 -7
  343. package/lib/validation/validate-display.js +37 -31
  344. package/lib/validation/validate-external-cert-sync.js +23 -0
  345. package/lib/validation/validate.js +8 -14
  346. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  347. package/lib/validation/validator.js +22 -65
  348. package/lib/validation/wizard-config-validator.js +2 -1
  349. package/package.json +9 -4
  350. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  351. package/scripts/diagnose-cli.js +150 -0
  352. package/scripts/install-local.js +307 -55
  353. package/scripts/pnpm-global-remove.js +48 -0
  354. package/templates/README.md +15 -2
  355. package/templates/applications/dataplane/application.yaml +52 -2
  356. package/templates/applications/dataplane/env.template +79 -17
  357. package/templates/applications/dataplane/rbac.yaml +8 -0
  358. package/templates/applications/keycloak/application.yaml +9 -1
  359. package/templates/applications/keycloak/env.template +15 -6
  360. package/templates/applications/miso-controller/application.yaml +10 -2
  361. package/templates/applications/miso-controller/env.template +42 -12
  362. package/templates/applications/miso-controller/rbac.yaml +5 -0
  363. package/templates/external-system/README.md.hbs +20 -7
  364. package/templates/external-system/deploy.js.hbs +5 -5
  365. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  366. package/templates/infra/compose.yaml.hbs +33 -16
  367. package/templates/infra/servers.json.hbs +3 -1
  368. package/templates/python/docker-compose.hbs +16 -0
  369. package/templates/typescript/docker-compose.hbs +16 -0
  370. package/lib/api/external-test.api.js +0 -111
  371. package/lib/schema/env-config.yaml +0 -60
@@ -0,0 +1,123 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "aifabrix://schema/type/message-service.json",
4
+ "title": "Message Service Configuration Schema",
5
+ "description": "Internal schema for validating message service configurations in ExternalDataSource. Supports Slack, Teams, and Email message services for notifications.",
6
+ "metadata": {
7
+ "key": "message-service-schema",
8
+ "name": "Message Service Configuration Schema",
9
+ "description": "JSON schema for validating message service configurations",
10
+ "version": "1.0.0",
11
+ "type": "schema",
12
+ "category": "message-service",
13
+ "author": "AI Fabrix Team",
14
+ "createdAt": "2026-01-15T00:00:00Z",
15
+ "updatedAt": "2026-01-15T00:00:00Z",
16
+ "compatibility": {
17
+ "minVersion": "1.0.0",
18
+ "maxVersion": "2.0.0",
19
+ "deprecated": false
20
+ },
21
+ "tags": [
22
+ "schema",
23
+ "message-service",
24
+ "dataplane",
25
+ "validation",
26
+ "notifications"
27
+ ],
28
+ "dependencies": [],
29
+ "changelog": [
30
+ {
31
+ "version": "1.0.0",
32
+ "date": "2026-01-15T00:00:00Z",
33
+ "changes": [
34
+ "Initial schema for message service validation",
35
+ "Support for Slack, Teams, and Email message services",
36
+ "CIP-based configuration for Slack and Teams",
37
+ "Provider-based configuration for Email (SendGrid, SES, SMTP)"
38
+ ],
39
+ "breaking": false
40
+ }
41
+ ]
42
+ },
43
+ "type": "object",
44
+ "required": ["enabled", "messageServiceType"],
45
+ "properties": {
46
+ "enabled": {
47
+ "type": "boolean",
48
+ "default": true,
49
+ "description": "Whether message service is enabled"
50
+ },
51
+ "messageServiceType": {
52
+ "type": "string",
53
+ "enum": ["slack", "teams", "email"],
54
+ "description": "Type of message service: 'slack' for Slack notifications, 'teams' for Microsoft Teams notifications, 'email' for email notifications"
55
+ },
56
+ "datasourceKey": {
57
+ "type": "string",
58
+ "description": "ExternalDataSource key for CIP-based services (Slack, Teams). Required when messageServiceType is 'slack' or 'teams'."
59
+ },
60
+ "email": {
61
+ "type": "object",
62
+ "description": "Email service configuration (required when messageServiceType is 'email')",
63
+ "properties": {
64
+ "provider": {
65
+ "type": "string",
66
+ "enum": ["sendgrid", "ses", "smtp"],
67
+ "description": "Email provider: 'sendgrid' for SendGrid API, 'ses' for AWS SES, 'smtp' for SMTP server"
68
+ },
69
+ "apiKey": {
70
+ "type": "string",
71
+ "description": "API key for SendGrid (required when provider is 'sendgrid')"
72
+ },
73
+ "accessKey": {
74
+ "type": "string",
75
+ "description": "AWS access key for SES (required when provider is 'ses')"
76
+ },
77
+ "secretKey": {
78
+ "type": "string",
79
+ "description": "AWS secret key for SES (required when provider is 'ses')"
80
+ },
81
+ "region": {
82
+ "type": "string",
83
+ "description": "AWS region for SES (required when provider is 'ses')"
84
+ },
85
+ "host": {
86
+ "type": "string",
87
+ "description": "SMTP server host (required when provider is 'smtp')"
88
+ },
89
+ "port": {
90
+ "type": "integer",
91
+ "description": "SMTP server port (required when provider is 'smtp')"
92
+ },
93
+ "useTls": {
94
+ "type": "boolean",
95
+ "default": true,
96
+ "description": "Use TLS for SMTP (when provider is 'smtp')"
97
+ },
98
+ "username": {
99
+ "type": "string",
100
+ "description": "SMTP username (optional when provider is 'smtp')"
101
+ },
102
+ "password": {
103
+ "type": "string",
104
+ "description": "SMTP password (optional when provider is 'smtp')"
105
+ },
106
+ "fromEmail": {
107
+ "type": "string",
108
+ "description": "From email address (required when messageServiceType is 'email')"
109
+ },
110
+ "recipients": {
111
+ "type": "array",
112
+ "items": {
113
+ "type": "string"
114
+ },
115
+ "description": "Default recipient email addresses (optional)"
116
+ }
117
+ },
118
+ "additionalProperties": false
119
+ }
120
+ },
121
+ "additionalProperties": false
122
+ }
123
+
@@ -0,0 +1,88 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "aifabrix://schema/type/vector-store.json",
4
+ "title": "Vector Store Configuration Schema",
5
+ "description": "Internal schema for validating vector-store type ExternalSystem configurations. Enforces semantic constraints: no filtering, no hybrid search, ID-constrained scoring only.",
6
+ "metadata": {
7
+ "key": "vector-store-schema",
8
+ "name": "Vector Store Configuration Schema",
9
+ "description": "JSON schema for validating vector-store type ExternalSystem configurations",
10
+ "version": "1.0.0",
11
+ "type": "schema",
12
+ "category": "vector-store",
13
+ "author": "AI Fabrix Team",
14
+ "createdAt": "2026-01-02T00:00:00Z",
15
+ "updatedAt": "2026-01-02T00:00:00Z",
16
+ "compatibility": {
17
+ "minVersion": "1.0.0",
18
+ "maxVersion": "2.0.0",
19
+ "deprecated": false
20
+ },
21
+ "tags": [
22
+ "schema",
23
+ "vector-store",
24
+ "dataplane",
25
+ "validation"
26
+ ],
27
+ "dependencies": [],
28
+ "changelog": [
29
+ {
30
+ "version": "1.0.0",
31
+ "date": "2026-01-02T00:00:00Z",
32
+ "changes": [
33
+ "Initial schema for vector-store type validation",
34
+ "Enforces no filtering and no hybrid search constraints",
35
+ "Defines required capabilities: score, upsert, delete"
36
+ ],
37
+ "breaking": false
38
+ }
39
+ ]
40
+ },
41
+ "type": "object",
42
+ "required": ["dimensions", "distanceMetric", "capabilities"],
43
+ "properties": {
44
+ "dimensions": {
45
+ "type": "integer",
46
+ "minimum": 128,
47
+ "description": "Embedding vector dimensions (e.g., 1536 for OpenAI text-embedding-ada-002)"
48
+ },
49
+ "distanceMetric": {
50
+ "type": "string",
51
+ "enum": ["cosine", "dot"],
52
+ "description": "Distance metric for similarity scoring. 'cosine' uses cosine similarity, 'dot' uses dot product."
53
+ },
54
+ "capabilities": {
55
+ "type": "object",
56
+ "required": ["score", "upsert", "delete"],
57
+ "properties": {
58
+ "score": {
59
+ "type": "boolean",
60
+ "description": "Supports similarity scoring operation. Must be true for vector stores."
61
+ },
62
+ "upsert": {
63
+ "type": "boolean",
64
+ "description": "Supports vector upsert operation. Must be true for vector stores."
65
+ },
66
+ "delete": {
67
+ "type": "boolean",
68
+ "description": "Supports vector deletion operation. Must be true for vector stores."
69
+ },
70
+ "stats": {
71
+ "type": "boolean",
72
+ "description": "Supports index statistics/health check operation. Optional capability."
73
+ },
74
+ "filter": {
75
+ "const": false,
76
+ "description": "Filtering is explicitly forbidden - vector stores do not filter. This must be false or absent."
77
+ },
78
+ "hybridSearch": {
79
+ "const": false,
80
+ "description": "Hybrid search is explicitly forbidden - vector stores only score pre-authorized IDs. This must be false or absent."
81
+ }
82
+ },
83
+ "additionalProperties": false
84
+ }
85
+ },
86
+ "additionalProperties": false
87
+ }
88
+
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Resolves the directory that contains `config.yaml` for CLI runtime.
3
+ * Shared by `paths.getConfigDirForPaths` and `config.getConfigDir` (no circular imports).
4
+ *
5
+ * When `AIFABRIX_HOME` is set to the POSIX home (builder-server pattern) but the real
6
+ * config file is under `~/.aifabrix/config.yaml`, use that nested directory so
7
+ * `secrets.local.yaml` and auth config stay beside `config.yaml`.
8
+ *
9
+ * Relative `AIFABRIX_HOME` / `AIFABRIX_CONFIG` values are anchored to the user home
10
+ * directory (not `process.cwd()`), so a mistaken `aifabrix-training` does not become
11
+ * `/aifabrix-training` when the shell cwd is `/` (EACCES on mkdir).
12
+ * Paths starting with `./` or `../` still resolve from cwd for project-local overrides.
13
+ *
14
+ * @fileoverview AIFABRIX_CONFIG / AIFABRIX_HOME → config directory
15
+ * @author AI Fabrix Team
16
+ * @version 2.0.0
17
+ */
18
+
19
+ 'use strict';
20
+
21
+ const { existsSync } = require('../internal/fs-real-sync');
22
+ const path = require('path');
23
+ const os = require('os');
24
+
25
+ /**
26
+ * @returns {string}
27
+ */
28
+ function safeHomedir() {
29
+ try {
30
+ const h = os.homedir();
31
+ if (typeof h === 'string' && h.length > 0) {
32
+ return h;
33
+ }
34
+ } catch {
35
+ // ignore
36
+ }
37
+ return process.env.HOME || process.env.USERPROFILE || '/';
38
+ }
39
+
40
+ /**
41
+ * @param {string} raw
42
+ * @returns {string}
43
+ */
44
+ function expandLeadingTilde(raw) {
45
+ const t = typeof raw === 'string' ? raw.trim() : '';
46
+ if (!t) {
47
+ return t;
48
+ }
49
+ if (t === '~') {
50
+ return safeHomedir();
51
+ }
52
+ if (t.startsWith('~/') || t.startsWith('~\\')) {
53
+ return path.join(safeHomedir(), t.slice(2));
54
+ }
55
+ return t;
56
+ }
57
+
58
+ /**
59
+ * True when the path is explicitly relative to cwd (project-local).
60
+ * @param {string} t
61
+ * @returns {boolean}
62
+ */
63
+ function isExplicitRelativeToCwd(t) {
64
+ if (t === '.' || t === '..') {
65
+ return true;
66
+ }
67
+ return (
68
+ t.startsWith('./') ||
69
+ t.startsWith('../') ||
70
+ t.startsWith('.\\') ||
71
+ t.startsWith('..\\')
72
+ );
73
+ }
74
+
75
+ /**
76
+ * Resolve `AIFABRIX_HOME` and config `aifabrix-home`: bare relative segments live under user home.
77
+ *
78
+ * @param {string} raw
79
+ * @returns {string}
80
+ */
81
+ function resolveAifabrixHomeLikePath(raw) {
82
+ const expanded = expandLeadingTilde(raw);
83
+ if (!expanded) {
84
+ return expanded;
85
+ }
86
+ if (path.isAbsolute(expanded)) {
87
+ return path.normalize(expanded);
88
+ }
89
+ if (isExplicitRelativeToCwd(expanded)) {
90
+ return path.resolve(expanded);
91
+ }
92
+ return path.resolve(safeHomedir(), expanded);
93
+ }
94
+
95
+ /**
96
+ * Resolve `AIFABRIX_CONFIG`: same rules as home-like (bare `foo/bar.yaml` → under ~).
97
+ *
98
+ * @param {string} raw
99
+ * @returns {string}
100
+ */
101
+ function resolveAifabrixConfigEnvPath(raw) {
102
+ return resolveAifabrixHomeLikePath(raw);
103
+ }
104
+
105
+ /**
106
+ * @returns {string} Absolute directory containing `config.yaml`
107
+ */
108
+ function getAifabrixRuntimeConfigDir() {
109
+ if (process.env.AIFABRIX_CONFIG && typeof process.env.AIFABRIX_CONFIG === 'string') {
110
+ const resolved = resolveAifabrixConfigEnvPath(process.env.AIFABRIX_CONFIG.trim());
111
+ return path.dirname(resolved);
112
+ }
113
+ if (process.env.AIFABRIX_HOME && typeof process.env.AIFABRIX_HOME === 'string') {
114
+ const homeDir = resolveAifabrixHomeLikePath(process.env.AIFABRIX_HOME.trim());
115
+ const directConfig = path.join(homeDir, 'config.yaml');
116
+ if (existsSync(directConfig)) {
117
+ return homeDir;
118
+ }
119
+ const nestedConfig = path.join(homeDir, '.aifabrix', 'config.yaml');
120
+ if (existsSync(nestedConfig)) {
121
+ return path.join(homeDir, '.aifabrix');
122
+ }
123
+ return homeDir;
124
+ }
125
+ return path.join(safeHomedir(), '.aifabrix');
126
+ }
127
+
128
+ module.exports = {
129
+ getAifabrixRuntimeConfigDir,
130
+ resolveAifabrixHomeLikePath,
131
+ resolveAifabrixConfigEnvPath
132
+ };
@@ -10,7 +10,7 @@
10
10
  * @version 2.0.0
11
11
  */
12
12
 
13
- const chalk = require('chalk');
13
+ const { formatBlockingError } = require('./cli-test-layout-chalk');
14
14
  const { parseErrorResponse } = require('./error-formatters/error-parser');
15
15
  const { formatPermissionError } = require('./error-formatters/permission-errors');
16
16
  const { formatValidationError } = require('./error-formatters/validation-errors');
@@ -30,7 +30,7 @@ const { formatNetworkError } = require('./error-formatters/network-errors');
30
30
  */
31
31
  function formatApiError(apiResponse, controllerUrl = null) {
32
32
  if (!apiResponse || apiResponse.success !== false) {
33
- return chalk.red('Unknown error occurred');
33
+ return formatBlockingError('Unknown error occurred');
34
34
  }
35
35
 
36
36
  // Use formattedError if already available
package/lib/utils/api.js CHANGED
@@ -16,6 +16,26 @@ const auditLogger = require('../core/audit-logger');
16
16
  /** Default timeout for HTTP requests (ms). Prevents hanging when the controller is unreachable. 30s allows Azure Web App cold start to complete. */
17
17
  const DEFAULT_REQUEST_TIMEOUT_MS = 30000;
18
18
 
19
+ /** Cap for optional per-request ``timeoutMs`` (validation run E2E can block on one POST). */
20
+ const MAX_SINGLE_REQUEST_TIMEOUT_MS = 45 * 60 * 1000;
21
+
22
+ /**
23
+ * Resolve per-request AbortSignal timeout from fetch options.
24
+ * @param {Object} options - Same object passed to fetch (may include timeoutMs / requestTimeoutMs)
25
+ * @returns {number}
26
+ */
27
+ function resolveSingleRequestTimeoutMs(options) {
28
+ const raw = options?.requestTimeoutMs ?? options?.timeoutMs;
29
+ if (raw === undefined || raw === null || raw === '') {
30
+ return DEFAULT_REQUEST_TIMEOUT_MS;
31
+ }
32
+ const n = typeof raw === 'number' ? raw : parseInt(String(raw), 10);
33
+ if (!Number.isFinite(n) || n <= 0) {
34
+ return DEFAULT_REQUEST_TIMEOUT_MS;
35
+ }
36
+ return Math.min(n, MAX_SINGLE_REQUEST_TIMEOUT_MS);
37
+ }
38
+
19
39
  /**
20
40
  * Logs API request performance metrics and errors to audit log
21
41
  * @param {Object} params - Performance logging parameters
@@ -169,6 +189,51 @@ function validateUrl(url, urlType = 'URL') {
169
189
  }
170
190
  }
171
191
 
192
+ /**
193
+ * Flattens Error.message and nested error.cause (Node fetch/undici wraps TLS errors under cause).
194
+ * @param {Error} error - Network error
195
+ * @returns {string} Combined detail for parsing and SSL detection
196
+ */
197
+ function flattenNetworkErrorDetail(error) {
198
+ if (!error) return '';
199
+ const parts = [];
200
+ let e = error;
201
+ let depth = 0;
202
+ const maxDepth = 12;
203
+ while (e && depth < maxDepth) {
204
+ if (typeof e === 'string') {
205
+ parts.push(e);
206
+ break;
207
+ }
208
+ if (e.message) parts.push(e.message);
209
+ if (e.code !== undefined && e.code !== null && String(e.code) !== e.message) {
210
+ parts.push(String(e.code));
211
+ }
212
+ e = e.cause;
213
+ depth++;
214
+ }
215
+ return parts.filter(Boolean).join(' ');
216
+ }
217
+
218
+ /**
219
+ * Adds URL context to validation / empty-URL network errors.
220
+ * @param {string} errorMessage - Base message
221
+ * @param {string} url - Request URL
222
+ * @returns {string}
223
+ */
224
+ function withUrlContextForNetworkError(errorMessage, url) {
225
+ if (errorMessage && (errorMessage.includes('cannot be empty') || errorMessage.includes('is required'))) {
226
+ if (!url || !url.trim()) {
227
+ return `${errorMessage} (URL was: ${JSON.stringify(url)})`;
228
+ }
229
+ return `${errorMessage} (URL was: ${url})`;
230
+ }
231
+ if (!url || !url.trim()) {
232
+ return `Invalid or missing URL. ${errorMessage} (URL was: ${JSON.stringify(url)})`;
233
+ }
234
+ return errorMessage;
235
+ }
236
+
172
237
  /**
173
238
  * Handles network error from API call
174
239
  * @async
@@ -180,19 +245,8 @@ function validateUrl(url, urlType = 'URL') {
180
245
  * @returns {Promise<Object>} Error response object
181
246
  */
182
247
  async function handleNetworkError(error, url, options, duration) {
183
- // Enhance error message with URL information if URL is missing or invalid
184
- let errorMessage = error.message;
185
- if (errorMessage && (errorMessage.includes('cannot be empty') || errorMessage.includes('is required'))) {
186
- // Add URL context to validation errors
187
- if (!url || !url.trim()) {
188
- errorMessage = `${errorMessage} (URL was: ${JSON.stringify(url)})`;
189
- } else {
190
- errorMessage = `${errorMessage} (URL was: ${url})`;
191
- }
192
- } else if (!url || !url.trim()) {
193
- // If URL is empty but error doesn't mention it, add context
194
- errorMessage = `Invalid or missing URL. ${errorMessage} (URL was: ${JSON.stringify(url)})`;
195
- }
248
+ const flat = flattenNetworkErrorDetail(error);
249
+ const errorMessage = withUrlContextForNetworkError(flat || error.message, url);
196
250
 
197
251
  const parsedError = parseErrorResponse(errorMessage, 0, true);
198
252
 
@@ -235,15 +289,18 @@ async function handleNetworkError(error, url, options, duration) {
235
289
  errorData: errorData,
236
290
  errorType: parsedError.type,
237
291
  formattedError: parsedError.formatted,
238
- network: true
292
+ network: true,
293
+ originalError: error
239
294
  };
240
295
  }
241
296
 
242
297
  /**
243
298
  * Make an API call with proper error handling
244
- * Uses a 30s timeout to avoid hanging when the controller is unreachable (Azure cold start can exceed 5s).
299
+ * Uses a 30s timeout by default. Pass ``options.timeoutMs`` or ``options.requestTimeoutMs`` for
300
+ * longer single requests (e.g. dataplane validation run E2E POST); capped at 45 minutes.
245
301
  * @param {string} url - API endpoint URL
246
302
  * @param {Object} options - Fetch options (signal, method, headers, body, etc.)
303
+ * @param {number} [options.timeoutMs] - Optional per-request timeout (ms) when ``signal`` omitted
247
304
  * @returns {Promise<Object>} Response object with success flag
248
305
  */
249
306
  async function makeApiCall(url, options = {}) {
@@ -257,9 +314,12 @@ async function makeApiCall(url, options = {}) {
257
314
 
258
315
  const startTime = Date.now();
259
316
  const fetchOptions = { ...options };
317
+ const singleRequestTimeoutMs = resolveSingleRequestTimeoutMs(fetchOptions);
260
318
  if (!fetchOptions.signal) {
261
- fetchOptions.signal = AbortSignal.timeout(DEFAULT_REQUEST_TIMEOUT_MS);
319
+ fetchOptions.signal = AbortSignal.timeout(singleRequestTimeoutMs);
262
320
  }
321
+ delete fetchOptions.timeoutMs;
322
+ delete fetchOptions.requestTimeoutMs;
263
323
 
264
324
  try {
265
325
  const response = await fetch(url, fetchOptions);
@@ -274,7 +334,7 @@ async function makeApiCall(url, options = {}) {
274
334
  const duration = Date.now() - startTime;
275
335
  const error = err?.name === 'AbortError'
276
336
  ? new Error(
277
- `Request timed out after ${DEFAULT_REQUEST_TIMEOUT_MS / 1000} seconds. The controller may be unreachable. Check the URL and network.`
337
+ `Request timed out after ${Math.round(singleRequestTimeoutMs / 1000)} seconds. The controller may be unreachable. Check the URL and network.`
278
338
  )
279
339
  : err;
280
340
  return await handleNetworkError(error, url, options, duration);
@@ -1,3 +1,4 @@
1
+ const { formatBlockingError } = require('./cli-test-layout-chalk');
1
2
  /**
2
3
  * AI Fabrix Builder - App Register API Utilities
3
4
  *
@@ -72,7 +73,7 @@ function extractApplicationData(response, apiUrl) {
72
73
  }
73
74
 
74
75
  // Fallback: return apiResponse as-is (shouldn't happen, but handle gracefully)
75
- logger.error(chalk.red('Invalid response: missing application data'));
76
+ logger.error(formatBlockingError('Invalid response: missing application data'));
76
77
  logger.error(chalk.gray(`\nController URL: ${apiUrl}`));
77
78
  logger.error(chalk.gray('\nFull response for debugging:'));
78
79
  logger.error(chalk.gray(JSON.stringify(response, null, 2)));
@@ -93,7 +94,7 @@ async function callRegisterApi(apiUrl, token, environment, registrationData) {
93
94
  return extractApplicationData(response, apiUrl);
94
95
  } catch (error) {
95
96
  // Include controller URL in error context
96
- logger.error(chalk.red('Registration API call failed'));
97
+ logger.error(formatBlockingError('Registration API call failed'));
97
98
  logger.error(chalk.gray(`Controller URL: ${apiUrl}`));
98
99
  logger.error(chalk.gray(`Error: ${error.message}`));
99
100
  throw error;
@@ -108,7 +108,7 @@ async function tryGetDeviceTokenForController(controllerUrl, attemptedUrls) {
108
108
  };
109
109
  }
110
110
  } catch (error) {
111
- logger.warn(chalk.yellow(`⚠️ Failed to get token for controller ${controllerUrl}: ${error.message}`));
111
+ logger.warn(chalk.yellow(`⚠ Failed to get token for controller ${controllerUrl}: ${error.message}`));
112
112
  return { error };
113
113
  }
114
114
  return null;
@@ -13,7 +13,7 @@ const chalk = require('chalk');
13
13
  const logger = require('./logger');
14
14
  const { detectAppType, resolveApplicationConfigPath } = require('./paths');
15
15
  const { loadConfigFile } = require('./config-format');
16
- const { getContainerPort, getLocalPort } = require('./port-resolver');
16
+ const { getContainerPort } = require('./port-resolver');
17
17
 
18
18
  // createApp is imported dynamically in createMinimalAppIfNeeded to handle test mocking
19
19
 
@@ -32,7 +32,7 @@ async function loadVariablesYaml(appKey) {
32
32
  } catch (error) {
33
33
  const isNotFound = error.code === 'ENOENT' || (error.message && error.message.includes('not found'));
34
34
  if (isNotFound) {
35
- logger.log(chalk.yellow(`⚠️ Application config not found for ${appKey}`));
35
+ logger.log(chalk.yellow(`⚠ Application config not found for ${appKey}`));
36
36
  logger.log(chalk.yellow('📝 Creating minimal configuration...\n'));
37
37
  return { variables: null, created: true };
38
38
  }
@@ -230,8 +230,8 @@ async function extractExternalAppConfiguration(appKey, variables, appKeyFromFile
230
230
  function extractWebappConfiguration(variables, appKeyFromFile, displayName, description, options) {
231
231
  const appType = variables.build?.language === 'typescript' ? 'webapp' : 'service';
232
232
  const registryMode = variables.image?.registryMode || 'external';
233
- const port = options.port ?? getContainerPort(variables, 3000);
234
- const localPort = getLocalPort(variables, port);
233
+ const port = options.port ?? getContainerPort(variables);
234
+ const localPort = port;
235
235
  const language = variables.build?.language || 'typescript';
236
236
  const image = buildImageReference(variables, appKeyFromFile);
237
237
  const url = variables.app?.url || variables.deployment?.dataplaneUrl || variables.deployment?.appUrl || null;
@@ -1,3 +1,4 @@
1
+ const { formatSuccessLine } = require('./cli-test-layout-chalk');
1
2
  /**
2
3
  * AI Fabrix Builder - App Register Display Utilities
3
4
  *
@@ -63,7 +64,7 @@ function resolveDisplayName(application, requestedDisplayName) {
63
64
  */
64
65
  function displayRegistrationResults(data, apiUrl, environment, requestedDisplayName) {
65
66
  const displayName = resolveDisplayName(data.application, requestedDisplayName);
66
- logger.log(chalk.green('Application registered successfully!\n'));
67
+ logger.log(formatSuccessLine('Application registered successfully!\n'));
67
68
  logger.log(chalk.bold('📋 Application Details:'));
68
69
  logger.log(` ID: ${data.application.id}`);
69
70
  logger.log(` Key: ${data.application.key}`);
@@ -74,7 +75,7 @@ function displayRegistrationResults(data, apiUrl, environment, requestedDisplayN
74
75
  logger.log(chalk.yellow(` Client ID: ${data.credentials.clientId}`));
75
76
  logger.log(chalk.yellow(` Client Secret: ${data.credentials.clientSecret}\n`));
76
77
 
77
- logger.log(chalk.red('⚠️ IMPORTANT: Client Secret will not be shown again!\n'));
78
+ logger.log(chalk.red(' IMPORTANT: Client Secret will not be shown again!\n'));
78
79
 
79
80
  const envPrefix = getEnvironmentPrefix(environment);
80
81
  logger.log(chalk.bold('📝 Add to GitHub Secrets:'));
@@ -1,3 +1,4 @@
1
+ const { formatBlockingError } = require('./cli-test-layout-chalk');
1
2
  /**
2
3
  * AI Fabrix Builder - App Register Validation Utilities
3
4
  *
@@ -114,7 +115,7 @@ async function validateAppRegistrationData(config, originalAppKey) {
114
115
  if (!config.displayName) missingFields.push('app.name');
115
116
 
116
117
  if (missingFields.length > 0) {
117
- logger.error(chalk.red('Missing required fields in application.yaml:'));
118
+ logger.error(formatBlockingError('Missing required fields in application.yaml:'));
118
119
  missingFields.forEach(field => logger.error(chalk.red(` - ${field}`)));
119
120
  // Detect app type to show correct path
120
121
  const { appPath } = await detectAppType(originalAppKey);
@@ -134,7 +135,7 @@ async function validateAppRegistrationData(config, originalAppKey) {
134
135
  externalIntegration: config.externalIntegration
135
136
  });
136
137
  } catch (error) {
137
- logger.error(chalk.red(`❌ Invalid configuration: ${error.message}`));
138
+ logger.error(formatBlockingError(`Invalid configuration: ${error.message}`));
138
139
  process.exit(1);
139
140
  }
140
141
  }