@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
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "$schema":"https://json-schema.org/draft/2020-12/schema",
3
- "$id":"https://raw.githubusercontent.com/esystemsdev/aifabrix-builder/refs/heads/main/lib/schema/external-datasource.schema.json",
3
+ "$id":"aifabrix://schema/external-datasource.schema.json",
4
4
  "title":"External Data Source",
5
5
  "description":"Configuration for AI Fabrix ExternalDataSource entities. Includes metadata schema, data dimensions, transformation mappings, OpenAPI/MCP exposure, execution logic, and sync behavior.",
6
6
  "metadata":{
7
7
  "key":"external-datasource-schema",
8
8
  "name":"External Data Source Configuration Schema",
9
9
  "description":"JSON schema for validating ExternalDataSource configuration files",
10
- "version":"2.3.0",
10
+ "version":"2.4.5",
11
11
  "type":"schema",
12
12
  "category":"integration",
13
13
  "author":"AI Fabrix Team",
14
14
  "createdAt":"2024-01-01T00:00:00Z",
15
- "updatedAt":"2026-01-19T00:00:00Z",
15
+ "updatedAt":"2026-04-07T00:00:00Z",
16
16
  "compatibility":{
17
17
  "minVersion":"1.0.0",
18
18
  "maxVersion":"3.0.0",
@@ -96,7 +96,7 @@
96
96
  "version":"2.2.0",
97
97
  "date":"2026-02-26T00:00:00Z",
98
98
  "changes":[
99
- "capabilities: preferred format is array [\"list\",\"get\",...]. Schema oneOf accepts both array and legacy object; runtime accepts both for backward compatibility."
99
+ "capabilities: preferred format is array [\"list\",\"get\",...]."
100
100
  ],
101
101
  "breaking":false
102
102
  },
@@ -107,6 +107,74 @@
107
107
  "BREAKING: Added required primaryKey (array of normalized attribute names). Used for get/update/delete and table indexing. Migration: add primaryKey array (e.g. [\"id\"] or [\"externalId\"]) to each datasource config."
108
108
  ],
109
109
  "breaking":true
110
+ },
111
+ {
112
+ "version":"2.4.0",
113
+ "date":"2026-03-24T00:00:00Z",
114
+ "changes":[
115
+ "BREAKING: Consolidated freeze baseline into 2.4.0 on feature branch before merge.",
116
+ "BREAKING: Removed metadataSchema.foreignKey, top-level references, and relationContract.",
117
+ "BREAKING: Removed fieldMappings.dimensions and datasource config.abac* contract surfaces.",
118
+ "BREAKING: Added root contract gate for entityType='none' (orchestration/chaining only).",
119
+ "BREAKING: Removed indexing section from datasource root; index/filter are metadataSchema-driven.",
120
+ "BREAKING: Simplified fieldMappings.attributes to expression-only normalization contract.",
121
+ "Updated expression contract to strict roots: raw.*, fk.*, dimension.* with FK traversal support.",
122
+ "Added top-level dimensions and strict foreignKeys[] contract (required name/fields/targetDatasource).",
123
+ "Simplified sync contract to mode/schedule/batchSize.",
124
+ "Hardened metadataSchema index/filter scalar-only constraints.",
125
+ "Applied naming guardrails for metadata fields (camelCase) and FK names (camelCase).",
126
+ "Added datetime representation guidance: type=string + format=date-time with UTC/native DB timestamp mapping.",
127
+ "Allowed contract/config.extensions for entityType=none orchestration datasources.",
128
+ "Added actor/operator strict defaults in dimensionBinding (eq for displayName/email/userId, in for groups/roles)."
129
+ ],
130
+ "breaking":true
131
+ },
132
+ {
133
+ "version":"2.4.1",
134
+ "date":"2026-03-29T00:00:00Z",
135
+ "changes":[
136
+ "CIP execution.cip.operations allows custom operation keys matching the same pattern as capabilities[].",
137
+ "recordStorage/documentStorage: dimensions are no longer JSON Schema-required; validator warns when missing or empty.",
138
+ "dimensionBinding type=fk: via remains required; actor is optional (warn when omitted).",
139
+ "dimensions object may be empty at schema level; recommend ≥1 binding via application validation warning.",
140
+ "testPayload: unknown top-level keys rejected by application validator (strict contract beyond JSON Schema).",
141
+ "cipStepFetch: fetch.openapiRef and fetch.operation (source=datasource) use the same naming pattern as capabilities[] and execution.cip.operations keys (^[a-z][a-zA-Z0-9]*$), not a fixed CRUD enum. Standard names list/get/create/update/delete remain valid; custom keys must match openapi.operations.<name> or the target datasource CIP operation."
142
+ ],
143
+ "breaking":false
144
+ },
145
+ {
146
+ "version":"2.4.2",
147
+ "date":"2026-03-31T00:00:00Z",
148
+ "changes":[
149
+ "recordStorage/documentStorage: metadataSchema.properties.externalId required (type=string, index=true) as global join identity (346.rules §10.1; plans SC-025/SC-029).",
150
+ "foreignKeys.targetFields: when omitted, resolution defaults to target externalId (not primaryKey); composite primaryKey must not be used as explicit cross-datasource join key (SC-026/SC-028).",
151
+ "Application validator enforces externalId field mapping and FK join semantics in lockstep with JSON Schema."
152
+ ],
153
+ "breaking":true
154
+ },
155
+ {
156
+ "version":"2.4.3",
157
+ "date":"2026-04-04T00:00:00Z",
158
+ "changes":[
159
+ "BREAKING: Removed CIP filter.enforceAbac from cipStepFilter.filter (WP-H / 346.13 matrix 18). Use filter.abac.mode (mandatory | optional | disabled) instead."
160
+ ],
161
+ "breaking":true
162
+ },
163
+ {
164
+ "version":"2.4.4",
165
+ "date":"2026-04-06T00:00:00Z",
166
+ "changes":[
167
+ "Added optional root mcpContract object for embedded MCP securityModel (tools/abac policy buckets). Required for integration manifests when CIP filter.abac uses mandatory datasource-scoped policies (static readiness vs runtime ExternalDataSource.mcpContract)."
168
+ ],
169
+ "breaking":false
170
+ },
171
+ {
172
+ "version":"2.4.5",
173
+ "date":"2026-04-07T00:00:00Z",
174
+ "changes":[
175
+ "exposed.profiles object profiles: attributes may be an object map (property names = field keys; values ignored), matching runtime exposed_profile_field_names and CIP/ExposedFieldsValidator behavior."
176
+ ],
177
+ "breaking":false
110
178
  }
111
179
  ]
112
180
  },
@@ -116,9 +184,7 @@
116
184
  "displayName",
117
185
  "systemKey",
118
186
  "entityType",
119
- "resourceType",
120
- "fieldMappings",
121
- "primaryKey"
187
+ "resourceType"
122
188
  ],
