@aifabrix/builder 2.43.0 → 2.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/.cursor/rules/cli-layout.mdc +75 -0
  3. package/.cursor/rules/project-rules.mdc +8 -0
  4. package/.npmrc.token +1 -0
  5. package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  6. package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  7. package/.nyc_output/processinfo/index.json +1 -0
  8. package/README.md +1 -1
  9. package/anchor-docs/README.md +10 -0
  10. package/anchor-docs/_TEMPLATE +24 -0
  11. package/bin/aifabrix.js +13 -4
  12. package/integration/hubspot-test/README.md +31 -0
  13. package/integration/hubspot-test/create-hubspot.js +5 -5
  14. package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
  15. package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
  16. package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
  17. package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
  18. package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
  19. package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
  20. package/integration/hubspot-test/test-dataplane-down.js +3 -3
  21. package/integration/hubspot-test/test.js +35 -43
  22. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  23. package/integration/roundtrip-test-local/README.md +144 -0
  24. package/integration/roundtrip-test-local/application.yaml +13 -0
  25. package/integration/roundtrip-test-local/env.template +15 -0
  26. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  27. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  28. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  29. package/integration/roundtrip-test-local2/README.md +144 -0
  30. package/integration/roundtrip-test-local2/application.yaml +13 -0
  31. package/integration/roundtrip-test-local2/env.template +15 -0
  32. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  33. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  34. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  35. package/integration/test/wizard.yaml +8 -0
  36. package/jest.config.default.js +10 -0
  37. package/jest.config.integration.fixtures.js +22 -0
  38. package/jest.config.integration.js +21 -18
  39. package/jest.config.isolated.js +10 -0
  40. package/jest.projects.js +301 -0
  41. package/lib/api/certificates.api.js +62 -0
  42. package/lib/api/datasources-core.api.js +3 -3
  43. package/lib/api/dev-mtls-request.js +110 -0
  44. package/lib/api/dev-server-https.js +145 -0
  45. package/lib/api/dev.api.js +133 -144
  46. package/lib/api/index.js +11 -3
  47. package/lib/api/pipeline.api.js +67 -20
  48. package/lib/api/types/certificates.types.js +48 -0
  49. package/lib/api/types/dev.types.js +4 -3
  50. package/lib/api/types/pipeline.types.js +8 -5
  51. package/lib/api/types/validation-run.types.js +56 -0
  52. package/lib/api/validation-run.api.js +111 -0
  53. package/lib/api/validation-runner.js +109 -0
  54. package/lib/app/certification-show-enrich.js +129 -0
  55. package/lib/app/certification-verify-rows.js +60 -0
  56. package/lib/app/config.js +1 -1
  57. package/lib/app/deploy-status-display.js +2 -2
  58. package/lib/app/deploy.js +7 -6
  59. package/lib/app/display.js +2 -1
  60. package/lib/app/dockerfile.js +3 -2
  61. package/lib/app/down.js +2 -1
  62. package/lib/app/helpers.js +6 -5
  63. package/lib/app/index.js +27 -8
  64. package/lib/app/list.js +7 -6
  65. package/lib/app/push.js +4 -3
  66. package/lib/app/register.js +16 -7
  67. package/lib/app/rotate-secret.js +14 -13
  68. package/lib/app/run-container-start.js +184 -0
  69. package/lib/app/run-docker-fallback.js +108 -0
  70. package/lib/app/run-env-compose.js +30 -42
  71. package/lib/app/run-helpers.js +49 -126
  72. package/lib/app/run-infra-requirements.js +30 -0
  73. package/lib/app/run-resolve-image.js +21 -0
  74. package/lib/app/run.js +74 -21
  75. package/lib/app/show-display.js +44 -1
  76. package/lib/app/show.js +93 -9
  77. package/lib/build/index.js +13 -10
  78. package/lib/certification/cli-cert-sync-skip.js +21 -0
  79. package/lib/certification/merge-certification-from-artifact.js +185 -0
  80. package/lib/certification/post-unified-cert-sync.js +33 -0
  81. package/lib/certification/sync-after-external-command.js +52 -0
  82. package/lib/certification/sync-system-certification.js +197 -0
  83. package/lib/cli/index.js +2 -0
  84. package/lib/cli/setup-app.help.js +67 -0
  85. package/lib/cli/setup-app.js +61 -121
  86. package/lib/cli/setup-app.test-commands.js +195 -0
  87. package/lib/cli/setup-auth.js +19 -5
  88. package/lib/cli/setup-credential-deployment.js +22 -8
  89. package/lib/cli/setup-dev-path-commands.js +124 -0
  90. package/lib/cli/setup-dev.js +170 -113
  91. package/lib/cli/setup-environment.js +7 -1
  92. package/lib/cli/setup-external-system.js +84 -23
  93. package/lib/cli/setup-infra.js +126 -47
  94. package/lib/cli/setup-parameters.js +32 -0
  95. package/lib/cli/setup-secrets.js +137 -18
  96. package/lib/cli/setup-service-user.js +1 -1
  97. package/lib/cli/setup-utility.js +54 -22
  98. package/lib/commands/app-down.js +5 -7
  99. package/lib/commands/app-install.js +14 -7
  100. package/lib/commands/app-logs.js +13 -10
  101. package/lib/commands/app-shell.js +4 -1
  102. package/lib/commands/app-test.js +25 -19
  103. package/lib/commands/app.js +32 -11
  104. package/lib/commands/auth-config.js +6 -6
  105. package/lib/commands/auth-status.js +4 -3
  106. package/lib/commands/credential-env.js +4 -3
  107. package/lib/commands/credential-list.js +5 -4
  108. package/lib/commands/credential-push.js +4 -3
  109. package/lib/commands/datasource-unified-test-cli.js +428 -0
  110. package/lib/commands/datasource-unified-test-cli.options.js +191 -0
  111. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
  112. package/lib/commands/datasource-validation-cli.js +143 -0
  113. package/lib/commands/datasource.js +125 -95
  114. package/lib/commands/deployment-list.js +6 -5
  115. package/lib/commands/dev-cli-handlers.js +122 -18
  116. package/lib/commands/dev-down.js +4 -3
  117. package/lib/commands/dev-init.js +231 -116
  118. package/lib/commands/dev-show-display.js +473 -0
  119. package/lib/commands/login-credentials.js +3 -2
  120. package/lib/commands/login-device.js +4 -3
  121. package/lib/commands/login.js +5 -4
  122. package/lib/commands/logout.js +8 -7
  123. package/lib/commands/parameters-validate.js +54 -0
  124. package/lib/commands/repair-datasource.js +314 -68
  125. package/lib/commands/repair-env-template.js +2 -2
  126. package/lib/commands/repair.js +21 -3
  127. package/lib/commands/secrets-list.js +23 -12
  128. package/lib/commands/secrets-remove-all.js +220 -0
  129. package/lib/commands/secrets-remove.js +21 -12
  130. package/lib/commands/secrets-set.js +21 -12
  131. package/lib/commands/secrets-validate.js +4 -4
  132. package/lib/commands/secure.js +10 -9
  133. package/lib/commands/service-user.js +26 -25
  134. package/lib/commands/test-e2e-external.js +27 -1
  135. package/lib/commands/up-common.js +3 -2
  136. package/lib/commands/up-dataplane.js +29 -16
  137. package/lib/commands/up-miso.js +19 -29
  138. package/lib/commands/upload.js +149 -39
  139. package/lib/commands/wizard-core-helpers.js +1 -1
  140. package/lib/commands/wizard-dataplane.js +4 -3
  141. package/lib/commands/wizard-helpers.js +3 -3
  142. package/lib/commands/wizard.js +2 -2
  143. package/lib/core/admin-secrets.js +14 -5
  144. package/lib/core/audit-logger.js +12 -4
  145. package/lib/core/config-attach-extensions.js +46 -0
  146. package/lib/core/config-runtime-paths.js +29 -0
  147. package/lib/core/config.js +55 -56
  148. package/lib/core/diff.js +3 -2
  149. package/lib/core/ensure-encryption-key.js +1 -1
  150. package/lib/core/secrets-ensure-infra.js +77 -0
  151. package/lib/core/secrets-ensure.js +120 -64
  152. package/lib/core/secrets-env-write.js +35 -7
  153. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  154. package/lib/core/secrets.js +200 -37
  155. package/lib/core/templates-env.js +4 -3
  156. package/lib/datasource/abac-validator.js +1 -10
  157. package/lib/datasource/deploy.js +75 -53
  158. package/lib/datasource/field-reference-validator.js +9 -6
  159. package/lib/datasource/integration-context.js +63 -0
  160. package/lib/datasource/list.js +8 -7
  161. package/lib/datasource/log-viewer.js +189 -67
  162. package/lib/datasource/resolve-app.js +4 -4
  163. package/lib/datasource/test-e2e.js +113 -146
  164. package/lib/datasource/test-integration.js +114 -122
  165. package/lib/datasource/unified-validation-run-body.js +68 -0
  166. package/lib/datasource/unified-validation-run-post.js +23 -0
  167. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  168. package/lib/datasource/unified-validation-run.js +93 -0
  169. package/lib/datasource/validate.js +157 -13
  170. package/lib/deployment/deployer.js +4 -3
  171. package/lib/deployment/environment.js +7 -6
  172. package/lib/deployment/push.js +17 -8
  173. package/lib/external-system/delete.js +4 -3
  174. package/lib/external-system/deploy.js +166 -53
  175. package/lib/external-system/download-helpers.js +1 -1
  176. package/lib/external-system/download.js +7 -6
  177. package/lib/external-system/generator.js +92 -6
  178. package/lib/external-system/integration-test-dispatch.js +26 -0
  179. package/lib/external-system/test-execution.js +5 -1
  180. package/lib/external-system/test-helpers.js +0 -4
  181. package/lib/external-system/test-system-level-helpers.js +110 -0
  182. package/lib/external-system/test-system-level.js +83 -44
  183. package/lib/external-system/test.js +59 -8
  184. package/lib/generator/builders.js +23 -11
  185. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  186. package/lib/generator/external.js +16 -4
  187. package/lib/generator/helpers.js +58 -3
  188. package/lib/generator/index.js +4 -0
  189. package/lib/generator/split-readme.js +12 -7
  190. package/lib/generator/split-variables.js +2 -1
  191. package/lib/generator/split.js +1 -1
  192. package/lib/generator/wizard-readme.js +3 -3
  193. package/lib/generator/wizard.js +8 -8
  194. package/lib/infrastructure/compose.js +70 -7
  195. package/lib/infrastructure/helpers-docker-check.js +67 -0
  196. package/lib/infrastructure/helpers.js +203 -42
  197. package/lib/infrastructure/index.js +31 -18
  198. package/lib/infrastructure/services.js +21 -67
  199. package/lib/internal/fs-real-sync.js +104 -0
  200. package/lib/internal/node-fs.js +98 -0
  201. package/lib/parameters/database-secret-values.js +173 -0
  202. package/lib/parameters/infra-kv-discovery.js +121 -0
  203. package/lib/parameters/infra-parameter-catalog.js +458 -0
  204. package/lib/parameters/infra-parameter-validate.js +64 -0
  205. package/lib/schema/application-schema.json +37 -17
  206. package/lib/schema/datasource-test-run.schema.json +493 -0
  207. package/lib/schema/deployment-rules.yaml +102 -63
  208. package/lib/schema/external-datasource.schema.json +1200 -442
  209. package/lib/schema/external-system.schema.json +203 -5
  210. package/lib/schema/flag-map-validation-run.json +31 -0
  211. package/lib/schema/infra-parameter.schema.json +106 -0
  212. package/lib/schema/infra.parameter.yaml +421 -0
  213. package/lib/schema/type/credential-auth-templates.json +40 -0
  214. package/lib/schema/type/document-storage.json +226 -0
  215. package/lib/schema/type/message-service.json +123 -0
  216. package/lib/schema/type/vector-store.json +88 -0
  217. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  218. package/lib/utils/api-error-handler.js +2 -2
  219. package/lib/utils/api.js +77 -17
  220. package/lib/utils/app-register-api.js +3 -2
  221. package/lib/utils/app-register-auth.js +1 -1
  222. package/lib/utils/app-register-config.js +4 -4
  223. package/lib/utils/app-register-display.js +3 -2
  224. package/lib/utils/app-register-validator.js +3 -2
  225. package/lib/utils/app-run-containers.js +26 -22
  226. package/lib/utils/app-scoped-config.js +31 -0
  227. package/lib/utils/app-service-env-from-builder.js +164 -0
  228. package/lib/utils/build-copy.js +1 -1
  229. package/lib/utils/build-helpers.js +20 -20
  230. package/lib/utils/build-resolve-image.js +165 -0
  231. package/lib/utils/cli-layout-chalk.js +8 -0
  232. package/lib/utils/cli-test-layout-chalk.js +267 -0
  233. package/lib/utils/cli-utils.js +88 -11
  234. package/lib/utils/compose-db-passwords.js +138 -0
  235. package/lib/utils/compose-generate-docker-compose.js +216 -0
  236. package/lib/utils/compose-generator.js +197 -291
  237. package/lib/utils/compose-miso-env.js +18 -0
  238. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  239. package/lib/utils/config-paths.js +166 -7
  240. package/lib/utils/config-scoped-resources-preference.js +41 -0
  241. package/lib/utils/configuration-env-resolver.js +11 -8
  242. package/lib/utils/controller-deployment-outcome.js +68 -0
  243. package/lib/utils/credential-display.js +2 -2
  244. package/lib/utils/credential-secrets-env.js +5 -5
  245. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  246. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  247. package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
  248. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  249. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  250. package/lib/utils/datasource-test-run-display.js +459 -0
  251. package/lib/utils/datasource-test-run-exit.js +83 -0
  252. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  253. package/lib/utils/datasource-test-run-report-version.js +51 -0
  254. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  255. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  256. package/lib/utils/datasource-validation-watch.js +266 -0
  257. package/lib/utils/declarative-url-ports.js +47 -0
  258. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  259. package/lib/utils/dev-ca-install.js +185 -23
  260. package/lib/utils/dev-cert-helper.js +266 -17
  261. package/lib/utils/dev-hosts-helper.js +307 -0
  262. package/lib/utils/dev-init-cert-hints.js +37 -0
  263. package/lib/utils/dev-init-health-messages.js +52 -0
  264. package/lib/utils/dev-init-resolve.js +86 -0
  265. package/lib/utils/dev-init-ssh-merge.js +65 -0
  266. package/lib/utils/dev-ssh-config-helper.js +196 -0
  267. package/lib/utils/dev-user-groups.js +93 -0
  268. package/lib/utils/docker-build.js +42 -17
  269. package/lib/utils/docker-exec.js +28 -0
  270. package/lib/utils/docker-manifest-public-port.js +116 -0
  271. package/lib/utils/docker-not-running-hint.js +52 -0
  272. package/lib/utils/docker.js +98 -11
  273. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  274. package/lib/utils/env-config-loader.js +10 -91
  275. package/lib/utils/env-copy.js +19 -10
  276. package/lib/utils/env-map.js +35 -8
  277. package/lib/utils/env-template.js +2 -2
  278. package/lib/utils/environment-scoped-resources.js +144 -0
  279. package/lib/utils/error-formatter.js +92 -13
  280. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  281. package/lib/utils/error-formatters/network-errors.js +2 -1
  282. package/lib/utils/error-formatters/permission-errors.js +2 -1
  283. package/lib/utils/error-formatters/validation-errors.js +2 -1
  284. package/lib/utils/external-readme.js +8 -1
  285. package/lib/utils/external-system-display.js +242 -136
  286. package/lib/utils/external-system-local-test-tty.js +389 -0
  287. package/lib/utils/external-system-readiness-core.js +377 -0
  288. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  289. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  290. package/lib/utils/external-system-readiness-display.js +186 -0
  291. package/lib/utils/external-system-system-test-tty-overview.js +120 -0
  292. package/lib/utils/external-system-system-test-tty.js +417 -0
  293. package/lib/utils/external-system-test-helpers.js +24 -6
  294. package/lib/utils/external-system-validators.js +30 -12
  295. package/lib/utils/health-check-url.js +119 -0
  296. package/lib/utils/health-check.js +59 -25
  297. package/lib/utils/help-builder.js +11 -8
  298. package/lib/utils/image-version.js +4 -8
  299. package/lib/utils/infra-containers.js +4 -7
  300. package/lib/utils/infra-env-defaults.js +162 -0
  301. package/lib/utils/infra-status-display.js +167 -0
  302. package/lib/utils/infra-status.js +16 -8
  303. package/lib/utils/local-secrets.js +3 -4
  304. package/lib/utils/paths.js +148 -47
  305. package/lib/utils/port-resolver.js +10 -23
  306. package/lib/utils/redis-env-scope.js +62 -0
  307. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  308. package/lib/utils/remote-builder-validation.js +99 -0
  309. package/lib/utils/remote-dev-auth.js +117 -21
  310. package/lib/utils/remote-docker-env.js +67 -15
  311. package/lib/utils/remote-secrets-loader.js +13 -4
  312. package/lib/utils/resolve-docker-image-ref.js +124 -0
  313. package/lib/utils/schema-loader.js +22 -9
  314. package/lib/utils/secrets-bash-kv.js +25 -0
  315. package/lib/utils/secrets-generator.js +169 -49
  316. package/lib/utils/secrets-helpers.js +70 -59
  317. package/lib/utils/secrets-kv-scope.js +60 -0
  318. package/lib/utils/secrets-utils.js +32 -38
  319. package/lib/utils/secrets-validation.js +3 -1
  320. package/lib/utils/secrets-yaml-preserve.js +109 -0
  321. package/lib/utils/ssh-key-helper.js +4 -2
  322. package/lib/utils/template-helpers.js +2 -2
  323. package/lib/utils/test-log-writer.js +3 -3
  324. package/lib/utils/token-manager.js +1 -2
  325. package/lib/utils/url-declarative-public-base.js +188 -0
  326. package/lib/utils/url-declarative-resolve-build.js +493 -0
  327. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  328. package/lib/utils/url-declarative-resolve.js +220 -0
  329. package/lib/utils/url-declarative-token-parse.js +74 -0
  330. package/lib/utils/url-declarative-url-flags.js +50 -0
  331. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  332. package/lib/utils/url-public-path-prefix.js +34 -0
  333. package/lib/utils/urls-local-registry.js +220 -0
  334. package/lib/utils/validation-report-tty-kit.js +77 -0
  335. package/lib/utils/validation-run-poll.js +112 -0
  336. package/lib/utils/validation-run-post-retry.js +85 -0
  337. package/lib/utils/validation-run-request.js +116 -0
  338. package/lib/utils/variable-transformer.js +21 -4
  339. package/lib/utils/yaml-preserve.js +33 -14
  340. package/lib/validation/datasource-warnings.js +56 -0
  341. package/lib/validation/env-template-auth.js +1 -1
  342. package/lib/validation/external-manifest-validator.js +27 -7
  343. package/lib/validation/validate-display.js +37 -31
  344. package/lib/validation/validate-external-cert-sync.js +23 -0
  345. package/lib/validation/validate.js +8 -14
  346. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  347. package/lib/validation/validator.js +22 -65
  348. package/lib/validation/wizard-config-validator.js +2 -1
  349. package/package.json +9 -4
  350. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  351. package/scripts/diagnose-cli.js +150 -0
  352. package/scripts/install-local.js +307 -55
  353. package/scripts/pnpm-global-remove.js +48 -0
  354. package/templates/README.md +15 -2
  355. package/templates/applications/dataplane/application.yaml +52 -2
  356. package/templates/applications/dataplane/env.template +79 -17
  357. package/templates/applications/dataplane/rbac.yaml +8 -0
  358. package/templates/applications/keycloak/application.yaml +9 -1
  359. package/templates/applications/keycloak/env.template +15 -6
  360. package/templates/applications/miso-controller/application.yaml +10 -2
  361. package/templates/applications/miso-controller/env.template +42 -12
  362. package/templates/applications/miso-controller/rbac.yaml +5 -0
  363. package/templates/external-system/README.md.hbs +20 -7
  364. package/templates/external-system/deploy.js.hbs +5 -5
  365. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  366. package/templates/infra/compose.yaml.hbs +33 -16
  367. package/templates/infra/servers.json.hbs +3 -1
  368. package/templates/python/docker-compose.hbs +16 -0
  369. package/templates/typescript/docker-compose.hbs +16 -0
  370. package/lib/api/external-test.api.js +0 -111
  371. package/lib/schema/env-config.yaml +0 -60
