@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,126 @@
1
+ /**
2
+ * Warn when datasource capabilities lack matching openapi.operations (autoRbac).
3
+ *
4
+ * @fileoverview repair-capability-openapi-warnings
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const path = require('path');
12
+ const fs = require('fs');
13
+ const { loadConfigFile } = require('../utils/config-format');
14
+ const { capabilityKeysFromManifest } = require('./repair-datasource-sync-operations');
15
+
16
+ /**
17
+ * @param {string} opKey
18
+ * @returns {string}
19
+ */
20
+ function normalizeRbacOperationKey(opKey) {
21
+ const s = typeof opKey === 'string' ? opKey.trim() : '';
22
+ if (!s) return '';
23
+ if (/^[a-z][a-zA-Z0-9]*$/.test(s)) return s.toLowerCase();
24
+ const withHyphens = s.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
25
+ const cleaned = withHyphens.replace(/[^a-z0-9-]+/g, '-');
26
+ return cleaned.replace(/-+/g, '-').replace(/^-+|-+$/g, '');
27
+ }
28
+
29
+ /**
30
+ * @param {Object} parsed
31
+ * @returns {boolean}
32
+ */
33
+ function hasAutoRbacOpenApi(parsed) {
34
+ const openapi = parsed?.openapi;
35
+ return (
36
+ openapi &&
37
+ typeof openapi === 'object' &&
38
+ openapi.autoRbac === true &&
39
+ openapi.operations &&
40
+ typeof openapi.operations === 'object' &&
41
+ !Array.isArray(openapi.operations)
42
+ );
43
+ }
44
+
45
+ /**
46
+ * @param {Object} parsed
47
+ * @returns {Set<string>}
48
+ */
49
+ function normalizedOpenApiOperationKeys(parsed) {
50
+ const ops = parsed?.openapi?.operations;
51
+ const out = new Set();
52
+ if (!ops || typeof ops !== 'object') {
53
+ return out;
54
+ }
55
+ for (const key of Object.keys(ops)) {
56
+ const norm = normalizeRbacOperationKey(key) || key;
57
+ if (norm) out.add(norm);
58
+ }
59
+ return out;
60
+ }
61
+
62
+ /**
63
+ * @param {Object} parsed
64
+ * @returns {string[]}
65
+ */
66
+ function findCapabilityKeysMissingFromOpenApi(parsed) {
67
+ if (!hasAutoRbacOpenApi(parsed)) {
68
+ return [];
69
+ }
70
+ const capKeys = capabilityKeysFromManifest(parsed?.capabilities);
71
+ if (capKeys.length === 0) {
72
+ return [];
73
+ }
74
+ const openApiKeys = normalizedOpenApiOperationKeys(parsed);
75
+ return capKeys.filter((key) => !openApiKeys.has(normalizeRbacOperationKey(key) || key));
76
+ }
77
+
78
+ /**
79
+ * @param {string} fileName
80
+ * @param {Object} parsed
81
+ * @param {string[]} missingKeys
82
+ * @returns {string}
83
+ */
84
+ function formatCapabilityOpenApiDriftWarning(fileName, parsed, missingKeys) {
85
+ const dsKey = typeof parsed?.key === 'string' && parsed.key.trim() ? parsed.key.trim() : fileName;
86
+ return (
87
+ `${dsKey}: capabilities declare ${missingKeys.join(', ')} but openapi.operations is missing them — ` +
88
+ 'RBAC repair may omit matching permissions; operations sync runs automatically with --rbac'
89
+ );
90
+ }
91
+
92
+ /**
93
+ * @param {string} appPath
94
+ * @param {string[]} datasourceFiles
95
+ * @param {string[]} warnings
96
+ * @returns {number}
97
+ */
98
+ function collectCapabilityOpenApiDriftWarnings(appPath, datasourceFiles, warnings) {
99
+ if (!Array.isArray(warnings) || !Array.isArray(datasourceFiles)) {
100
+ return 0;
101
+ }
102
+ let count = 0;
103
+ for (const fileName of datasourceFiles) {
104
+ const filePath = path.join(appPath, fileName);
105
+ if (!fs.existsSync(filePath)) continue;
106
+ let parsed;
107
+ try {
108
+ parsed = loadConfigFile(filePath);
109
+ } catch {
110
+ continue;
111
+ }
112
+ const missingKeys = findCapabilityKeysMissingFromOpenApi(parsed);
113
+ if (missingKeys.length === 0) continue;
114
+ warnings.push(formatCapabilityOpenApiDriftWarning(fileName, parsed, missingKeys));
115
+ count += 1;
116
+ }
117
+ return count;
118
+ }
119
+
120
+ module.exports = {
121
+ normalizeRbacOperationKey,
122
+ hasAutoRbacOpenApi,
123
+ findCapabilityKeysMissingFromOpenApi,
124
+ collectCapabilityOpenApiDriftWarnings,
125
+ formatCapabilityOpenApiDriftWarning
126
+ };
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Datasource repair orchestration (service contract, base/openapi/optional passes).
3
+ *
4
+ * @fileoverview Repair datasource file apply orchestration
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { repairOpenapiSection } = require('./repair-datasource-openapi');
12
+ const { repairSyncOperationsFromCapabilities } = require('./repair-datasource-sync-operations');
13
+ const { normalizeAutoRbacOperationKeys } = require('./repair-datasource-auto-rbac');
14
+ const { repairTestPayload } = require('./repair-datasource-test-payload');
15
+ const { repairComV2Manifest } = require('./repair-datasource-com-v2');
16
+ const {
17
+ isDeprecatedNoneLlmManifest,
18
+ repairNoneLlmToServiceContract
19
+ } = require('./repair-datasource-service-contract');
20
+ const {
21
+ isDeprecatedNoneOpenapiHttpManifest,
22
+ repairNoneOpenapiHttpToServiceContract,
23
+ normalizeCipOpenapiRefs
24
+ } = require('./repair-datasource-http-service-contract');
25
+ const {
26
+ repairWebhookSection,
27
+ repairSyncBridgeSection,
28
+ collectWebhookSyncBridgeSystemWarnings
29
+ } = require('./repair-datasource-webhooks-sync-bridge');
30
+
31
+ /**
32
+ * @param {Object} parsed
33
+ * @param {Object} options
34
+ * @returns {boolean}
35
+ */
36
+ function shouldApplyServiceContractRepair(parsed, options) {
37
+ return (
38
+ isDeprecatedNoneLlmManifest(parsed) ||
39
+ isDeprecatedNoneOpenapiHttpManifest(parsed) ||
40
+ (options.serviceContract && parsed?.resourceType === 'llm')
41
+ );
42
+ }
43
+
44
+ /**
45
+ * @param {Object} parsed
46
+ * @param {Object} options
47
+ * @param {boolean} none
48
+ * @param {string[]} changes
49
+ * @param {Object} helpers
50
+ * @returns {boolean}
51
+ */
52
+ function applyOptionalDatasourceRepairs(parsed, options, none, changes, helpers) {
53
+ let updated = false;
54
+ if (options.operations) {
55
+ updated = repairSyncOperationsFromCapabilities(parsed, changes) || updated;
56
+ }
57
+ if (options.expose) {
58
+ updated = helpers.repairExposeFromAttributes(parsed, changes) || updated;
59
+ }
60
+ if (!none && options.sync) {
61
+ updated = helpers.repairSyncSection(parsed, changes) || updated;
62
+ }
63
+ if (options.test) {
64
+ helpers.sanitizeTestPayloadTopLevel(parsed, changes);
65
+ updated = repairTestPayload(parsed, changes) || updated;
66
+ updated = helpers.sanitizeTestPayloadTopLevel(parsed, changes) || updated;
67
+ }
68
+ return updated;
69
+ }
70
+
71
+ /**
72
+ * @param {Object} parsed
73
+ * @param {boolean} none
74
+ * @param {string[]} changes
75
+ * @param {Object} [options]
76
+ * @param {Object} helpers
77
+ * @returns {boolean}
78
+ */
79
+ function applyBaseDatasourceRepairs(parsed, none, changes, options, helpers) {
80
+ let updated = repairComV2Manifest(parsed, changes);
81
+ if (none) return updated;
82
+ updated = helpers.repairDimensionBindingShape(parsed, changes) || updated;
83
+ updated = helpers.repairRootDimensionsFromAttributes(parsed, changes) || updated;
84
+ updated = helpers.repairMetadataSchemaFromAttributes(parsed, changes) || updated;
85
+ const warnings = Array.isArray(options.warnings) ? options.warnings : [];
86
+ updated = repairWebhookSection(parsed, changes, warnings) || updated;
87
+ updated = repairSyncBridgeSection(parsed, changes, warnings) || updated;
88
+ collectWebhookSyncBridgeSystemWarnings(parsed, options.systemParsed, warnings);
89
+ return updated;
90
+ }
91
+
92
+ /**
93
+ * @param {Object} parsed
94
+ * @param {string[]} changes
95
+ * @returns {boolean}
96
+ */
97
+ function applyOpenapiDatasourceRepairs(parsed, changes) {
98
+ let updated = false;
99
+ updated = repairOpenapiSection(parsed, changes) || updated;
100
+ updated = normalizeAutoRbacOperationKeys(parsed, changes) || updated;
101
+ return updated;
102
+ }
103
+
104
+ /**
105
+ * Runs all requested datasource repairs.
106
+ *
107
+ * @param {Object} parsed - Parsed datasource object (mutated)
108
+ * @param {Object} options - Repair flags
109
+ * @param {string[]} changes - Change log
110
+ * @param {Object} helpers - Functions from repair-datasource.js
111
+ * @returns {{ updated: boolean, changes: string[] }}
112
+ */
113
+ function runRepairDatasourceFile(parsed, options, changes, helpers) {
114
+ const out = Array.isArray(changes) ? changes : [];
115
+ let updated = helpers.stripDeprecatedServiceCategory(parsed, out);
116
+
117
+ if (shouldApplyServiceContractRepair(parsed, options)) {
118
+ updated = repairNoneLlmToServiceContract(parsed, out) || updated;
119
+ updated = repairNoneOpenapiHttpToServiceContract(parsed, out) || updated;
120
+ }
121
+
122
+ updated = normalizeCipOpenapiRefs(parsed, out) || updated;
123
+
124
+ const none = helpers.isNoneEntityType(parsed?.entityType);
125
+
126
+ updated = applyBaseDatasourceRepairs(parsed, none, out, options, helpers) || updated;
127
+ updated = applyOpenapiDatasourceRepairs(parsed, out) || updated;
128
+ updated = applyOptionalDatasourceRepairs(parsed, options, none, out, helpers) || updated;
129
+
130
+ return { updated, changes: out };
131
+ }
132
+
133
+ module.exports = {
134
+ runRepairDatasourceFile
135
+ };
@@ -120,12 +120,71 @@ function renameScenarioOperations(parsed, renameMap) {
120
120
  return updated;
121
121
  }