123
189
  "properties":{
124
190
  "key":{
@@ -145,8 +211,8 @@
145
211
  },
146
212
  "entityType":{
147
213
  "type":"string",
148
- "enum":["document-storage","documentStorage","vector-store","vectorStore","record-storage","recordStorage","message-service","messageService","none"],
149
- "description":"Entity type identifier. Defines storage semantics and behavior: 'document-storage' or 'documentStorage' (creates document storage service with vector-storage), 'vector-store' or 'vectorStore' (external vector storage system), 'record-storage' or 'recordStorage' (creates record-based system with metadata sync and access rights), 'message-service' or 'messageService' (message service for notifications - Slack, Teams, Email), 'none' (uses external system data directly or connects other data sources). Required field. Supports both camelCase and kebab-case formats for backward compatibility."
214
+ "enum":["documentStorage","vectorStore","recordStorage","messageService","none"],
215
+ "description":"Entity type identifier. Defines storage semantics and behavior: 'documentStorage' (creates document storage service with vector-storage), 'vectorStore' (external vector storage system), 'recordStorage' (creates record-based system with metadata sync and access rights), 'messageService' (message service for notifications - Slack, Teams, Email), 'none' (uses external system data directly or connects other data sources). Required field. Canonical values are camelCase."
150
216
  },
151
217
  "resourceType":{
152
218
  "type":"string",
@@ -160,75 +226,72 @@
160
226
  "default":"1.0.0"
161
227
  },
162
228
  "metadataSchema":{
163
- "type":"object",
164
- "description":"Subset of JSON Schema used to validate raw input metadata.",
165
- "additionalProperties":true
229
+ "$ref":"#/$defs/metadataSchemaNode"
166
230
  },
167
231
  "primaryKey":{
168
232
  "type":"array",
169
- "description":"Normalized field names that uniquely identify a record (used for get/update/delete and table indexing). Each element must exist in fieldMappings.dimensions or fieldMappings.attributes.",
233
+ "description":"Normalized field names that uniquely identify a record (used for get/update/delete and table indexing). Each element must exist in metadataSchema and be index=true.",
170
234
  "minItems":1,
171
235
  "items":{
172
236
  "type":"string",
173
- "pattern":"^[a-zA-Z0-9_]+$"
237
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
238
+ },
239
+ "uniqueItems":true
240
+ },
241
+ "labelKey":{
242
+ "type":"array",
243
+ "description":"Normalized field names used for display and dimension labels. Each element must exist in metadataSchema and be scalar with index=true or filter=true.",
244
+ "minItems":1,
245
+ "items":{
246
+ "type":"string",
247
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
174
248
  },
175
249
  "uniqueItems":true
176
250
  },
251
+ "foreignKeys":{
252
+ "type":"array",
253
+ "description":"Foreign key definitions referencing other datasources. Defines relational integrity and join capability.",
254
+ "items":{
255
+ "$ref":"#/$defs/foreignKeyDefinition"
256
+ },
257
+ "uniqueItems":true
258
+ },
259
+ "dimensions":{
260
+ "type":"object",
261
+ "description":"Canonical dimension bindings for this datasource. Keys must exist in Dimension Catalog when catalog validation runs. For recordStorage/documentStorage, at least one binding is recommended (application validator may warn if missing or empty).",
262
+ "propertyNames":{
263
+ "pattern":"^[a-zA-Z0-9_]+$"
264
+ },
265
+ "additionalProperties":{
266
+ "$ref":"#/$defs/dimensionBinding"
267
+ }
268
+ },
177
269
  "fieldMappings":{
178
270
  "type":"object",
179
- "description":"Transformation rules and data dimensions. Maps canonical dimensions to system attributes.",
271
+ "description":"Normalization rules only (raw/fk traversal to normalized attributes). For storage datasources, attribute keys must correspond to metadataSchema fields (builder/runtime validation).",
180
272
  "required":[
181
- "dimensions",
182
273
  "attributes"
183
274
  ],
184
275
  "properties":{
185
- "dimensions":{
186
- "type":"object",
187
- "description":"Data dimensions mapping. Key = dimension key (from Dimension Catalog), Value = attribute path (e.g., 'metadata.department').",
188
- "additionalProperties":{
189
- "type":"string",
190
- "pattern":"^[a-zA-Z0-9_.]+$"
191
- },
192
- "minProperties":0
193
- },
194
276
  "attributes":{
195
277
  "type":"object",
196
- "description":"Key = normalized attribute name. Value = transformation expression + type.",
278
+ "description":"Key = normalized attribute name. Value = transformation configuration.",
279
+ "propertyNames":{
280
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
281
+ },
197
282
  "additionalProperties":{
198
283
  "type":"object",
199
- "required":[
200
- "expression",
201
- "type"
202
- ],
203
284
  "properties":{
204
285
  "expression":{
205
286
  "type":"string",
206
- "description":"Pipe-based DSL expression: '{{raw.path}} | toLower | trim' or record reference: 'record_ref:customer'.",
207
- "pattern":"^\\s*((\\{\\{[^}]+\\}\\}(\\s*\\|\\s*[a-zA-Z0-9_]+(\\([^)]*\\))?)*)|(record_ref:[a-z0-9-]+))\\s*$"
208
- },
209
- "type":{
210
- "type":"string",
211
- "enum":[
212
- "string",
213
- "number",
214
- "integer",
215
- "boolean",
216
- "array",
217
- "object"
218
- ]
219
- },
220
- "indexed":{
221
- "type":"boolean",
222
- "default":false,
223
- "description":"If true, creates database index for fast search/filtering. Dimensions are automatically indexed."
287
+ "description":"Pipe-based DSL expression. Allowed roots: raw.<path>, fk.<fk>.metadata.<field>, fk.<fk>.dimension.<dimension>[.label], dimension.<dimension>[.label]. FK traversal in DSL is one-hop only.",
288
+ "maxLength":512,
289
+ "pattern":"^\\s*\\{\\{(raw\\.[a-zA-Z0-9_.]+|fk\\.[a-z][a-zA-Z0-9]*\\.metadata\\.[a-z][a-zA-Z0-9]*|fk\\.[a-z][a-zA-Z0-9]*\\.dimension\\.[a-zA-Z0-9_]+(\\.label)?|dimension\\.[a-zA-Z0-9_]+(\\.label)?)\\}\\}(\\s*\\|\\s*[a-zA-Z0-9_]+(\\([^)]*\\))?)*\\s*$"
224
290
  },
225
291
  "description":{
226
292
  "type":"string",
227
293
  "description":"Technical description of the normalized field."
228
294
  },
229
- "required":{
230
- "type":"boolean"
231
- },
232
295
  "semantic":{
233
296
  "type":"object",
234
297
  "description":"Semantic metadata for AI agents and schema generation.",
@@ -265,53 +328,61 @@
265
328
  "lineage":{
266
329
  "$ref":"#/$defs/fieldMappingLineage"
267
330
  }
268
- }
331
+ },
332
+ "required":[
333
+ "expression"
334
+ ],
335
+ "additionalProperties":false
269
336
  }
270
337
  }
271
- }
338
+ },
339
+ "additionalProperties":false
272
340
  },