@@ -5,113 +5,72 @@
5
5
  "systemKey": "hubspot-test",
6
6
  "enabled": true,
7
7
  "entityType": "recordStorage",
8
- "primaryKey": ["id"],
9
- "description": "Comprehensive HubSpot users datasource with full CRUD operations, comprehensive metadata schema, ABAC dimensions, and OpenAPI support",
8
+ "description": "HubSpot users datasource (minimal v2.4 fixture)",
9
+ "primaryKey": [
10
+ "id"
11
+ ],
12
+ "labelKey": [
13
+ "email"
14
+ ],
10
15
  "metadataSchema": {
11
16
  "type": "object",
17
+ "required": [
18
+ "id",
19
+ "externalId",
20
+ "properties"
21
+ ],
12
22
  "properties": {
13
23
  "id": {
14
24
  "type": "string",
15
- "description": "HubSpot user ID"
16
- },
17
- "properties": {
18
- "type": "object",
19
- "description": "User properties object containing all CRM fields",
20
- "additionalProperties": true,
21
- "properties": {
22
- "email": {
23
- "type": "string",
24
- "format": "email",
25
- "description": "User email address"
26
- },
27
- "firstName": {
28
- "type": "string",
29
- "description": "User first name"
30
- },
31
- "lastName": {
32
- "type": "string",
33
- "description": "User last name"
34
- },
35
- "role": {
36
- "type": "string",
37
- "description": "User role"
38
- },
39
- "timezone": {
40
- "type": "string",
41
- "description": "User timezone"
42
- }
43
- }
44
- },
45
- "createdAt": {
46
- "type": "string",
47
- "format": "date-time",
48
- "description": "User creation timestamp"
49
- },
50
- "updatedAt": {
51
- "type": "string",
52
- "format": "date-time",
53
- "description": "User last update timestamp"
54
- },
55
- "archived": {
56
- "type": "boolean",
57
- "description": "Whether the user is archived"
58
- },
59
- "archivedAt": {
60
- "type": "string",
61
- "format": "date-time",
62
- "description": "User archive timestamp"
63
- },
64
- "associations": {
65
- "type": "object",
66
- "description": "Associated records",
67
- "additionalProperties": true
25
+ "index": true
68
26
  },
69
- "url": {
27
+ "externalId": {
70
28
  "type": "string",
71
- "format": "uri",
72
- "description": "HubSpot object URL"
29
+ "index": true
73
30
  },
74
- "objectWriteTraceId": {
31
+ "email": {
75
32
  "type": "string",
76
- "description": "Trace ID for tracking writes"
33
+ "filter": true
77
34
  },
78
- "propertiesWithHistory": {
35
+ "properties": {
79
36
  "type": "object",
80
- "description": "Properties with change history",
81
37
  "additionalProperties": true
82
38
  }
83
- },
84
- "required": [
85
- "id"
86
- ]
39
+ }
40
+ },
41
+ "dimensions": {
42
+ "department": {
43
+ "type": "local",
44
+ "field": "department"
45
+ }
87
46
  },
88
47
  "fieldMappings": {
89
48
  "attributes": {
90
49
  "id": {
91
- "expression": "{{id}}",
92
- "type": "string",
93
- "indexed": true
50
+ "expression": "{{raw.id}}"
51
+ },
52
+ "externalId": {
53
+ "expression": "{{raw.id}}"
54
+ },
55
+ "email": {
56
+ "expression": "{{raw.properties.email.value}} | trim"
94
57
  },
95
58
  "department": {
96
- "expression": "{{id}}",
97
- "type": "string",
98
- "indexed": true,
99
- "description": "Default dimension for catalog compatibility"
59
+ "expression": "{{raw.properties.department.value}} | trim"
100
60
  }
101
- },
102
- "dimensions": {
61
+ }
62
+ },
63
+ "exposed": {
64
+ "schema": {
65
+ "id": "metadata.id",
66
+ "externalId": "metadata.externalId",
67
+ "email": "metadata.email",
103
68
  "department": "metadata.department"
104
69
  }
105
70
  },
106
71
  "sync": {
107
72
  "mode": "pull",
108
73
  "schedule": "0 */6 * * *",
109
- "batchSize": 100,
110
- "maxParallelRequests": 5,
111
- "pagination": {
112
- "strategy": "cursor",
113
- "cursorField": "$.paging.next.after",
114
- "cursorParam": "after"
115
- }
74
+ "batchSize": 100
116
75
  }
117
- }
76
+ }
@@ -262,7 +262,7 @@
262
262
  "displayName": "HubSpot Company",
