@aifabrix/builder 2.49.1 → 2.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. package/.cursor/process/README.md +9 -0
  2. package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +49 -0
  3. package/.cursor/rules/plan-rules/application-lifecycle.mdc +30 -0
  4. package/.cursor/rules/plan-rules/plan-frontmatter.mdc +35 -0
  5. package/.cursor/rules/plan-rules/plan-lifecycle.mdc +31 -0
  6. package/.cursor/rules/plan-rules/plan-validation-gate.mdc +34 -0
  7. package/.cursor/skills/README.md +1 -0
  8. package/.dockerignore +52 -0
  9. package/.eslintignore +22 -0
  10. package/README.md +2 -0
  11. package/bin/builder-api-cleanup.js +26 -0
  12. package/bin/builder-api-nest.js +10 -0
  13. package/bin/builder-api-spike.js +19 -0
  14. package/enterprise-knowledge/README.md +50 -0
  15. package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +22 -0
  16. package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +15 -0
  17. package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +69 -0
  18. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +52 -0
  19. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +29 -0
  20. package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +2 -0
  21. package/integration/README.md +81 -0
  22. package/integration/github/README.md +53 -0
  23. package/integration/github/application.json +21 -0
  24. package/integration/github/deploy.js +72 -0
  25. package/integration/github/env.template +11 -0
  26. package/integration/github/github-datasource-issue-comments.json +239 -0
  27. package/integration/github/github-datasource-issues.json +399 -0
  28. package/integration/github/github-datasource-repository.json +354 -0
  29. package/integration/github/github-deploy.json +1202 -0
  30. package/integration/github/github-system.json +82 -0
  31. package/integration/hubspot-test/README.md +1 -1
  32. package/jest.isolated-projects.js +31 -1
  33. package/jest.projects.js +87 -1
  34. package/lib/api/dev-server-https.js +1 -1
  35. package/lib/api/dev.api.js +1 -0
  36. package/lib/api/enterprise-knowledge.api.js +63 -0
  37. package/lib/api/evidence.api.js +172 -0
  38. package/lib/api/external-systems.api.js +8 -2
  39. package/lib/api/host-ops.api.js +69 -0
  40. package/lib/api/resource-types.api.js +1 -0
  41. package/lib/api/types/enterprise-knowledge.types.js +46 -0
  42. package/lib/api/types/evidence.types.js +67 -0
  43. package/lib/api/types/resource-types.types.js +2 -0
  44. package/lib/app/controller-application-filter.js +36 -0
  45. package/lib/app/deploy.js +1 -1
  46. package/lib/app/list-external-systems.js +130 -0
  47. package/lib/app/list.js +20 -8
  48. package/lib/app/run.js +3 -1
  49. package/lib/app/show-display.js +8 -3
  50. package/lib/app/show-online.js +178 -0
  51. package/lib/app/show.js +37 -88
  52. package/lib/build/builder-api-docker-staging.js +47 -0
  53. package/lib/build/miso-controller-npm-sdk-guard.js +2 -2
  54. package/lib/build/standard-docker-build.js +2 -0
  55. package/lib/certification/post-unified-cert-sync.js +4 -31
  56. package/lib/certification/sync-after-external-command.js +0 -1
  57. package/lib/certification/sync-system-certification.js +0 -3
  58. package/lib/channels/add-channel.js +40 -34
  59. package/lib/channels/approval-guides/chatgpt.js +33 -0
  60. package/lib/channels/approval-guides/credential-portal.js +38 -0
  61. package/lib/channels/approval-guides/index.js +110 -0
  62. package/lib/channels/approval-guides/microsoft-copilot.js +34 -0
  63. package/lib/channels/approval-guides/slack.js +34 -0
  64. package/lib/channels/approval-guides/teams-bot.js +35 -0
  65. package/lib/channels/approval-guides/web-embed.js +32 -0
  66. package/lib/channels/channel-approval-guide.js +11 -0
  67. package/lib/channels/channel-artifact-generator.js +16 -4
  68. package/lib/channels/channel-audit.js +3 -0
  69. package/lib/channels/channel-auth-context.js +1 -1
  70. package/lib/channels/channel-description.js +59 -0
  71. package/lib/channels/channel-integration-generator.js +13 -230
  72. package/lib/channels/channel-integration-template.js +94 -0
  73. package/lib/channels/channel-runtime-resolver.js +43 -3
  74. package/lib/channels/channel-status-display.js +66 -26
  75. package/lib/channels/channel-targets.js +3 -3
  76. package/lib/cli/index.js +27 -3
  77. package/lib/cli/infra-guided.js +5 -1
  78. package/lib/cli/setup-app-external-create.js +111 -0
  79. package/lib/cli/setup-app.help.js +1 -1
  80. package/lib/cli/setup-app.js +38 -125
  81. package/lib/cli/setup-app.test-commands.js +26 -52
  82. package/lib/cli/setup-certification-commands.js +4 -4
  83. package/lib/cli/setup-certification.help.js +9 -9
  84. package/lib/cli/setup-dev-path-commands.js +24 -0
  85. package/lib/cli/setup-dev.js +115 -16
  86. package/lib/cli/setup-external-system-help.js +4 -6
  87. package/lib/cli/setup-external-system.js +58 -52
  88. package/lib/cli/setup-infra-up-builder-api-action.js +64 -0
  89. package/lib/cli/setup-infra-up-platform-action.js +3 -1
  90. package/lib/cli/setup-infra.js +15 -0
  91. package/lib/cli/setup-list.js +43 -0
  92. package/lib/cli/setup-utility-repair.js +26 -7
  93. package/lib/cli/setup-utility.js +5 -3
  94. package/lib/commands/app.js +15 -43
  95. package/lib/commands/channel-add-setup.js +110 -0
  96. package/lib/commands/channel.js +42 -8
  97. package/lib/commands/datasource-sync-display.js +96 -0
  98. package/lib/commands/datasource-sync-policy.js +210 -0
  99. package/lib/commands/datasource-test-trust-cli.js +6 -6
  100. package/lib/commands/datasource-unified-test-cli.js +2 -1
  101. package/lib/commands/datasource-unified-test-cli.options.js +33 -23
  102. package/lib/commands/deploy-gate-failure-details.js +163 -0
  103. package/lib/commands/deploy-gate-orchestrator.js +322 -0
  104. package/lib/commands/dev-cli-handlers.js +64 -61
  105. package/lib/commands/dev-host-ops-params.js +91 -0
  106. package/lib/commands/dev-host-ops-poll.js +111 -0
  107. package/lib/commands/dev-host-ops.js +252 -0
  108. package/lib/commands/dev-init.js +3 -1
  109. package/lib/commands/enterprise-knowledge.js +284 -0
  110. package/lib/commands/evidence-cli-leaves.js +250 -0
  111. package/lib/commands/evidence.js +51 -0
  112. package/lib/commands/governance-cli-shared.js +2 -2
  113. package/lib/commands/governance-command-action.js +2 -2
  114. package/lib/commands/governance-fixture-subjects.js +85 -0
  115. package/lib/commands/governance.js +1 -1
  116. package/lib/commands/lifecycle-command-action.js +2 -2
  117. package/lib/commands/lifecycle-external.js +3 -3
  118. package/lib/commands/manifest-cli-auth.js +29 -0
  119. package/lib/commands/manifest-cli-commands.js +170 -0
  120. package/lib/commands/manifest-cli-integration-path.js +63 -0
  121. package/lib/commands/manifest.js +21 -0
  122. package/lib/commands/protection-cli-leaves.js +3 -3
  123. package/lib/commands/repair-auth-apply.js +15 -1
  124. package/lib/commands/repair-authentications-454.js +169 -0
  125. package/lib/commands/repair-capability-openapi-warnings.js +126 -0
  126. package/lib/commands/repair-datasource-apply.js +135 -0
  127. package/lib/commands/repair-datasource-auto-rbac.js +62 -1
  128. package/lib/commands/repair-datasource-http-service-contract.js +239 -0
  129. package/lib/commands/repair-datasource-operation-security.js +180 -0
  130. package/lib/commands/repair-datasource-run.js +7 -2
  131. package/lib/commands/repair-datasource-sync-operations.js +177 -0
  132. package/lib/commands/repair-datasource-webhooks-sync-bridge.js +133 -0
  133. package/lib/commands/repair-datasource.js +12 -68
  134. package/lib/commands/repair-env-template.js +11 -1
  135. package/lib/commands/repair-external-run.js +121 -31
  136. package/lib/commands/repair-internal.js +1 -1
  137. package/lib/commands/repair-openapi-export.js +156 -0
  138. package/lib/commands/repair-openapi-sync.js +19 -2
  139. package/lib/commands/repair-orchestration-datasource-split.js +259 -0
  140. package/lib/commands/repair-persist.js +22 -1
  141. package/lib/commands/repair-rbac-platform-preset.js +204 -0
  142. package/lib/commands/repair-rbac-reader-roles.js +191 -0
  143. package/lib/commands/repair-rbac.js +163 -86
  144. package/lib/commands/repair-steps.js +83 -18
  145. package/lib/commands/repair-system-permissions.js +1 -0
  146. package/lib/commands/repair.js +1 -1
  147. package/lib/commands/resource-type.js +65 -26
  148. package/lib/commands/run-post-publish-data-sync.js +68 -0
  149. package/lib/commands/setup-modes.js +1 -1
  150. package/lib/commands/test-e2e-external.js +21 -8
  151. package/lib/commands/test-governance-cli-options.js +2 -2
  152. package/lib/commands/test-trust-cli-options.js +2 -2
  153. package/lib/commands/up-builder-api-bootstrap.js +71 -0
  154. package/lib/commands/up-builder-api-provision.js +241 -0
  155. package/lib/commands/up-builder-api.js +88 -0
  156. package/lib/commands/up-common.js +25 -1
  157. package/lib/commands/upload-credential-push-log.js +117 -0
  158. package/lib/commands/upload-data-sync-finalize.js +60 -0
  159. package/lib/commands/upload-probe.js +66 -0
  160. package/lib/commands/upload-publish-context.js +4 -1
  161. package/lib/commands/upload-sidecar-followups.js +55 -27
  162. package/lib/commands/upload.js +116 -157
  163. package/lib/commands/verify-governance-combined-external.js +1 -1
  164. package/lib/commands/verify-governance-db.js +2 -2
  165. package/lib/commands/verify-operations-command-action.js +2 -2
  166. package/lib/commands/verify-operations-step-plan.js +2 -2
  167. package/lib/commands/verify-operations-steps.js +2 -2
  168. package/lib/commands/verify-trust-command-action.js +1 -1
  169. package/lib/commands/wizard-core.js +1 -1
  170. package/lib/commands/wizard-headless.js +2 -1
  171. package/lib/core/admin-secrets.js +2 -6
  172. package/lib/core/secrets-env-content.js +10 -4
  173. package/lib/core/secrets-env-write.js +2 -13
  174. package/lib/datasource/agent-trust-run.js +3 -3
  175. package/lib/datasource/deploy.js +3 -1
  176. package/lib/datasource/test-e2e.js +6 -1
  177. package/lib/datasource/unified-validation-run-body.js +4 -1
  178. package/lib/datasource/unified-validation-run.js +1 -1
  179. package/lib/deployment/deploy-poll-ui.js +73 -12
  180. package/lib/deployment/deployer-poll-run.js +113 -0
  181. package/lib/deployment/deployer.js +17 -87
  182. package/lib/evidence/dataplane-context.js +21 -0
  183. package/lib/evidence/evidence-display.js +78 -0
  184. package/lib/evidence/evidence-service.js +392 -0
  185. package/lib/external-system/deploy.js +290 -112
  186. package/lib/external-system/download.js +7 -3
  187. package/lib/external-system/test-execution.js +1 -1
  188. package/lib/external-system/test-system-level.js +8 -10
  189. package/lib/external-system/test.js +12 -6
  190. package/lib/generator/deploy-script.js +73 -0
  191. package/lib/generator/external.js +2 -1
  192. package/lib/generator/index.js +17 -2
  193. package/lib/generator/wizard.js +3 -36
  194. package/lib/internal/fs-real-sync.js +22 -1
  195. package/lib/internal/node-fs.js +2 -0
  196. package/lib/lifecycle/lifecycle-governance-options.js +1 -1
  197. package/lib/lifecycle/verify-step-progress.js +1 -1
  198. package/lib/programmatic/access-log.js +26 -0
  199. package/lib/programmatic/auth-config.js +44 -0
  200. package/lib/programmatic/bearer-auth.js +176 -0
  201. package/lib/programmatic/builder-api-request.js +175 -0
  202. package/lib/programmatic/builder-api-route-dispatch.js +82 -0
  203. package/lib/programmatic/builder-api-runtime-config.js +42 -0
  204. package/lib/programmatic/builder-api-server.js +230 -0
  205. package/lib/programmatic/builder-help-authentication-catalog.js +282 -0
  206. package/lib/programmatic/builder-help-connected-system-ui.js +266 -0
  207. package/lib/programmatic/builder-help-enterprise-sync-fabrix.js +60 -0
  208. package/lib/programmatic/builder-help-envelope.js +36 -0
  209. package/lib/programmatic/builder-help-fixtures.js +200 -0
  210. package/lib/programmatic/builder-help-governance.js +172 -0
  211. package/lib/programmatic/builder-help-schema-catalog.js +92 -0
  212. package/lib/programmatic/builder-help.js +361 -0
  213. package/lib/programmatic/capability-registry.js +77 -0
  214. package/lib/programmatic/command-options.js +32 -0
  215. package/lib/programmatic/enterprise-mcp-client.js +98 -0
  216. package/lib/programmatic/http-problem-details.js +99 -0
  217. package/lib/programmatic/http-route-match.js +40 -0
  218. package/lib/programmatic/idempotency-cache.js +69 -0
  219. package/lib/programmatic/index.js +53 -0
  220. package/lib/programmatic/integration-path-scope.js +39 -0
  221. package/lib/programmatic/log-redaction.js +66 -0
  222. package/lib/programmatic/manifest-get-section.js +146 -0
  223. package/lib/programmatic/manifest-patch-section.js +252 -0
  224. package/lib/programmatic/manifest-repair.js +122 -0
  225. package/lib/programmatic/manifest-section-dependency-graph.js +160 -0
  226. package/lib/programmatic/manifest-section-io.js +225 -0
  227. package/lib/programmatic/manifest-section-quality.js +171 -0
  228. package/lib/programmatic/manifest-section-registry-data.js +269 -0
  229. package/lib/programmatic/manifest-section-registry.js +205 -0
  230. package/lib/programmatic/nest-http-bridge.js +34 -0
  231. package/lib/programmatic/openapi-component-schemas.js +68 -0
  232. package/lib/programmatic/openapi-description-enricher.js +117 -0
  233. package/lib/programmatic/openapi-descriptions.js +190 -0
  234. package/lib/programmatic/openapi-docs-serving.js +123 -0
  235. package/lib/programmatic/openapi-help-schemas.js +63 -0
  236. package/lib/programmatic/openapi-manifest-schemas.js +141 -0
  237. package/lib/programmatic/openapi-operation-bindings.js +274 -0
  238. package/lib/programmatic/openapi-request-schemas.js +155 -0
  239. package/lib/programmatic/openapi-result-schemas.js +476 -0
  240. package/lib/programmatic/openapi-schema-descriptions-certify.js +139 -0
  241. package/lib/programmatic/openapi-schema-descriptions-core.js +159 -0
  242. package/lib/programmatic/openapi-schema-descriptions-help.js +40 -0
  243. package/lib/programmatic/openapi-schema-descriptions-manifest.js +143 -0
  244. package/lib/programmatic/openapi-schema-descriptions-mcp.js +118 -0
  245. package/lib/programmatic/openapi-schema-descriptions-operations.js +281 -0
  246. package/lib/programmatic/openapi-schema-helpers.js +93 -0
  247. package/lib/programmatic/openapi-spec.js +203 -0
  248. package/lib/programmatic/orchestration-openapi-meta.js +159 -0
  249. package/lib/programmatic/platform-rbac-catalog.js +90 -0
  250. package/lib/programmatic/request-timeout.js +53 -0
  251. package/lib/programmatic/route-handler-map.js +143 -0
  252. package/lib/programmatic/route-handlers-context.js +29 -0
  253. package/lib/programmatic/route-handlers.js +33 -0
  254. package/lib/programmatic/run-certify.js +57 -0
  255. package/lib/programmatic/run-enterprise-mcp.js +32 -0
  256. package/lib/programmatic/run-lifecycle.js +29 -0
  257. package/lib/programmatic/run-repair.js +41 -0
  258. package/lib/programmatic/run-repository-emcp.js +54 -0
  259. package/lib/programmatic/run-template-workspace.js +61 -0
  260. package/lib/programmatic/run-test.js +49 -0
  261. package/lib/programmatic/run-upload.js +63 -0
  262. package/lib/programmatic/run-validate.js +53 -0
  263. package/lib/programmatic/run-wizard.js +40 -0
  264. package/lib/programmatic/system-key.js +48 -0
  265. package/lib/programmatic/wizard-config-normalize.js +118 -0
  266. package/lib/programmatic/workspace-cleanup.js +128 -0
  267. package/lib/programmatic/workspace-context.js +145 -0
  268. package/lib/programmatic/workspace-lock.js +75 -0
  269. package/lib/programmatic/workspace-meta.js +64 -0
  270. package/lib/programmatic/workspace-ops.js +149 -0
  271. package/lib/protection/run-commands-upload-sync.js +35 -0
  272. package/lib/protection/run-commands.js +2 -20
  273. package/lib/protection/upload-batch.js +11 -7
  274. package/lib/resolvers/resource-type-file.js +22 -0
  275. package/lib/schema/external-datasource.schema.json +161 -1
  276. package/lib/schema/external-system.schema.json +242 -4
  277. package/lib/schema/flag-map-validation-run.json +3 -0
  278. package/lib/schema/type/credential-field-registry.json +2 -2
  279. package/lib/schema/type/document-storage.json +9 -0
  280. package/lib/utils/agent-trust-run-display.js +1 -1
  281. package/lib/utils/app-path-resolve.js +168 -0
  282. package/lib/utils/authentication-env-template.js +222 -0
  283. package/lib/utils/cli-sync-options.js +7 -11
  284. package/lib/utils/cli-utils.js +4 -0
  285. package/lib/utils/cli-workspace-options.js +29 -0
  286. package/lib/utils/compose-generate-docker-compose.js +102 -0
  287. package/lib/utils/configuration-env-resolver.js +203 -27
  288. package/lib/utils/datasource-test-run-certificate-tty.js +28 -2
  289. package/lib/utils/datasource-test-run-certification-debug.js +130 -0
  290. package/lib/utils/datasource-test-run-debug-display.js +2 -0
  291. package/lib/utils/datasource-test-run-debug-slice.js +7 -0
  292. package/lib/utils/datasource-test-run-display.js +2 -1
  293. package/lib/utils/dev-init-ssh-merge.js +165 -23
  294. package/lib/utils/dev-pin-share-instructions.js +110 -0
  295. package/lib/utils/dev-ssh-config-helper.js +177 -33
  296. package/lib/utils/enterprise-knowledge-paths.js +142 -0
  297. package/lib/utils/env-copy.js +2 -1
  298. package/lib/utils/env-dotenv-format.js +103 -0
  299. package/lib/utils/external-env-template.js +4 -1
  300. package/lib/utils/external-system-display.js +5 -1
  301. package/lib/utils/external-system-readiness-compact-blocks.js +221 -0
  302. package/lib/utils/external-system-readiness-compact-display.js +324 -0
  303. package/lib/utils/external-system-readiness-core.js +16 -0
  304. package/lib/utils/external-system-readiness-deploy-display.js +29 -11
  305. package/lib/utils/external-system-readiness-display-internals.js +3 -1
  306. package/lib/utils/external-system-readiness-display.js +20 -30
  307. package/lib/utils/external-system-system-test-tty-certification.js +135 -0
  308. package/lib/utils/external-system-system-test-tty.js +5 -41
  309. package/lib/utils/help-builder.js +6 -1
  310. package/lib/utils/host-ops-job-labels.js +236 -0
  311. package/lib/utils/host-ops-job-result.js +61 -0
  312. package/lib/utils/host-ops-poll-ui.js +163 -0
  313. package/lib/utils/integration-path-resolve.js +112 -0
  314. package/lib/utils/paths-reload-source.js +148 -0
  315. package/lib/utils/paths-system-builder-keys.js +25 -0
  316. package/lib/utils/paths.js +151 -26
  317. package/lib/utils/runtime-configuration-values.js +64 -2
  318. package/lib/utils/secrets-helpers.js +5 -1
  319. package/lib/utils/ssh-known-hosts.js +130 -0
  320. package/lib/utils/test-target-cli-options.js +75 -0
  321. package/lib/utils/upload-sync-options.js +4 -0
  322. package/lib/utils/validation-run-request.js +11 -2
  323. package/lib/validation/external-manifest-validator.js +11 -1
  324. package/lib/validation/openapi-contract-surface-validator.js +426 -0
  325. package/lib/validation/openapi-contract-vendor-validation.js +238 -0
  326. package/lib/validation/validate-external-file.js +160 -0
  327. package/lib/validation/validate.js +6 -117
  328. package/package.json +46 -29
  329. package/packages/builder-api/README.md +120 -0
  330. package/packages/builder-api/package.json +30 -0
  331. package/packages/builder-api/src/app.module.ts +7 -0
  332. package/packages/builder-api/src/auth/auth.module.ts +5 -0
  333. package/packages/builder-api/src/external-system/external-system.module.ts +5 -0
  334. package/packages/builder-api/src/main.ts +16 -0
  335. package/packages/builder-api/tsconfig.json +15 -0
  336. package/scripts/check-builder-api-architecture-grep.js +79 -0
  337. package/scripts/docker_image_content_gate.js +47 -0
  338. package/scripts/docker_image_content_gate.sh +5 -0
  339. package/scripts/export-builder-api-evidence.js +262 -0
  340. package/scripts/lib/builder-api-docker-staging-copy.js +60 -0
  341. package/scripts/lib/builder-api-docker-staging-core.js +183 -0
  342. package/scripts/lib/docker-image-content-gate-core.js +166 -0
  343. package/scripts/lib/plan-actor.js +109 -0
  344. package/scripts/lib/plan-config.js +20 -0
  345. package/scripts/lib/plan-gates.js +154 -0
  346. package/scripts/lib/plan-meta.js +104 -0
  347. package/scripts/lib/plan-parse.js +162 -0
  348. package/scripts/lib/plan-prevalidate-gates.js +326 -0
  349. package/scripts/lib/plan-run-core.js +125 -0
  350. package/scripts/lib/plan-run-report.js +108 -0
  351. package/scripts/plan-approve.js +24 -0
  352. package/scripts/plan-archive.js +49 -0
  353. package/scripts/plan-run.js +13 -0
  354. package/scripts/plan-set-actor.js +21 -0
  355. package/scripts/plan-validate.js +80 -0
  356. package/scripts/pnpm/af.mjs +110 -0
  357. package/scripts/pnpm/check-quiet.mjs +32 -0
  358. package/scripts/pnpm/dev-install.mjs +29 -0
  359. package/scripts/pnpm/dev-reload.mjs +18 -0
  360. package/scripts/pnpm/help.mjs +55 -0
  361. package/scripts/pnpm/lib/dev-reload-core.mjs +189 -0
  362. package/scripts/pnpm/lib/dev-reload-log-capture.mjs +67 -0
  363. package/scripts/pnpm/lib/dev-reload-log-utils.mjs +32 -0
  364. package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +124 -0
  365. package/scripts/pnpm/lib/resolve-app-url.mjs +183 -0
  366. package/scripts/pnpm/lib/spinner.mjs +42 -0
  367. package/scripts/stage_builder_api_for_docker.js +65 -0
  368. package/scripts/sync-builder-api-template.js +44 -0
  369. package/templates/README.md +3 -0
  370. package/templates/applications/builder-api/Dockerfile +38 -0
  371. package/templates/applications/builder-api/application.yaml +75 -0
  372. package/templates/applications/builder-api/env.template +48 -0
  373. package/templates/applications/dataplane/application.yaml +1 -1
  374. package/templates/applications/dataplane/env.template +10 -6
  375. package/templates/applications/dataplane/rbac.yaml +21 -1
  376. package/templates/applications/miso-controller/application.yaml +1 -1
  377. package/templates/applications/miso-controller/env.template +1 -3
  378. package/templates/channels/README.md +18 -0
  379. package/templates/channels/ai-fabrix-icon.jpg +0 -0
  380. package/templates/channels/chatgpt/install.template.md.hbs +21 -24
  381. package/templates/channels/chatgpt/integration/README.md +11 -0
  382. package/templates/channels/chatgpt/integration/application.json +15 -0
  383. package/templates/channels/chatgpt/integration/chatgpt-system.json +29 -0
  384. package/templates/channels/chatgpt/integration/env.template +4 -0
  385. package/templates/channels/microsoft-copilot/install.template.md.hbs +20 -25
  386. package/templates/channels/microsoft-copilot/integration/README.md +11 -0
  387. package/templates/channels/microsoft-copilot/integration/application.json +15 -0
  388. package/templates/channels/microsoft-copilot/integration/env.template +6 -0
  389. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +34 -0
  390. package/templates/channels/slack/install.template.md.hbs +48 -18
  391. package/templates/channels/slack/integration/README.md +38 -0
  392. package/templates/channels/slack/integration/application.json +18 -0
  393. package/templates/channels/slack/integration/env.template +29 -0
  394. package/templates/channels/slack/integration/slack-datasource-conversations.json +226 -0
  395. package/templates/channels/slack/integration/slack-datasource-messages.json +269 -0
  396. package/templates/channels/slack/integration/slack-system.json +86 -0
  397. package/templates/channels/slack/manifest.template.json.hbs +20 -10
  398. package/templates/channels/teams-bot/install.template.md.hbs +31 -17
  399. package/templates/channels/teams-bot/integration/README.md +18 -0
  400. package/templates/channels/teams-bot/integration/application.json +17 -0
  401. package/templates/channels/teams-bot/integration/env.template +5 -0
  402. package/templates/channels/teams-bot/integration/teams-bot-system.json +55 -0
  403. package/templates/channels/teams-bot/manifest.template.json.hbs +27 -0
  404. package/templates/channels/web-embed/install.template.md.hbs +16 -26
  405. package/templates/channels/web-embed/integration/README.md +11 -0
  406. package/templates/channels/web-embed/integration/application.json +15 -0
  407. package/templates/channels/web-embed/integration/env.template +4 -0
  408. package/templates/channels/web-embed/integration/web-embed-system.json +29 -0
  409. package/templates/openapi/redoc_page.html +86 -0
  410. package/templates/python/docker-compose.hbs +11 -0
  411. package/templates/python/requirements.txt +1 -1
  412. package/templates/typescript/docker-compose.hbs +11 -0
  413. package/lib/certification/cli-cert-sync-skip.js +0 -21
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @fileoverview CLI normalization for manifest version target and test sync policy (456.17).
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const SYNC_MODES = new Set(['auto', 'never', 'force']);
10
+ const VERSION_KEYWORDS = new Set(['latest', 'running']);
11
+
12
+ /**
13
+ * @param {string|undefined|null} raw
14
+ * @param {string} [defaultValue='latest']
15
+ * @returns {string}
16
+ */
17
+ function normalizeVersionTarget(raw, defaultValue = 'latest') {
18
+ const value = String(raw ?? defaultValue).trim();
19
+ if (!value) {
20
+ throw new Error('--version is required (latest, running, or explicit version id).');
21
+ }
22
+ const lower = value.toLowerCase();
23
+ if (VERSION_KEYWORDS.has(lower)) {
24
+ return lower;
25
+ }
26
+ if (!/^[a-zA-Z0-9._-]+$/.test(value)) {
27
+ throw new Error(
28
+ '--version must be latest, running, or an explicit version id (letters, numbers, ., _, -).'
29
+ );
30
+ }
31
+ return value;
32
+ }
33
+
34
+ /**
35
+ * @param {string|undefined|null} raw
36
+ * @param {string} [defaultValue='auto']
37
+ * @returns {string}
38
+ */
39
+ function normalizeSyncMode(raw, defaultValue = 'auto') {
40
+ const value = String(raw ?? defaultValue).trim().toLowerCase();
41
+ if (!SYNC_MODES.has(value)) {
42
+ throw new Error('--sync-mode must be auto, never, or force.');
43
+ }
44
+ return value;
45
+ }
46
+
47
+ /**
48
+ * Merge versionTarget and syncMode from CLI options into e2eOptions for ValidationRunRequest.
49
+ *
50
+ * @param {Object} cliOptions - Commander-parsed options
51
+ * @param {Object} [e2eOptions={}]
52
+ * @returns {Object}
53
+ */
54
+ function mergeTestTargetIntoE2eOptions(cliOptions, e2eOptions = {}) {
55
+ const merged = { ...e2eOptions };
56
+ if (cliOptions && cliOptions.version !== undefined && cliOptions.version !== null) {
57
+ merged.versionTarget = normalizeVersionTarget(cliOptions.version);
58
+ } else {
59
+ merged.versionTarget = normalizeVersionTarget(undefined, 'latest');
60
+ }
61
+ if (cliOptions && cliOptions.syncMode !== undefined && cliOptions.syncMode !== null) {
62
+ merged.syncMode = normalizeSyncMode(cliOptions.syncMode);
63
+ } else {
64
+ merged.syncMode = normalizeSyncMode(undefined, 'auto');
65
+ }
66
+ return merged;
67
+ }
68
+
69
+ module.exports = {
70
+ SYNC_MODES,
71
+ VERSION_KEYWORDS,
72
+ normalizeVersionTarget,
73
+ normalizeSyncMode,
74
+ mergeTestTargetIntoE2eOptions
75
+ };
@@ -19,11 +19,15 @@ function buildMinimalUploadSyncOptions(options = {}) {
19
19
  verbose: false,
20
20
  silentResolve: true,
21
21
  syncMode: true,
22
+ skipDataSync: true,
22
23
  suppressPipelineSpinner: options.suppressPipelineSpinner === true
23
24
  };
