@aifabrix/builder 2.49.2 → 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 (409) hide show
  1. package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +49 -0
  2. package/.cursor/rules/plan-rules/application-lifecycle.mdc +30 -0
  3. package/.cursor/rules/plan-rules/plan-frontmatter.mdc +35 -0
  4. package/.cursor/rules/plan-rules/plan-lifecycle.mdc +31 -0
  5. package/.cursor/rules/plan-rules/plan-validation-gate.mdc +34 -0
  6. package/.cursor/skills/README.md +1 -0
  7. package/.dockerignore +52 -0
  8. package/.eslintignore +22 -0
  9. package/README.md +2 -0
  10. package/bin/builder-api-cleanup.js +26 -0
  11. package/bin/builder-api-nest.js +10 -0
  12. package/bin/builder-api-spike.js +19 -0
  13. package/enterprise-knowledge/README.md +50 -0
  14. package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +22 -0
  15. package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +15 -0
  16. package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +69 -0
  17. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +52 -0
  18. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +29 -0
  19. package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +2 -0
  20. package/integration/README.md +81 -0
  21. package/integration/github/README.md +53 -0
  22. package/integration/github/application.json +21 -0
  23. package/integration/github/deploy.js +72 -0
  24. package/integration/github/env.template +11 -0
  25. package/integration/github/github-datasource-issue-comments.json +239 -0
  26. package/integration/github/github-datasource-issues.json +399 -0
  27. package/integration/github/github-datasource-repository.json +354 -0
  28. package/integration/github/github-deploy.json +1202 -0
  29. package/integration/github/github-system.json +82 -0
  30. package/integration/hubspot-test/README.md +1 -1
  31. package/jest.isolated-projects.js +31 -1
  32. package/jest.projects.js +87 -1
  33. package/lib/api/dev-server-https.js +1 -1
  34. package/lib/api/enterprise-knowledge.api.js +63 -0
  35. package/lib/api/evidence.api.js +172 -0
  36. package/lib/api/external-systems.api.js +8 -2
  37. package/lib/api/resource-types.api.js +1 -0
  38. package/lib/api/types/enterprise-knowledge.types.js +46 -0
  39. package/lib/api/types/evidence.types.js +67 -0
  40. package/lib/api/types/resource-types.types.js +2 -0
  41. package/lib/app/controller-application-filter.js +36 -0
  42. package/lib/app/deploy.js +1 -1
  43. package/lib/app/list-external-systems.js +130 -0
  44. package/lib/app/list.js +20 -8
  45. package/lib/app/run.js +3 -1
  46. package/lib/app/show-display.js +8 -3
  47. package/lib/app/show-online.js +178 -0
  48. package/lib/app/show.js +37 -88
  49. package/lib/build/builder-api-docker-staging.js +47 -0
  50. package/lib/build/miso-controller-npm-sdk-guard.js +2 -2
  51. package/lib/build/standard-docker-build.js +2 -0
  52. package/lib/certification/post-unified-cert-sync.js +4 -31
  53. package/lib/certification/sync-after-external-command.js +0 -1
  54. package/lib/certification/sync-system-certification.js +0 -3
  55. package/lib/channels/add-channel.js +40 -34
  56. package/lib/channels/approval-guides/chatgpt.js +33 -0
  57. package/lib/channels/approval-guides/credential-portal.js +38 -0
  58. package/lib/channels/approval-guides/index.js +110 -0
  59. package/lib/channels/approval-guides/microsoft-copilot.js +34 -0
  60. package/lib/channels/approval-guides/slack.js +34 -0
  61. package/lib/channels/approval-guides/teams-bot.js +35 -0
  62. package/lib/channels/approval-guides/web-embed.js +32 -0
  63. package/lib/channels/channel-approval-guide.js +11 -0
  64. package/lib/channels/channel-artifact-generator.js +16 -4
  65. package/lib/channels/channel-audit.js +3 -0
  66. package/lib/channels/channel-auth-context.js +1 -1
  67. package/lib/channels/channel-description.js +59 -0
  68. package/lib/channels/channel-integration-generator.js +13 -230
  69. package/lib/channels/channel-integration-template.js +94 -0
  70. package/lib/channels/channel-runtime-resolver.js +43 -3
  71. package/lib/channels/channel-status-display.js +66 -26
  72. package/lib/channels/channel-targets.js +3 -3
  73. package/lib/cli/index.js +27 -3
  74. package/lib/cli/infra-guided.js +5 -1
  75. package/lib/cli/setup-app-external-create.js +111 -0
  76. package/lib/cli/setup-app.help.js +1 -1
  77. package/lib/cli/setup-app.js +38 -125
  78. package/lib/cli/setup-app.test-commands.js +26 -52
  79. package/lib/cli/setup-certification-commands.js +4 -4
  80. package/lib/cli/setup-certification.help.js +9 -9
  81. package/lib/cli/setup-dev.js +7 -2
  82. package/lib/cli/setup-external-system-help.js +4 -6
  83. package/lib/cli/setup-external-system.js +58 -52
  84. package/lib/cli/setup-infra-up-builder-api-action.js +64 -0
  85. package/lib/cli/setup-infra-up-platform-action.js +3 -1
  86. package/lib/cli/setup-infra.js +15 -0
  87. package/lib/cli/setup-list.js +43 -0
  88. package/lib/cli/setup-utility-repair.js +26 -7
  89. package/lib/cli/setup-utility.js +5 -3
  90. package/lib/commands/app.js +15 -43
  91. package/lib/commands/channel-add-setup.js +110 -0
  92. package/lib/commands/channel.js +42 -8
  93. package/lib/commands/datasource-sync-display.js +96 -0
  94. package/lib/commands/datasource-sync-policy.js +210 -0
  95. package/lib/commands/datasource-test-trust-cli.js +6 -6
  96. package/lib/commands/datasource-unified-test-cli.js +2 -1
  97. package/lib/commands/datasource-unified-test-cli.options.js +33 -23
  98. package/lib/commands/deploy-gate-failure-details.js +163 -0
  99. package/lib/commands/deploy-gate-orchestrator.js +322 -0
  100. package/lib/commands/dev-cli-handlers.js +1 -59
  101. package/lib/commands/dev-host-ops-params.js +91 -0
  102. package/lib/commands/dev-host-ops-poll.js +111 -0
  103. package/lib/commands/dev-host-ops.js +107 -94
  104. package/lib/commands/dev-init.js +3 -1
  105. package/lib/commands/enterprise-knowledge.js +284 -0
  106. package/lib/commands/evidence-cli-leaves.js +250 -0
  107. package/lib/commands/evidence.js +51 -0
  108. package/lib/commands/governance-cli-shared.js +2 -2
  109. package/lib/commands/governance-command-action.js +2 -2
  110. package/lib/commands/governance-fixture-subjects.js +85 -0
  111. package/lib/commands/governance.js +1 -1
  112. package/lib/commands/lifecycle-command-action.js +2 -2
  113. package/lib/commands/lifecycle-external.js +3 -3
  114. package/lib/commands/manifest-cli-auth.js +29 -0
  115. package/lib/commands/manifest-cli-commands.js +170 -0
  116. package/lib/commands/manifest-cli-integration-path.js +63 -0
  117. package/lib/commands/manifest.js +21 -0
  118. package/lib/commands/protection-cli-leaves.js +3 -3
  119. package/lib/commands/repair-auth-apply.js +15 -1
  120. package/lib/commands/repair-authentications-454.js +169 -0
  121. package/lib/commands/repair-capability-openapi-warnings.js +126 -0
  122. package/lib/commands/repair-datasource-apply.js +135 -0
  123. package/lib/commands/repair-datasource-auto-rbac.js +62 -1
  124. package/lib/commands/repair-datasource-http-service-contract.js +239 -0
  125. package/lib/commands/repair-datasource-operation-security.js +180 -0
  126. package/lib/commands/repair-datasource-run.js +7 -2
  127. package/lib/commands/repair-datasource-sync-operations.js +177 -0
  128. package/lib/commands/repair-datasource-webhooks-sync-bridge.js +133 -0
  129. package/lib/commands/repair-datasource.js +12 -68
  130. package/lib/commands/repair-env-template.js +11 -1
  131. package/lib/commands/repair-external-run.js +121 -31
  132. package/lib/commands/repair-internal.js +1 -1
  133. package/lib/commands/repair-openapi-export.js +156 -0
  134. package/lib/commands/repair-openapi-sync.js +19 -2
  135. package/lib/commands/repair-orchestration-datasource-split.js +259 -0
  136. package/lib/commands/repair-persist.js +22 -1
  137. package/lib/commands/repair-rbac-platform-preset.js +204 -0
  138. package/lib/commands/repair-rbac-reader-roles.js +191 -0
  139. package/lib/commands/repair-rbac.js +163 -86
  140. package/lib/commands/repair-steps.js +83 -18
  141. package/lib/commands/repair-system-permissions.js +1 -0
  142. package/lib/commands/repair.js +1 -1
  143. package/lib/commands/resource-type.js +65 -26
  144. package/lib/commands/run-post-publish-data-sync.js +68 -0
  145. package/lib/commands/setup-modes.js +1 -1
  146. package/lib/commands/test-e2e-external.js +21 -8
  147. package/lib/commands/test-governance-cli-options.js +2 -2
  148. package/lib/commands/test-trust-cli-options.js +2 -2
  149. package/lib/commands/up-builder-api-bootstrap.js +71 -0
  150. package/lib/commands/up-builder-api-provision.js +241 -0
  151. package/lib/commands/up-builder-api.js +88 -0
  152. package/lib/commands/up-common.js +25 -1
  153. package/lib/commands/upload-credential-push-log.js +117 -0
  154. package/lib/commands/upload-data-sync-finalize.js +60 -0
  155. package/lib/commands/upload-probe.js +66 -0
  156. package/lib/commands/upload-publish-context.js +4 -1
  157. package/lib/commands/upload-sidecar-followups.js +55 -27
  158. package/lib/commands/upload.js +116 -157
  159. package/lib/commands/verify-governance-combined-external.js +1 -1
  160. package/lib/commands/verify-governance-db.js +2 -2
  161. package/lib/commands/verify-operations-command-action.js +2 -2
  162. package/lib/commands/verify-operations-step-plan.js +2 -2
  163. package/lib/commands/verify-operations-steps.js +2 -2
  164. package/lib/commands/verify-trust-command-action.js +1 -1
  165. package/lib/commands/wizard-core.js +1 -1
  166. package/lib/commands/wizard-headless.js +2 -1
  167. package/lib/core/admin-secrets.js +2 -6
  168. package/lib/core/secrets-env-content.js +10 -4
  169. package/lib/core/secrets-env-write.js +2 -13
  170. package/lib/datasource/agent-trust-run.js +3 -3
  171. package/lib/datasource/deploy.js +3 -1
  172. package/lib/datasource/test-e2e.js +6 -1
  173. package/lib/datasource/unified-validation-run-body.js +4 -1
  174. package/lib/datasource/unified-validation-run.js +1 -1
  175. package/lib/deployment/deploy-poll-ui.js +73 -12
  176. package/lib/deployment/deployer-poll-run.js +113 -0
  177. package/lib/deployment/deployer.js +17 -87
  178. package/lib/evidence/dataplane-context.js +21 -0
  179. package/lib/evidence/evidence-display.js +78 -0
  180. package/lib/evidence/evidence-service.js +392 -0
  181. package/lib/external-system/deploy.js +290 -112
  182. package/lib/external-system/download.js +7 -3
  183. package/lib/external-system/test-execution.js +1 -1
  184. package/lib/external-system/test-system-level.js +8 -10
  185. package/lib/external-system/test.js +12 -6
  186. package/lib/generator/deploy-script.js +73 -0
  187. package/lib/generator/external.js +2 -1
  188. package/lib/generator/index.js +17 -2
  189. package/lib/generator/wizard.js +3 -36
  190. package/lib/internal/fs-real-sync.js +22 -1
  191. package/lib/internal/node-fs.js +2 -0
  192. package/lib/lifecycle/lifecycle-governance-options.js +1 -1
  193. package/lib/lifecycle/verify-step-progress.js +1 -1
  194. package/lib/programmatic/access-log.js +26 -0
  195. package/lib/programmatic/auth-config.js +44 -0
  196. package/lib/programmatic/bearer-auth.js +176 -0
  197. package/lib/programmatic/builder-api-request.js +175 -0
  198. package/lib/programmatic/builder-api-route-dispatch.js +82 -0
  199. package/lib/programmatic/builder-api-runtime-config.js +42 -0
  200. package/lib/programmatic/builder-api-server.js +230 -0
  201. package/lib/programmatic/builder-help-authentication-catalog.js +282 -0
  202. package/lib/programmatic/builder-help-connected-system-ui.js +266 -0
  203. package/lib/programmatic/builder-help-enterprise-sync-fabrix.js +60 -0
  204. package/lib/programmatic/builder-help-envelope.js +36 -0
  205. package/lib/programmatic/builder-help-fixtures.js +200 -0
  206. package/lib/programmatic/builder-help-governance.js +172 -0
  207. package/lib/programmatic/builder-help-schema-catalog.js +92 -0
  208. package/lib/programmatic/builder-help.js +361 -0
  209. package/lib/programmatic/capability-registry.js +77 -0
  210. package/lib/programmatic/command-options.js +32 -0
  211. package/lib/programmatic/enterprise-mcp-client.js +98 -0
  212. package/lib/programmatic/http-problem-details.js +99 -0
  213. package/lib/programmatic/http-route-match.js +40 -0
  214. package/lib/programmatic/idempotency-cache.js +69 -0
  215. package/lib/programmatic/index.js +53 -0
  216. package/lib/programmatic/integration-path-scope.js +39 -0
  217. package/lib/programmatic/log-redaction.js +66 -0
  218. package/lib/programmatic/manifest-get-section.js +146 -0
  219. package/lib/programmatic/manifest-patch-section.js +252 -0
  220. package/lib/programmatic/manifest-repair.js +122 -0
  221. package/lib/programmatic/manifest-section-dependency-graph.js +160 -0
  222. package/lib/programmatic/manifest-section-io.js +225 -0
  223. package/lib/programmatic/manifest-section-quality.js +171 -0
  224. package/lib/programmatic/manifest-section-registry-data.js +269 -0
  225. package/lib/programmatic/manifest-section-registry.js +205 -0
  226. package/lib/programmatic/nest-http-bridge.js +34 -0
  227. package/lib/programmatic/openapi-component-schemas.js +68 -0
  228. package/lib/programmatic/openapi-description-enricher.js +117 -0
  229. package/lib/programmatic/openapi-descriptions.js +190 -0
  230. package/lib/programmatic/openapi-docs-serving.js +123 -0
  231. package/lib/programmatic/openapi-help-schemas.js +63 -0
  232. package/lib/programmatic/openapi-manifest-schemas.js +141 -0
  233. package/lib/programmatic/openapi-operation-bindings.js +274 -0
  234. package/lib/programmatic/openapi-request-schemas.js +155 -0
  235. package/lib/programmatic/openapi-result-schemas.js +476 -0
  236. package/lib/programmatic/openapi-schema-descriptions-certify.js +139 -0
  237. package/lib/programmatic/openapi-schema-descriptions-core.js +159 -0
  238. package/lib/programmatic/openapi-schema-descriptions-help.js +40 -0
  239. package/lib/programmatic/openapi-schema-descriptions-manifest.js +143 -0
  240. package/lib/programmatic/openapi-schema-descriptions-mcp.js +118 -0
  241. package/lib/programmatic/openapi-schema-descriptions-operations.js +281 -0
  242. package/lib/programmatic/openapi-schema-helpers.js +93 -0
  243. package/lib/programmatic/openapi-spec.js +203 -0
  244. package/lib/programmatic/orchestration-openapi-meta.js +159 -0
  245. package/lib/programmatic/platform-rbac-catalog.js +90 -0
  246. package/lib/programmatic/request-timeout.js +53 -0
  247. package/lib/programmatic/route-handler-map.js +143 -0
  248. package/lib/programmatic/route-handlers-context.js +29 -0
  249. package/lib/programmatic/route-handlers.js +33 -0
  250. package/lib/programmatic/run-certify.js +57 -0
  251. package/lib/programmatic/run-enterprise-mcp.js +32 -0
  252. package/lib/programmatic/run-lifecycle.js +29 -0
  253. package/lib/programmatic/run-repair.js +41 -0
  254. package/lib/programmatic/run-repository-emcp.js +54 -0
  255. package/lib/programmatic/run-template-workspace.js +61 -0
  256. package/lib/programmatic/run-test.js +49 -0
  257. package/lib/programmatic/run-upload.js +63 -0
  258. package/lib/programmatic/run-validate.js +53 -0
  259. package/lib/programmatic/run-wizard.js +40 -0
  260. package/lib/programmatic/system-key.js +48 -0
  261. package/lib/programmatic/wizard-config-normalize.js +118 -0
  262. package/lib/programmatic/workspace-cleanup.js +128 -0
  263. package/lib/programmatic/workspace-context.js +145 -0
  264. package/lib/programmatic/workspace-lock.js +75 -0
  265. package/lib/programmatic/workspace-meta.js +64 -0
  266. package/lib/programmatic/workspace-ops.js +149 -0
  267. package/lib/protection/run-commands-upload-sync.js +35 -0
  268. package/lib/protection/run-commands.js +2 -20
  269. package/lib/protection/upload-batch.js +11 -7
  270. package/lib/resolvers/resource-type-file.js +22 -0
  271. package/lib/schema/external-datasource.schema.json +161 -1
  272. package/lib/schema/external-system.schema.json +244 -118
  273. package/lib/schema/flag-map-validation-run.json +3 -0
  274. package/lib/schema/type/credential-field-registry.json +2 -2
  275. package/lib/schema/type/document-storage.json +9 -0
  276. package/lib/utils/agent-trust-run-display.js +1 -1
  277. package/lib/utils/app-path-resolve.js +168 -0
  278. package/lib/utils/authentication-env-template.js +222 -0
  279. package/lib/utils/cli-sync-options.js +7 -11
  280. package/lib/utils/cli-utils.js +4 -0
  281. package/lib/utils/cli-workspace-options.js +29 -0
  282. package/lib/utils/compose-generate-docker-compose.js +102 -0
  283. package/lib/utils/configuration-env-resolver.js +203 -27
  284. package/lib/utils/datasource-test-run-certificate-tty.js +28 -2
  285. package/lib/utils/datasource-test-run-certification-debug.js +130 -0
  286. package/lib/utils/datasource-test-run-debug-display.js +2 -0
  287. package/lib/utils/datasource-test-run-debug-slice.js +7 -0
  288. package/lib/utils/datasource-test-run-display.js +2 -1
  289. package/lib/utils/dev-init-ssh-merge.js +165 -23
  290. package/lib/utils/dev-pin-share-instructions.js +110 -0
  291. package/lib/utils/dev-ssh-config-helper.js +177 -33
  292. package/lib/utils/enterprise-knowledge-paths.js +142 -0
  293. package/lib/utils/env-copy.js +2 -1
  294. package/lib/utils/env-dotenv-format.js +103 -0
  295. package/lib/utils/external-env-template.js +4 -1
  296. package/lib/utils/external-system-display.js +5 -1
  297. package/lib/utils/external-system-readiness-compact-blocks.js +221 -0
  298. package/lib/utils/external-system-readiness-compact-display.js +324 -0
  299. package/lib/utils/external-system-readiness-core.js +16 -0
  300. package/lib/utils/external-system-readiness-deploy-display.js +29 -11
  301. package/lib/utils/external-system-readiness-display-internals.js +3 -1
  302. package/lib/utils/external-system-readiness-display.js +20 -30
  303. package/lib/utils/external-system-system-test-tty-certification.js +135 -0
  304. package/lib/utils/external-system-system-test-tty.js +5 -41
  305. package/lib/utils/help-builder.js +6 -1
  306. package/lib/utils/host-ops-job-labels.js +236 -0
  307. package/lib/utils/host-ops-job-result.js +61 -0
  308. package/lib/utils/host-ops-poll-ui.js +163 -0
  309. package/lib/utils/integration-path-resolve.js +112 -0
  310. package/lib/utils/paths-reload-source.js +148 -0
  311. package/lib/utils/paths-system-builder-keys.js +25 -0
  312. package/lib/utils/paths.js +151 -26
  313. package/lib/utils/runtime-configuration-values.js +64 -2
  314. package/lib/utils/secrets-helpers.js +5 -1
  315. package/lib/utils/ssh-known-hosts.js +130 -0
  316. package/lib/utils/test-target-cli-options.js +75 -0
  317. package/lib/utils/upload-sync-options.js +4 -0
  318. package/lib/utils/validation-run-request.js +11 -2
  319. package/lib/validation/external-manifest-validator.js +11 -1
  320. package/lib/validation/openapi-contract-surface-validator.js +426 -0
  321. package/lib/validation/openapi-contract-vendor-validation.js +238 -0
  322. package/lib/validation/validate-external-file.js +160 -0
  323. package/lib/validation/validate.js +6 -117
  324. package/package.json +46 -29
  325. package/packages/builder-api/README.md +120 -0
  326. package/packages/builder-api/package.json +30 -0
  327. package/packages/builder-api/src/app.module.ts +7 -0
  328. package/packages/builder-api/src/auth/auth.module.ts +5 -0
  329. package/packages/builder-api/src/external-system/external-system.module.ts +5 -0
  330. package/packages/builder-api/src/main.ts +16 -0
  331. package/packages/builder-api/tsconfig.json +15 -0
  332. package/scripts/check-builder-api-architecture-grep.js +79 -0
  333. package/scripts/docker_image_content_gate.js +47 -0
  334. package/scripts/docker_image_content_gate.sh +5 -0
  335. package/scripts/export-builder-api-evidence.js +262 -0
  336. package/scripts/lib/builder-api-docker-staging-copy.js +60 -0
  337. package/scripts/lib/builder-api-docker-staging-core.js +183 -0
  338. package/scripts/lib/docker-image-content-gate-core.js +166 -0
  339. package/scripts/lib/plan-actor.js +109 -0
  340. package/scripts/lib/plan-config.js +20 -0
  341. package/scripts/lib/plan-gates.js +154 -0
  342. package/scripts/lib/plan-meta.js +104 -0
  343. package/scripts/lib/plan-parse.js +162 -0
  344. package/scripts/lib/plan-prevalidate-gates.js +326 -0
  345. package/scripts/lib/plan-run-core.js +125 -0
  346. package/scripts/lib/plan-run-report.js +108 -0
  347. package/scripts/plan-approve.js +24 -0
  348. package/scripts/plan-archive.js +49 -0
  349. package/scripts/plan-run.js +13 -0
  350. package/scripts/plan-set-actor.js +21 -0
  351. package/scripts/plan-validate.js +80 -0
  352. package/scripts/pnpm/af.mjs +110 -0
  353. package/scripts/pnpm/check-quiet.mjs +32 -0
  354. package/scripts/pnpm/dev-install.mjs +29 -0
  355. package/scripts/pnpm/dev-reload.mjs +18 -0
  356. package/scripts/pnpm/help.mjs +55 -0
  357. package/scripts/pnpm/lib/dev-reload-core.mjs +189 -0
  358. package/scripts/pnpm/lib/dev-reload-log-capture.mjs +67 -0
  359. package/scripts/pnpm/lib/dev-reload-log-utils.mjs +32 -0
  360. package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +124 -0
  361. package/scripts/pnpm/lib/resolve-app-url.mjs +183 -0
  362. package/scripts/pnpm/lib/spinner.mjs +42 -0
  363. package/scripts/stage_builder_api_for_docker.js +65 -0
  364. package/scripts/sync-builder-api-template.js +44 -0
  365. package/templates/README.md +3 -0
  366. package/templates/applications/builder-api/Dockerfile +38 -0
  367. package/templates/applications/builder-api/application.yaml +75 -0
  368. package/templates/applications/builder-api/env.template +48 -0
  369. package/templates/applications/dataplane/application.yaml +1 -1
  370. package/templates/applications/dataplane/env.template +10 -6
  371. package/templates/applications/dataplane/rbac.yaml +21 -1
  372. package/templates/applications/miso-controller/application.yaml +1 -1
  373. package/templates/applications/miso-controller/env.template +1 -3
  374. package/templates/channels/README.md +18 -0
  375. package/templates/channels/ai-fabrix-icon.jpg +0 -0
  376. package/templates/channels/chatgpt/install.template.md.hbs +21 -24
  377. package/templates/channels/chatgpt/integration/README.md +11 -0
  378. package/templates/channels/chatgpt/integration/application.json +15 -0
  379. package/templates/channels/chatgpt/integration/chatgpt-system.json +29 -0
  380. package/templates/channels/chatgpt/integration/env.template +4 -0
  381. package/templates/channels/microsoft-copilot/install.template.md.hbs +20 -25
  382. package/templates/channels/microsoft-copilot/integration/README.md +11 -0
  383. package/templates/channels/microsoft-copilot/integration/application.json +15 -0
  384. package/templates/channels/microsoft-copilot/integration/env.template +6 -0
  385. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +34 -0
  386. package/templates/channels/slack/install.template.md.hbs +48 -18
  387. package/templates/channels/slack/integration/README.md +38 -0
  388. package/templates/channels/slack/integration/application.json +18 -0
  389. package/templates/channels/slack/integration/env.template +29 -0
  390. package/templates/channels/slack/integration/slack-datasource-conversations.json +226 -0
  391. package/templates/channels/slack/integration/slack-datasource-messages.json +269 -0
  392. package/templates/channels/slack/integration/slack-system.json +86 -0
  393. package/templates/channels/slack/manifest.template.json.hbs +20 -10
  394. package/templates/channels/teams-bot/install.template.md.hbs +31 -17
  395. package/templates/channels/teams-bot/integration/README.md +18 -0
  396. package/templates/channels/teams-bot/integration/application.json +17 -0
  397. package/templates/channels/teams-bot/integration/env.template +5 -0
  398. package/templates/channels/teams-bot/integration/teams-bot-system.json +55 -0
  399. package/templates/channels/teams-bot/manifest.template.json.hbs +27 -0
  400. package/templates/channels/web-embed/install.template.md.hbs +16 -26
  401. package/templates/channels/web-embed/integration/README.md +11 -0
  402. package/templates/channels/web-embed/integration/application.json +15 -0
  403. package/templates/channels/web-embed/integration/env.template +4 -0
  404. package/templates/channels/web-embed/integration/web-embed-system.json +29 -0
  405. package/templates/openapi/redoc_page.html +86 -0
  406. package/templates/python/docker-compose.hbs +11 -0
  407. package/templates/python/requirements.txt +1 -1
  408. package/templates/typescript/docker-compose.hbs +11 -0
  409. package/lib/certification/cli-cert-sync-skip.js +0 -21
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Resolve product-repo source roots for platform app --reload bind mounts.
3
+ *
4
+ * @fileoverview When builder manifests live under aifabrix-work/builder/<app>, build.context
5
+ * ../.. may point at the work root instead of the product repo; reload mounts must target
6
+ * the repo that contains app/ or packages/.
7
+ * @author AI Fabrix Team
8
+ * @version 1.0.0
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const path = require('path');
14
+ const { isSystemBuilderAppName } = require('./paths-system-builder-keys');
15
+
16
+ const nodeFs = () => require('../internal/fs-real-sync');
17
+
18
+ /** @type {Readonly<Record<string, string[]>>} */
19
+ const SYSTEM_APP_SOURCE_REPO_DIR_NAMES = Object.freeze({
20
+ dataplane: ['aifabrix-dataplane'],
21
+ 'miso-controller': ['aifabrix-miso'],
22
+ 'builder-api': ['aifabrix-builder']
23
+ });
24
+
25
+ /** @type {Readonly<Record<string, string[]>>} */
26
+ const SYSTEM_APP_RELOAD_MARKERS = Object.freeze({
27
+ dataplane: ['app/main.py'],
28
+ 'miso-controller': ['packages/miso-controller/package.json'],
29
+ 'builder-api': ['lib/cli.js', 'bin/aifabrix.js']
30
+ });
31
+
32
+ /**
33
+ * @param {string} appName
34
+ * @param {string} rootPath
35
+ * @returns {boolean}
36
+ */
37
+ function isValidReloadSourceRoot(appName, rootPath) {
38
+ if (!rootPath || typeof rootPath !== 'string') {
39
+ return false;
40
+ }
41
+ const markers = SYSTEM_APP_RELOAD_MARKERS[appName];
42
+ if (!markers || markers.length === 0) {
43
+ return nodeFs().existsSync(rootPath);
44
+ }
45
+ return markers.some((rel) => nodeFs().existsSync(path.join(rootPath, rel)));
46
+ }
47
+
48
+ /**
49
+ * @param {string} builderPath
50
+ * @param {string} [buildContext]
51
+ * @returns {string}
52
+ */
53
+ function resolveBuildContextFromBuilder(builderPath, buildContext = '../..') {
54
+ const ctx = buildContext && typeof buildContext === 'string' ? buildContext : '.';
55
+ return path.resolve(builderPath, ctx);
56
+ }
57
+
58
+ /**
59
+ * @param {{ getAifabrixWork?: () => (string|null), getCwdBuilderAppPath?: (string) => (string|null) }} deps
60
+ * @returns {{ getWork: () => (string|null), getCwdBuilder: (string) => (string|null) }}
61
+ */
62
+ function resolveReloadDeps(deps) {
63
+ return {
64
+ getWork: deps.getAifabrixWork || (() => require('./paths').getAifabrixWork()),
65
+ getCwdBuilder: deps.getCwdBuilderAppPath || ((name) => require('./paths').getCwdBuilderAppPath(name))
66
+ };
67
+ }
68
+
69
+ /**
70
+ * @param {string} appName
71
+ * @param {string} builderPath
72
+ * @param {string} buildContext
73
+ * @param {{ getAifabrixWork?: () => (string|null), getCwdBuilderAppPath?: (string) => (string|null) }} deps
74
+ * @returns {string[]}
75
+ */
76
+ function collectReloadSourceCandidates(appName, builderPath, buildContext, deps) {
77
+ const { getWork, getCwdBuilder } = resolveReloadDeps(deps);
78
+ const candidates = [];
79
+ const cwdHit = getCwdBuilder(appName);
80
+ if (cwdHit) {
81
+ candidates.push(resolveBuildContextFromBuilder(cwdHit, buildContext));
82
+ }
83
+
84
+ const work = getWork();
85
+ if (!work) {
86
+ return candidates;
87
+ }
88
+
89
+ const repoNames = SYSTEM_APP_SOURCE_REPO_DIR_NAMES[appName] || [];
90
+ for (const repoName of repoNames) {
91
+ candidates.push(path.join(work, repoName));
92
+ }
93
+ try {
94
+ for (const entry of nodeFs().readdirSync(work)) {
95
+ if (!entry || entry.startsWith('.')) continue;
96
+ const builderSub = path.join(work, entry, 'builder', appName);
97
+ if (nodeFs().existsSync(builderSub)) {
98
+ candidates.push(resolveBuildContextFromBuilder(builderSub, buildContext));
99
+ }
100
+ }
101
+ } catch {
102
+ // ignore unreadable work root
103
+ }
104
+ return candidates;
105
+ }
106
+
107
+ /**
108
+ * @param {string} appName
109
+ * @param {string[]} candidates
110
+ * @param {string} fallback
111
+ * @returns {string}
112
+ */
113
+ function pickFirstValidReloadRoot(appName, candidates, fallback) {
114
+ for (const candidate of candidates) {
115
+ if (isValidReloadSourceRoot(appName, candidate)) {
116
+ return candidate;
117
+ }
118
+ }
119
+ return fallback;
120
+ }
121
+
122
+ /**
123
+ * Resolve bind-mount source for `--reload` on platform system apps.
124
+ *
125
+ * @param {string} appName
126
+ * @param {string} builderPath - builder/<app> directory used for run
127
+ * @param {string} [buildContext='../..'] - build.context from application.yaml
128
+ * @param {{ getAifabrixWork?: () => (string|null), getCwdBuilderAppPath?: (string) => (string|null) }} [deps]
129
+ * @returns {string}
130
+ */
131
+ function resolveSystemAppReloadSourceRoot(appName, builderPath, buildContext = '../..', deps = {}) {
132
+ const direct = resolveBuildContextFromBuilder(builderPath, buildContext);
133
+ if (!isSystemBuilderAppName(appName)) {
134
+ return direct;
135
+ }
136
+ if (isValidReloadSourceRoot(appName, direct)) {
137
+ return direct;
138
+ }
139
+ const candidates = collectReloadSourceCandidates(appName, builderPath, buildContext, deps);
140
+ return pickFirstValidReloadRoot(appName, candidates, direct);
141
+ }
142
+
143
+ module.exports = {
144
+ SYSTEM_APP_SOURCE_REPO_DIR_NAMES,
145
+ SYSTEM_APP_RELOAD_MARKERS,
146
+ isValidReloadSourceRoot,
147
+ resolveSystemAppReloadSourceRoot
148
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Platform system builder app keys (shared to avoid circular requires in paths.js).
3
+ *
4
+ * @fileoverview SYSTEM_BUILDER_APP_KEYS for dataplane, miso-controller, etc.
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const SYSTEM_BUILDER_APP_KEYS = Object.freeze(['keycloak', 'miso-controller', 'dataplane', 'builder-api']);
12
+
13
+ /**
14
+ * @param {string} appName
15
+ * @returns {boolean}
16
+ */
17
+ function isSystemBuilderAppName(appName) {
18
+ if (!appName || typeof appName !== 'string') return false;
19
+ return SYSTEM_BUILDER_APP_KEYS.includes(appName);
20
+ }
21
+
22
+ module.exports = {
23
+ SYSTEM_BUILDER_APP_KEYS,
24
+ isSystemBuilderAppName
25
+ };
@@ -447,7 +447,7 @@ function getBuilderRoot() {
447
447
  * {@link getSystemBuilderRoot} (= {@link getAppsMaterializationParent}`/builder`), never the global CLI package tree.
448
448
  * @readonly
449
449
  */
450
- const SYSTEM_BUILDER_APP_KEYS = Object.freeze(['keycloak', 'miso-controller', 'dataplane']);
450
+ const SYSTEM_BUILDER_APP_KEYS = Object.freeze(['keycloak', 'miso-controller', 'dataplane', 'builder-api']);
451
451
 
452
452
  /**
453
453
  * @param {string} appName
@@ -611,6 +611,15 @@ function getIntegrationPath(appName) {
611
611
  if (!appName || typeof appName !== 'string') {
612
612
  throw new Error('App name is required and must be a string');
613
613
  }
614
+ try {
615
+ const { getIntegrationPathScope } = require('../programmatic/integration-path-scope');
616
+ const scope = getIntegrationPathScope();
617
+ if (scope && typeof scope.resolveIntegrationPath === 'function') {
618
+ return scope.resolveIntegrationPath(appName);
619
+ }
620
+ } catch {
621
+ // programmatic module optional for CLI-only usage
622
+ }
614
623
  const cwdInt = path.join(path.resolve(process.cwd()), 'integration', appName);
615
624
  try {
616
625
  if (nodeFs().existsSync(cwdInt)) {
@@ -727,25 +736,81 @@ function isExternalAppType(variables) {
727
736
  * @param {string} appName - Application name
728
737
  * @returns {Object|null} App type info or null if no config found
729
738
  */
730
- function checkIntegrationFolder(appName) {
731
- const integrationPath = getIntegrationPath(appName);
732
- let variables;
739
+ function isScopedIntegrationPathActive() {
733
740
  try {
734
- const configPath = resolveApplicationConfigPath(integrationPath);
735
- variables = loadConfigFile(configPath);
741
+ const { getIntegrationPathScope } = require('../programmatic/integration-path-scope');
742
+ const scope = getIntegrationPathScope();
743
+ return Boolean(scope && typeof scope.resolveIntegrationPath === 'function');
736
744
  } catch {
745
+ return false;
746
+ }
747
+ }
748
+
749
+ function externalIntegrationFolderResult(appPath, baseDir = 'integration') {
750
+ return {
751
+ isExternal: true,
752
+ appPath,
753
+ appType: 'external',
754
+ baseDir
755
+ };
756
+ }
757
+
758
+ function isExistingAppDirectory(dirPath) {
759
+ try {
760
+ return fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory();
761
+ } catch {
762
+ return false;
763
+ }
764
+ }
765
+
766
+ function resolveExistingWorkspacePath(appName, options) {
767
+ const { resolveAppWorkspace } = require('./app-path-resolve');
768
+ const { appPath, baseDir } = resolveAppWorkspace(appName, options);
769
+ if (isExistingAppDirectory(appPath)) {
770
+ return { appPath, baseDir };
771
+ }
772
+ const altWorkspace =
773
+ baseDir === 'enterprise-knowledge' ? 'integration' : 'enterprise-knowledge';
774
+ const alt = resolveAppWorkspace(appName, { ...options, workspace: altWorkspace });
775
+ if (!isExistingAppDirectory(alt.appPath)) {
737
776
  return null;
738
777
  }
739
- if (variables) {
778
+ return { appPath: alt.appPath, baseDir: alt.baseDir };
779
+ }
780
+
781
+ function externalWorkspaceFolderFromConfig(appPath, baseDir, scopedWorkspace) {
782
+ try {
783
+ const configPath = resolveApplicationConfigPath(appPath);
784
+ const variables = loadConfigFile(configPath);
785
+ if (!variables) {
786
+ return null;
787
+ }
740
788
  const isExternal = isExternalAppType(variables);
741
789
  return {
742
790
  isExternal,
743
- appPath: integrationPath,
791
+ appPath,
744
792
  appType: isExternal ? 'external' : 'regular',
745
- baseDir: 'integration'
793
+ baseDir
746
794
  };
795
+ } catch {
796
+ if (scopedWorkspace && isExistingAppDirectory(appPath)) {
797
+ return externalIntegrationFolderResult(appPath, baseDir);
798
+ }
799
+ return null;
747
800
  }
748
- return null;
801
+ }
802
+
803
+ function checkExternalWorkspaceFolder(appName, options = {}) {
804
+ const located = resolveExistingWorkspacePath(appName, options);
805
+ if (!located) {
806
+ return null;
807
+ }
808
+ const { appPath, baseDir } = located;
809
+ const scopedWorkspace = isScopedIntegrationPathActive();
810
+ if (scopedWorkspace && !isExistingAppDirectory(appPath)) {
811
+ return null;
812
+ }
813
+ return externalWorkspaceFolderFromConfig(appPath, baseDir, scopedWorkspace);
749
814
  }
750
815
 
751
816
  /**
@@ -776,6 +841,41 @@ function checkBuilderFolder(appName) {
776
841
  }
777
842
  return null;
778
843
  }
844
+
845
+ /**
846
+ * When {@link getBuilderPath} has no application config but the CLI ships
847
+ * `templates/applications/<appName>/`, materialize `builder/<appName>/` (same as
848
+ * `ensureAppFromTemplate` for platform apps on `up-miso` / `up-dataplane`).
849
+ *
850
+ * @param {string} appName
851
+ * @returns {Promise<boolean>} True when template was copied
852
+ */
853
+ async function ensureShippedBuilderAppTemplate(appName) {
854
+ if (!appName || typeof appName !== 'string') {
855
+ return false;
856
+ }
857
+ if (isSystemBuilderAppName(appName)) {
858
+ return false;
859
+ }
860
+ const projectRoot = getProjectRoot();
861
+ const templateDir = path.join(projectRoot, 'templates', 'applications', appName);
862
+ if (!fs.existsSync(templateDir) || !fs.statSync(templateDir).isDirectory()) {
863
+ return false;
864
+ }
865
+ const builderPath = getBuilderPath(appName);
866
+ try {
867
+ resolveApplicationConfigPath(builderPath);
868
+ return false;
869
+ } catch {
870
+ // No application config under builder/<appName>; copy shipped template.
871
+ }
872
+ const { copyTemplateFiles } = require('../validation/template');
873
+ const { ensureReadmeForAppPath } = require('../app/readme');
874
+ await copyTemplateFiles(appName, builderPath);
875
+ await ensureReadmeForAppPath(builderPath, appName);
876
+ return true;
877
+ }
878
+
779
879
  /**
780
880
  * Detects if an app is external type by checking application config.
781
881
  * Resolution order: integration/ first, then builder/; if neither exists, throws.
@@ -786,15 +886,20 @@ function checkBuilderFolder(appName) {
786
886
  * @returns {Promise<{isExternal: boolean, appPath: string, appType: string, baseDir?: string}>}
787
887
  * @throws {Error} When app not found in integration/ or builder/
788
888
  */
789
- async function detectAppType(appName, _options = {}) {
889
+ async function detectAppType(appName, options = {}) {
790
890
  if (!appName || typeof appName !== 'string') {
791
891
  throw new Error('App name is required and must be a string');
792
892
  }
793
- const integrationResult = checkIntegrationFolder(appName);
794
- if (integrationResult) return integrationResult;
893
+ const externalResult = checkExternalWorkspaceFolder(appName, options);
894
+ if (externalResult) return externalResult;
795
895
  const builderResult = checkBuilderFolder(appName);
796
896
  if (builderResult) return builderResult;
797
- throw new Error(`App '${appName}' not found in integration/${appName} or builder/${appName}`);
897
+ await ensureShippedBuilderAppTemplate(appName);
898
+ const builderAfterTemplate = checkBuilderFolder(appName);
899
+ if (builderAfterTemplate) return builderAfterTemplate;
900
+ throw new Error(
901
+ `App '${appName}' not found in integration/${appName}, enterprise-knowledge/${appName}, or builder/${appName}`
902
+ );
798
903
  }
799
904
 
800
905
  /**
@@ -808,19 +913,32 @@ async function detectAppType(appName, _options = {}) {
808
913
  * @returns {Promise<{appPath: string, envOnly: boolean}>} appPath and envOnly (true when only env.template is used)
809
914
  * @throws {Error} When app not found in integration or builder
810
915
  */
811
- async function getResolveAppPath(appName) {
916
+ function tryResolveEnvOnlyPath(dirPath) {
917
+ const envTemplatePath = path.join(dirPath, 'env.template');
918
+ if (!fs.existsSync(dirPath) || !fs.existsSync(envTemplatePath)) {
919
+ return null;
920
+ }
921
+ try {
922
+ resolveApplicationConfigPath(dirPath);
923
+ return { appPath: dirPath, envOnly: false };
924
+ } catch {
925
+ return { appPath: dirPath, envOnly: true };
926
+ }
927
+ }
928
+
929
+ async function getResolveAppPath(appName, options = {}) {
812
930
  if (!appName || typeof appName !== 'string') {
813
931
  throw new Error('App name is required and must be a string');
814
932
  }
815
- const integrationPath = getIntegrationPath(appName);
816
- const envTemplatePath = path.join(integrationPath, 'env.template');
817
- if (fs.existsSync(integrationPath) && fs.existsSync(envTemplatePath)) {
818
- try {
819
- resolveApplicationConfigPath(integrationPath);
820
- return { appPath: integrationPath, envOnly: false };
821
- } catch {
822
- return { appPath: integrationPath, envOnly: true };
823
- }
933
+ const { resolveAppWorkspace } = require('./app-path-resolve');
934
+ const { appPath: workspacePath } = resolveAppWorkspace(appName, options);
935
+ const workspaceHit = tryResolveEnvOnlyPath(workspacePath);
936
+ if (workspaceHit) {
937
+ return workspaceHit;
938
+ }
939
+ const integrationHit = tryResolveEnvOnlyPath(getIntegrationPath(appName));
940
+ if (integrationHit) {
941
+ return integrationHit;
824
942
  }
825
943
  const { resolveApplicationManifestPathSync } = require('./manifest-location');
826
944
  const manifestHit = resolveApplicationManifestPathSync({
@@ -831,7 +949,7 @@ async function getResolveAppPath(appName) {
831
949
  if (manifestHit) {
832
950
  return { appPath: manifestHit.absolutePath, envOnly: false };
833
951
  }
834
- const result = await detectAppType(appName);
952
+ const result = await detectAppType(appName, options);
835
953
  return { appPath: result.appPath, envOnly: false };
836
954
  }
837
955
 
@@ -918,9 +1036,16 @@ module.exports = {
918
1036
  getDeployJsonPath,
919
1037
  resolveApplicationConfigPath,
920
1038
  resolveRbacPath,
1039
+ ensureShippedBuilderAppTemplate,
921
1040
  detectAppType,
922
1041
  getResolveAppPath,
923
1042
  resolveIntegrationAppKeyFromCwd,
924
- clearProjectRootCache
1043
+ clearProjectRootCache,
1044
+ resolveSystemAppReloadSourceRoot: require('./paths-reload-source').resolveSystemAppReloadSourceRoot,
1045
+ getEnterpriseKnowledgePath: require('./enterprise-knowledge-paths').getEnterpriseKnowledgePath,
1046
+ getEnterpriseKnowledgeRoot: require('./enterprise-knowledge-paths').getEnterpriseKnowledgeRoot,
1047
+ listEnterpriseKnowledgeAnchors: require('./enterprise-knowledge-paths').listEnterpriseKnowledgeAnchors,
1048
+ resolveAppWorkspace: require('./app-path-resolve').resolveAppWorkspace,
1049
+ resolveExternalSystemPath: require('./app-path-resolve').resolveExternalSystemPath
925
1050
  };
926
1051
 
@@ -44,6 +44,65 @@ function collectSystemVariablePutRequests(systemConfiguration, envMap) {
44
44
  return requests;
45
45
  }
46
46
 
47
+ /** OpenAPI path param names resolved from env.template (not valid configuration[] names). */
48
+ const OPENAPI_PATH_PARAM_ENV_KEYS = ['systemKey', 'pillar'];
49
+
50
+ const PATH_PARAM_FALLBACK_ENV_KEYS = {
51
+ systemKey: 'E2E_SYSTEM_KEY',
52
+ pillar: 'E2E_CERTIFY_PILLAR'
53
+ };
54
+
55
+ /**
56
+ * @param {unknown} raw
57
+ * @param {{ allowKv?: boolean }} [options]
58
+ * @returns {string|null}
59
+ */
60
+ function resolvedEnvLiteral(raw, options = {}) {
61
+ if (raw === undefined || raw === null) {
62
+ return null;
63
+ }
64
+ const value = String(raw).trim();
65
+ if (!value || value.includes('{{')) {
66
+ return null;
67
+ }
68
+ if (!options.allowKv && value.startsWith('kv://')) {
69
+ return null;
70
+ }
71
+ return value;
72
+ }
73
+
74
+ function resolvePathParamValue(envMap, name) {
75
+ const direct = resolvedEnvLiteral(envMap[name]);
76
+ if (direct) {
77
+ return direct;
78
+ }
79
+ const fallbackKey = PATH_PARAM_FALLBACK_ENV_KEYS[name];
80
+ if (!fallbackKey) {
81
+ return null;
82
+ }
83
+ return resolvedEnvLiteral(envMap[fallbackKey], { allowKv: true });
84
+ }
85
+
86
+ /**
87
+ * @param {Object.<string, string>} envMap
88
+ * @param {Set<string>} [alreadyPushed]
89
+ * @returns {Array<{ name: string, value: string }>}
90
+ */
91
+ function collectOpenApiPathParamAliasPutRequests(envMap, alreadyPushed = new Set()) {
92
+ const requests = [];
93
+ for (const name of OPENAPI_PATH_PARAM_ENV_KEYS) {
94
+ if (alreadyPushed.has(name)) {
95
+ continue;
96
+ }
97
+ const value = resolvePathParamValue(envMap, name);
98
+ if (!value) {
99
+ continue;
100
+ }
101
+ requests.push({ name, value });
102
+ }
103
+ return requests;
104
+ }
105
+
47
106
  /**
48
107
  * Datasource overrides are name+value only; values may already be resolved in upload payload.
49
108
  *
@@ -83,7 +142,7 @@ function collectDatasourceOverridePutRequests(datasourceConfiguration) {
83
142
  * @returns {Promise<{ pushed: number, names: string[] }>}
84
143
  */
85
144
  async function pushRuntimeConfigurationValues(dataplaneUrl, authConfig, systemKey, payload) {
86
- const { envMap } = await buildResolvedEnvMapForIntegration(systemKey);
145
+ const { envMap } = await buildResolvedEnvMapForIntegration(systemKey, { dataplaneRuntime: true });
87
146
  const names = [];
88
147
  let pushed = 0;
89
148
 
@@ -91,7 +150,9 @@ async function pushRuntimeConfigurationValues(dataplaneUrl, authConfig, systemKe
91
150
  payload?.application?.configuration,
92
151
  envMap
93
152
  );
94
- for (const body of systemRequests) {
153
+ const pushedNames = new Set(systemRequests.map((r) => r.name));
154
+ const aliasRequests = collectOpenApiPathParamAliasPutRequests(envMap, pushedNames);
155
+ for (const body of [...systemRequests, ...aliasRequests]) {
95
156
  await putExternalSystemConfiguration(dataplaneUrl, systemKey, authConfig, body);
96
157
  names.push(body.name);
97
158
  pushed += 1;
@@ -114,6 +175,7 @@ async function pushRuntimeConfigurationValues(dataplaneUrl, authConfig, systemKe
114
175
 
115
176
  module.exports = {
116
177
  collectSystemVariablePutRequests,
178
+ collectOpenApiPathParamAliasPutRequests,
117
179
  collectDatasourceOverridePutRequests,
118
180
  pushRuntimeConfigurationValues
119
181
  };
@@ -226,7 +226,11 @@ function replaceKvInContent(content, secrets, envVars, scopedKv = null) {
226
226
  return envVars[envVar] || m;
227
227
  });
228
228
  }
229
- return value !== null && value !== undefined ? String(value) : match;
229
+ if (value !== null && value !== undefined) {
230
+ const { formatDotenvSubstitutionValue } = require('./env-dotenv-format');
231
+ return formatDotenvSubstitutionValue(String(value));
232
+ }
233
+ return match;
230
234
  });
231
235
  return replaced + suffix;
232
236
  });
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Remove stale OpenSSH known_hosts entries after server reprovision or Host alias rename.
3
+ *
4
+ * @fileoverview ssh-keygen -R helpers for dev init / refresh
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { execFile } = require('child_process');
12
+ const { promisify } = require('util');
13
+ const path = require('path');
14
+ const { getDefaultSshDir } = require('./ssh-key-helper');
15
+ const { getDevSshHostAlias, resolveDevSshHostAlias } = require('./dev-ssh-config-helper');
16
+
17
+ const execFileAsync = promisify(execFile);
18
+
19
+ /**
20
+ * @param {string} baseUrl
21
+ * @returns {string|null}
22
+ */
23
+ function hostnameFromBaseUrl(baseUrl) {
24
+ if (!baseUrl || typeof baseUrl !== 'string') return null;
25
+ const s = baseUrl.trim().replace(/\/+$/, '');
26
+ const withProtocol = /^https?:\/\//i.test(s) ? s : `https://${s}`;
27
+ try {
28
+ return new URL(withProtocol).hostname || null;
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * @param {string} hostname
36
+ * @param {string} knownHostsPath
37
+ * @returns {Promise<{ hostname: string, ok: boolean, error?: string }>}
38
+ */
39
+ async function removeKnownHostEntry(hostname, knownHostsPath) {
40
+ const host = String(hostname || '').trim();
41
+ if (!host) {
42
+ return { hostname: host, ok: false, error: 'empty hostname' };
43
+ }
44
+ try {
45
+ await execFileAsync('ssh-keygen', ['-R', host, '-f', knownHostsPath], {
46
+ encoding: 'utf8'
47
+ });
48
+ return { hostname: host, ok: true };
49
+ } catch (err) {
50
+ if (err && err.code === 'ENOENT') {
51
+ return { hostname: host, ok: false, error: 'ssh-keygen not found' };
52
+ }
53
+ return { hostname: host, ok: false, error: err.message || String(err) };
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Hostnames that may appear in known_hosts for a Builder dev SSH connection.
59
+ * Includes current Host alias, HostName (sync-ssh-host), remote-server host, and legacy Host aliases.
60
+ *
61
+ * @param {Object} p
62
+ * @param {string} p.syncHost - sync-ssh-host / HostName
63
+ * @param {string} p.syncUser - sync-ssh-user
64
+ * @param {string} [p.hostAlias] - Preferred ssh config Host alias
65
+ * @param {string} [p.baseUrl] - remote-server URL
66
+ * @param {string} [p.developerId]
67
+ * @param {string} [p.developerRootDomain]
68
+ * @param {string[]} [p.legacyHostAliases] - Previous Host keywords from ~/.ssh/config
69
+ * @returns {string[]}
70
+ */
71
+ function collectDevSshKnownHostCandidates(p) {
72
+ const syncHost = String(p.syncHost || '').trim();
73
+ const syncUser = String(p.syncUser || '').trim();
74
+ const candidates = new Set();
75
+ if (syncHost) {
76
+ candidates.add(syncHost);
77
+ }
78
+ if (p.hostAlias) {
79
+ candidates.add(String(p.hostAlias).trim());
80
+ }
81
+ const preferred = resolveDevSshHostAlias({
82
+ syncUser,
83
+ syncHost,
84
+ developerId: p.developerId,
85
+ developerRootDomain: p.developerRootDomain
86
+ });
87
+ if (preferred) {
88
+ candidates.add(preferred);
89
+ }
90
+ if (syncUser && syncHost) {
91
+ candidates.add(getDevSshHostAlias(syncUser, syncHost));
92
+ }
93
+ const fromUrl = hostnameFromBaseUrl(p.baseUrl);
94
+ if (fromUrl) {
95
+ candidates.add(fromUrl);
96
+ }
97
+ for (const alias of p.legacyHostAliases || []) {
98
+ const trimmed = String(alias || '').trim();
99
+ if (trimmed) {
100
+ candidates.add(trimmed);
101
+ }
102
+ }
103
+ return [...candidates].filter(Boolean);
104
+ }
105
+
106
+ /**
107
+ * @param {string[]} hostnames
108
+ * @param {string} [sshDir]
109
+ * @returns {Promise<{ cleared: string[], failed: Array<{ hostname: string, error: string }> }>}
110
+ */
111
+ async function refreshDevSshKnownHosts(hostnames, sshDir) {
112
+ const knownHostsPath = path.join(sshDir || getDefaultSshDir(), 'known_hosts');
113
+ const cleared = [];
114
+ const failed = [];
115
+ for (const hostname of hostnames) {
116
+ const result = await removeKnownHostEntry(hostname, knownHostsPath);
117
+ if (result.ok) {
118
+ cleared.push(result.hostname);
119
+ } else if (result.error && result.error !== 'empty hostname') {
120
+ failed.push({ hostname: result.hostname, error: result.error });
121
+ }
122
+ }
123
+ return { cleared, failed };
124
+ }
125
+
126
+ module.exports = {
127
+ collectDevSshKnownHostCandidates,
128
+ removeKnownHostEntry,
129
+ refreshDevSshKnownHosts
130
+ };