263
263
  "description": "HubSpot companies datasource with field mappings for CRM company data",
264
264
  "systemKey": "hubspot-test",
265
- "entityType": "record-storage",
265
+ "entityType": "recordStorage",
266
266
  "resourceType": "customer",
267
267
  "enabled": true,
268
268
  "version": "1.0.0",
@@ -806,7 +806,7 @@
806
806
  "displayName": "HubSpot Contact",
807
807
  "description": "HubSpot contacts datasource with field mappings for CRM contact data",
808
808
  "systemKey": "hubspot-test",
809
- "entityType": "record-storage",
809
+ "entityType": "recordStorage",
810
810
  "resourceType": "contact",
811
811
  "enabled": true,
812
812
  "version": "1.0.0",
@@ -1448,7 +1448,7 @@
1448
1448
  "displayName": "HubSpot Deal",
1449
1449
  "description": "HubSpot deals datasource with field mappings for CRM deal data",
1450
1450
  "systemKey": "hubspot-test",
1451
- "entityType": "record-storage",
1451
+ "entityType": "recordStorage",
1452
1452
  "resourceType": "deal",
1453
1453
  "enabled": true,
1454
1454
  "version": "1.0.0",
@@ -200,13 +200,7 @@ async function createTestDatasource(datasourcePath) {
200
200
  * @returns {string[]} Command arguments
201
201
  */
202
202
  function buildDatasourceUploadArgs(datasourcePath) {
203
- return [
204
- 'bin/aifabrix.js',
205
- 'datasource',
206
- 'upload',
207
- 'test-app',
208
- datasourcePath
209
- ];
203
+ return ['bin/aifabrix.js', 'datasource', 'upload', datasourcePath];
210
204
  }
211
205
 
212
206
  /**
@@ -152,15 +152,15 @@ async function runTests() {
152
152
  results.push(result);
153
153
 
154
154
  if (result.success) {
155
- logSuccess(`✓ ${result.name}: Error handling validated`);
155
+ logSuccess(`✔ ${result.name}: Error handling validated`);
156
156
  } else {
157
- logError(`✗ ${result.name}: Error handling failed`);
157
+ logError(`✖ ${result.name}: Error handling failed`);
158
158
  if (result.output) {
159
159
  logWarn(` Output: ${result.output.substring(0, 200)}...`);
160
160
  }
161
161
  }
162
162
  } catch (error) {
163
- logError(`✗ ${testFn.name}: Unexpected error: ${error.message}`);
163
+ logError(`✖ ${testFn.name}: Unexpected error: ${error.message}`);
164
164
  results.push({
165
165
  name: testFn.name,
166
166
  success: false,
@@ -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
  }
@@ -1216,7 +1216,7 @@ function buildNegativeCredentialTestCases(context) {
1216
1216
  * @param {string} appName - Application name
1217
1217
  * @param {Object} context - Test context
1218
1218
  * @param {Object} options - Options object
1219
- * @param {string} expectedMessage - Expected error message
1219
+ * @param {string|string[]} expectedMessage - Expected error substring(s); any match passes
1220
1220
  * @returns {Promise<void>} Resolves when validation fails as expected
1221
1221
  * @throws {Error} If validation succeeds or expected message not found
1222
1222
  */
@@ -1228,8 +1228,12 @@ async function runValidationExpectFailure(appName, context, options, expectedMes
1228
1228
  }
1229
1229
  if (expectedMessage) {
1230
1230
  const combined = `${result.stdout}\n${result.stderr}`;
1231
- if (!combined.includes(expectedMessage)) {
1232
- 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
+ );
1233
1237
  }
1234
1238
  }