122
122
 
123
+ /**
124
+ * @param {unknown} cap
125
+ * @param {string[]} caps
126
+ * @param {Object} renameMap
127
+ * @returns {boolean}
128
+ */
129
+ function renameStringCapabilityKey(caps, cap, renameMap) {
130
+ if (typeof cap !== 'string') {
131
+ return false;
132
+ }
133
+ const newKey = renameMap[cap];
134
+ if (!newKey || newKey === cap) {
135
+ return false;
136
+ }
137
+ const idx = caps.indexOf(cap);
138
+ if (idx >= 0) {
139
+ caps[idx] = newKey;
140
+ }
141
+ return true;
142
+ }
143
+
144
+ /**
145
+ * @param {Object} cap
146
+ * @param {Object} renameMap
147
+ * @returns {boolean}
148
+ */
149
+ function renameObjectCapabilityKey(cap, renameMap) {
150
+ if (!cap || typeof cap !== 'object') {
151
+ return false;
152
+ }
153
+ const k = safeString(cap.key);
154
+ if (!k) {
155
+ return false;
156
+ }
157
+ const newKey = renameMap[k];
158
+ if (!newKey || newKey === k) {
159
+ return false;
160
+ }
161
+ cap.key = newKey;
162
+ return true;
163
+ }
164
+
123
165
  /**
124
166
  * When OpenAPI autoRbac is enabled, ensure operation keys are schema-valid and consistent across:
125
167
  * - openapi.operations
126
168
  * - execution.cip.operations
127
169
  * - testPayload.scenarios[].operation
128
170
  */
