@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
@@ -23,8 +23,8 @@ const { resolveEnvironment } = require('../../lib/core/config');
23
23
 
24
24
  const execFileAsync = promisify(execFile);
25
25
 
26
- /** Single source for test config: integration/hubspot/.env */
27
- const HUBSPOT_DIR = path.join(process.cwd(), 'integration', 'hubspot');
26
+ /** Single source for test config: integration/hubspot-test/.env */
27
+ const HUBSPOT_DIR = path.join(process.cwd(), 'integration', 'hubspot-test');
28
28
  const LOCAL_ENV_PATH = path.join(HUBSPOT_DIR, '.env');
29
29
  const ARTIFACT_DIR = path.join(HUBSPOT_DIR, 'test-artifacts');
30
30
  const MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
@@ -96,10 +96,10 @@ function printUsage() {
96
96
  // eslint-disable-next-line no-console
97
97
  console.log([
98
98
  'Usage:',
99
- ' node integration/hubspot/test.js',
100
- ' node integration/hubspot/test.js --test "1.1"',
101
- ' node integration/hubspot/test.js --type positive',
102
- ' node integration/hubspot/test.js --type negative --verbose',
99
+ ' node integration/hubspot-test/test.js',
100
+ ' node integration/hubspot-test/test.js --test "1.1"',
101
+ ' node integration/hubspot-test/test.js --type positive',
102
+ ' node integration/hubspot-test/test.js --type negative --verbose',
103
103
  '',
104
104
  'Options:',
105
105
  ' --test <id[,id]> Run specific test IDs',
@@ -266,7 +266,7 @@ async function loadEnvFile(envPath, options) {
266
266
  process.env[key] = value;
267
267
  }
268
268
  }
269
- // Map common .env keys so tests and wizard use credentials from integration/hubspot/.env
269
+ // Map common .env keys so tests and wizard use credentials from integration/hubspot-test/.env
270
270
  if (process.env.CLIENTID && process.env.HUBSPOT_CLIENT_ID === undefined) {
271
271
  process.env.HUBSPOT_CLIENT_ID = process.env.CLIENTID;
272
272
  }
@@ -280,7 +280,7 @@ async function loadEnvFile(envPath, options) {
280
280
 
281
281
  /**
282
282
  * Load test config (controller, environment, dataplane, openapi file).
283
- * Reads integration/hubspot/.env; missing CONTROLLER_URL/ENVIRONMENT fall back to
283
+ * Reads integration/hubspot-test/.env; missing CONTROLLER_URL/ENVIRONMENT fall back to
284
284
  * the same resolution as the CLI (af auth status) so tests use the same controller.
285
285
  * @async
286
286
  * @function loadTestConfigFromEnv
@@ -430,7 +430,7 @@ async function validateAuth(context, options) {
430
430
  throw new Error('Authentication check failed. Run: node bin/aifabrix.js login --controller <url> --method device');
431
431
  }
432
432
  const output = `${result.stdout}\n${result.stderr}`;
433
- // Only treat "Not authenticated" as failure; " Not reachable" (dataplane) is not auth failure
433
+ // Only treat "Not authenticated" as failure; " Not reachable" (dataplane) is not auth failure
434
434
  if (output.includes('Not authenticated')) {
435
435
  throw new Error('Not authenticated. Run: node bin/aifabrix.js login --controller <url> --method device');
436
436
  }
@@ -502,7 +502,20 @@ async function checkAppDirectory(appPath) {
502
502
  }
503
503
 
504
504
  /**
505
- * Validates required files exist
505
+ * Resolves application config path (application.json or application.yaml)
506
+ * @param {string} appPath - Application directory path
507
+ * @returns {string|null} Path to config file or null if neither exists
508
+ */
509
+ async function resolveApplicationConfigPath(appPath) {
510
+ const jsonPath = path.join(appPath, 'application.json');
511
+ const yamlPath = path.join(appPath, 'application.yaml');
512
+ if (await fileExists(jsonPath)) return jsonPath;
513
+ if (await fileExists(yamlPath)) return yamlPath;
514
+ return null;
515
+ }
516
+
517
+ /**
518
+ * Validates required files exist (application config can be application.json or application.yaml)
506
519
  * @async
507
520
  * @function validateRequiredFiles
508
521
  * @param {string} appPath - Application directory path
@@ -511,8 +524,12 @@ async function checkAppDirectory(appPath) {
511
524
  * @throws {Error} If required files are missing
512
525
  */
513
526
  async function validateRequiredFiles(appPath, entries) {
514
- const requiredFiles = ['application.yaml', 'env.template', 'README.md', 'deploy.js'];
527
+ const applicationConfigPath = await resolveApplicationConfigPath(appPath);
528
+ const requiredFiles = ['env.template', 'README.md', 'deploy.js'];
515
529
  const missingFiles = [];
530
+ if (!applicationConfigPath) {
531
+ missingFiles.push('application.yaml or application.json');
532
+ }
516
533
  for (const fileName of requiredFiles) {
517
534
  const filePath = path.join(appPath, fileName);
518
535
  const exists = await fileExists(filePath);
@@ -557,11 +574,19 @@ function validateDeployFiles(appPath, entries) {
557
574
  * @throws {Error} If file contents are invalid
558
575
  */
559
576
  async function validateFileContents(appPath, deployFiles) {
577
+ const configPath = await resolveApplicationConfigPath(appPath);
578
+ if (!configPath) {
579
+ throw new Error('Application config (application.yaml or application.json) not found');
580
+ }
560
581
  try {
561
- const variablesContent = await fs.readFile(path.join(appPath, 'application.yaml'), 'utf8');
562
- yaml.load(variablesContent);
582
+ const content = await fs.readFile(configPath, 'utf8');
583
+ if (configPath.endsWith('.json')) {
584
+ JSON.parse(content);
585
+ } else {
586
+ yaml.load(content);
587
+ }
563
588
  } catch (error) {
564
- throw new Error(`Invalid YAML syntax in application.yaml: ${error.message}`);
589
+ throw new Error(`Invalid syntax in ${path.basename(configPath)}: ${error.message}`);
565
590
  }
566
591
  for (const fileName of deployFiles) {
567
592
  try {
@@ -597,22 +622,23 @@ async function validateGeneratedFiles(appName) {
597
622
  * @returns {Promise<Object>} Snapshot of file contents keyed by path
598
623
  */
599
624
  async function captureExternalSnapshot(appPath) {
600
- const variablesPath = path.join(appPath, 'application.yaml');
601
- const variablesContent = await fs.readFile(variablesPath, 'utf8');
602
- const variables = yaml.load(variablesContent);
625
+ const configPath = await resolveApplicationConfigPath(appPath);
626
+ if (!configPath) {
627
+ throw new Error(`Application config not found in ${appPath}`);
628
+ }
629
+ const content = await fs.readFile(configPath, 'utf8');
630
+ const variables = configPath.endsWith('.json') ? JSON.parse(content) : yaml.load(content);
603
631
 
604
632
  if (!variables || !variables.externalIntegration) {
605
- throw new Error(`externalIntegration block not found in ${variablesPath}`);
633
+ throw new Error(`externalIntegration block not found in ${configPath}`);
606
634
  }
607
635
 
608
- const systemFiles = variables.externalIntegration.systems || [];
609
- const datasourceFiles = variables.externalIntegration.dataSources || [];
610
636
  const fileNames = [
611
- 'application.yaml',
637
+ path.basename(configPath),
612
638
  'env.template',
613
639
  'README.md',
614
- ...systemFiles,
615
- ...datasourceFiles
640
+ ...(variables.externalIntegration.systems || []),
641
+ ...(variables.externalIntegration.dataSources || [])
616
642
  ];
617
643
 
618
644
  const rbacPath = path.join(appPath, 'rbac.yml');
@@ -658,7 +684,7 @@ function compareSnapshots(before, after) {
658
684
  * @returns {boolean} True if test app name
659
685
  */
660
686
  function isTestAppName(appName) {
661
- return appName.startsWith('hubspot-test-');
687
+ return appName.startsWith('wizard-e2e-');
662
688
  }
663
689
 
664
690
  /**
@@ -769,6 +795,20 @@ async function testDownloadAndSplit(appName, context, options) {
769
795
  logSuccess('Download and split workflow validated.');
770
796
  }
771
797
 
798
+ /**
799
+ * Returns a skip message only when the wizard failure is due to dataplane unreachable (no service).
800
+ * Does not skip for auth/session errors when dataplane is up (so tests fail with the real error).
801
+ * @param {string} errorOutput - Combined stdout + stderr from wizard command
802
+ * @returns {string|null} Skip message or null
803
+ */
804
+ function getWizardEnvironmentSkipMessage(errorOutput) {
805
+ if (errorOutput.includes('Failed to discover dataplane URL') ||
806
+ errorOutput.includes('Application not found')) {
807
+ return 'Dataplane service not found in environment. Deploy dataplane service to the controller.';
808
+ }
809
+ return null;
810
+ }
811
+
772
812
  /**
773
813
  * Runs wizard and validates generated files
774
814
  * @async
@@ -778,12 +818,17 @@ async function testDownloadAndSplit(appName, context, options) {
778
818
  * @param {Object} context - Test context
779
819
  * @param {Object} options - Options object
780
820
  * @returns {Promise<void>} Resolves when wizard completes and files are validated
821
+ * @throws {SkipTestError} If wizard fails due to environment (dataplane/auth)
781
822
  * @throws {Error} If wizard fails or validation fails
782
823
  */
783
824
  async function runWizardAndValidate(configPath, appName, context, options) {
784
825
  const result = await runWizard(configPath, context, options);
785
826
  if (!result.success) {
786
827
  const errorOutput = `${result.stdout}\n${result.stderr}`;
828
+ const skipMsg = getWizardEnvironmentSkipMessage(errorOutput);
829
+ if (skipMsg) {
830
+ throw new SkipTestError(skipMsg);
831
+ }
787
832
  throw new Error(`Wizard failed for ${appName}:\n${errorOutput}`);
788
833
  }
789
834
 
@@ -884,18 +929,18 @@ function buildPositiveTestCases(context) {
884
929
  throw new Error(`OpenAPI file not found: ${context.openapiFile}`);
885
930
  }
886
931
  ensureEnvVar('CONTROLLER_URL', context.controllerUrl);
887
- // Try to run wizard - if dataplane discovery fails, skip the test
932
+ // Try to run wizard - if dataplane/auth fails, skip the test
888
933
  const result = await runWizard(configPath, context, options);
889
934
  if (!result.success) {
890
935
  const errorOutput = `${result.stdout}\n${result.stderr}`;
891
- if (errorOutput.includes('Failed to discover dataplane URL') ||
892
- errorOutput.includes('Application not found')) {
893
- throw new SkipTestError('Dataplane service not found in environment. Deploy dataplane service to the controller.');
936
+ const skipMsg = getWizardEnvironmentSkipMessage(errorOutput);
937
+ if (skipMsg) {
938
+ throw new SkipTestError(skipMsg);
894
939
  }
895
940
  throw new Error(`Wizard failed: ${errorOutput}`);
896
941
  }
897
- await validateGeneratedFiles('hubspot-test-e2e');
898
- await cleanupAppArtifacts('hubspot-test-e2e', options);
942
+ await validateGeneratedFiles('wizard-e2e-e2e');
943
+ await cleanupAppArtifacts('wizard-e2e-e2e', options);
899
944
  }
900
945
  },
901
946
  {
@@ -908,11 +953,11 @@ function buildPositiveTestCases(context) {
908
953
  throw new Error(`Missing config file: ${configPath}`);
909
954
  }
910
955
  try {
911
- await ensureDataplaneUrl(context, 'hubspot-test-platform');
956
+ await ensureDataplaneUrl(context, 'wizard-e2e-platform');
912
957
  } catch (error) {
913
958
  throw new SkipTestError(`Dataplane service not found: ${error.message}`);
914
959
  }
915
- await runWizardAndValidate(configPath, 'hubspot-test-platform', context, options);
960
+ await runWizardAndValidate(configPath, 'wizard-e2e-platform', context, options);
916
961
  }
917
962
  },
918
963
  {
@@ -922,14 +967,14 @@ function buildPositiveTestCases(context) {
922
967
  run: async(options) => {
923
968
  let dataplaneUrl;
924
969
  try {
925
- dataplaneUrl = await ensureDataplaneUrl(context, 'hubspot-test-env-vars');
970
+ dataplaneUrl = await ensureDataplaneUrl(context, 'wizard-e2e-env-vars');
926
971
  } catch (error) {
927
972
  throw new SkipTestError(`Dataplane service not found: ${error.message}`);
928
973
  }
929
974
  ensureEnvVar('CONTROLLER_URL', context.controllerUrl);
930
975
  ensureEnvVar('DATAPLANE_URL', dataplaneUrl);
931
976
  const configPath = await writeWizardConfig('wizard-hubspot-env-vars', {
932
- appName: 'hubspot-test-env-vars',
977
+ appName: 'wizard-e2e-env-vars',
933
978
  mode: 'create-system',
934
979
  source: {
935
980
  type: 'openapi-file',
@@ -941,7 +986,7 @@ function buildPositiveTestCases(context) {
941
986
  environment: context.environment
942
987
  }
943
988
  });
944
- await runWizardAndValidate(configPath, 'hubspot-test-env-vars', context, options);
989
+ await runWizardAndValidate(configPath, 'wizard-e2e-env-vars', context, options);
945
990
  }
946
991
  }
947
992
  ];
@@ -966,7 +1011,7 @@ function buildRealDataTestCases(context) {
966
1011
  requireEnvVars(['HUBSPOT_CLIENT_ID', 'HUBSPOT_CLIENT_SECRET']);
967
1012
  ensureEnvVar('HUBSPOT_TOKEN_URL', 'https://api.hubapi.com/oauth/v1/token');
968
1013
  const configPath = await writeWizardConfig('wizard-hubspot-credential-real', {
969
- appName: 'hubspot-test-credential-real',
1014
+ appName: 'wizard-e2e-credential-real',
970
1015
  mode: 'create-system',
971
1016
  source: {
972
1017
  type: 'openapi-file',
@@ -975,7 +1020,7 @@ function buildRealDataTestCases(context) {
975
1020
  credential: {
976
1021
  action: 'create',
977
1022
  config: {
978
- key: 'hubspot-test-cred-real',
1023
+ key: 'wizard-e2e-cred-real',
979
1024
  displayName: 'HubSpot Test Credential (Real)',
980
1025
  type: 'OAUTH2',
981
1026
  config: {
@@ -992,7 +1037,7 @@ function buildRealDataTestCases(context) {
992
1037
  }
993
1038
  }
994
1039
  });
995
- await runWizardAndValidate(configPath, 'hubspot-test-credential-real', context, options);
1040
+ await runWizardAndValidate(configPath, 'wizard-e2e-credential-real', context, options);
996
1041
  }
997
1042
  }
998
1043
  ];
@@ -1038,7 +1083,7 @@ function buildNegativeConfigTestCases(context) {
1038
1083
  name: 'Missing source block',
1039
1084
  run: async(options) => {
1040
1085
  const configPath = await writeWizardConfig('wizard-invalid-missing-source', {
1041
- appName: 'hubspot-test-negative-missing-source',
1086
+ appName: 'wizard-e2e-negative-missing-source',
1042
1087
  mode: 'create-system'
1043
1088
  });
1044
1089
  await runWizardExpectFailure(configPath, context, options, 'Missing required field: source');
@@ -1050,7 +1095,7 @@ function buildNegativeConfigTestCases(context) {
1050
1095
  name: 'Invalid source type',
1051
1096
  run: async(options) => {
1052
1097
  const configPath = await writeWizardConfig('wizard-invalid-source', {
1053
- appName: 'hubspot-test-negative-source',
1098
+ appName: 'wizard-e2e-negative-source',
1054
1099
  mode: 'create-system',
1055
1100
  source: { type: 'invalid-type' }
1056
1101
  });
@@ -1063,7 +1108,7 @@ function buildNegativeConfigTestCases(context) {
1063
1108
  name: 'Invalid mode',
1064
1109
  run: async(options) => {
1065
1110
  const configPath = await writeWizardConfig('wizard-invalid-mode', {
1066
- appName: 'hubspot-test-negative-mode',
1111
+ appName: 'wizard-e2e-negative-mode',
1067
1112
  mode: 'invalid-mode',
1068
1113
  source: { type: 'known-platform', platform: 'hubspot' }
1069
1114
  });
@@ -1076,7 +1121,7 @@ function buildNegativeConfigTestCases(context) {
1076
1121
  name: 'Known platform missing platform',
1077
1122
  run: async(options) => {
1078
1123
  const configPath = await writeWizardConfig('wizard-invalid-known-platform', {
1079
- appName: 'hubspot-test-negative-platform',
1124
+ appName: 'wizard-e2e-negative-platform',
1080
1125
  mode: 'create-system',
1081
1126
  source: { type: 'known-platform' }
1082
1127
  });
@@ -1089,7 +1134,7 @@ function buildNegativeConfigTestCases(context) {
1089
1134
  name: 'Missing OpenAPI file path',
1090
1135
  run: async(options) => {
1091
1136
  const configPath = await writeWizardConfig('wizard-invalid-openapi-file', {
1092
- appName: 'hubspot-test-negative-openapi',
1137
+ appName: 'wizard-e2e-negative-openapi',
1093
1138
  mode: 'create-system',
1094
1139
  source: { type: 'openapi-file', filePath: '/tmp/does-not-exist.json' }
1095
1140
  });
@@ -1102,7 +1147,7 @@ function buildNegativeConfigTestCases(context) {
1102
1147
  name: 'OpenAPI URL missing url',
1103
1148
  run: async(options) => {
1104
1149
  const configPath = await writeWizardConfig('wizard-invalid-openapi-url', {
1105
- appName: 'hubspot-test-negative-openapi-url',
1150
+ appName: 'wizard-e2e-negative-openapi-url',
1106
1151
  mode: 'create-system',
1107
1152
  source: { type: 'openapi-url' }
1108
1153
  });
@@ -1126,7 +1171,7 @@ function buildNegativeCredentialTestCases(context) {
1126
1171
  name: 'Add datasource missing systemIdOrKey',
1127
1172
  run: async(options) => {
1128
1173
  const configPath = await writeWizardConfig('wizard-invalid-add-datasource', {
1129
- appName: 'hubspot-test-negative-add-datasource',
1174
+ appName: 'wizard-e2e-negative-add-datasource',
1130
1175
  mode: 'add-datasource',
1131
1176
  source: { type: 'known-platform', platform: 'hubspot' }
1132
1177
  });
@@ -1139,7 +1184,7 @@ function buildNegativeCredentialTestCases(context) {
1139
1184
  name: 'Credential select missing credentialIdOrKey',
1140
1185
  run: async(options) => {
1141
1186
  const configPath = await writeWizardConfig('wizard-invalid-credential-select', {
1142
- appName: 'hubspot-test-negative-credential-select',
1187
+ appName: 'wizard-e2e-negative-credential-select',
1143
1188
  mode: 'create-system',
1144
1189
  source: { type: 'known-platform', platform: 'hubspot' },
1145
1190
  credential: { action: 'select' }
@@ -1153,7 +1198,7 @@ function buildNegativeCredentialTestCases(context) {
1153
1198
  name: 'Credential create missing config',
1154
1199
  run: async(options) => {
1155
1200
  const configPath = await writeWizardConfig('wizard-invalid-credential-create', {
1156
- appName: 'hubspot-test-negative-credential-create',
1201
+ appName: 'wizard-e2e-negative-credential-create',
1157
1202
  mode: 'create-system',
1158
1203
  source: { type: 'known-platform', platform: 'hubspot' },
1159
1204
  credential: { action: 'create' }
@@ -1171,26 +1216,24 @@ function buildNegativeCredentialTestCases(context) {
1171
1216
  * @param {string} appName - Application name
1172
1217
  * @param {Object} context - Test context
1173
1218
  * @param {Object} options - Options object
1174
- * @param {string} expectedMessage - Expected error message
1219
+ * @param {string|string[]} expectedMessage - Expected error substring(s); any match passes
1175
1220
  * @returns {Promise<void>} Resolves when validation fails as expected
1176
1221
  * @throws {Error} If validation succeeds or expected message not found
1177
1222
  */
1178
1223
  async function runValidationExpectFailure(appName, context, options, expectedMessage = null) {
1179
- const validateArgs = [
1180
- 'bin/aifabrix.js',
1181
- 'validate',
1182
- appName,
1183
- '--type',
1184
- 'external'
1185
- ];
1224
+ const validateArgs = ['bin/aifabrix.js', 'validate', appName];
1186
1225
  const result = await runCommand('node', validateArgs, options);
1187
1226
  if (result.success) {
1188
1227
  throw new Error('Expected validation to fail, but it succeeded.');
1189
1228
  }
1190
1229
  if (expectedMessage) {
1191
1230
  const combined = `${result.stdout}\n${result.stderr}`;
1192
- if (!combined.includes(expectedMessage)) {
1193
- throw new Error(`Expected error message not found: ${expectedMessage}\nActual output: ${combined}`);
1231
+ const needles = Array.isArray(expectedMessage) ? expectedMessage : [expectedMessage];
1232
+ const found = needles.some(n => combined.includes(n));
1233
+ if (!found) {
1234
+ throw new Error(
1235
+ `Expected error message not found (any of): ${needles.join(' | ')}\nActual output: ${combined}`
1236
+ );
1194
1237
  }
1195
1238
  }
1196
1239
  }
@@ -1276,20 +1319,16 @@ async function getFirstDatasourcePath(appPath) {
1276
1319
  }
1277
1320
 
1278
1321
  /**
1279
- * Corrupts datasource file by removing dimensions
1322
+ * Corrupts root v2.4 ``dimensions``: local binding without required ``field`` (schema failure).
1280
1323
  * @async
1281
- * @function corruptDatasourceRemoveDimensions
1324
+ * @function corruptDatasourceLocalBindingMissingField
1282
1325
  * @param {string} datasourcePath - Datasource file path
1283
1326
  * @returns {Promise<void>} Resolves when file is corrupted
1284
1327
  */
1285
- async function corruptDatasourceRemoveDimensions(datasourcePath) {
1328
+ async function corruptDatasourceLocalBindingMissingField(datasourcePath) {
1286
1329
  const datasourceContent = await fs.readFile(datasourcePath, 'utf8');
1287
1330
  const datasourceJson = JSON.parse(datasourceContent);
1288
- if (datasourceJson.fieldMappings) {
1289
- delete datasourceJson.fieldMappings.dimensions;
1290
- } else {
1291
- datasourceJson.fieldMappings = {};
1292
- }
1331
+ datasourceJson.dimensions = { orphan_local: { type: 'local' } };
1293
1332
  await fs.writeFile(datasourcePath, JSON.stringify(datasourceJson, null, 2), 'utf8');
1294
1333
  }
1295
1334
 
@@ -1303,13 +1342,9 @@ async function corruptDatasourceRemoveDimensions(datasourcePath) {
1303
1342
  async function corruptDatasourceInvalidDimensionKey(datasourcePath) {
1304
1343
  const datasourceContent = await fs.readFile(datasourcePath, 'utf8');
1305
1344
  const datasourceJson = JSON.parse(datasourceContent);
1306
- if (!datasourceJson.fieldMappings) {
1307
- datasourceJson.fieldMappings = {};
1308
- }
1309
- if (!datasourceJson.fieldMappings.dimensions) {
1310
- datasourceJson.fieldMappings.dimensions = {};
1311
- }
1312
- datasourceJson.fieldMappings.dimensions['invalid-key-with-hyphen'] = 'metadata.id';
1345
+ datasourceJson.dimensions = {
1346
+ 'invalid-key-with-hyphen': { type: 'local', field: 'id' }
1347
+ };
1313
1348
  await fs.writeFile(datasourcePath, JSON.stringify(datasourceJson, null, 2), 'utf8');
1314
1349
  }
1315
1350
 
@@ -1323,30 +1358,23 @@ async function corruptDatasourceInvalidDimensionKey(datasourcePath) {
1323
1358
  async function corruptDatasourceInvalidAttributePath(datasourcePath) {
1324
1359
  const datasourceContent = await fs.readFile(datasourcePath, 'utf8');
1325
1360
  const datasourceJson = JSON.parse(datasourceContent);
1326
- if (!datasourceJson.fieldMappings) {
1327
- datasourceJson.fieldMappings = {};
1328
- }
1329
- if (!datasourceJson.fieldMappings.dimensions) {
1330
- datasourceJson.fieldMappings.dimensions = {};
1331
- }
1332
- datasourceJson.fieldMappings.dimensions['valid_key'] = 'metadata.id-with-invalid-chars@';
1361
+ datasourceJson.dimensions = {
1362
+ valid_key: { type: 'local', field: 'id-with-invalid-chars@' }
1363
+ };
1333
1364
  await fs.writeFile(datasourcePath, JSON.stringify(datasourceJson, null, 2), 'utf8');
1334
1365
  }
1335
1366
 
1336
1367
  /**
1337
- * Corrupts datasource file with dimensions as array
1368
+ * Corrupts root ``dimensions`` with a non-object JSON value (schema type error).
1338
1369
  * @async
1339
- * @function corruptDatasourceDimensionsAsArray
1370
+ * @function corruptDatasourceDimensionsWrongJsonType
1340
1371
  * @param {string} datasourcePath - Datasource file path
1341
1372
  * @returns {Promise<void>} Resolves when file is corrupted
1342
1373
  */
1343
- async function corruptDatasourceDimensionsAsArray(datasourcePath) {
1374
+ async function corruptDatasourceDimensionsWrongJsonType(datasourcePath) {
1344
1375
  const datasourceContent = await fs.readFile(datasourcePath, 'utf8');
1345
1376
  const datasourceJson = JSON.parse(datasourceContent);
1346
- if (!datasourceJson.fieldMappings) {
1347
- datasourceJson.fieldMappings = {};
1348
- }
1349
- datasourceJson.fieldMappings.dimensions = ['invalid', 'array', 'format'];
1377
+ datasourceJson.dimensions = ['invalid', 'array', 'format'];
1350
1378
  await fs.writeFile(datasourcePath, JSON.stringify(datasourceJson, null, 2), 'utf8');
1351
1379
  }
1352
1380
 
@@ -1363,7 +1391,7 @@ function buildNegativeRbacTestCases(context) {
1363
1391
  type: 'negative',
1364
1392
  name: 'RBAC missing role referenced in permissions',
1365
1393
  run: async(options) => {
1366
- const appName = 'hubspot-test-negative-rbac-missing-role';
1394
+ const appName = 'wizard-e2e-negative-rbac-missing-role';
1367
1395
  const appPath = await createSystemForNegativeTest(appName, 'wizard-valid-for-rbac-test', context, options);
1368
1396
  await corruptSystemFileWithInvalidRole(appPath);
1369
1397
  await runValidationExpectFailure(appName, context, options, 'references role "non-existent-role" which does not exist');
@@ -1375,10 +1403,17 @@ function buildNegativeRbacTestCases(context) {
1375
1403
  type: 'negative',
1376
1404
  name: 'RBAC invalid YAML syntax',
1377
1405
  run: async(options) => {
1378
- const appName = 'hubspot-test-negative-rbac-invalid-yaml';
1406
+ const appName = 'wizard-e2e-negative-rbac-invalid-yaml';
1407
+ const appDir = path.join(process.cwd(), 'integration', appName);
1408
+ if (fsSync.existsSync(appDir)) {
1409
+ await fs.rm(appDir, { recursive: true, force: true });
1410
+ }
1379
1411
  const appPath = await createSystemForNegativeTest(appName, 'wizard-valid-for-rbac-yaml-test', context, options);
1380
1412
  await corruptRbacFile(appPath);
1381
- await runValidationExpectFailure(appName, context, options, 'Invalid YAML syntax in rbac.yaml');
1413
+ await runValidationExpectFailure(appName, context, options, [
1414
+ 'Invalid syntax in rbac.yaml',
1415
+ 'Invalid YAML syntax'
1416
+ ]);
1382
1417
  await cleanupAppArtifacts(appName, options);
1383
1418
  }
1384
1419
  }
@@ -1408,35 +1443,35 @@ function buildNegativeDimensionTestCases(context) {
1408
1443
  return [
1409
1444
  createTestCase(
1410
1445
  '2.14',
1411
- 'Datasource missing dimensions in fieldMappings',
1412
- 'hubspot-test-negative-dimension-missing',
1446
+ 'Datasource dimensions: local binding missing required field',
1447
+ 'wizard-e2e-negative-dimension-missing',
1413
1448
  'wizard-valid-for-dimension-test',
1414
- corruptDatasourceRemoveDimensions,
1415
- 'Missing required property "dimensions"'
1449
+ corruptDatasourceLocalBindingMissingField,
1450
+ 'Missing required property "field"'
1416
1451
  ),
1417
1452
  createTestCase(
1418
1453
  '2.15',
1419
- 'Datasource invalid dimension key pattern',
1420
- 'hubspot-test-negative-dimension-invalid-key',
1454
+ 'Datasource invalid dimension key (root dimensions propertyNames)',
1455
+ 'wizard-e2e-negative-dimension-invalid-key',
1421
1456
  'wizard-valid-for-dimension-key-test',
1422
1457
  corruptDatasourceInvalidDimensionKey,
1423
- 'Must be at most 40 characters'
1458
+ ['letters, numbers, and underscores only', 'property name must be valid']
1424
1459
  ),
1425
1460
  createTestCase(
1426
1461
  '2.16',
1427
- 'Datasource invalid attribute path pattern',
1428
- 'hubspot-test-negative-dimension-invalid-path',
1462
+ 'Datasource invalid dimension binding field pattern',
1463
+ 'wizard-e2e-negative-dimension-invalid-path',
1429
1464
  'wizard-valid-for-dimension-path-test',
1430
1465
  corruptDatasourceInvalidAttributePath,
1431
1466
  'must match pattern'
1432
1467
  ),
1433
1468
  createTestCase(
1434
1469
  '2.17',
1435
- 'Datasource dimensions as array instead of object',
1436
- 'hubspot-test-negative-dimension-array',
1470
+ 'Datasource dimensions wrong JSON type (array)',
1471
+ 'wizard-e2e-negative-dimension-array',
1437
1472
  'wizard-valid-for-dimension-array-test',
1438
- corruptDatasourceDimensionsAsArray,
1439
- 'Expected object, got undefined'
1473
+ corruptDatasourceDimensionsWrongJsonType,
1474
+ 'Expected object'
1440
1475
  )
1441
1476
  ];
1442
1477
  }
@@ -1,8 +1,8 @@
1
- appName: hubspot-test-e2e
1
+ appName: wizard-e2e-e2e
2
2
  mode: create-system
3
3
  source:
4
4
  type: openapi-file
5
- filePath: /workspace/aifabrix-builder/integration/hubspot/companies.json
5
+ filePath: /workspace/aifabrix-builder/integration/hubspot-test/companies.json
6
6
  credential:
7
7
  action: skip
8
8
  preferences:
@@ -1,4 +1,4 @@
1
- appName: hubspot-test-platform
1
+ appName: wizard-e2e-platform
2
2
  mode: create-system
3
3
  source:
4
4
  type: known-platform
@@ -0,0 +1,23 @@
1
+ # Headless wizard: regenerate HubSpot integration under integration/hubspot-test/
2
+ # Requires dataplane access (controller → dataplane) and auth (login or client credentials).
3
+ #
4
+ # From repo root:
5
+ # node bin/aifabrix.js wizard --config integration/hubspot-test/wizard-hubspot-test-headless.yaml \
6
+ # --controller <CONTROLLER_URL> --environment <ENV>
7
+ #
8
+ # Or set deployment.controller / deployment.environment below and omit CLI flags if your
9
+ # wizard runner merges them (see docs/commands/external-integration.md).
10
+
11
+ appName: hubspot-test
12
+ mode: create-system
13
+ source:
14
+ type: known-platform
15
+ platform: hubspot
16
+ credential:
17
+ action: skip
18
+ preferences:
19
+ intent: "HubSpot CRM integration (hubspot-test fixtures)"
20
+ fieldOnboardingLevel: standard
21
+ deployment:
22
+ controller: http://localhost:3110
23
+ environment: dev