@aifabrix/builder 2.43.0 → 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 (346) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/README.md +1 -1
  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 +31 -0
  7. package/integration/hubspot-test/create-hubspot.js +5 -5
  8. package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
  9. package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
  10. package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
  11. package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
  12. package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
  13. package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
  14. package/integration/hubspot-test/test-dataplane-down.js +3 -3
  15. package/integration/hubspot-test/test.js +35 -43
  16. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  17. package/integration/roundtrip-test-local/README.md +144 -0
  18. package/integration/roundtrip-test-local/application.yaml +13 -0
  19. package/integration/roundtrip-test-local/env.template +15 -0
  20. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  21. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  22. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  23. package/integration/roundtrip-test-local2/README.md +144 -0
  24. package/integration/roundtrip-test-local2/application.yaml +13 -0
  25. package/integration/roundtrip-test-local2/env.template +15 -0
  26. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  27. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  28. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  29. package/integration/test/wizard.yaml +8 -0
  30. package/jest.config.default.js +10 -0
  31. package/jest.config.integration.fixtures.js +22 -0
  32. package/jest.config.integration.js +21 -18
  33. package/jest.config.isolated.js +10 -0
  34. package/jest.projects.js +288 -0
  35. package/lib/api/datasources-core.api.js +3 -3
  36. package/lib/api/dev-mtls-request.js +110 -0
  37. package/lib/api/dev-server-https.js +145 -0
  38. package/lib/api/dev.api.js +133 -144
  39. package/lib/api/index.js +0 -1
  40. package/lib/api/pipeline.api.js +67 -20
  41. package/lib/api/types/dev.types.js +4 -3
  42. package/lib/api/types/pipeline.types.js +8 -5
  43. package/lib/api/types/validation-run.types.js +56 -0
  44. package/lib/api/validation-run.api.js +99 -0
  45. package/lib/api/validation-runner.js +99 -0
  46. package/lib/app/config.js +1 -1
  47. package/lib/app/deploy-status-display.js +2 -2
  48. package/lib/app/deploy.js +7 -6
  49. package/lib/app/display.js +2 -1
  50. package/lib/app/dockerfile.js +3 -2
  51. package/lib/app/down.js +2 -1
  52. package/lib/app/helpers.js +6 -5
  53. package/lib/app/index.js +27 -8
  54. package/lib/app/list.js +7 -6
  55. package/lib/app/push.js +4 -3
  56. package/lib/app/register.js +16 -7
  57. package/lib/app/rotate-secret.js +14 -13
  58. package/lib/app/run-container-start.js +184 -0
  59. package/lib/app/run-docker-fallback.js +108 -0
  60. package/lib/app/run-env-compose.js +30 -42
  61. package/lib/app/run-helpers.js +49 -126
  62. package/lib/app/run-infra-requirements.js +30 -0
  63. package/lib/app/run-resolve-image.js +21 -0
  64. package/lib/app/run.js +74 -21
  65. package/lib/app/show-display.js +1 -1
  66. package/lib/app/show.js +1 -1
  67. package/lib/build/index.js +13 -10
  68. package/lib/cli/index.js +2 -0
  69. package/lib/cli/setup-app.help.js +67 -0
  70. package/lib/cli/setup-app.js +57 -121
  71. package/lib/cli/setup-app.test-commands.js +179 -0
  72. package/lib/cli/setup-auth.js +19 -5
  73. package/lib/cli/setup-credential-deployment.js +22 -8
  74. package/lib/cli/setup-dev-path-commands.js +124 -0
  75. package/lib/cli/setup-dev.js +170 -113
  76. package/lib/cli/setup-environment.js +7 -1
  77. package/lib/cli/setup-external-system.js +62 -22
  78. package/lib/cli/setup-infra.js +126 -47
  79. package/lib/cli/setup-parameters.js +32 -0
  80. package/lib/cli/setup-secrets.js +106 -8
  81. package/lib/cli/setup-service-user.js +1 -1
  82. package/lib/cli/setup-utility.js +36 -20
  83. package/lib/commands/app-down.js +5 -7
  84. package/lib/commands/app-install.js +14 -7
  85. package/lib/commands/app-logs.js +13 -10
  86. package/lib/commands/app-shell.js +4 -1
  87. package/lib/commands/app-test.js +25 -19
  88. package/lib/commands/app.js +22 -10
  89. package/lib/commands/auth-config.js +6 -6
  90. package/lib/commands/auth-status.js +4 -3
  91. package/lib/commands/credential-env.js +4 -3
  92. package/lib/commands/credential-list.js +5 -4
  93. package/lib/commands/credential-push.js +4 -3
  94. package/lib/commands/datasource-unified-test-cli.js +495 -0
  95. package/lib/commands/datasource-unified-test-cli.options.js +149 -0
  96. package/lib/commands/datasource-validation-cli.js +129 -0
  97. package/lib/commands/datasource.js +105 -98
  98. package/lib/commands/deployment-list.js +6 -5
  99. package/lib/commands/dev-cli-handlers.js +122 -18
  100. package/lib/commands/dev-down.js +4 -3
  101. package/lib/commands/dev-init.js +231 -116
  102. package/lib/commands/dev-show-display.js +473 -0
  103. package/lib/commands/login-credentials.js +3 -2
  104. package/lib/commands/login-device.js +4 -3
  105. package/lib/commands/login.js +5 -4
  106. package/lib/commands/logout.js +8 -7
  107. package/lib/commands/parameters-validate.js +54 -0
  108. package/lib/commands/repair-datasource.js +314 -68
  109. package/lib/commands/repair-env-template.js +2 -2
  110. package/lib/commands/repair.js +21 -3
  111. package/lib/commands/secrets-list.js +23 -12
  112. package/lib/commands/secrets-remove-all.js +220 -0
  113. package/lib/commands/secrets-remove.js +21 -12
  114. package/lib/commands/secrets-set.js +21 -12
  115. package/lib/commands/secrets-validate.js +4 -4
  116. package/lib/commands/secure.js +10 -9
  117. package/lib/commands/service-user.js +26 -25
  118. package/lib/commands/test-e2e-external.js +27 -1
  119. package/lib/commands/up-common.js +3 -2
  120. package/lib/commands/up-dataplane.js +29 -16
  121. package/lib/commands/up-miso.js +19 -29
  122. package/lib/commands/upload.js +138 -39
  123. package/lib/commands/wizard-core-helpers.js +1 -1
  124. package/lib/commands/wizard-dataplane.js +4 -3
  125. package/lib/commands/wizard-helpers.js +3 -3
  126. package/lib/commands/wizard.js +2 -2
  127. package/lib/core/admin-secrets.js +14 -5
  128. package/lib/core/audit-logger.js +12 -4
  129. package/lib/core/config-attach-extensions.js +46 -0
  130. package/lib/core/config-runtime-paths.js +29 -0
  131. package/lib/core/config.js +55 -56
  132. package/lib/core/diff.js +3 -2
  133. package/lib/core/ensure-encryption-key.js +1 -1
  134. package/lib/core/secrets-ensure-infra.js +77 -0
  135. package/lib/core/secrets-ensure.js +120 -64
  136. package/lib/core/secrets-env-write.js +35 -7
  137. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  138. package/lib/core/secrets.js +200 -37
  139. package/lib/core/templates-env.js +4 -3
  140. package/lib/datasource/abac-validator.js +1 -10
  141. package/lib/datasource/deploy.js +75 -53
  142. package/lib/datasource/field-reference-validator.js +9 -6
  143. package/lib/datasource/integration-context.js +63 -0
  144. package/lib/datasource/list.js +8 -7
  145. package/lib/datasource/log-viewer.js +84 -53
  146. package/lib/datasource/resolve-app.js +4 -4
  147. package/lib/datasource/test-e2e.js +95 -146
  148. package/lib/datasource/test-integration.js +114 -122
  149. package/lib/datasource/unified-validation-run-body.js +65 -0
  150. package/lib/datasource/unified-validation-run-post.js +23 -0
  151. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  152. package/lib/datasource/unified-validation-run.js +92 -0
  153. package/lib/datasource/validate.js +157 -13
  154. package/lib/deployment/deployer.js +4 -3
  155. package/lib/deployment/environment.js +7 -6
  156. package/lib/deployment/push.js +17 -8
  157. package/lib/external-system/delete.js +4 -3
  158. package/lib/external-system/deploy.js +131 -53
  159. package/lib/external-system/download-helpers.js +1 -1
  160. package/lib/external-system/download.js +7 -6
  161. package/lib/external-system/generator.js +92 -6
  162. package/lib/external-system/integration-test-dispatch.js +26 -0
  163. package/lib/external-system/test-execution.js +5 -1
  164. package/lib/external-system/test-helpers.js +0 -4
  165. package/lib/external-system/test-system-level-helpers.js +110 -0
  166. package/lib/external-system/test-system-level.js +83 -44
  167. package/lib/external-system/test.js +59 -8
  168. package/lib/generator/builders.js +23 -11
  169. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  170. package/lib/generator/external.js +16 -4
  171. package/lib/generator/helpers.js +58 -3
  172. package/lib/generator/index.js +4 -0
  173. package/lib/generator/split-readme.js +12 -7
  174. package/lib/generator/split-variables.js +2 -1
  175. package/lib/generator/split.js +1 -1
  176. package/lib/generator/wizard-readme.js +3 -3
  177. package/lib/generator/wizard.js +8 -8
  178. package/lib/infrastructure/compose.js +60 -6
  179. package/lib/infrastructure/helpers.js +201 -29
  180. package/lib/infrastructure/index.js +28 -17
  181. package/lib/infrastructure/services.js +21 -15
  182. package/lib/internal/fs-real-sync.js +104 -0
  183. package/lib/internal/node-fs.js +98 -0
  184. package/lib/parameters/database-secret-values.js +173 -0
  185. package/lib/parameters/infra-kv-discovery.js +121 -0
  186. package/lib/parameters/infra-parameter-catalog.js +458 -0
  187. package/lib/parameters/infra-parameter-validate.js +64 -0
  188. package/lib/schema/application-schema.json +37 -17
  189. package/lib/schema/datasource-test-run.schema.json +493 -0
  190. package/lib/schema/deployment-rules.yaml +102 -63
  191. package/lib/schema/external-datasource.schema.json +1200 -442
  192. package/lib/schema/external-system.schema.json +181 -5
  193. package/lib/schema/flag-map-validation-run.json +31 -0
  194. package/lib/schema/infra-parameter.schema.json +106 -0
  195. package/lib/schema/infra.parameter.yaml +421 -0
  196. package/lib/schema/type/credential-auth-templates.json +40 -0
  197. package/lib/schema/type/document-storage.json +213 -0
  198. package/lib/schema/type/message-service.json +123 -0
  199. package/lib/schema/type/vector-store.json +88 -0
  200. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  201. package/lib/utils/api-error-handler.js +2 -2
  202. package/lib/utils/api.js +49 -14
  203. package/lib/utils/app-register-api.js +3 -2
  204. package/lib/utils/app-register-auth.js +1 -1
  205. package/lib/utils/app-register-config.js +4 -4
  206. package/lib/utils/app-register-display.js +3 -2
  207. package/lib/utils/app-register-validator.js +3 -2
  208. package/lib/utils/app-run-containers.js +26 -22
  209. package/lib/utils/app-scoped-config.js +31 -0
  210. package/lib/utils/app-service-env-from-builder.js +164 -0
  211. package/lib/utils/build-copy.js +1 -1
  212. package/lib/utils/build-helpers.js +20 -20
  213. package/lib/utils/build-resolve-image.js +165 -0
  214. package/lib/utils/cli-layout-chalk.js +8 -0
  215. package/lib/utils/cli-test-layout-chalk.js +267 -0
  216. package/lib/utils/cli-utils.js +88 -11
  217. package/lib/utils/compose-db-passwords.js +138 -0
  218. package/lib/utils/compose-generate-docker-compose.js +216 -0
  219. package/lib/utils/compose-generator.js +197 -291
  220. package/lib/utils/compose-miso-env.js +18 -0
  221. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  222. package/lib/utils/config-paths.js +166 -7
  223. package/lib/utils/config-scoped-resources-preference.js +41 -0
  224. package/lib/utils/controller-deployment-outcome.js +68 -0
  225. package/lib/utils/credential-display.js +2 -2
  226. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  227. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  228. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  229. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  230. package/lib/utils/datasource-test-run-display.js +442 -0
  231. package/lib/utils/datasource-test-run-exit.js +58 -0
  232. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  233. package/lib/utils/datasource-test-run-report-version.js +51 -0
  234. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  235. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  236. package/lib/utils/datasource-validation-watch.js +266 -0
  237. package/lib/utils/declarative-url-ports.js +47 -0
  238. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  239. package/lib/utils/dev-ca-install.js +185 -23
  240. package/lib/utils/dev-cert-helper.js +266 -17
  241. package/lib/utils/dev-hosts-helper.js +307 -0
  242. package/lib/utils/dev-init-cert-hints.js +37 -0
  243. package/lib/utils/dev-init-health-messages.js +52 -0
  244. package/lib/utils/dev-init-resolve.js +86 -0
  245. package/lib/utils/dev-init-ssh-merge.js +65 -0
  246. package/lib/utils/dev-ssh-config-helper.js +196 -0
  247. package/lib/utils/dev-user-groups.js +93 -0
  248. package/lib/utils/docker-build.js +42 -17
  249. package/lib/utils/docker-exec.js +28 -0
  250. package/lib/utils/docker-manifest-public-port.js +116 -0
  251. package/lib/utils/docker-not-running-hint.js +52 -0
  252. package/lib/utils/docker.js +98 -11
  253. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  254. package/lib/utils/env-config-loader.js +10 -91
  255. package/lib/utils/env-copy.js +19 -10
  256. package/lib/utils/env-map.js +35 -8
  257. package/lib/utils/env-template.js +2 -2
  258. package/lib/utils/environment-scoped-resources.js +144 -0
  259. package/lib/utils/error-formatter.js +92 -13
  260. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  261. package/lib/utils/error-formatters/network-errors.js +2 -1
  262. package/lib/utils/error-formatters/permission-errors.js +2 -1
  263. package/lib/utils/error-formatters/validation-errors.js +2 -1
  264. package/lib/utils/external-readme.js +8 -1
  265. package/lib/utils/external-system-display.js +234 -136
  266. package/lib/utils/external-system-local-test-tty.js +389 -0
  267. package/lib/utils/external-system-readiness-core.js +377 -0
  268. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  269. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  270. package/lib/utils/external-system-readiness-display.js +186 -0
  271. package/lib/utils/external-system-test-helpers.js +24 -6
  272. package/lib/utils/external-system-validators.js +30 -12
  273. package/lib/utils/health-check-url.js +119 -0
  274. package/lib/utils/health-check.js +59 -25
  275. package/lib/utils/help-builder.js +11 -8
  276. package/lib/utils/image-version.js +4 -8
  277. package/lib/utils/infra-containers.js +4 -7
  278. package/lib/utils/infra-env-defaults.js +162 -0
  279. package/lib/utils/infra-status-display.js +167 -0
  280. package/lib/utils/infra-status.js +16 -8
  281. package/lib/utils/local-secrets.js +3 -4
  282. package/lib/utils/paths.js +134 -47
  283. package/lib/utils/port-resolver.js +10 -23
  284. package/lib/utils/redis-env-scope.js +62 -0
  285. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  286. package/lib/utils/remote-builder-validation.js +99 -0
  287. package/lib/utils/remote-dev-auth.js +117 -21
  288. package/lib/utils/remote-docker-env.js +67 -15
  289. package/lib/utils/remote-secrets-loader.js +13 -4
  290. package/lib/utils/resolve-docker-image-ref.js +124 -0
  291. package/lib/utils/schema-loader.js +22 -9
  292. package/lib/utils/secrets-bash-kv.js +25 -0
  293. package/lib/utils/secrets-generator.js +169 -49
  294. package/lib/utils/secrets-helpers.js +70 -59
  295. package/lib/utils/secrets-kv-scope.js +60 -0
  296. package/lib/utils/secrets-utils.js +32 -38
  297. package/lib/utils/secrets-validation.js +3 -1
  298. package/lib/utils/secrets-yaml-preserve.js +109 -0
  299. package/lib/utils/ssh-key-helper.js +4 -2
  300. package/lib/utils/template-helpers.js +2 -2
  301. package/lib/utils/test-log-writer.js +3 -3
  302. package/lib/utils/token-manager.js +1 -2
  303. package/lib/utils/url-declarative-public-base.js +188 -0
  304. package/lib/utils/url-declarative-resolve-build.js +493 -0
  305. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  306. package/lib/utils/url-declarative-resolve.js +220 -0
  307. package/lib/utils/url-declarative-token-parse.js +74 -0
  308. package/lib/utils/url-declarative-url-flags.js +50 -0
  309. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  310. package/lib/utils/url-public-path-prefix.js +34 -0
  311. package/lib/utils/urls-local-registry.js +220 -0
  312. package/lib/utils/validation-report-tty-kit.js +77 -0
  313. package/lib/utils/validation-run-poll.js +89 -0
  314. package/lib/utils/validation-run-post-retry.js +73 -0
  315. package/lib/utils/validation-run-request.js +98 -0
  316. package/lib/utils/variable-transformer.js +21 -4
  317. package/lib/utils/yaml-preserve.js +33 -14
  318. package/lib/validation/datasource-warnings.js +56 -0
  319. package/lib/validation/env-template-auth.js +1 -1
  320. package/lib/validation/external-manifest-validator.js +27 -7
  321. package/lib/validation/validate-display.js +37 -31
  322. package/lib/validation/validate.js +4 -13
  323. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  324. package/lib/validation/validator.js +22 -65
  325. package/lib/validation/wizard-config-validator.js +2 -1
  326. package/package.json +7 -3
  327. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  328. package/scripts/diagnose-cli.js +150 -0
  329. package/scripts/install-local.js +304 -55
  330. package/templates/README.md +15 -2
  331. package/templates/applications/dataplane/application.yaml +52 -2
  332. package/templates/applications/dataplane/env.template +75 -17
  333. package/templates/applications/dataplane/rbac.yaml +8 -0
  334. package/templates/applications/keycloak/application.yaml +9 -1
  335. package/templates/applications/keycloak/env.template +15 -6
  336. package/templates/applications/miso-controller/application.yaml +10 -2
  337. package/templates/applications/miso-controller/env.template +42 -12
  338. package/templates/applications/miso-controller/rbac.yaml +5 -0
  339. package/templates/external-system/README.md.hbs +20 -7
  340. package/templates/external-system/deploy.js.hbs +5 -5
  341. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  342. package/templates/infra/compose.yaml.hbs +20 -4
  343. package/templates/python/docker-compose.hbs +16 -0
  344. package/templates/typescript/docker-compose.hbs +16 -0
  345. package/lib/api/external-test.api.js +0 -111
  346. 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