1235
1239
  }
@@ -1315,20 +1319,16 @@ async function getFirstDatasourcePath(appPath) {
1315
1319
  }
1316
1320
 
1317
1321
  /**
1318
- * Corrupts datasource file by removing dimensions
1322
+ * Corrupts root v2.4 ``dimensions``: local binding without required ``field`` (schema failure).
1319
1323
  * @async
1320
- * @function corruptDatasourceRemoveDimensions
1324
+ * @function corruptDatasourceLocalBindingMissingField
1321
1325
  * @param {string} datasourcePath - Datasource file path
1322
1326
  * @returns {Promise<void>} Resolves when file is corrupted
1323
1327
  */
1324
- async function corruptDatasourceRemoveDimensions(datasourcePath) {
1328
+ async function corruptDatasourceLocalBindingMissingField(datasourcePath) {
1325
1329
  const datasourceContent = await fs.readFile(datasourcePath, 'utf8');
1326
1330
  const datasourceJson = JSON.parse(datasourceContent);
1327
- if (datasourceJson.fieldMappings) {
1328
- delete datasourceJson.fieldMappings.dimensions;
1329
- } else {
1330
- datasourceJson.fieldMappings = {};
1331
- }
1331
+ datasourceJson.dimensions = { orphan_local: { type: 'local' } };
1332
1332
  await fs.writeFile(datasourcePath, JSON.stringify(datasourceJson, null, 2), 'utf8');
1333
1333
  }
1334
1334
 
@@ -1342,13 +1342,9 @@ async function corruptDatasourceRemoveDimensions(datasourcePath) {
1342
1342
  async function corruptDatasourceInvalidDimensionKey(datasourcePath) {
1343
1343
  const datasourceContent = await fs.readFile(datasourcePath, 'utf8');
1344
1344
  const datasourceJson = JSON.parse(datasourceContent);
1345
- if (!datasourceJson.fieldMappings) {
1346
- datasourceJson.fieldMappings = {};
1347
- }
1348
- if (!datasourceJson.fieldMappings.dimensions) {
1349
- datasourceJson.fieldMappings.dimensions = {};
1350
- }
1351
- datasourceJson.fieldMappings.dimensions['invalid-key-with-hyphen'] = 'metadata.id';
1345
+ datasourceJson.dimensions = {
1346
+ 'invalid-key-with-hyphen': { type: 'local', field: 'id' }
1347
+ };
1352
1348
  await fs.writeFile(datasourcePath, JSON.stringify(datasourceJson, null, 2), 'utf8');
1353
1349
  }
1354
1350
 
@@ -1362,30 +1358,23 @@ async function corruptDatasourceInvalidDimensionKey(datasourcePath) {
1362
1358
  async function corruptDatasourceInvalidAttributePath(datasourcePath) {
1363
1359
  const datasourceContent = await fs.readFile(datasourcePath, 'utf8');
1364
1360
  const datasourceJson = JSON.parse(datasourceContent);
1365
- if (!datasourceJson.fieldMappings) {
1366
- datasourceJson.fieldMappings = {};
1367
- }
1368
- if (!datasourceJson.fieldMappings.dimensions) {
1369
- datasourceJson.fieldMappings.dimensions = {};
1370
- }
1371
- datasourceJson.fieldMappings.dimensions['valid_key'] = 'metadata.id-with-invalid-chars@';
1361
+ datasourceJson.dimensions = {
1362
+ valid_key: { type: 'local', field: 'id-with-invalid-chars@' }
1363
+ };
1372
1364
  await fs.writeFile(datasourcePath, JSON.stringify(datasourceJson, null, 2), 'utf8');
1373
1365
  }
1374
1366
 
1375
1367
  /**
1376
- * Corrupts datasource file with dimensions as array
1368
+ * Corrupts root ``dimensions`` with a non-object JSON value (schema type error).
1377
1369
  * @async
1378
- * @function corruptDatasourceDimensionsAsArray
1370
+ * @function corruptDatasourceDimensionsWrongJsonType
1379
1371
  * @param {string} datasourcePath - Datasource file path
1380
1372
  * @returns {Promise<void>} Resolves when file is corrupted
1381
1373
  */
1382
- async function corruptDatasourceDimensionsAsArray(datasourcePath) {
1374
+ async function corruptDatasourceDimensionsWrongJsonType(datasourcePath) {
1383
1375
  const datasourceContent = await fs.readFile(datasourcePath, 'utf8');
1384
1376
  const datasourceJson = JSON.parse(datasourceContent);
1385
- if (!datasourceJson.fieldMappings) {
1386
- datasourceJson.fieldMappings = {};
1387
- }
1388
- datasourceJson.fieldMappings.dimensions = ['invalid', 'array', 'format'];
1377
+ datasourceJson.dimensions = ['invalid', 'array', 'format'];
1389
1378
  await fs.writeFile(datasourcePath, JSON.stringify(datasourceJson, null, 2), 'utf8');
1390
1379
  }
1391
1380
 
@@ -1421,7 +1410,10 @@ function buildNegativeRbacTestCases(context) {
1421
1410
  }
1422
1411
  const appPath = await createSystemForNegativeTest(appName, 'wizard-valid-for-rbac-yaml-test', context, options);
1423
1412
  await corruptRbacFile(appPath);
1424
- 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
+ ]);
1425
1417
  await cleanupAppArtifacts(appName, options);
1426
1418
  }
1427
1419
  }