273
341
  "exposed":{
274
342
  "type":"object",
275
- "description":"Defines which normalized fields are exposed through MCP/OpenAPI. Ensures ISO27001-safe output and predictable AI model behavior.",
343
+ "description":"Defines public API exposure contract. v2.4.0 freeze requires exposed.schema as canonical response shape.",
276
344
  "properties":{
277
- "attributes":{
345
+ "schema":{
346
+ "type":"object",
347
+ "description":"Canonical public response contract. Keys define output shape; values are expressions using metadata./fk./dimension paths.",
348
+ "minProperties":1,
349
+ "additionalProperties":{
350
+ "$ref":"#/$defs/exposedSchemaNode"
351
+ }
352
+ },
353
+ "omit":{
278
354
  "type":"array",
279
- "description":"List of normalized attributes (from fieldMappings.attributes keys) that the MCP/OpenAPI layers will return.",
355
+ "description":"Fields that exist in normalized metadata but must NEVER be exposed by MCP/OpenAPI (e.g., secrets, internal IDs). Overrides 'fields'.",
280
356
  "items":{
281
357
  "type":"string",
282
- "pattern":"^[a-zA-Z0-9_]+$"
358
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
283
359
  },
284
- "minItems":1,
285
360
  "uniqueItems":true
286
361
  },
287
- "omit":{
362
+ "filterable":{
288
363
  "type":"array",
289
- "description":"Fields that exist in normalized metadata but must NEVER be exposed by MCP/OpenAPI (e.g., secrets, internal IDs). Overrides 'fields'.",
364
+ "description":"Fields that may be used as deterministic filters in exposed APIs. Must reference materialized fields (`index=true` or `filter=true`).",
290
365
  "items":{
291
366
  "type":"string",
292
- "pattern":"^[a-zA-Z0-9_]+$"
367
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
293
368
  },
294
369
  "uniqueItems":true
295
370
  },
296
- "groups":{
297
- "type":"object",
298
- "description":"Optional logical grouping for OpenAPI/MCP schema generation (e.g., 'default', 'analytics', 'light').",
299
- "additionalProperties":{
300
- "type":"array",
301
- "items":{
302
- "type":"string",
303
- "pattern":"^[a-zA-Z0-9_]+$"
304
- },
305
- "minItems":1,
306
- "uniqueItems":true
307
- }
371
+ "required":{
372
+ "type":"array",
373
+ "description":"Fields that profile contracts require to be present.",
374
+ "items":{
375
+ "type":"string",
376
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
377
+ },
378
+ "uniqueItems":true
308
379
  },
309
380
  "readonly":{
310
381
  "type":"array",
311
382
  "description":"Fields exposed via MCP/OpenAPI but cannot be modified via write operations.",
312
383
  "items":{
313
384
  "type":"string",
314
- "pattern":"^[a-zA-Z0-9_]+$"
385
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
315
386
  },
316
387
  "uniqueItems":true
317
388
  },
@@ -321,20 +392,74 @@
321
392
  },
322
393
  "profiles":{
323
394
  "type":"object",
324
- "description":"Named exposure profiles mapping profile keys to lists of normalized field names. Useful for AI-light, AI-embedding, analytics, etc.",
395
+ "description":"Named exposure profiles mapping profile keys to deterministic field contracts.",
325
396
  "additionalProperties":{
326
- "type":"array",
327
- "items":{
328
- "type":"string",
329
- "pattern":"^[a-zA-Z0-9_]+$"
330
- },
331
- "minItems":1,
332
- "uniqueItems":true
397
+ "oneOf":[
398
+ {
399
+ "type":"array",
400
+ "items":{
401
+ "type":"string",
402
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
403
+ },
404
+ "minItems":1,
405
+ "uniqueItems":true
406
+ },
407
+ {
408
+ "type":"object",
409
+ "properties":{
410
+ "attributes":{
411
+ "oneOf":[
412
+ {
413
+ "type":"array",
414
+ "items":{
415
+ "type":"string",
416
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
417
+ },
418
+ "minItems":1,
419
+ "uniqueItems":true
420
+ },
421
+ {
422
+ "type":"object",
423
+ "minProperties":1,
424
+ "propertyNames":{
425
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
426
+ },
427
+ "additionalProperties":true
428
+ }
429
+ ]
430
+ },
431
+ "required":{
432
+ "type":"array",
433
+ "items":{
434
+ "type":"string",
435
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
436
+ },
437
+ "uniqueItems":true
438
+ },
439
+ "readonly":{
440
+ "type":"array",
441
+ "items":{
442
+ "type":"string",
443
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
444
+ },
445
+ "uniqueItems":true
446
+ }
447
+ },
448
+ "anyOf":[
449
+ {
450
+ "required":[
451
+ "attributes"
452
+ ]
453
+ }
454
+ ],
455
+ "additionalProperties":false
456
+ }
457
+ ]
333
458
  }
334
459
  }
335
460
  },
336
- "required":[
337
- "attributes"
461
+ "required":[
462
+ "schema"
338
463
  ],
339
464
  "additionalProperties":false
340
465
  },
@@ -352,21 +477,18 @@
352
477
  "default":"pull"
353
478
  },
354
479
  "schedule":{
355
- "type":"string"
480
+ "type":"string",
481
+ "description":"Cron schedule for sync execution. Supports 5-field cron syntax or @hourly/@daily/@weekly/@monthly.",
482
+ "pattern":"^(@hourly|@daily|@weekly|@monthly|([0-9*/,-]+\\s+){4}[0-9*/,-]+)$"
356
483
  },
357
484
  "batchSize":{
358
485
  "type":"integer",
359
486
  "minimum":1,
360
487
  "maximum":10000,
361
488
  "default":500
362
- },
363
- "maxParallelRequests":{
364
- "type":"integer",
365
- "minimum":1,
366
- "maximum":50,
367
- "default":5
368
489
  }
369
- }
490
+ },
491
+ "additionalProperties":false
370
492
  },
371
493
  "openapi":{
372
494
  "type":"object",
@@ -377,7 +499,8 @@
377
499
  "default":false
378
500
  },
379
501
  "documentKey":{
380
- "type":"string"
502
+ "type":"string",
503
+ "description":"OpenAPI document key used to resolve selected operations. Warning-only in this story when unresolved at validation time."
381
504
  },
382
505
  "baseUrl":{
383
506
  "type":"string",
@@ -391,106 +514,35 @@
391
514
  "description":"Selected operations from the OpenAPI document. Only endpoints chosen during wizard onboarding are included.",
392
515
  "properties":{
393
516
  "list":{
394
- "type":"object",
517
+ "$ref":"#/$defs/openapiOperation",
395
518
  "required":[
396
519
  "operationId"
397
- ],
398
- "properties":{
399
- "operationId":{
400
- "type":"string"
401
- },
402
- "method":{
403
- "type":"string",
404
- "enum":[
405
- "GET",
406
- "POST"
407
- ]
408
- },
409
- "path":{
410
- "type":"string"
411
- }
412
- }
520
+ ]
413
521
  },
414
522
  "get":{
415
- "type":"object",
523
+ "$ref":"#/$defs/openapiOperation",
416
524
  "required":[
417
525
  "operationId"
418
- ],
419
- "properties":{
420
- "operationId":{
421
- "type":"string"
422
- },
423
- "method":{
424
- "type":"string",
425
- "enum":[
426
- "GET"
427
- ]
428
- },
429
- "path":{
430
- "type":"string"
431
- }
432
- }
526
+ ]
433
527
  },
434
528
  "create":{
435
- "type":"object",
436
- "properties":{
437
- "operationId":{
438
- "type":"string"
439
- },
440
- "method":{
441
- "type":"string",
442
- "enum":[
443
- "POST",
444
- "PUT"
445
- ]
446
- },
447
- "path":{
448
- "type":"string"
449
- }
450
- }
529
+ "$ref":"#/$defs/openapiOperation"
451
530
  },
452
531
  "update":{
453
- "type":"object",
454
- "properties":{
455
- "operationId":{
456
- "type":"string"
457
- },
458
- "method":{
459
- "type":"string",
460
- "enum":[
461
- "PATCH",
462
- "PUT",
463
- "POST"
464
- ]
465
- },
466
- "path":{
467
- "type":"string"
468
- }
469
- }
532
+ "$ref":"#/$defs/openapiOperation"
470
533
  },
471
534
  "delete":{
472
- "type":"object",
473
- "properties":{
474
- "operationId":{
475
- "type":"string"
476
- },
477
- "method":{
478
- "type":"string",
479
- "enum":[
480
- "DELETE"
481
- ]
482
- },
483
- "path":{
484
- "type":"string"
485
- }
486
- }
535
+ "$ref":"#/$defs/openapiOperation"
487
536
  }
537
+ },
538
+ "additionalProperties":{
539
+ "$ref":"#/$defs/openapiOperation"
488
540
  }
489
541
  },
490
542
  "autoRbac":{
491
543
  "type":"boolean",
492
544
  "default":false,
493
- "description":"Generates <system>.<entity>.<action> RBAC permissions."
545
+ "description":"When true and no explicit operation security scopes are configured, the runtime resolves required RBAC permission as '<resourceType>:<operation>' for each operation (resourceType from the datasource config, default document), matching builder repair RBAC permission names. Explicit operation-level scopes (openapi.operations.*.security/permissions) take precedence and disable autoRbac for that operation."
494
546
  }
495
547
  }
496
548
  },
@@ -522,8 +574,8 @@
522
574
  "type":"string",
523
575
  "enum":[
524
576
  "reject",
525
- "latest-wins",
526
- "first-wins",
577
+ "lastWriteWins",
578
+ "firstWriteWins",
527
579
  "merge"
528
580
  ]
529
581
  },
@@ -554,7 +606,7 @@
554
606
  "properties":{
555
607
  "field":{
556
608
  "type":"string",
557
- "pattern":"^[a-zA-Z0-9_]+$",
609
+ "pattern":"^[a-z][a-zA-Z0-9]*$",
558
610
  "description":"Normalized field name to evaluate."
559
611
  },
560
612
  "operator":{
@@ -585,39 +637,6 @@
585
637
  },
586
638
  "additionalProperties":false
587
639
  },
588
- "indexing":{
589
- "type":"object",
590
- "description":"Indexing and embedding strategy for this datasource.",
591
- "properties":{
592
- "embedding":{
593
- "type":"array",
594
- "description":"List of normalized fields whose values should be concatenated and embedded for vector search.",
595
- "items":{
596
- "type":"string",
597
- "pattern":"^[a-zA-Z0-9_]+$"
598
- },
599
- "minItems":1,
600
- "uniqueItems":true
601
- },
602
- "uniqueKey":{
603
- "type":"string",
604
- "pattern":"^[a-zA-Z0-9_]+$",
605
- "description":"Normalized field used as unique identifier for deduplication and upserts."
606
- },
607
- "dedupeStrategy":{
608
- "type":"string",
609
- "enum":[
610
- "reject",
611
- "latest-wins",
612
- "first-wins",
613
- "merge"
614
- ],
615
- "default":"latest-wins",
616
- "description":"Strategy to apply when multiple records share the same uniqueKey."
617
- }
618
- },
619
- "additionalProperties":false
620
- },
621
640
  "context":{
622
641
  "type":"object",
623
642
  "description":"Natural-language and semantic hints for AI agents.",
@@ -647,258 +666,861 @@
647
666
  "additionalProperties":false
648
667
  },