24
25
  if (options.force === true) {
25
26
  out.force = true;
26
27
  }
28
+ if (options.suppressSummary === true) {
29
+ out.suppressSummary = true;
30
+ }
27
31
  return out;
28
32
  }
29
33
 
@@ -4,6 +4,8 @@
4
4
  * @version 2.0.0
5
5
  */
6
6
 
7
+ const { mergeTestTargetIntoE2eOptions, normalizeVersionTarget } = require('./test-target-cli-options');
8
+
7
9
  /**
8
10
  * Whether the unified validation request should set includeDebug (any `--debug` or `--debug <level>`).
9
11
  * @param {*} debugOpt - Commander `options.debug`
@@ -60,7 +62,7 @@ function buildE2eOptionsFromCli(options = {}) {
60
62
  if (options.e2eOptionsExtra && typeof options.e2eOptionsExtra === 'object') {
61
63
  Object.assign(e2e, options.e2eOptionsExtra);
62
64
  }
63
- return e2e;
65
+ return mergeTestTargetIntoE2eOptions(options, e2e);
64
66
  }
65
67
 
66
68
  /**
@@ -73,6 +75,8 @@ function buildE2eOptionsFromCli(options = {}) {
73
75
  * @param {boolean} [params.asyncRun]
74
76
  * @param {boolean} [params.includeDebug]
75
77
  * @param {boolean} [params.explain]
78
+ * @param {boolean} [params.explainCertification]
79
+ * @param {boolean} [params.explainMetrics]
76
80
  * @param {Object} [params.e2eOptions] - Merged with buildE2eOptionsFromCli when both used by caller
77
81
  * @returns {import('../api/types/validation-run.types').ValidationRunRequestBody}
78
82
  */