@@ -1451,23 +1443,23 @@ function buildNegativeDimensionTestCases(context) {
1451
1443
  return [
1452
1444
  createTestCase(
1453
1445
  '2.14',
1454
- 'Datasource missing dimensions in fieldMappings',
1446
+ 'Datasource dimensions: local binding missing required field',
1455
1447
  'wizard-e2e-negative-dimension-missing',
1456
1448
  'wizard-valid-for-dimension-test',
1457
- corruptDatasourceRemoveDimensions,
1458
- 'Missing required property "dimensions"'
1449
+ corruptDatasourceLocalBindingMissingField,
1450
+ 'Missing required property "field"'
1459
1451
  ),
1460
1452
  createTestCase(
1461
1453
  '2.15',
1462
- 'Datasource invalid dimension key pattern',
1454
+ 'Datasource invalid dimension key (root dimensions propertyNames)',
1463
1455
  'wizard-e2e-negative-dimension-invalid-key',
1464
1456
  'wizard-valid-for-dimension-key-test',
1465
1457
  corruptDatasourceInvalidDimensionKey,
1466
- 'Must be at most 40 characters'
1458
+ ['letters, numbers, and underscores only', 'property name must be valid']
1467
1459
  ),
1468
1460
  createTestCase(
1469
1461
  '2.16',
1470
- 'Datasource invalid attribute path pattern',
1462
+ 'Datasource invalid dimension binding field pattern',
1471
1463
  'wizard-e2e-negative-dimension-invalid-path',
1472
1464
  'wizard-valid-for-dimension-path-test',
1473
1465
  corruptDatasourceInvalidAttributePath,
@@ -1475,11 +1467,11 @@ function buildNegativeDimensionTestCases(context) {
1475
1467
  ),
1476
1468
  createTestCase(
1477
1469
  '2.17',
1478
- 'Datasource dimensions as array instead of object',
1470
+ 'Datasource dimensions wrong JSON type (array)',
1479
1471
  'wizard-e2e-negative-dimension-array',
1480
1472
  'wizard-valid-for-dimension-array-test',
1481
- corruptDatasourceDimensionsAsArray,
1482
- 'Expected object, got undefined'
1473
+ corruptDatasourceDimensionsWrongJsonType,
1474
+ 'Expected object'
1483
1475
  )
1484
1476
  ];
1485
1477
  }
@@ -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
@@ -0,0 +1,144 @@
1
+ # Roundtrip Test
2
+
3
+ Roundtrip validation test
4
+
5
+ ## System Information
6
+
7
+ - **System Key**: `roundtrip-test-local`
8
+ - **System Type**: `openapi`
9
+ - **Datasources**: 1
10
+
11
+ ## Files
12
+
13
+ - `application.yaml` – Application configuration with `app` and `externalIntegration` blocks
14
+ - `roundtrip-test-local-system.yaml` – External system definition (authentication, OpenAPI/MCP, RBAC)
15
+ - `roundtrip-test-local-datasource-roundtrip-test-company.yaml` – Datasource: Company
16
+ - `env.template` – Environment variables template (secrets, API keys)
17
+ - `roundtrip-test-local-deploy.json` – Deployment manifest (generated by `aifabrix json roundtrip-test-local`)
18
+ - `deploy.js` – Deploy script for the integration
19
+ - `wizard.yaml` – Wizard configuration (if created via wizard)
20
+
21
+ Optional: `rbac.yaml` – Roles and permissions merged into the system when present.
22
+
23
+ ## Quick Start
24
+
25
+ Login to your controller
26
+ ```bash
27
+ aifabrix auth config --set-controller <url> --set-environment dev
28
+ aifabrix login
29
+ ```
30
+
31
+ ### 1. Extend External System
32
+
33
+ Use the interactive wizard to extend your existing system:
34
+
35
+ ```bash
36
+ aifabrix wizard --app roundtrip-test-local
37
+ ```
38
+
39
+ ### 2. Configure Authentication and Datasources
40
+
41
+ Edit files in `integration/roundtrip-test-local/`:
42
+
43
+ - **Authentication**: `roundtrip-test-local-system.yaml` (auth type, credentials placeholders)
44
+ - **Field mappings**: `roundtrip-test-local-datasource-*-datasource.yaml` (dimensions, attributes, operations)
45
+ - **Credential and configuration**: `env.template` (security settings and configuration variables)
46
+
47
+
48
+ ### Secrets
49
+
50
+ Secrets are resolved from `.aifabrix` or key vault. Set them with:
51
+
52
+ ```bash
53
+ aifabrix secret set roundtrip-test-local/apiKey <your value> # API Key
54
+ ```
55
+
56
+
57
+ ### 3. Validate Configuration
58
+
59
+ ```bash
60
+ aifabrix validate roundtrip-test-local
61
+ ```
62
+
63
+ ### 4. Repair Deployment Manifest
64
+
65
+ **Run repair regularly.** It keeps naming conventions, filenames, and the deployment manifest aligned with AI Fabrix platform best practices. Use it after editing datasources, env.template, or system config—and run it often to catch drift early.
66
+
67
+ ```bash
68
+ aifabrix repair roundtrip-test-local
69
+ ```
70
+
71
+ Options:
72
+ --auth <method> Set authentication method (oauth2, aad, apikey, basic, queryParam, oidc, hmac, none); updates system file and env.template
73
+ --dry-run Report changes only; do not write
74
+ --rbac Ensure RBAC permissions per datasource and add default Admin/Reader roles if none exist
75
+ --expose Set exposed.attributes on each datasource to all fieldMappings.attributes keys
76
+ --sync Add default sync section to datasources that lack it
77
+ --test Generate testPayload.payloadTemplate and testPayload.expectedResult from attributes
78
+
79
+ ### 5. Upload to dataplane
80
+
81
+ ```bash
82
+ aifabrix upload roundtrip-test-local
83
+ ```
84
+
85
+ ## Testing
86
+
87
+ ### Unit Tests (Local Validation, No API)
88
+
89
+ ```bash
90
+ aifabrix test roundtrip-test-local
91
+ ```
92
+
93
+ ### Integration Tests (Via Dataplane)
94
+
95
+ ```bash
96
+ aifabrix test-integration roundtrip-test-local
97
+ ```
98
+
99
+ ### End-to-end Tests (Via Dataplane)
100
+
101
+ ```bash
102
+ aifabrix test-e2e roundtrip-test-local
103
+ ```
104
+
105
+ Options:
106
+ -e, --env <env> Environment: dev, tst, or pro (builder: dev/tst for container)
107
+ -v, --verbose Show detailed step output and poll progress
108
+ --debug Include debug output and write log to integration/roundtrip-test-local/logs/
109
+ --no-async Use sync mode (no polling); single POST per datasource
110
+
111
+ ### E2E tests per datasource
112
+
113
+ To run a full E2E test for a single datasource (config, credential, sync, data, CIP), use `aifabrix datasource test-e2e` with the datasource key and app:
114
+
115
+ ```bash
116
+ # Company
117
+ aifabrix datasource test-e2e roundtrip-test-company --app roundtrip-test-local
118
+
119
+ ```
120
+
121
+ Options:
122
+ -a, --app roundtrip-test-local App key (default: resolve from cwd if inside integration/roundtrip-test-local/)
123
+ -e, --env <env> Environment: dev, tst, or pro
124
+ -v, --verbose Show detailed step output and poll progress
125
+ --debug Include debug output and write log to integration/roundtrip-test-local/logs/
126
+ --test-crud Enable CRUD lifecycle test (body testCrud: true)
127
+ --record-id <id> Record ID for test (body recordId)
128
+ --no-cleanup Disable cleanup after test (body cleanup: false)
129
+ --primary-key-value <value|@path> Primary key value or path to JSON file (e.g. @pk.json) for body primaryKeyValue
130
+ --no-async Use sync mode (no polling); single POST, no asyncRun
131
+
132
+ ## Deployment
133
+
134
+ Deploy via miso-controller pipeline (same as regular apps). Auth and controller come from `aifabrix login` and `aifabrix auth config`:
135
+
136
+ ```bash
137
+ aifabrix deploy roundtrip-test-local
138
+ ```
139
+
140
+ ## Troubleshooting
141
+
142
+ - **Validation errors**: Run `aifabrix validate roundtrip-test-local` to see schema and manifest errors.
143
+ - **Deployment / auth**: Run `aifabrix auth config --set-controller <url> --set-environment <env>` and `aifabrix login` before `aifabrix deploy`.
144
+ - **File not found**: Run commands from the project root (where `package.json` and `integration/` live).
@@ -0,0 +1,13 @@
1
+ app:
2
+ key: roundtrip-test-local
3
+ displayName: Roundtrip Test
4
+ description: Roundtrip validation test
5
+ type: external
6
+ externalIntegration:
7
+ schemaBasePath: ./
8
+ systems:
9
+ - roundtrip-test-local-system.yaml
10
+ dataSources:
11
+ - roundtrip-test-local-datasource-roundtrip-test-company.yaml
12
+ autopublish: true
13
+ version: 1.0.0
@@ -0,0 +1,15 @@
1
+ # Environment variables for external system integration
2
+ # Use kv:// (or aifabrix secret set) for sensitive values; plain values for non-sensitive configuration.
3
+ #
4
+
5
+ # Authentication
6
+ # Type: oauth2
7
+ KV_ROUNDTRIP_TEST_LOCAL_CLIENTID=kv://roundtrip-test-local/clientId
8
+ KV_ROUNDTRIP_TEST_LOCAL_CLIENTSECRET=kv://roundtrip-test-local/clientSecret
9
+ # Non-secure (e.g. URLs): baseUrl, tokenUrl, authorizationUrl
10
+
11
+ # Configuration
12
+ # KV_ROUNDTRIP_TEST_CLIENTID
13
+ KV_ROUNDTRIP_TEST_CLIENTID=kv://roundtrip-test/clientId
14
+ # KV_ROUNDTRIP_TEST_CLIENTSECRET
15
+ KV_ROUNDTRIP_TEST_CLIENTSECRET=kv://roundtrip-test/clientSecret
@@ -0,0 +1,14 @@
1
+ key: roundtrip-test-company
2
+ displayName: Company
3
+ systemKey: roundtrip-test-local
4
+ entityType: record-storage
5
+ resourceType: customer
6
+ primaryKey:
7
+ - country
8
+ fieldMappings:
9
+ dimensions:
10
+ country: metadata.country
11
+ attributes:
12
+ country:
13
+ expression: '{{metadata.country}}'
14
+ type: string
@@ -0,0 +1,61 @@
1
+ {
2
+ "system": {
3
+ "key": "roundtrip-test-local",
4
+ "displayName": "Roundtrip Test",
5
+ "description": "Roundtrip validation test",
6
+ "type": "openapi",
7
+ "enabled": true,
8
+ "authentication": {
9
+ "method": "oauth2",
10
+ "variables": {
11
+ "baseUrl": "https://api.example.com",
12
+ "tokenUrl": "https://api.example.com/oauth/token",
13
+ "authorizationUrl": "https://api.example.com/oauth/authorize"
14
+ },
15
+ "security": {
16
+ "clientId": "kv://roundtrip-test/clientId",
17
+ "clientSecret": "kv://roundtrip-test/clientSecret"
18
+ }
19
+ },
20
+ "configuration": [
21
+ {
22
+ "name": "KV_ROUNDTRIP_TEST_CLIENTID",
23
+ "value": "roundtrip-test/clientId",
24
+ "location": "keyvault",
25
+ "required": true
26
+ },
27
+ {
28
+ "name": "KV_ROUNDTRIP_TEST_CLIENTSECRET",
29
+ "value": "roundtrip-test/clientSecret",
30
+ "location": "keyvault",
31
+ "required": true
32
+ }
33
+ ],
34
+ "dataSources": [
35
+ "roundtrip-test-company"
36
+ ]
37
+ },
38
+ "dataSources": [
39
+ {
40
+ "key": "roundtrip-test-company",
41
+ "displayName": "Company",
42
+ "systemKey": "roundtrip-test-local",
43
+ "entityType": "record-storage",
44
+ "resourceType": "customer",
45
+ "primaryKey": [
46
+ "country"
47
+ ],
48
+ "fieldMappings": {
49
+ "dimensions": {
50
+ "country": "metadata.country"
51
+ },
52
+ "attributes": {
53
+ "country": {
54
+ "expression": "{{metadata.country}}",
55
+ "type": "string"
56
+ }
57
+ }
58
+ }
59
+ }
60
+ ]
61
+ }