171
+ function renameCapabilitiesKeys(parsed, renameMap, changes) {
172
+ const caps = parsed?.capabilities;
173
+ if (!Array.isArray(caps) || !renameMap || typeof renameMap !== 'object') {
174
+ return false;
175
+ }
176
+ let updated = false;
177
+ for (const cap of caps) {
178
+ if (renameStringCapabilityKey(caps, cap, renameMap) || renameObjectCapabilityKey(cap, renameMap)) {
179
+ updated = true;
180
+ }
181
+ }
182
+ if (updated && Array.isArray(changes)) {
183
+ changes.push('Aligned capabilities[].key with normalized autoRbac operation keys');
184
+ }
185
+ return updated;
186
+ }
187
+
129
188
  function normalizeAutoRbacOperationKeys(parsed, changes) {
130
189
  const openapi = parsed?.openapi;
131
190
  if (!openapi || typeof openapi !== 'object') return false;
@@ -148,6 +207,7 @@ function normalizeAutoRbacOperationKeys(parsed, changes) {
148
207
  updated = renameKeysInObject(wsAllowed, renameMap) || updated;
149
208
  // If both alias + canonical exist, merge and drop alias (schema requires canonical camelCase keys).
150
209
  updated = mergeAndDeleteAliasKeys(wsAllowed, renameMap) || updated;
210
+ updated = renameCapabilitiesKeys(parsed, renameMap, changes) || updated;
151
211
 
152
212
  if (updated && Array.isArray(changes)) {
153
213
  const pairs = keysToRename.map((k) => `${k}→${renameMap[k]}`).join(', ');
@@ -161,6 +221,7 @@ function normalizeAutoRbacOperationKeys(parsed, changes) {
161
221
 
162
222
  module.exports = {
163
223
  normalizeAutoRbacOperationKeys,
164
- toCamelCaseKey
224
+ toCamelCaseKey,
225
+ toKebabAliasKey
165
226
  };
166
227
 
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Migrate deprecated entityType none + vendor OpenAPI HTTP manifests to serviceContract (439.2).
3
+ *
4
+ * @fileoverview repair-datasource-http-service-contract
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const HTTP_CANONICAL_METADATA_SCHEMA = {
12
+ type: 'object',
13
+ properties: {
14
+ successPayload: {
15
+ type: 'object',
16
+ nullable: true,
17
+ description: 'Normalized success body from upstream HTTP response'
18
+ },
19
+ successMessage: {
20
+ type: 'string',
21
+ nullable: true,
22
+ description: 'Human-readable success message when present'
23
+ },
24
+ errorCode: {
25
+ type: 'string',
26
+ nullable: true,
27
+ description: 'Provider error code when the operation fails'
28
+ },
29
+ errorMessage: {
30
+ type: 'string',
31
+ nullable: true,
32
+ description: 'Human-readable provider error message'
33
+ }
34
+ }
35
+ };
36
+
37
+ const HTTP_CANONICAL_EXPOSED_SCHEMA = {
38
+ success: {
39
+ payload: 'metadata.successPayload',
40
+ message: 'metadata.successMessage'
41
+ },
42
+ error: {
43
+ code: 'metadata.errorCode',
44
+ message: 'metadata.errorMessage'
45
+ }
46
+ };
47
+
48
+ const HTTP_STUB_FIELD_MAPPINGS = {
49
+ successPayload: { expression: '{{raw.data}}' },
50
+ successMessage: { expression: '{{raw.message}}' },
51
+ errorCode: { expression: '{{raw.code}}' },
52
+ errorMessage: { expression: '{{raw.message}}' }
53
+ };
54
+
55
+ /**
56
+ * @param {Object} parsed
57
+ * @returns {boolean}
58
+ */
59
+ function hasVendorOpenapiBinding(parsed) {
60
+ const openapi = parsed?.openapi;
61
+ if (!openapi || typeof openapi !== 'object' || openapi.enabled === false) {
62
+ return false;
63
+ }
64
+ const operations = openapi.operations;
65
+ if (operations && typeof operations === 'object' && Object.keys(operations).length > 0) {
66
+ return true;
67
+ }
68
+ const documentKey =
69
+ typeof openapi.documentKey === 'string' ? openapi.documentKey.trim() : '';
70
+ return Boolean(documentKey) || openapi.enabled === true;
71
+ }
72
+
73
+ /**
74
+ * @param {Object} parsed
75
+ * @returns {boolean}
76
+ */
77
+ function isDeprecatedNoneOpenapiHttpManifest(parsed) {
78
+ if (parsed?.entityType !== 'none') {
79
+ return false;
80
+ }
81
+ if (parsed?.resourceType === 'llm') {
82
+ return false;
83
+ }
84
+ return hasVendorOpenapiBinding(parsed);
85
+ }
86
+
87
+ /**
88
+ * @param {*} value
89
+ * @returns {*}
90
+ */
91
+ function deepClone(value) {
92
+ return JSON.parse(JSON.stringify(value));
93
+ }
94
+
95
+ /**
96
+ * @param {Object} parsed
97
+ * @param {string[]} changes
98
+ * @returns {boolean}
99
+ */
100
+ function ensureHttpCipMapSteps(parsed, changes) {
101
+ const operations = parsed?.execution?.cip?.operations;
102
+ if (!operations || typeof operations !== 'object') {
103
+ return false;
104
+ }
105
+ let updated = false;
106
+ for (const [opKey, op] of Object.entries(operations)) {
107
+ if (!op || !Array.isArray(op.steps)) {
108
+ continue;
109
+ }
110
+ if (op.steps.some((step) => step && step.map)) {
111
+ continue;
112
+ }
113
+ const fetchIdx = op.steps.findIndex((step) => step && step.fetch);
114
+ if (fetchIdx < 0) {
115
+ continue;
116
+ }
117
+ op.steps.splice(fetchIdx + 1, 0, {
118
+ map: { useFieldMappings: true, inputPath: '$' }
119
+ });
120
+ if (!op.steps.some((step) => step && step.output)) {
121
+ op.steps.push({ output: { mode: 'records' } });
122
+ }
123
+ changes.push(`Inserted map+output steps for CIP operation "${opKey}"`);
124
+ updated = true;
125
+ }
126
+ return updated;
127
+ }
128
+
129
+ /**
130
+ * @param {Object} parsed
131
+ * @param {string[]} changes
132
+ */
133
+ function ensureHttpFieldMappings(parsed, changes) {
134
+ if (!parsed.fieldMappings) {
135
+ parsed.fieldMappings = {};
136
+ }
137
+ const attrs = parsed.fieldMappings.attributes;
138
+ if (!attrs || typeof attrs !== 'object' || Object.keys(attrs).length === 0) {
139
+ parsed.fieldMappings.attributes = deepClone(HTTP_STUB_FIELD_MAPPINGS);
140
+ changes.push(
141
+ 'Added stub fieldMappings.attributes — customize {{raw.*}} per operation'
142
+ );
143
+ }
144
+ }
145
+
146
+ /**
147
+ * @param {Object} parsed
148
+ * @param {string[]} changes
149
+ */
150
+ function ensureHttpExposedEnvelope(parsed, changes) {
151
+ if (!parsed.exposed) {
152
+ parsed.exposed = {};
153
+ }
154
+ if (!parsed.exposed.schema || typeof parsed.exposed.schema !== 'object') {
155
+ parsed.exposed.schema = deepClone(HTTP_CANONICAL_EXPOSED_SCHEMA);
156
+ changes.push('Set HTTP serviceContract exposed.schema envelope');
157
+ }
158
+ if (parsed.exposed.attributes !== undefined) {
159
+ delete parsed.exposed.attributes;
160
+ }
161
+ if (!parsed.exposed.profiles || typeof parsed.exposed.profiles !== 'object') {
162
+ parsed.exposed.profiles = { default: ['success', 'error'] };
163
+ changes.push('Set exposed.profiles default envelope');
164
+ }
165
+ }
166
+
167
+ /**
168
+ * @param {Object} parsed
169
+ * @param {string[]} changes
170
+ * @returns {boolean}
171
+ */
172
+ function applyHttpServiceContractStubs(parsed, changes) {
173
+ parsed.entityType = 'serviceContract';
174
+ changes.push('Migrated entityType none → serviceContract (HTTP/OpenAPI facade)');
175
+
176
+ parsed.metadataSchema = deepClone(HTTP_CANONICAL_METADATA_SCHEMA);
177
+ changes.push('Set HTTP serviceContract metadataSchema stub');
178
+
179
+ ensureHttpFieldMappings(parsed, changes);
180
+ ensureHttpExposedEnvelope(parsed, changes);
181
+ return true;
182
+ }
183
+
184
+ /**
185
+ * @param {Object} parsed
186
+ * @param {string[]} changes
187
+ * @returns {boolean}
188
+ */
189
+ function repairNoneOpenapiHttpToServiceContract(parsed, changes) {
190
+ if (!isDeprecatedNoneOpenapiHttpManifest(parsed)) {
191
+ return false;
192
+ }
193
+ let updated = applyHttpServiceContractStubs(parsed, changes);
194
+ updated = ensureHttpCipMapSteps(parsed, changes) || updated;
195
+ updated = normalizeCipOpenapiRefs(parsed, changes) || updated;
196
+ return updated;
197
+ }
198
+
199
+ /**
200
+ * Align fetch.openapiRef with execution.cip.operations keys (manifest SSOT).
201
+ *
202
+ * @param {Object} parsed
203
+ * @param {string[]} changes
204
+ * @returns {boolean}
205
+ */
206
+ function normalizeCipOpenapiRefs(parsed, changes) {
207
+ const operations = parsed?.execution?.cip?.operations;
208
+ if (!operations || typeof operations !== 'object') {
209
+ return false;
210
+ }
211
+ let updated = false;
212
+ for (const [opKey, op] of Object.entries(operations)) {
213
+ if (!op || !Array.isArray(op.steps)) {
214
+ continue;
215
+ }
216
+ for (const step of op.steps) {
217
+ const fetch = step?.fetch;
218
+ if (!fetch || fetch.source !== 'openapi') {
219
+ continue;
220
+ }
221
+ if (fetch.openapiRef !== opKey) {
222
+ fetch.openapiRef = opKey;
223
+ changes.push(
224
+ `Normalized fetch.openapiRef → "${opKey}" for CIP operation "${opKey}"`
225
+ );
226
+ updated = true;
227
+ }
228
+ }
229
+ }
230
+ return updated;
231
+ }
232
+
233
+ module.exports = {
234
+ HTTP_CANONICAL_METADATA_SCHEMA,
235
+ HTTP_CANONICAL_EXPOSED_SCHEMA,
236
+ isDeprecatedNoneOpenapiHttpManifest,
237
+ normalizeCipOpenapiRefs,
238
+ repairNoneOpenapiHttpToServiceContract
239
+ };