@@ -85,6 +89,8 @@ function buildExternalDataSourceValidationRequest(params) {
85
89
  asyncRun,
86
90
  includeDebug,
87
91
  explain,
92
+ explainCertification,
93
+ explainMetrics,
88
94
  e2eOptions
89
95
  } = params;
90
96
  if (!systemKey || !datasourceKey || !runType) {
@@ -101,6 +107,8 @@ function buildExternalDataSourceValidationRequest(params) {
101
107
  if (asyncRun === true) body.asyncRun = true;
102
108
  if (includeDebug === true) body.includeDebug = true;
103
109
  if (explain === true) body.explain = true;
110
+ if (explainCertification === true) body.explainCertification = true;
111
+ if (explainMetrics === true) body.explainMetrics = true;
104
112
  if (e2eOptions && typeof e2eOptions === 'object' && Object.keys(e2eOptions).length > 0) {
105
113
  body.e2eOptions = e2eOptions;
106
114
  }
@@ -110,5 +118,6 @@ function buildExternalDataSourceValidationRequest(params) {
110
118
  module.exports = {
111
119
  includeDebugForRequest,
112
120
  buildE2eOptionsFromCli,
113
- buildExternalDataSourceValidationRequest
121
+ buildExternalDataSourceValidationRequest,
122
+ normalizeVersionTarget
114
123
  };
@@ -17,6 +17,7 @@ const { formatValidationErrors } = require('../utils/error-formatter');
17
17
  const { validateFieldReferences } = require('../datasource/field-reference-validator');
18
18
  const { validateAbac } = require('../datasource/abac-validator');
19
19
  const { validateManifestRuntimeConfiguration } = require('./runtime-configuration-rules');
20
+ const { validateAppContractSurface } = require('./openapi-contract-surface-validator');
20
21
 
21
22
  /**
22
23
  * Load and normalize external-system + external-datasource schema objects for manifest AJV.
@@ -223,6 +224,7 @@ function validateDatasourceSystemKeyAlignment(manifest, errors) {
223
224
  * @async
224
225
  * @function validateControllerManifest
225
226
  * @param {Object} manifest - Controller manifest object
227
+ * @param {Object} [options] - Optional context (appPath for contract-surface checks)
226
228
  * @returns {Promise<Object>} Validation result
227
229
  * @throws {Error} If validation fails critically
228
230
  *
@@ -230,7 +232,7 @@ function validateDatasourceSystemKeyAlignment(manifest, errors) {
230
232
  * const result = await validateControllerManifest(manifest);
231
233
  * // Returns: { valid: true, errors: [], warnings: [] }
232
234
  */
233
- async function validateControllerManifest(manifest) {
235
+ async function validateControllerManifest(manifest, options = {}) {
234
236
  if (!manifest || typeof manifest !== 'object') {
235
237
  return {
236
238
  valid: false,
@@ -249,6 +251,14 @@ async function validateControllerManifest(manifest) {
249
251
  validateDatasources(manifest, ajv, externalDatasourceSchema, errors, warnings);
250
252
  validateDatasourceSystemKeyAlignment(manifest, errors);
251
253
  errors.push(...validateManifestRuntimeConfiguration(manifest));
254
+ if (manifest.type === 'external' && Array.isArray(manifest.dataSources) && manifest.system?.key) {
255
+ const appPath = options.appPath;
256
+ if (typeof appPath === 'string' && appPath) {
257
+ const contract = validateAppContractSurface(appPath, manifest.system.key, manifest.dataSources);
258
+ errors.push(...contract.errors);
259
+ warnings.push(...contract.warnings);
260
+ }
261
+ }
252
262
  validateConditionalRequirements(manifest, errors, warnings);
253
263
  validateRequiredFields(manifest, errors);
254
264
 
@@ -0,0 +1,426 @@
1
+ /**
2
+ * Validate that OpenAPI / MCP contract surfaces are meaningful (not dataplane stubs).
3
+ *
4
+ * @fileoverview Contract surface validation for orchestration vs record datasources
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const { buildOpenApiSpec } = require('../programmatic/openapi-spec');
14
+ const {
15
+ documentKeyToLocalOpenApiPath,
16
+ isProgrammaticOrchestrationSystem,
17
+ specHasComponentSchemas
18
+ } = require('../commands/repair-openapi-export');
19
+ const {
20
+ validateVendorOperationContract,
21
+ findVendorOperation,
22
+ validateOrchestrationDatasourceContracts
23
+ } = require('./openapi-contract-vendor-validation');
24
+
25
+ const JSON_METHODS = new Set(['get', 'post', 'put', 'patch', 'delete', 'head', 'options']);
26
+
27
+ /**
28
+ * @param {Object} ds
29
+ * @returns {boolean}
30
+ */
31
+ function isServiceContractDatasource(ds) {
32
+ const entity = String(ds?.entityType || '').trim().toLowerCase();
33
+ return entity === 'servicecontract';
34
+ }
35
+
36
+ /**
37
+ * @param {Object} ds
38
+ * @returns {boolean}
39
+ */
40
+ function isCompositionNoneDatasource(ds) {
41
+ return String(ds?.entityType || '').trim().toLowerCase() === 'none';
42
+ }
43
+
44
+ /**
45
+ * @param {Object} ds
46
+ * @returns {boolean}
47
+ */
48
+ function hasVendorOpenapiOnManifest(ds) {
49
+ const openapi = ds?.openapi;
50
+ if (!openapi || typeof openapi !== 'object' || openapi.enabled === false) {
51
+ return false;
52
+ }
53
+ const operations = openapi.operations;
54
+ if (operations && typeof operations === 'object' && Object.keys(operations).length > 0) {
55
+ return true;
56
+ }
57
+ const documentKey =
58
+ typeof openapi.documentKey === 'string' ? openapi.documentKey.trim() : '';
59
+ return Boolean(documentKey) || openapi.enabled === true;
60
+ }
61
+
62
+ /**
63
+ * @deprecated use isServiceContractDatasource — kept for tests importing legacy name
64
+ * @param {Object} ds
65
+ * @returns {boolean}
66
+ */
67
+ function isOrchestrationDatasource(ds) {
68
+ return isServiceContractDatasource(ds);
69
+ }
70
+
71
+ /**
72
+ * @param {Object|undefined} op
73
+ * @returns {boolean}
74
+ */
75
+ function operationHasRequestOrResponseSchema(op) {
76
+ if (!op || typeof op !== 'object') {
77
+ return false;
78
+ }
79
+ if (op.requestBody) {
80
+ return true;
81
+ }
82
+ const responses = op.responses;
83
+ if (!responses || typeof responses !== 'object') {
84
+ return false;
85
+ }
86
+ for (const response of Object.values(responses)) {
87
+ if (response && typeof response === 'object' && response.content) {
88
+ return true;
89
+ }
90
+ }
91
+ return false;
92
+ }
93
+
94
+ /**
95
+ * @param {Object|undefined} paths
96
+ * @returns {boolean}
97
+ */
98
+ function pathsHaveRequestOrResponseSchemas(paths) {
99
+ if (!paths || typeof paths !== 'object') {
100
+ return false;
101
+ }
102
+ for (const pathItem of Object.values(paths)) {
103
+ if (!pathItem || typeof pathItem !== 'object') {
104
+ continue;
105
+ }
106
+ for (const [method, op] of Object.entries(pathItem)) {
107
+ if (!JSON_METHODS.has(method)) {
108
+ continue;
109
+ }
110
+ if (operationHasRequestOrResponseSchema(op)) {
111
+ return true;
112
+ }
113
+ }
114
+ }
115
+ return false;
116
+ }
117
+
118
+ /**
119
+ * @param {unknown} spec
120
+ * @returns {boolean}
121
+ */
122
+ function isThinOpenApiSpec(spec) {
123
+ if (!spec || typeof spec !== 'object') {
124
+ return true;
125
+ }
126
+ if (specHasComponentSchemas(spec)) {
127
+ return false;
128
+ }
129
+ return !pathsHaveRequestOrResponseSchemas(spec.paths);
130
+ }
131
+
132
+ /**
133
+ * @param {string} filePath
134
+ * @returns {Object|null}
135
+ */
136
+ function readJsonIfExists(filePath) {
137
+ if (!filePath || !fs.existsSync(filePath)) {
138
+ return null;
139
+ }
140
+ try {
141
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
142
+ } catch {
143
+ return null;
144
+ }
145
+ }
146
+
147
+ /**
148
+ * @param {string} appPath
149
+ * @param {string} systemKey
150
+ * @param {string} documentKey
151
+ * @returns {{ spec: Object|null, localPath: string, fromMemory: boolean }}
152
+ */
153
+ function resolveVendorOpenApiSpec(appPath, systemKey, documentKey) {
154
+ const localPath = documentKeyToLocalOpenApiPath(appPath, systemKey, documentKey);
155
+ const fromDisk = readJsonIfExists(localPath);
156
+ if (fromDisk) {
157
+ return { spec: fromDisk, localPath, fromMemory: false };
158
+ }
159
+ if (isProgrammaticOrchestrationSystem(systemKey)) {
160
+ const spec = buildOpenApiSpec();
161
+ return { spec, localPath, fromMemory: true };
162
+ }
163
+ return { spec: null, localPath, fromMemory: false };
164
+ }
165
+
166
+ /**
167
+ * @param {Object} ds
168
+ * @param {string} prefix
169
+ * @returns {string[]}
170
+ */
171
+ function collectServiceContractFieldMappingErrors(ds, prefix) {
172
+ const fieldMappings = ds.fieldMappings;
173
+ const attributes =
174
+ fieldMappings && typeof fieldMappings === 'object' ? fieldMappings.attributes : null;
175
+ const hasAttributes =
176
+ attributes && typeof attributes === 'object' && Object.keys(attributes).length > 0;
177
+ if (hasAttributes) {
178
+ return [];
179
+ }
180
+ return [
181
+ `${prefix}serviceContract requires fieldMappings.attributes — public contract must be testable`
182
+ ];
183
+ }
184
+
185
+ /**
186
+ * @param {Object} ds
187
+ * @param {string} prefix
188
+ * @returns {{ errors: string[], warnings: string[] }}
189
+ */
190
+ function collectServiceContractExposedIssues(ds, prefix) {
191
+ const errors = [];
192
+ const warnings = [];
193
+ const exposed = ds.exposed;
194
+ const schema = exposed && typeof exposed === 'object' ? exposed.schema : null;
195
+ if (!schema || typeof schema !== 'object' || Object.keys(schema).length === 0) {
196
+ errors.push(`${prefix}serviceContract requires exposed.schema for MCP/REST contract`);
197
+ }
198
+ const profiles = exposed && typeof exposed === 'object' ? exposed.profiles : null;
199
+ if (!profiles || typeof profiles !== 'object' || Object.keys(profiles).length === 0) {
200
+ warnings.push(`${prefix}serviceContract missing exposed.profiles — add default envelope`);
201
+ }
202
+ return { errors, warnings };
203
+ }
204
+
205
+ /**
206
+ * @param {Object} ds
207
+ * @param {string} prefix
208
+ * @returns {{ errors: string[], warnings: string[] }}
209
+ */
210
+ function validateServiceContractDatasourceContracts(ds, prefix) {
211
+ const errors = collectServiceContractFieldMappingErrors(ds, prefix);
212
+ const exposed = collectServiceContractExposedIssues(ds, prefix);
213
+ errors.push(...exposed.errors);
214
+ return { errors, warnings: exposed.warnings };
215
+ }
216
+
217
+ /**
218
+ * @param {Object} ds
219
+ * @param {string} prefix
220
+ * @returns {{ errors: string[], warnings: string[] }}
221
+ */
222
+ function validateRecordDatasourceContracts(ds, prefix) {
223
+ const errors = [];
224
+ const warnings = [];
225
+ const caps = ds.capabilities;
226
+ const capList = Array.isArray(caps) ? caps.map((c) => String(c).toLowerCase()) : [];
227
+ const needsExposed = capList.some((c) => ['create', 'update', 'list', 'get'].includes(c));
228
+ const fieldMappings = ds.fieldMappings;
229
+ const attributes =
230
+ fieldMappings && typeof fieldMappings === 'object' ? fieldMappings.attributes : null;
231
+ const hasAttributes =
232
+ attributes && typeof attributes === 'object' && Object.keys(attributes).length > 0;
233
+ if (!hasAttributes) {
234
+ errors.push(
235
+ `${prefix}fieldMappings.attributes is missing or empty — record entities need mapped fields for sync and MCP schemas`
236
+ );
237
+ }
238
+ const exposed = ds.exposed;
239
+ const profiles = exposed && typeof exposed === 'object' ? exposed.profiles : null;
240
+ const hasProfiles =
241
+ profiles && typeof profiles === 'object' && Object.keys(profiles).length > 0;
242
+ if (needsExposed && !hasProfiles) {
243
+ errors.push(
244
+ `${prefix}exposed.profiles is missing or empty — record entities need exposed schema profiles for MCP/OpenAPI`
245
+ );
246
+ }
247
+ return { errors, warnings };
248
+ }
249
+
250
+ /**
251
+ * @param {Object} ds
252
+ * @param {string} prefix
253
+ * @returns {{ errors: string[], warnings: string[] }}
254
+ */
255
+ function validateNoneDatasourceContract(ds, prefix) {
256
+ const errors = [];
257
+ const warnings = [];
258
+ if (hasVendorOpenapiOnManifest(ds)) {
259
+ warnings.push(
260
+ `${prefix}entityType none must not bind vendor OpenAPI — run repair to migrate to serviceContract`
261
+ );
262
+ }
263
+ return { errors, warnings };
264
+ }
265
+
266
+ /**
267
+ * @param {string} documentKey
268
+ * @param {string} prefix
269
+ * @param {string} appPath
270
+ * @param {string} systemKey
271
+ * @param {Map<string, Object|null>} vendorCache
272
+ * @returns {{ errors: string[], warnings: string[] }}
273
+ */
274
+ function resolveCachedVendorSpec(documentKey, prefix, appPath, systemKey, vendorCache) {
275
+ const errors = [];
276
+ const warnings = [];
277
+ const resolved = resolveVendorOpenApiSpec(appPath, systemKey, documentKey);
278
+ vendorCache.set(documentKey, resolved.spec);
279
+ if (!resolved.spec) {
280
+ errors.push(
281
+ `${prefix}missing vendor OpenAPI at ${resolved.localPath} — run: aifabrix repair ${systemKey} --api`
282
+ );
283
+ return { errors, warnings, spec: null };
284
+ }
285
+ if (isThinOpenApiSpec(resolved.spec)) {
286
+ errors.push(
287
+ `${prefix}vendor OpenAPI "${documentKey}" is a thin stub (no component schemas / body schemas) — run: aifabrix repair ${systemKey} --api`
288
+ );
289
+ return { errors, warnings, spec: null };
290
+ }
291
+ if (resolved.fromMemory) {
292
+ warnings.push(
293
+ `${prefix}vendor OpenAPI "${documentKey}" not on disk; validated from in-memory programmatic spec — run: aifabrix repair ${systemKey} --api to materialize openapi/`
294
+ );
295
+ }
296
+ return { errors, warnings, spec: resolved.spec };
297
+ }
298
+
299
+ /**
300
+ * @param {Object} ds
301
+ * @param {string} prefix
302
+ * @param {string} appPath
303
+ * @param {string} systemKey
304
+ * @param {Map<string, Object|null>} vendorCache
305
+ * @returns {{ errors: string[], warnings: string[] }}
306
+ */
307
+ function validateServiceContractVendorOpenApi(ds, prefix, appPath, systemKey, vendorCache) {
308
+ const errors = [];
309
+ const warnings = [];
310
+ const documentKey =
311
+ typeof ds.openapi?.documentKey === 'string' ? ds.openapi.documentKey.trim() : '';
312
+ if (!documentKey) {
313
+ errors.push(`${prefix}serviceContract with OpenAPI upstream requires openapi.documentKey`);
314
+ return { errors, warnings };
315
+ }
316
+ if (!vendorCache.has(documentKey)) {
317
+ const cached = resolveCachedVendorSpec(documentKey, prefix, appPath, systemKey, vendorCache);
318
+ errors.push(...cached.errors);
319
+ warnings.push(...cached.warnings);
320
+ if (!cached.spec) {
321
+ return { errors, warnings };
322
+ }
323
+ }
324
+ const vendorSpec = vendorCache.get(documentKey);
325
+ const orch = validateOrchestrationDatasourceContracts(ds, vendorSpec, prefix);
326
+ errors.push(...orch.errors);
327
+ warnings.push(...orch.warnings);
328
+ return { errors, warnings };
329
+ }
330
+
331
+ /**
332
+ * @param {Object} ds
333
+ * @param {string} appPath
334
+ * @param {string} systemKey
335
+ * @param {Map<string, Object|null>} vendorCache
336
+ * @returns {{ errors: string[], warnings: string[] }}
337
+ */
338
+ function validateDatasourceContractSurface(ds, appPath, systemKey, vendorCache) {
339
+ const prefix = `Datasource "${ds.key || '(unknown)'}": `;
340
+ if (isCompositionNoneDatasource(ds)) {
341
+ return validateNoneDatasourceContract(ds, prefix);
342
+ }
343
+ if (isServiceContractDatasource(ds)) {
344
+ const sc = validateServiceContractDatasourceContracts(ds, prefix);
345
+ const vendor = validateServiceContractVendorOpenApi(
346
+ ds,
347
+ prefix,
348
+ appPath,
349
+ systemKey,
350
+ vendorCache
351
+ );
352
+ return {
353
+ errors: [...sc.errors, ...vendor.errors],
354
+ warnings: [...sc.warnings, ...vendor.warnings]
355
+ };
356
+ }
357
+ return validateRecordDatasourceContracts(ds, prefix);
358
+ }
359
+
360
+ /**
361
+ * @param {string} appPath
362
+ * @param {string} systemKey
363
+ * @param {Object[]} datasources
364
+ * @returns {{ errors: string[], warnings: string[] }}
365
+ */
366
+ function validateAppContractSurface(appPath, systemKey, datasources) {
367
+ const errors = [];
368
+ const warnings = [];
369
+ const vendorCache = new Map();
370
+ for (const ds of datasources || []) {
371
+ if (!ds || typeof ds !== 'object') {
372
+ continue;
373
+ }
374
+ const result = validateDatasourceContractSurface(ds, appPath, systemKey, vendorCache);
375
+ errors.push(...result.errors);
376
+ warnings.push(...result.warnings);
377
+ }
378
+ return { errors, warnings };
379
+ }
380
+
381
+ /**
382
+ * @param {string} filePath
383
+ * @returns {{ appPath: string, systemKey: string }|null}
384
+ */
385
+ function inferIntegrationContextFromPath(filePath) {
386
+ const normalized = path.normalize(filePath);
387
+ const parts = normalized.split(path.sep);
388
+ const integrationIdx = parts.lastIndexOf('integration');
389
+ if (integrationIdx < 0 || integrationIdx + 1 >= parts.length) {
390
+ return null;
391
+ }
392
+ const systemKey = parts[integrationIdx + 1];
393
+ const appPath = parts.slice(0, integrationIdx + 2).join(path.sep);
394
+ return { appPath, systemKey };
395
+ }
396
+
397
+ /**
398
+ * @param {Object} parsedDatasource
399
+ * @param {string} filePath
400
+ * @returns {{ errors: string[], warnings: string[] }}
401
+ */
402
+ function validateDatasourceFileContractSurface(parsedDatasource, filePath) {
403
+ const ctx = inferIntegrationContextFromPath(filePath);
404
+ if (!ctx) {
405
+ return { errors: [], warnings: [] };
406
+ }
407
+ return validateDatasourceContractSurface(
408
+ parsedDatasource,
409
+ ctx.appPath,
410
+ ctx.systemKey,
411
+ new Map()
412
+ );
413
+ }
414
+
415
+ module.exports = {
416
+ isOrchestrationDatasource,
417
+ isServiceContractDatasource,
418
+ isCompositionNoneDatasource,
419
+ hasVendorOpenapiOnManifest,
420
+ isThinOpenApiSpec,
421
+ validateAppContractSurface,
422
+ validateDatasourceFileContractSurface,
423
+ validateVendorOperationContract,
424
+ validateServiceContractDatasourceContracts,
425
+ findVendorOperation
426
+ };