@@ -169,6 +169,51 @@ function validateUrl(url, urlType = 'URL') {
169
169
  }
170
170
  }
171
171
 
172
+ /**
173
+ * Flattens Error.message and nested error.cause (Node fetch/undici wraps TLS errors under cause).
174
+ * @param {Error} error - Network error
175
+ * @returns {string} Combined detail for parsing and SSL detection
176
+ */
177
+ function flattenNetworkErrorDetail(error) {
178
+ if (!error) return '';
179
+ const parts = [];
180
+ let e = error;
181
+ let depth = 0;
182
+ const maxDepth = 12;
183
+ while (e && depth < maxDepth) {
184
+ if (typeof e === 'string') {
185
+ parts.push(e);
186
+ break;
187
+ }
188
+ if (e.message) parts.push(e.message);
189
+ if (e.code !== undefined && e.code !== null && String(e.code) !== e.message) {
190
+ parts.push(String(e.code));
191
+ }
192
+ e = e.cause;
193
+ depth++;
194
+ }
195
+ return parts.filter(Boolean).join(' ');
196
+ }
197
+
198
+ /**
199
+ * Adds URL context to validation / empty-URL network errors.
200
+ * @param {string} errorMessage - Base message
201
+ * @param {string} url - Request URL
202
+ * @returns {string}
203
+ */
204
+ function withUrlContextForNetworkError(errorMessage, url) {
205
+ if (errorMessage && (errorMessage.includes('cannot be empty') || errorMessage.includes('is required'))) {
206
+ if (!url || !url.trim()) {
207
+ return `${errorMessage} (URL was: ${JSON.stringify(url)})`;
208
+ }
209
+ return `${errorMessage} (URL was: ${url})`;
210
+ }
211
+ if (!url || !url.trim()) {
212
+ return `Invalid or missing URL. ${errorMessage} (URL was: ${JSON.stringify(url)})`;
213
+ }
214
+ return errorMessage;
215
+ }
216
+
172
217
  /**
173
218
  * Handles network error from API call
174
219
  * @async
@@ -180,19 +225,8 @@ function validateUrl(url, urlType = 'URL') {
180
225
  * @returns {Promise<Object>} Error response object
181
226
  */
182
227
  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
- }
228
+ const flat = flattenNetworkErrorDetail(error);
229
+ const errorMessage = withUrlContextForNetworkError(flat || error.message, url);
196
230
 
197
231
  const parsedError = parseErrorResponse(errorMessage, 0, true);
198
232
 
@@ -235,7 +269,8 @@ async function handleNetworkError(error, url, options, duration) {
235
269
  errorData: errorData,
236
270
  errorType: parsedError.type,
237
271
  formattedError: parsedError.formatted,
238
- network: true
272
+ network: true,
273
+ originalError: error
239
274
  };
240
275
  }
241
276
 
@@ -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
  }