649
668
  "documentStorage":{
669
+ "$ref":"aifabrix://schema/type/document-storage.json",
670
+ "description":"Document storage configuration (optional). Schema is canonical under type/document-storage.json."
671
+ },
672
+ "messageService":{
673
+ "$ref":"aifabrix://schema/type/message-service.json",
674
+ "description":"Message service configuration (optional). Schema is canonical under type/message-service.json."
675
+ },
676
+ "testPayload":{
650
677
  "type":"object",
651
- "description":"Document storage configuration (optional, enables vector storage). Validated against type/document-storage.json schema.",
678
+ "description":"Execution-aware test payload configuration for unit and integration testing. Only the listed properties are allowed at this level; nested shapes for payloadTemplate/expectedResult/fk fixtures are validated strictly by the application validator where required.",
652
679
  "properties":{
653
- "enabled":{
654
- "type":"boolean",
655
- "default":true
656
- },
657
- "twoPhaseSync":{
658
- "type":"boolean",
659
- "default":true,
660
- "description":"Enable two-phase sync pattern. When true: validates metadata first (quality rules, comparison with DocumentRecords), then fetches binaries via CIP for changed/new documents. When false: fetches binaries directly without metadata validation phase (single-phase sync). Note: Files are never synced back to external systems (one-way sync only: external → dataplane)."
661
- },
662
- "ingestAfterSync":{
663
- "type":"boolean",
664
- "default":false,
665
- "description":"When true, chunk and embed each document after store during sync so vector search returns hits immediately. When false, ingestion runs later (e.g. Celery task or on approval). Set true for E2E tests that validate vector step."
666
- },
667
- "binaryOperationRef":{
668
- "type":"string",
669
- "default":"get",
670
- "description":"CIP operation name for binary document retrieval. Must exist in execution.cip.operations. Defaults to 'get' operation."
671
- },
672
- "responseType":{
680
+ "mode":{
673
681
  "type":"string",
674
682
  "enum":[
675
- "binary",
676
- "base64",
677
- "json"
678
- ],
679
- "default":"binary",
680
- "description":"Expected response type from CIP operation. 'binary' for raw binary data, 'base64' for base64-encoded data, 'json' for JSON response with binary field."
681
- },
682
- "binaryField":{
683
- "type":"string",
684
- "description":"Field name containing binary data if responseType is 'json' or 'base64'. Required when responseType is not 'binary'."
683
+ "mock",
684
+ "live"
685
+ ]
685
686
  },
686
- "parameterMapping":{
687
+ "primaryKey":{
687
688
  "type":"object",
688
- "additionalProperties":{
689
- "type":"string"
690
- },
691
- "description":"Map metadata record fields to CIP operation parameters. Example: {\"fileId\": \"{{key}}\", \"downloadUrl\": \"{{metadata.downloadUrl}}\"}"
689
+ "description":"Optional key/value payload for primary-key focused operation tests.",
690
+ "additionalProperties":true
692
691
  },
693
- "processing":{
694
- "type":"object",
695
- "properties":{
696
- "fileStoragePath":{
697
- "type":"string",
698
- "default":"/data/documents"
699
- },
700
- "aiValidation":{
701
- "type":"object"
702
- },
703
- "spacyEnrichment":{
704
- "type":"object"
705
- },
706
- "notifications":{
707
- "type":"object"
692
+ "scenarios":{
693
+ "type":"array",
694
+ "description":"Optional operation-specific test scenarios.",
695
+ "items":{
696
+ "type":"object",
697
+ "required":[
698
+ "operation"
699
+ ],
700
+ "properties":{
701
+ "operation":{
702
+ "type":"string",
703
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
704
+ },
705
+ "input":{
706
+ "type":"object",
707
+ "additionalProperties":true
708
+ }
708
709
  },
709
- "ingestAfterSync":{
710
- "type":"boolean",
711
- "default":false,
712
- "description":"When true, chunk and embed each document after store during sync so vector search returns hits."
710
+ "additionalProperties":false
711
+ }
712
+ },
713
+ "fk":{
714
+ "type":"object",
715
+ "description":"Optional FK fixture payload used by expression and join tests.",
716
+ "additionalProperties":true
717
+ },
718
+ "actors":{
719
+ "type":"array",
720
+ "description":"Optional actor fixture list for ABAC/runtime tests.",
721
+ "items":{
722
+ "type":"object",
723
+ "properties":{
724
+ "email":{
725
+ "type":"string"
726
+ },
727
+ "userId":{
728
+ "type":"string"
729
+ }
730
+ },
731
+ "additionalProperties":true
732
+ }
733
+ },
734
+ "payloadTemplate":{
735
+ "type":"object",
736
+ "description":"Sample payload matching the expected API response structure. Used for testing field mappings and metadata schema validation.",
737
+ "additionalProperties":true
738
+ },
739
+ "expectedResult":{
740
+ "type":"object",
741
+ "description":"Expected normalized result after field mapping transformations (optional, for validation)",
742
+ "additionalProperties":true
743
+ }
744
+ },
745
+ "additionalProperties":false
746
+ },
747
+ "capabilities":{
748
+ "type":"array",
749
+ "description":"Supported operations list.",
750
+ "items":{
751
+ "type":"string",
752
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
753
+ },
754
+ "uniqueItems":true
755
+ },
756
+ "execution":{
757
+ "type":"object",
758
+ "description":"Execution engine configuration for this datasource (CIP, Python, or datasource-chaining). CIP is the native declarative mode.",
759
+ "required":[
760
+ "engine"
761
+ ],
762
+ "properties":{
763
+ "engine":{
764
+ "type":"string",
765
+ "enum":[
766
+ "cip",
767
+ "python",
768
+ "datasource"
769
+ ],
770
+ "description":"Execution engine. 'cip' for declarative pipelines, 'python' for custom handlers, 'datasource' for datasource-chained CIP execution."
771
+ },
772
+ "cip":{
773
+ "$ref":"#/$defs/cipDefinition"
774
+ },
775
+ "python":{
776
+ "$ref":"#/$defs/pythonExecution"
777
+ }
778
+ },
779
+ "additionalProperties":false
780
+ },
781
+ "config":{
782
+ "type":"object",
783
+ "description":"Additional configuration for this datasource.",
784
+ "properties":{
785
+ "extensions":{
786
+ "type":"object",
787
+ "description":"Vendor extensions namespace for controlled schema evolution.",
788
+ "propertyNames":{
789
+ "pattern":"^x[A-Z][a-zA-Z0-9]*$"
790
+ },
791
+ "additionalProperties":true
792
+ }
793
+ },
794
+ "additionalProperties":false
795
+ },
796
+ "contract":{
797
+ "$ref":"#/$defs/contractConfig"
798
+ },
799
+ "mcpContract":{
800
+ "type":"object",
801
+ "description":"Optional embedded MCP contract material (e.g. securityModel.tools and securityModel.abac) for manifest validation and CIP filter.abac policy-scope readiness. Persisted on ExternalDataSource.mcpContract when published.",
802
+ "additionalProperties":true
803
+ }
804
+ },
805
+ "allOf":[
806
+ {
807
+ "if":{
808
+ "properties":{
809
+ "entityType":{
810
+ "const":"none"
811
+ }
812
+ },
813
+ "required":[
814
+ "entityType"
815
+ ]
816
+ },
817
+ "then":{
818
+ "not":{
819
+ "anyOf":[
820
+ {
821
+ "required":[
822
+ "metadataSchema"
823
+ ]
824
+ },
825
+ {
826
+ "required":[
827
+ "primaryKey"
828
+ ]
829
+ },
830
+ {
831
+ "required":[
832
+ "labelKey"
833
+ ]
834
+ },
835
+ {
836
+ "required":[
837
+ "foreignKeys"
838
+ ]
839
+ },
840
+ {
841
+ "required":[
842
+ "dimensions"
843
+ ]
844
+ },
845
+ {
846
+ "required":[
847
+ "fieldMappings"
848
+ ]
849
+ },
850
+ {
851
+ "required":[
852
+ "sync"
853
+ ]
854
+ },
855
+ {
856
+ "required":[
857
+ "quality"
858
+ ]
859
+ },
860
+ {
861
+ "required":[
862
+ "context"
863
+ ]
864
+ },
865
+ {
866
+ "required":[
867
+ "validation"
868
+ ]
869
+ },
870
+ {
871
+ "required":[
872
+ "documentStorage"
873
+ ]
874
+ }
875
+ ]
876
+ }
877
+ },
878
+ "else":{
879
+ "required":[
880
+ "metadataSchema",
881
+ "primaryKey",
882
+ "labelKey",
883
+ "fieldMappings"
884
+ ]
885
+ }
886
+ },
887
+ {
888
+ "if":{
889
+ "properties":{
890
+ "entityType":{
891
+ "enum":[
892
+ "recordStorage",
893
+ "documentStorage"
894
+ ]
895
+ }
896
+ },
897
+ "required":[
898
+ "entityType"
899
+ ]
900
+ },
901
+ "then":{
902
+ "properties":{
903
+ "metadataSchema":{
904
+ "allOf":[
905
+ {
906
+ "$ref":"#/$defs/metadataSchemaNode"
907
+ },
908
+ {
909
+ "type":"object",
910
+ "required":[
911
+ "properties"
912
+ ],
913
+ "properties":{
914
+ "properties":{
915
+ "type":"object",
916
+ "required":[
917
+ "externalId"
918
+ ],
919
+ "properties":{
920
+ "externalId":{
921
+ "allOf":[
922
+ {
923
+ "$ref":"#/$defs/metadataSchemaNode"
924
+ },
925
+ {
926
+ "type":"object",
927
+ "properties":{
928
+ "type":{
929
+ "const":"string"
930
+ },
931
+ "index":{
932
+ "const":true
933
+ }
934
+ },
935
+ "required":[
936
+ "type",
937
+ "index"
938
+ ]
939
+ }
940
+ ]
941
+ }
942
+ }
943
+ }
944
+ }
945
+ }
946
+ ]
947
+ }
948
+ }
949
+ }
950
+ }
951
+ ],
952
+ "$defs":{
953
+ "metadataSchemaNode":{
954
+ "type":"object",
955
+ "description":"Strict supported subset of JSON Schema for metadataSchema.",
956
+ "properties":{
957
+ "description":{
958
+ "type":"string"
959
+ },
960
+ "type":{
961
+ "type":"string",
962
+ "enum":[
963
+ "object",
964
+ "array",
965
+ "string",
966
+ "number",
967
+ "integer",
968
+ "boolean",
969
+ "null"
970
+ ]
971
+ },
972
+ "properties":{
973
+ "type":"object",
974
+ "propertyNames":{
975
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
976
+ },
977
+ "additionalProperties":{
978
+ "$ref":"#/$defs/metadataSchemaNode"
979
+ }
980
+ },
981
+ "required":{
982
+ "type":"array",
983
+ "items":{
984
+ "type":"string"
985
+ },
986
+ "uniqueItems":true
987
+ },
988
+ "items":{
989
+ "$ref":"#/$defs/metadataSchemaNode"
990
+ },
991
+ "additionalProperties":{
992
+ "oneOf":[
993
+ {
994
+ "type":"boolean"
995
+ },
996
+ {
997
+ "$ref":"#/$defs/metadataSchemaNode"
998
+ }
999
+ ]
1000
+ },
1001
+ "index":{
1002
+ "type":"boolean",
1003
+ "description":"Storage/index hint for metadata persistence. True marks this field as index-eligible."
1004
+ },
1005
+ "filter":{
1006
+ "type":"boolean",
1007
+ "description":"Filterability hint for metadata-driven query planning."
1008
+ },
1009
+ "nullable":{
1010
+ "type":"boolean"
1011
+ },
1012
+ "format":{
1013
+ "type":"string",
1014
+ "description":"For datetime semantics use type='string' with format='date-time' (UTC at runtime)."
1015
+ },
1016
+ "pattern":{
1017
+ "type":"string"
1018
+ },
1019
+ "minimum":{
1020
+ "type":"number"
1021
+ },
1022
+ "maximum":{
1023
+ "type":"number"
1024
+ },
1025
+ "exclusiveMinimum":{
1026
+ "type":"number"
1027
+ },
1028
+ "exclusiveMaximum":{
1029
+ "type":"number"
1030
+ },
1031
+ "multipleOf":{
1032
+ "type":"number",
1033
+ "exclusiveMinimum":0
1034
+ },
1035
+ "minLength":{
1036
+ "type":"integer",
1037
+ "minimum":0
1038
+ },
1039
+ "maxLength":{
1040
+ "type":"integer",
1041
+ "minimum":0
1042
+ },
1043
+ "minItems":{
1044
+ "type":"integer",
1045
+ "minimum":0
1046
+ },
1047
+ "maxItems":{
1048
+ "type":"integer",
1049
+ "minimum":0
1050
+ },
1051
+ "uniqueItems":{
1052
+ "type":"boolean"
1053
+ },
1054
+ "minProperties":{
1055
+ "type":"integer",
1056
+ "minimum":0
1057
+ },
1058
+ "maxProperties":{
1059
+ "type":"integer",
1060
+ "minimum":0
1061
+ }
1062
+ },
1063
+ "allOf":[
1064
+ {
1065
+ "if":{
1066
+ "properties":{
1067
+ "format":{
1068
+ "const":"date-time"
1069
+ }
1070
+ },
1071
+ "required":[
1072
+ "format"
1073
+ ]
1074
+ },
1075
+ "then":{
1076
+ "properties":{
1077
+ "type":{
1078
+ "const":"string"
1079
+ }
1080
+ },
1081
+ "required":[
1082
+ "type"
1083
+ ]
1084
+ }
1085
+ },
1086
+ {
1087
+ "if":{
1088
+ "properties":{
1089
+ "index":{
1090
+ "const":true
1091
+ }
1092
+ },
1093
+ "required":[
1094
+ "index"
1095
+ ]
1096
+ },
1097
+ "then":{
1098
+ "properties":{
1099
+ "type":{
1100
+ "type":"string",
1101
+ "enum":[
1102
+ "string",
1103
+ "number",
1104
+ "integer",
1105
+ "boolean"
1106
+ ]
1107
+ }
1108
+ },
1109
+ "not":{
1110
+ "anyOf":[
1111
+ {
1112
+ "required":[
1113
+ "properties"
1114
+ ]
1115
+ },
1116
+ {
1117
+ "required":[
1118
+ "items"
1119
+ ]
1120
+ }
1121
+ ]
1122
+ }
1123
+ }
1124
+ },
1125
+ {
1126
+ "if":{
1127
+ "properties":{
1128
+ "filter":{
1129
+ "const":true
1130
+ }
1131
+ },
1132
+ "required":[
1133
+ "filter"
1134
+ ]
1135
+ },
1136
+ "then":{
1137
+ "properties":{
1138
+ "type":{
1139
+ "type":"string",
1140
+ "enum":[
1141
+ "string",
1142
+ "number",
1143
+ "integer",
1144
+ "boolean"
1145
+ ]
1146
+ }
1147
+ },
1148
+ "not":{
1149
+ "anyOf":[
1150
+ {
1151
+ "required":[
1152
+ "properties"
1153
+ ]
1154
+ },
1155
+ {
1156
+ "required":[
1157
+ "items"
1158
+ ]
1159
+ }
1160
+ ]
1161
+ }
1162
+ }
1163
+ }
1164
+ ],
1165
+ "additionalProperties":false
1166
+ },
1167
+ "foreignKeyDefinition":{
1168
+ "type":"object",
1169
+ "required":[
1170
+ "name",
1171
+ "fields",
1172
+ "targetDatasource"
1173
+ ],
1174
+ "properties":{
1175
+ "name":{
1176
+ "type":"string",
1177
+ "pattern":"^[a-z][a-zA-Z0-9]*$",
1178
+ "description":"Mandatory foreign key name (camelCase) for debugging, UI, and generated contracts (must be unique per datasource)."
1179
+ },
1180
+ "fields":{
1181
+ "type":"array",
1182
+ "description":"Local normalized fields forming the foreign key. Each field must exist in metadataSchema and have index=true (builder/runtime enforced).",
1183
+ "minItems":1,
1184
+ "items":{
1185
+ "type":"string",
1186
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
1187
+ },
1188
+ "uniqueItems":true
1189
+ },
1190
+ "targetDatasource":{
1191
+ "type":"string",
1192
+ "pattern":"^[a-z0-9-]+$",
1193
+ "description":"Target datasource key"
1194
+ },
1195
+ "targetFields":{
1196
+ "type":"array",
1197
+ "description":"Target fields joined by this FK. If omitted, defaults to target metadataSchema externalId ([\"externalId\"]) for cross-datasource identity (not target primaryKey). Explicit multi-field lists must not mirror the target composite primaryKey as the join contract.",
1198
+ "items":{
1199
+ "type":"string",
1200
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
1201
+ },
1202
+ "minItems":1
1203
+ },
1204
+ "required":{
1205
+ "type":"boolean",
1206
+ "default":false,
1207
+ "description":"If true, missing or invalid reference causes validation failure"
1208
+ },
1209
+ "description":{
1210
+ "type":"string"
1211
+ }
1212
+ },
1213
+ "additionalProperties":false
1214
+ },
1215
+ "dimensionBinding":{
1216
+ "type":"object",
1217
+ "required":[
1218
+ "type"
1219
+ ],
1220
+ "properties":{
1221
+ "type":{
1222
+ "type":"string",
1223
+ "enum":[
1224
+ "local",
1225
+ "fk"
1226
+ ]
1227
+ },
1228
+ "field":{
1229
+ "type":"string",
1230
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
1231
+ },
1232
+ "actor":{
1233
+ "type":"string",
1234
+ "enum":[
1235
+ "displayName",
1236
+ "email",
1237
+ "userId",
1238
+ "groups",
1239
+ "roles"
1240
+ ]
1241
+ },
1242
+ "operator":{
1243
+ "type":"string",
1244
+ "enum":[
1245
+ "eq",
1246
+ "in"
1247
+ ]
1248
+ },
1249
+ "via":{
1250
+ "type":"array",
1251
+ "minItems":1,
1252
+ "items":{
1253
+ "$ref":"#/$defs/dimensionVia"
1254
+ }
1255
+ },
1256
+ "required":{
1257
+ "type":"boolean",
1258
+ "default":true
1259
+ }
1260
+ },
1261
+ "oneOf":[
1262
+ {
1263
+ "required":[
1264
+ "field"
1265
+ ]
1266
+ },
1267
+ {
1268
+ "required":[
1269
+ "via"
1270
+ ]
1271
+ }
1272
+ ],
1273
+ "allOf":[
1274
+ {
1275
+ "if":{
1276
+ "properties":{
1277
+ "type":{
1278
+ "const":"local"
1279
+ }
1280
+ },
1281
+ "required":[
1282
+ "type"
1283
+ ]
1284
+ },
1285
+ "then":{
1286
+ "required":[
1287
+ "field"
1288
+ ],
1289
+ "not":{
1290
+ "required":[
1291
+ "via"
1292
+ ]
713
1293
  }
714
- },
715
- "additionalProperties":false
1294
+ }
716
1295
  },
717
- "credentialId":{
718
- "type":"string"
719
- }
720
- },
721
- "required":[
722
- "enabled"
723
- ],
724
- "additionalProperties":false
725
- },
726
- "portalInput":{
727
- "type":"array",
728
- "description":"Optional UI metadata definition for the AI Fabrix portal.",
729
- "items":{
730
- "type":"object",
731
- "required":[
732
- "name",
733
- "field",
734
- "label"
735
- ],
736
- "properties":{
737
- "name":{
738
- "type":"string"
739
- },
740
- "field":{
741
- "type":"string",
742
- "enum":[
743
- "text",
744
- "textarea",
745
- "select",
746
- "json",
747
- "boolean",
748
- "number"
1296
+ {
1297
+ "if":{
1298
+ "properties":{
1299
+ "type":{
1300
+ "const":"fk"
1301
+ }
1302
+ },
1303
+ "required":[
1304
+ "type"
749
1305
  ]
750
1306
  },
751
- "label":{
752
- "type":"string"
753
- },
754
- "placeholder":{
755
- "type":"string"
756
- },
757
- "options":{
758
- "type":"array",
759
- "items":{
760
- "type":"string"
1307
+ "then":{
1308
+ "required":[
1309
+ "via"
1310
+ ],
1311
+ "not":{
1312
+ "required":[
1313
+ "field"
1314
+ ]
761
1315
  }
1316
+ }
1317
+ },
1318
+ {
1319
+ "if":{
1320
+ "properties":{
1321
+ "actor":{
1322
+ "enum":[
1323
+ "displayName",
1324
+ "email",
1325
+ "userId"
1326
+ ]
1327
+ }
1328
+ },
1329
+ "required":[
1330
+ "actor"
1331
+ ]
762
1332
  },
763
- "masked":{
764
- "type":"boolean"
1333
+ "then":{
1334
+ "properties":{
1335
+ "operator":{
1336
+ "const":"eq",
1337
+ "default":"eq"
1338
+ }
1339
+ }
1340
+ }
1341
+ },
1342
+ {
1343
+ "if":{
1344
+ "properties":{
1345
+ "actor":{
1346
+ "enum":[
1347
+ "groups",
1348
+ "roles"
1349
+ ]
1350
+ }
1351
+ },
1352
+ "required":[
1353
+ "actor"
1354
+ ]
765
1355
  },
766
- "validation":{
767
- "type":"object",
1356
+ "then":{
768
1357
  "properties":{
769
- "minLength":{
770
- "type":"integer"
771
- },
772
- "maxLength":{
773
- "type":"integer"
774
- },
775
- "pattern":{
776
- "type":"string"
777
- },
778
- "required":{
779
- "type":"boolean"
1358
+ "operator":{
1359
+ "const":"in",
1360
+ "default":"in"
780
1361
  }
781
1362
  }
782
1363
  }
783
1364
  }
784
- }
1365
+ ],
1366
+ "additionalProperties":false
785
1367
  },
786
- "testPayload":{
1368
+ "dimensionVia":{
787
1369
  "type":"object",
788
- "description":"Test payload configuration for unit and integration testing",
1370
+ "required":[
1371
+ "fk",
1372
+ "dimension"
1373
+ ],
789
1374
  "properties":{
790
- "payloadTemplate":{
791
- "type":"object",
792
- "description":"Sample payload matching the expected API response structure. Used for testing field mappings and metadata schema validation.",
793
- "additionalProperties":true
1375
+ "fk":{
1376
+ "type":"string",
1377
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
794
1378
  },
795
- "expectedResult":{
796
- "type":"object",
797
- "description":"Expected normalized result after field mapping transformations (optional, for validation)",
798
- "additionalProperties":true
1379
+ "dimension":{
1380
+ "type":"string",
1381
+ "pattern":"^[a-zA-Z0-9_]+$"
799
1382
  }
800
1383
  },
801
1384
  "additionalProperties":false
802
1385
  },
803
- "capabilities":{
1386
+ "exposedSchemaNode":{
1387
+ "description":"Recursive exposed.schema node. Object values create nested API objects; string values are expression leaves.",
804
1388
  "oneOf":[
805
1389
  {
806
- "type":"array",
807
- "description":"Preferred: list of supported operation names. Values: list, get, create, update, delete.",
808
- "items":{"type":"string","enum":["list","get","create","update","delete"]},
809
- "uniqueItems":true
1390
+ "type":"string",
1391
+ "maxLength":512,
1392
+ "pattern":"^(metadata\\.[a-z][a-zA-Z0-9]*(\\.[a-zA-Z0-9_]+)*|fk\\.[a-z][a-zA-Z0-9]*\\.metadata\\.[a-z][a-zA-Z0-9]*|fk\\.[a-z][a-zA-Z0-9]*\\.dimension\\.[a-zA-Z0-9_]+(\\.label)?|dimension\\.[a-zA-Z0-9_]+(\\.label)?)$"
810
1393
  },
811
1394
  {
812
1395
  "type":"object",
813
- "description":"Legacy: object with boolean flags per operation. Accepted for backward compatibility.",
814
- "properties":{
815
- "list":{"type":"boolean"},
816
- "get":{"type":"boolean"},
817
- "create":{"type":"boolean"},
818
- "update":{"type":"boolean"},
819
- "delete":{"type":"boolean"}
820
- },
821
- "additionalProperties":false
1396
+ "minProperties":1,
1397
+ "additionalProperties":{
1398
+ "$ref":"#/$defs/exposedSchemaNode"
1399
+ }
822
1400
  }
823
- ],
824
- "description":"Supported operations. When omitted, derived from execution.engine (CIP operations or list-only for Python)."
1401
+ ]
825
1402
  },
826
- "execution":{
1403
+ "openapiOperation":{
827
1404
  "type":"object",
828
- "description":"Execution engine configuration for this datasource (CIP or Python). CIP is the native declarative mode.",
829
- "required":[
830
- "engine"
831
- ],
1405
+ "description":"Selected OpenAPI operation contract with explicit security metadata.",
832
1406
  "properties":{
833
- "engine":{
1407
+ "operationId":{
1408
+ "type":"string"
1409
+ },
1410
+ "method":{
834
1411
  "type":"string",
835
1412
  "enum":[
836
- "cip",
837
- "python"
838
- ],
839
- "description":"Execution engine. 'cip' for declarative pipelines, 'python' for custom handlers."
1413
+ "GET",
1414
+ "POST",
1415
+ "PUT",
1416
+ "PATCH",
1417
+ "DELETE"
1418
+ ]
840
1419
  },
841
- "cip":{
842
- "$ref":"#/$defs/cipDefinition"
1420
+ "path":{
1421
+ "type":"string"
843
1422
  },
844
- "python":{
845
- "$ref":"#/$defs/pythonExecution"
846
- }
847
- },
848
- "additionalProperties":false
849
- },
850
- "config":{
851
- "type":"object",
852
- "description":"Additional configuration for this datasource, including ABAC settings, MCP contracts, and other metadata.",
853
- "properties":{
854
- "abac":{
855
- "type":"object",
856
- "description":"Attribute-Based Access Control (ABAC) configuration for this datasource.",
857
- "properties":{
858
- "dimensions":{
859
- "type":"object",
860
- "description":"Data dimensions mapping. Key = dimension key (from Dimension Catalog), Value = attribute path. Overrides fieldMappings.dimensions if specified.",
861
- "additionalProperties":{
862
- "type":"string",
863
- "pattern":"^[a-zA-Z0-9_.]+$"
864
- }
1423
+ "permissions":{
1424
+ "oneOf":[
1425
+ {
1426
+ "type":"string"
865
1427
  },
866
- "crossSystemSql":{
867
- "type":"string",
868
- "description":"Cross-system ABAC filter expression in SQL format (advanced, for developers). Example: 'hubspot-companies.country = user.country AND hubspot-companies.revenue >= 1000000'"
1428
+ {
1429
+ "type":"array",
1430
+ "items":{
1431
+ "type":"string"
1432
+ },
1433
+ "minItems":1,
1434
+ "uniqueItems":true
1435
+ }
1436
+ ]
1437
+ },
1438
+ "security":{
1439
+ "description":"OpenAPI security requirements. Supports object/list/string forms consumed by RBAC coverage validation.",
1440
+ "oneOf":[
1441
+ {
1442
+ "type":"string"
869
1443
  },
870
- "crossSystemJson":{
1444
+ {
871
1445
  "type":"object",
872
- "description":"Cross-system ABAC filter expression in JSON format (simple, for UI). Example: {'hubspot-companies.country': {'eq': 'user.country'}, 'hubspot-companies.revenue': {'gte': 1000000}}",
873
1446
  "additionalProperties":{
874
- "type":"object",
875
- "properties":{
876
- "eq":{"type":["string","number","boolean"]},
877
- "ne":{"type":["string","number","boolean"]},
878
- "gt":{"type":["string","number"]},
879
- "lt":{"type":["string","number"]},
880
- "gte":{"type":["string","number"]},
881
- "lte":{"type":["string","number"]},
882
- "in":{"type":"array"},
883
- "nin":{"type":"array"},
884
- "contains":{"type":"string"},
885
- "like":{"type":"string"},
886
- "isNull":{"type":"null"},
887
- "isNotNull":{"type":"null"}
888
- }
1447
+ "oneOf":[
1448
+ {
1449
+ "type":"string"
1450
+ },
1451
+ {
1452
+ "type":"array",
1453
+ "items":{
1454
+ "type":"string"
1455
+ }
1456
+ }
1457
+ ]
1458
+ }
1459
+ },
1460
+ {
1461
+ "type":"array",
1462
+ "items":{
1463
+ "oneOf":[
1464
+ {
1465
+ "type":"string"
1466
+ },
1467
+ {
1468
+ "type":"object",
1469
+ "additionalProperties":{
1470
+ "oneOf":[
1471
+ {
1472
+ "type":"string"
1473
+ },
1474
+ {
1475
+ "type":"array",
1476
+ "items":{
1477
+ "type":"string"
1478
+ }
1479
+ }
1480
+ ]
1481
+ }
1482
+ }
1483
+ ]
889
1484
  }
890
1485
  }
1486
+ ]
1487
+ }
1488
+ },
1489
+ "additionalProperties":false
1490
+ },
1491
+ "cipRuntimeContext":{
1492
+ "type":"object",
1493
+ "description":"Runtime context requirements for CIP execution.",
1494
+ "properties":{
1495
+ "requires":{
1496
+ "type":"array",
1497
+ "items":{
1498
+ "type":"string",
1499
+ "enum":[
1500
+ "user",
1501
+ "groups",
1502
+ "environment",
1503
+ "request"
1504
+ ]
891
1505
  },
892
- "additionalProperties":false
1506
+ "uniqueItems":true
1507
+ },
1508
+ "optional":{
1509
+ "type":"array",
1510
+ "items":{
1511
+ "type":"string",
1512
+ "enum":[
1513
+ "user",
1514
+ "groups",
1515
+ "environment",
1516
+ "request"
1517
+ ]
1518
+ },
1519
+ "uniqueItems":true
893
1520
  }
894
1521
  },
895
- "additionalProperties":true
1522
+ "additionalProperties":false
896
1523
  },
897
- "contract":{
898
- "$ref":"#/$defs/contractConfig"
899
- }
900
- },
901
- "$defs":{
902
1524
  "pythonExecution":{
903
1525
  "type":"object",
904
1526
  "description":"Python-based execution config for advanced/custom use cases.",
@@ -962,7 +1584,10 @@
962
1584
  },
963
1585
  "operations":{
964
1586
  "type":"object",
965
- "description":"Logical operations (list/get/create/update/delete) implemented for this datasource.",
1587
+ "description":"Logical operations implemented for this datasource. Standard names: list, get, create, update, delete. Additional keys are allowed when they match the capability naming pattern (same as capabilities[] items).",
1588
+ "propertyNames":{
1589
+ "pattern":"^[a-z][a-zA-Z0-9]*$"
1590
+ },
966
1591
  "properties":{
967
1592
  "list":{
968
1593
  "$ref":"#/$defs/cipOperation"
@@ -980,10 +1605,15 @@
980
1605
  "$ref":"#/$defs/cipOperation"
981
1606
  }
982
1607
  },
983
- "additionalProperties":false
1608
+ "additionalProperties":{
1609
+ "$ref":"#/$defs/cipOperation"
1610
+ }
984
1611
  },
985
1612
  "idempotency":{
986
1613
  "$ref":"#/$defs/idempotencyConfig"
1614
+ },
1615
+ "runtimeContext":{
1616
+ "$ref":"#/$defs/cipRuntimeContext"
987
1617
  }
988
1618
  },
989
1619
  "additionalProperties":false
@@ -1001,9 +1631,41 @@
1001
1631
  "type":"boolean",
1002
1632
  "default":true
1003
1633
  },
1634
+ "method":{
1635
+ "type":"string",
1636
+ "enum":[
1637
+ "GET",
1638
+ "POST",
1639
+ "PUT",
1640
+ "PATCH",
1641
+ "DELETE"
1642
+ ],
1643
+ "description":"Optional canonical HTTP method for this operation contract."
1644
+ },
1645
+ "path":{
1646
+ "type":"string",
1647
+ "description":"Optional canonical route/path for this operation contract."
1648
+ },
1649
+ "input":{
1650
+ "type":"object",
1651
+ "description":"Optional operation input contract schema.",
1652
+ "additionalProperties":true
1653
+ },
1654
+ "output":{
1655
+ "type":"object",
1656
+ "description":"Optional operation output contract schema.",
1657
+ "additionalProperties":true
1658
+ },
1659
+ "safe":{
1660
+ "type":"boolean",
1661
+ "description":"Optional safety hint for operation execution."
1662
+ },
1004
1663
  "lineage":{
1005
1664
  "$ref":"#/$defs/cipLineage"
1006
1665
  },
1666
+ "identity":{
1667
+ "$ref":"#/$defs/identitySpec"
1668
+ },
1007
1669
  "steps":{
1008
1670
  "type":"array",
1009
1671
  "minItems":1,
@@ -1037,6 +1699,48 @@
1037
1699
  }
1038
1700
  ]
1039
1701
  },
1702
+ "identityMode":{
1703
+ "type":"string",
1704
+ "enum":[
1705
+ "impersonation",
1706
+ "attribution",
1707
+ "system"
1708
+ ],
1709
+ "description":"Identity execution mode for operation-level override."
1710
+ },
1711
+ "identitySpec":{
1712
+ "type":"object",
1713
+ "description":"Operation-level identity override. When omitted, external-system default applies.",
1714
+ "required":[
1715
+ "mode"
1716
+ ],
1717
+ "properties":{
1718
+ "mode":{
1719
+ "$ref":"#/$defs/identityMode"
1720
+ },
1721
+ "required":{
1722
+ "type":"boolean",
1723
+ "default":false,
1724
+ "description":"When true, fail operation if requested mode cannot be applied."
1725
+ },
1726
+ "fallback":{
1727
+ "type":"array",
1728
+ "description":"Fallback mode chain evaluated when primary mode fails.",
1729
+ "items":{
1730
+ "$ref":"#/$defs/identityMode"
1731
+ },
1732
+ "uniqueItems":true
1733
+ },
1734
+ "scopes":{
1735
+ "type":"array",
1736
+ "description":"Optional scopes requested for impersonation minting.",
1737
+ "items":{
1738
+ "type":"string"
1739
+ }
1740
+ }
1741
+ },
1742
+ "additionalProperties":false
1743
+ },
1040
1744
  "cipStepFetch":{
1041
1745
  "type":"object",
1042
1746
  "required":[
@@ -1054,20 +1758,15 @@
1054
1758
  "type":"string",
1055
1759
  "enum":[
1056
1760
  "openapi",
1057
- "http"
1761
+ "http",
1762
+ "datasource"
1058
1763
  ],
1059
- "description":"If 'openapi', refer to openapi.operations.*. If 'http', use explicit method/path."
1764
+ "description":"If 'openapi', refer to openapi.operations.*. If 'http', use explicit method/path. If 'datasource', execute another datasource operation."
1060
1765
  },
1061
1766
  "openapiRef":{
1062
1767
  "type":"string",
1063
- "enum":[
1064
- "list",
1065
- "get",
1066
- "create",
1067
- "update",
1068
- "delete"
1069
- ],
1070
- "description":"Reference to openapi.operations.<openapiRef> entry."
1768
+ "pattern":"^[a-z][a-zA-Z0-9]*$",
1769
+ "description":"Key under openapi.operations (standard CRUD: list, get, create, update, delete, or any custom name matching capabilities[] / execution.cip.operations naming)."
1071
1770
  },
1072
1771
  "operationId":{
1073
1772
  "type":"string",
@@ -1088,6 +1787,22 @@
1088
1787
  "type":"string",
1089
1788
  "description":"Explicit HTTP path when source='http'."
1090
1789
  },
1790
+ "datasource":{
1791
+ "type":"string",
1792
+ "pattern":"^[a-z0-9-]+$",
1793
+ "description":"Target datasource key when source='datasource'."
1794
+ },
1795
+ "operation":{
1796
+ "type":"string",
1797
+ "pattern":"^[a-z][a-zA-Z0-9]*$",
1798
+ "default":"list",
1799
+ "description":"Target datasource operation when source='datasource' (standard CRUD or custom CIP operation key on the target). Defaults to list."
1800
+ },
1801
+ "parameters":{
1802
+ "type":"object",
1803
+ "description":"Optional operation parameters forwarded to datasource execution when source='datasource'.",
1804
+ "additionalProperties":true
1805
+ },
1091
1806
  "query":{
1092
1807
  "type":"object",
1093
1808
  "description":"Static query parameters. ABAC/runtime can still override or append at runtime.",
@@ -1104,9 +1819,13 @@
1104
1819
  "description":"Optional static request body or template for POST/PUT/PATCH fetches.",
1105
1820
  "type":["object","string","null"]
1106
1821
  },
1822
+ "expectedItemsPath":{
1823
+ "type":"string",
1824
+ "description":"Optional response shape guard. When set, runtime validates this path exists and is non-null in fetch response."
1825
+ },
1107
1826
  "headers":{
1108
1827
  "type":"object",
1109
- "description":"Optional HTTP headers for the request.",
1828
+ "description":"Optional HTTP headers for the request (compatibility contract; runtime support may depend on executor path).",
1110
1829
  "additionalProperties":{
1111
1830
  "type":"string"
1112
1831
  }
@@ -1150,6 +1869,20 @@
1150
1869
  "path"
1151
1870
  ]
1152
1871
  }
1872
+ },
1873
+ {
1874
+ "if":{
1875
+ "properties":{
1876
+ "source":{
1877
+ "const":"datasource"
1878
+ }
1879
+ }
1880
+ },
1881
+ "then":{
1882
+ "required":[
1883
+ "datasource"
1884
+ ]
1885
+ }
1153
1886
  }
1154
1887
  ],
1155
1888
  "additionalProperties":false
@@ -1286,27 +2019,52 @@
1286
2019
  "properties":{
1287
2020
  "filter":{
1288
2021
  "type":"object",
1289
- "description":"Filter mapped records before output. Dimension enforcement is applied automatically based on fieldMappings.dimensions.",
2022
+ "description":"Filter mapped records before output.",
1290
2023
  "properties":{
1291
- "enforceAbac":{
1292
- "type":"boolean",
1293
- "default":true
1294
- },
1295
- "expression":{
1296
- "oneOf":[
1297
- {
2024
+ "abac":{
2025
+ "type":"object",
2026
+ "description":"ABAC filtering behavior for this step.",
2027
+ "properties":{
2028
+ "mode":{
1298
2029
  "type":"string",
1299
- "description":"SQL filter expression (e.g., 'status = \"active\" AND revenue >= 1000000')"
2030
+ "enum":[
2031
+ "mandatory",
2032
+ "optional",
2033
+ "disabled"
2034
+ ],
2035
+ "default":"mandatory"
1300
2036
  },
1301
- {
1302
- "type":"object",
1303
- "description":"JSON filter expression (e.g., {'status': {'eq': 'active'}, 'revenue': {'gte': 1000000}})",
1304
- "additionalProperties":{
1305
- "type":"object"
1306
- }
2037
+ "policyScope":{
2038
+ "type":"string",
2039
+ "enum":[
2040
+ "datasource",
2041
+ "system",
2042
+ "cross-system"
2043
+ ],
2044
+ "default":"datasource"
2045
+ },
2046
+ "explain":{
2047
+ "type":"boolean",
2048
+ "default":false
1307
2049
  }
2050
+ },
2051
+ "additionalProperties":false
2052
+ },
2053
+ "expression":{
2054
+ "type":"string",
2055
+ "description":"JMESPath expression evaluated after ABAC filtering."
2056
+ },
2057
+ "expressionLanguage":{
2058
+ "type":"string",
2059
+ "enum":[
2060
+ "jmespath"
1308
2061
  ],
1309
- "description":"Optional additional filter expression. Supports both SQL and JSON formats."
2062
+ "default":"jmespath"
2063
+ },
2064
+ "maxComplexity":{
2065
+ "type":"integer",
2066
+ "minimum":1,
2067
+ "default":50
1310
2068
  }
1311
2069
  },
1312
2070
  "additionalProperties":false
@@ -1432,7 +2190,7 @@
1432
2190
  },
1433
2191
  "cipCompensationConfig":{
1434
2192
  "type":"object",
1435
- "description":"Compensation (rollback) configuration for error handling.",
2193
+ "description":"Compensation (rollback) configuration for error handling. Current runtime compensation execution is focused on fetch/map step flows.",
1436
2194
  "properties":{
1437
2195
  "enabled":{
1438
2196
  "type":"boolean",