@aifabrix/builder 2.49.2 → 2.51.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 (459) hide show
  1. package/.cursor/plans/157.1-security-quality-violations-by-type.csv +374 -0
  2. package/.cursor/rules/assistant-driven-integration-build.mdc +40 -0
  3. package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +49 -0
  4. package/.cursor/rules/plan-rules/application-lifecycle.mdc +30 -0
  5. package/.cursor/rules/plan-rules/plan-frontmatter.mdc +35 -0
  6. package/.cursor/rules/plan-rules/plan-lifecycle.mdc +31 -0
  7. package/.cursor/rules/plan-rules/plan-validation-gate.mdc +34 -0
  8. package/.cursor/skills/README.md +1 -0
  9. package/.dockerignore +52 -0
  10. package/.eslintignore +22 -0
  11. package/README.md +2 -0
  12. package/bin/builder-api-cleanup.js +26 -0
  13. package/bin/builder-api-nest.js +10 -0
  14. package/bin/builder-api-spike.js +19 -0
  15. package/enterprise-knowledge/README.md +50 -0
  16. package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +22 -0
  17. package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +15 -0
  18. package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +69 -0
  19. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +52 -0
  20. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +29 -0
  21. package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +2 -0
  22. package/integration/README.md +81 -0
  23. package/integration/github/README.md +53 -0
  24. package/integration/github/application.json +21 -0
  25. package/integration/github/deploy.js +72 -0
  26. package/integration/github/env.template +11 -0
  27. package/integration/github/github-datasource-issue-comments.json +239 -0
  28. package/integration/github/github-datasource-issues.json +399 -0
  29. package/integration/github/github-datasource-repository.json +354 -0
  30. package/integration/github/github-deploy.json +1202 -0
  31. package/integration/github/github-system.json +82 -0
  32. package/integration/hubspot-test/README.md +1 -1
  33. package/integration/hubspot-test/create-hubspot.js +1 -16
  34. package/jest.isolated-projects.js +31 -1
  35. package/jest.projects.js +87 -1
  36. package/lib/api/dev-server-https.js +1 -1
  37. package/lib/api/enterprise-knowledge.api.js +63 -0
  38. package/lib/api/evidence-kinds.api.js +128 -0
  39. package/lib/api/evidence.api.js +172 -0
  40. package/lib/api/external-systems.api.js +8 -2
  41. package/lib/api/pipeline.api.js +5 -1
  42. package/lib/api/resource-types.api.js +5 -4
  43. package/lib/api/roles.api.js +121 -0
  44. package/lib/api/types/enterprise-knowledge.types.js +46 -0
  45. package/lib/api/types/evidence-kinds.types.js +42 -0
  46. package/lib/api/types/evidence.types.js +67 -0
  47. package/lib/api/types/resource-types.types.js +2 -0
  48. package/lib/api/types/roles.types.js +36 -0
  49. package/lib/app/certification-verify-rows.js +1 -1
  50. package/lib/app/controller-application-filter.js +36 -0
  51. package/lib/app/deploy.js +1 -1
  52. package/lib/app/list-external-systems.js +130 -0
  53. package/lib/app/list.js +20 -8
  54. package/lib/app/run.js +3 -1
  55. package/lib/app/show-display.js +8 -3
  56. package/lib/app/show-online.js +178 -0
  57. package/lib/app/show.js +39 -90
  58. package/lib/build/builder-api-docker-staging.js +47 -0
  59. package/lib/build/miso-controller-npm-sdk-guard.js +2 -2
  60. package/lib/build/standard-docker-build.js +2 -0
  61. package/lib/certification/merge-certification-from-artifact.js +1 -1
  62. package/lib/certification/post-unified-cert-sync.js +4 -31
  63. package/lib/certification/sync-after-external-command.js +0 -1
  64. package/lib/certification/sync-system-certification.js +0 -3
  65. package/lib/channels/add-channel.js +40 -34
  66. package/lib/channels/approval-guides/chatgpt.js +33 -0
  67. package/lib/channels/approval-guides/credential-portal.js +38 -0
  68. package/lib/channels/approval-guides/index.js +110 -0
  69. package/lib/channels/approval-guides/microsoft-copilot.js +34 -0
  70. package/lib/channels/approval-guides/slack.js +34 -0
  71. package/lib/channels/approval-guides/teams-bot.js +35 -0
  72. package/lib/channels/approval-guides/web-embed.js +32 -0
  73. package/lib/channels/channel-approval-guide.js +11 -0
  74. package/lib/channels/channel-artifact-generator.js +18 -5
  75. package/lib/channels/channel-audit.js +3 -0
  76. package/lib/channels/channel-auth-context.js +1 -1
  77. package/lib/channels/channel-description.js +59 -0
  78. package/lib/channels/channel-integration-generator.js +13 -230
  79. package/lib/channels/channel-integration-template.js +94 -0
  80. package/lib/channels/channel-runtime-resolver.js +43 -3
  81. package/lib/channels/channel-status-display.js +66 -26
  82. package/lib/channels/channel-targets.js +3 -3
  83. package/lib/cli/index.js +31 -3
  84. package/lib/cli/infra-guided.js +5 -1
  85. package/lib/cli/setup-app-external-create.js +111 -0
  86. package/lib/cli/setup-app.help.js +1 -1
  87. package/lib/cli/setup-app.js +60 -130
  88. package/lib/cli/setup-app.test-commands.js +26 -52
  89. package/lib/cli/setup-certification-commands.js +4 -4
  90. package/lib/cli/setup-certification.help.js +9 -9
  91. package/lib/cli/setup-dev.js +30 -9
  92. package/lib/cli/setup-external-system-help.js +4 -6
  93. package/lib/cli/setup-external-system.js +58 -52
  94. package/lib/cli/setup-infra-up-builder-api-action.js +64 -0
  95. package/lib/cli/setup-infra-up-platform-action.js +3 -1
  96. package/lib/cli/setup-infra.js +15 -0
  97. package/lib/cli/setup-list.js +43 -0
  98. package/lib/cli/setup-utility-help-after.js +12 -0
  99. package/lib/cli/setup-utility-repair.js +26 -7
  100. package/lib/cli/setup-utility-validate.js +41 -2
  101. package/lib/cli/setup-utility.js +5 -3
  102. package/lib/commands/app.js +15 -43
  103. package/lib/commands/channel-add-setup.js +110 -0
  104. package/lib/commands/channel.js +42 -8
  105. package/lib/commands/datasource-sync-display.js +96 -0
  106. package/lib/commands/datasource-sync-policy.js +210 -0
  107. package/lib/commands/datasource-test-trust-cli.js +6 -6
  108. package/lib/commands/datasource-unified-test-cli.js +2 -1
  109. package/lib/commands/datasource-unified-test-cli.options.js +33 -23
  110. package/lib/commands/deploy-gate-failure-details.js +184 -0
  111. package/lib/commands/deploy-gate-orchestrator.js +368 -0
  112. package/lib/commands/dev-cli-handlers.js +7 -62
  113. package/lib/commands/dev-host-ops-params.js +91 -0
  114. package/lib/commands/dev-host-ops-poll.js +111 -0
  115. package/lib/commands/dev-host-ops.js +107 -94
  116. package/lib/commands/dev-init.js +6 -106
  117. package/lib/commands/dev-refresh.js +197 -0
  118. package/lib/commands/enterprise-knowledge.js +284 -0
  119. package/lib/commands/evidence-cli-leaves.js +250 -0
  120. package/lib/commands/evidence-kind.js +428 -0
  121. package/lib/commands/evidence.js +51 -0
  122. package/lib/commands/governance-cli-shared.js +2 -2
  123. package/lib/commands/governance-command-action.js +5 -3
  124. package/lib/commands/governance-fixture-subjects.js +85 -0
  125. package/lib/commands/governance.js +1 -1
  126. package/lib/commands/lifecycle-command-action.js +2 -2
  127. package/lib/commands/lifecycle-external.js +3 -3
  128. package/lib/commands/manifest-cli-auth.js +29 -0
  129. package/lib/commands/manifest-cli-commands.js +170 -0
  130. package/lib/commands/manifest-cli-integration-path.js +63 -0
  131. package/lib/commands/manifest.js +21 -0
  132. package/lib/commands/protection-cli-leaves.js +3 -3
  133. package/lib/commands/repair-auth-apply.js +15 -1
  134. package/lib/commands/repair-authentications-454.js +169 -0
  135. package/lib/commands/repair-capability-openapi-warnings.js +126 -0
  136. package/lib/commands/repair-datasource-apply.js +135 -0
  137. package/lib/commands/repair-datasource-auto-rbac.js +62 -1
  138. package/lib/commands/repair-datasource-http-service-contract.js +239 -0
  139. package/lib/commands/repair-datasource-operation-security.js +180 -0
  140. package/lib/commands/repair-datasource-run.js +7 -2
  141. package/lib/commands/repair-datasource-sync-operations.js +177 -0
  142. package/lib/commands/repair-datasource-webhooks-sync-bridge.js +133 -0
  143. package/lib/commands/repair-datasource.js +12 -68
  144. package/lib/commands/repair-env-template.js +11 -1
  145. package/lib/commands/repair-external-run.js +121 -31
  146. package/lib/commands/repair-internal.js +1 -1
  147. package/lib/commands/repair-openapi-export.js +156 -0
  148. package/lib/commands/repair-openapi-sync.js +33 -8
  149. package/lib/commands/repair-orchestration-datasource-split.js +259 -0
  150. package/lib/commands/repair-persist.js +22 -1
  151. package/lib/commands/repair-rbac-platform-preset.js +204 -0
  152. package/lib/commands/repair-rbac-reader-roles.js +191 -0
  153. package/lib/commands/repair-rbac.js +163 -86
  154. package/lib/commands/repair-steps.js +83 -18
  155. package/lib/commands/repair-system-permissions.js +1 -0
  156. package/lib/commands/repair.js +1 -1
  157. package/lib/commands/resource-type.js +166 -44
  158. package/lib/commands/role.js +452 -0
  159. package/lib/commands/run-post-publish-data-sync.js +68 -0
  160. package/lib/commands/setup-modes.js +1 -1
  161. package/lib/commands/setup.js +1 -1
  162. package/lib/commands/test-e2e-external.js +21 -8
  163. package/lib/commands/test-governance-cli-options.js +2 -2
  164. package/lib/commands/test-trust-cli-options.js +2 -2
  165. package/lib/commands/up-builder-api-bootstrap.js +71 -0
  166. package/lib/commands/up-builder-api-provision.js +241 -0
  167. package/lib/commands/up-builder-api.js +88 -0
  168. package/lib/commands/up-common.js +25 -1
  169. package/lib/commands/upload-credential-push-log.js +117 -0
  170. package/lib/commands/upload-data-sync-finalize.js +60 -0
  171. package/lib/commands/upload-probe.js +66 -0
  172. package/lib/commands/upload-publish-context.js +4 -1
  173. package/lib/commands/upload-sidecar-followups.js +55 -27
  174. package/lib/commands/upload.js +116 -157
  175. package/lib/commands/validate-json.js +230 -0
  176. package/lib/commands/verify-governance-combined-external.js +1 -1
  177. package/lib/commands/verify-governance-db.js +2 -2
  178. package/lib/commands/verify-operations-command-action.js +2 -2
  179. package/lib/commands/verify-operations-step-plan.js +79 -41
  180. package/lib/commands/verify-operations-steps.js +2 -2
  181. package/lib/commands/verify-trust-command-action.js +1 -1
  182. package/lib/commands/wizard-core.js +1 -1
  183. package/lib/commands/wizard-headless.js +2 -1
  184. package/lib/core/admin-secrets.js +2 -6
  185. package/lib/core/audit-logger.js +1 -1
  186. package/lib/core/secrets-env-content.js +10 -4
  187. package/lib/core/secrets-env-write.js +2 -13
  188. package/lib/core/secrets-load.js +1 -3
  189. package/lib/datasource/agent-trust-run.js +3 -3
  190. package/lib/datasource/capability/relate-operations.js +1 -1
  191. package/lib/datasource/deploy.js +3 -1
  192. package/lib/datasource/test-e2e.js +6 -1
  193. package/lib/datasource/unified-validation-run-body.js +4 -1
  194. package/lib/datasource/unified-validation-run.js +1 -1
  195. package/lib/deployment/deploy-poll-ui.js +73 -12
  196. package/lib/deployment/deployer-poll-run.js +113 -0
  197. package/lib/deployment/deployer.js +17 -87
  198. package/lib/evidence/dataplane-context.js +21 -0
  199. package/lib/evidence/evidence-display.js +78 -0
  200. package/lib/evidence/evidence-service.js +392 -0
  201. package/lib/external-system/deploy.js +290 -112
  202. package/lib/external-system/download.js +7 -3
  203. package/lib/external-system/test-execution.js +1 -1
  204. package/lib/external-system/test-system-level.js +8 -10
  205. package/lib/external-system/test.js +12 -6
  206. package/lib/generator/deploy-script.js +73 -0
  207. package/lib/generator/external.js +2 -1
  208. package/lib/generator/helpers.js +13 -5
  209. package/lib/generator/index.js +17 -2
  210. package/lib/generator/split-variables.js +9 -3
  211. package/lib/generator/wizard.js +3 -36
  212. package/lib/infrastructure/helpers-docker-check.js +6 -0
  213. package/lib/infrastructure/helpers.js +1 -1
  214. package/lib/internal/fs-real-sync.js +22 -1
  215. package/lib/internal/node-fs.js +2 -0
  216. package/lib/lifecycle/lifecycle-governance-options.js +1 -1
  217. package/lib/lifecycle/verify-step-progress.js +1 -1
  218. package/lib/programmatic/access-log.js +26 -0
  219. package/lib/programmatic/auth-config.js +45 -0
  220. package/lib/programmatic/bearer-auth.js +176 -0
  221. package/lib/programmatic/builder-api-request.js +175 -0
  222. package/lib/programmatic/builder-api-route-dispatch.js +82 -0
  223. package/lib/programmatic/builder-api-runtime-config.js +42 -0
  224. package/lib/programmatic/builder-api-server.js +230 -0
  225. package/lib/programmatic/builder-help-authentication-catalog.js +282 -0
  226. package/lib/programmatic/builder-help-connected-system-ui.js +266 -0
  227. package/lib/programmatic/builder-help-enterprise-sync-fabrix.js +60 -0
  228. package/lib/programmatic/builder-help-envelope.js +36 -0
  229. package/lib/programmatic/builder-help-fixtures.js +200 -0
  230. package/lib/programmatic/builder-help-governance.js +172 -0
  231. package/lib/programmatic/builder-help-schema-catalog.js +92 -0
  232. package/lib/programmatic/builder-help.js +361 -0
  233. package/lib/programmatic/capability-registry.js +77 -0
  234. package/lib/programmatic/command-options.js +32 -0
  235. package/lib/programmatic/enterprise-mcp-client.js +114 -0
  236. package/lib/programmatic/http-problem-details.js +99 -0
  237. package/lib/programmatic/http-route-match.js +40 -0
  238. package/lib/programmatic/idempotency-cache.js +69 -0
  239. package/lib/programmatic/index.js +53 -0
  240. package/lib/programmatic/integration-path-scope.js +39 -0
  241. package/lib/programmatic/log-redaction.js +66 -0
  242. package/lib/programmatic/manifest-get-section.js +146 -0
  243. package/lib/programmatic/manifest-patch-section.js +252 -0
  244. package/lib/programmatic/manifest-repair.js +122 -0
  245. package/lib/programmatic/manifest-section-dependency-graph.js +160 -0
  246. package/lib/programmatic/manifest-section-io.js +225 -0
  247. package/lib/programmatic/manifest-section-quality.js +171 -0
  248. package/lib/programmatic/manifest-section-registry-data.js +269 -0
  249. package/lib/programmatic/manifest-section-registry.js +222 -0
  250. package/lib/programmatic/nest-http-bridge.js +34 -0
  251. package/lib/programmatic/openapi-component-schemas.js +68 -0
  252. package/lib/programmatic/openapi-description-enricher.js +117 -0
  253. package/lib/programmatic/openapi-descriptions.js +190 -0
  254. package/lib/programmatic/openapi-docs-serving.js +123 -0
  255. package/lib/programmatic/openapi-help-schemas.js +63 -0
  256. package/lib/programmatic/openapi-manifest-schemas.js +141 -0
  257. package/lib/programmatic/openapi-operation-bindings.js +274 -0
  258. package/lib/programmatic/openapi-request-schemas.js +155 -0
  259. package/lib/programmatic/openapi-result-schemas.js +493 -0
  260. package/lib/programmatic/openapi-schema-descriptions-certify.js +139 -0
  261. package/lib/programmatic/openapi-schema-descriptions-core.js +162 -0
  262. package/lib/programmatic/openapi-schema-descriptions-help.js +40 -0
  263. package/lib/programmatic/openapi-schema-descriptions-manifest.js +143 -0
  264. package/lib/programmatic/openapi-schema-descriptions-mcp.js +118 -0
  265. package/lib/programmatic/openapi-schema-descriptions-operations.js +281 -0
  266. package/lib/programmatic/openapi-schema-helpers.js +108 -0
  267. package/lib/programmatic/openapi-spec.js +203 -0
  268. package/lib/programmatic/orchestration-openapi-meta.js +159 -0
  269. package/lib/programmatic/platform-rbac-catalog.js +90 -0
  270. package/lib/programmatic/request-timeout.js +53 -0
  271. package/lib/programmatic/route-handler-map.js +143 -0
  272. package/lib/programmatic/route-handlers-context.js +29 -0
  273. package/lib/programmatic/route-handlers.js +33 -0
  274. package/lib/programmatic/run-certify.js +57 -0
  275. package/lib/programmatic/run-enterprise-mcp.js +32 -0
  276. package/lib/programmatic/run-lifecycle.js +29 -0
  277. package/lib/programmatic/run-repair.js +41 -0
  278. package/lib/programmatic/run-repository-emcp.js +62 -0
  279. package/lib/programmatic/run-template-workspace.js +74 -0
  280. package/lib/programmatic/run-test.js +49 -0
  281. package/lib/programmatic/run-upload.js +63 -0
  282. package/lib/programmatic/run-validate.js +53 -0
  283. package/lib/programmatic/run-wizard.js +40 -0
  284. package/lib/programmatic/system-key.js +48 -0
  285. package/lib/programmatic/wizard-config-normalize.js +118 -0
  286. package/lib/programmatic/workspace-cleanup.js +128 -0
  287. package/lib/programmatic/workspace-context.js +145 -0
  288. package/lib/programmatic/workspace-lock.js +75 -0
  289. package/lib/programmatic/workspace-meta.js +64 -0
  290. package/lib/programmatic/workspace-ops.js +149 -0
  291. package/lib/protection/run-commands-upload-sync.js +35 -0
  292. package/lib/protection/run-commands.js +2 -20
  293. package/lib/protection/upload-batch.js +11 -7
  294. package/lib/resolvers/evidence-kind-file.js +230 -0
  295. package/lib/resolvers/resource-type-file.js +58 -1
  296. package/lib/resolvers/role-file.js +227 -0
  297. package/lib/schema/application-schema.json +22 -2
  298. package/lib/schema/external-datasource.schema.json +245 -2
  299. package/lib/schema/external-system.schema.json +259 -119
  300. package/lib/schema/flag-map-validation-run.json +3 -0
  301. package/lib/schema/infra.parameter.yaml +25 -1
  302. package/lib/schema/type/credential-field-registry.json +21 -5
  303. package/lib/schema/type/document-storage.json +9 -0
  304. package/lib/utils/agent-trust-run-display.js +1 -1
  305. package/lib/utils/api.js +8 -2
  306. package/lib/utils/app-path-resolve.js +168 -0
  307. package/lib/utils/app-register-config.js +4 -3
  308. package/lib/utils/authentication-env-template.js +222 -0
  309. package/lib/utils/cli-sync-options.js +62 -10
  310. package/lib/utils/cli-utils.js +15 -3
  311. package/lib/utils/cli-workspace-options.js +29 -0
  312. package/lib/utils/compose-generate-docker-compose.js +102 -0
  313. package/lib/utils/configuration-env-resolver.js +203 -27
  314. package/lib/utils/datasource-test-run-certificate-tty.js +28 -2
  315. package/lib/utils/datasource-test-run-certification-debug.js +130 -0
  316. package/lib/utils/datasource-test-run-debug-display.js +2 -0
  317. package/lib/utils/datasource-test-run-debug-slice.js +7 -0
  318. package/lib/utils/datasource-test-run-display.js +2 -1
  319. package/lib/utils/dev-ca-install.js +5 -6
  320. package/lib/utils/dev-config.js +2 -2
  321. package/lib/utils/dev-init-ssh-merge.js +165 -23
  322. package/lib/utils/dev-list-sort.js +145 -0
  323. package/lib/utils/dev-pin-share-instructions.js +110 -0
  324. package/lib/utils/dev-platform-tls.js +0 -63
  325. package/lib/utils/dev-ssh-config-helper.js +177 -33
  326. package/lib/utils/docker-build.js +46 -27
  327. package/lib/utils/docker-daemon-tls-ca.js +1 -1
  328. package/lib/utils/docker-exec.js +91 -6
  329. package/lib/utils/enterprise-knowledge-paths.js +142 -0
  330. package/lib/utils/env-copy.js +3 -4
  331. package/lib/utils/env-dotenv-format.js +103 -0
  332. package/lib/utils/error-formatters/error-parser.js +0 -3
  333. package/lib/utils/external-env-template.js +5 -2
  334. package/lib/utils/external-system-display.js +5 -1
  335. package/lib/utils/external-system-readiness-compact-blocks.js +248 -0
  336. package/lib/utils/external-system-readiness-compact-display.js +324 -0
  337. package/lib/utils/external-system-readiness-core.js +16 -0
  338. package/lib/utils/external-system-readiness-deploy-display.js +29 -11
  339. package/lib/utils/external-system-readiness-display-internals.js +3 -1
  340. package/lib/utils/external-system-readiness-display.js +20 -30
  341. package/lib/utils/external-system-system-test-tty-certification.js +135 -0
  342. package/lib/utils/external-system-system-test-tty.js +5 -41
  343. package/lib/utils/health-check-request.js +2 -3
  344. package/lib/utils/help-builder.js +9 -1
  345. package/lib/utils/host-ops-job-labels.js +236 -0
  346. package/lib/utils/host-ops-job-result.js +61 -0
  347. package/lib/utils/host-ops-poll-ui.js +163 -0
  348. package/lib/utils/image-name.js +22 -4
  349. package/lib/utils/integration-path-resolve.js +112 -0
  350. package/lib/utils/logger.js +37 -4
  351. package/lib/utils/manifest-source-emit.js +1 -1
  352. package/lib/utils/paths-reload-source.js +148 -0
  353. package/lib/utils/paths-system-builder-keys.js +25 -0
  354. package/lib/utils/paths.js +183 -30
  355. package/lib/utils/pipeline-upload-auth-retry.js +4 -0
  356. package/lib/utils/postgres-platform-bootstrap.js +24 -17
  357. package/lib/utils/postgres-wipe.js +5 -2
  358. package/lib/utils/remote-dev-auth.js +39 -4
  359. package/lib/utils/resolve-docker-image-ref.js +36 -6
  360. package/lib/utils/runtime-configuration-values.js +64 -2
  361. package/lib/utils/secrets-helpers.js +5 -1
  362. package/lib/utils/ssh-known-hosts.js +130 -0
  363. package/lib/utils/test-target-cli-options.js +75 -0
  364. package/lib/utils/token-manager.js +16 -0
  365. package/lib/utils/upload-sync-options.js +20 -2
  366. package/lib/utils/validation-run-request.js +11 -2
  367. package/lib/validation/external-manifest-validator.js +11 -1
  368. package/lib/validation/openapi-contract-surface-validator.js +430 -0
  369. package/lib/validation/openapi-contract-vendor-validation.js +238 -0
  370. package/lib/validation/validate-external-file.js +160 -0
  371. package/lib/validation/validate.js +6 -117
  372. package/lib/validation/validator.js +6 -5
  373. package/package.json +76 -37
  374. package/packages/builder-api/README.md +120 -0
  375. package/packages/builder-api/package.json +30 -0
  376. package/packages/builder-api/src/app.module.ts +7 -0
  377. package/packages/builder-api/src/auth/auth.module.ts +5 -0
  378. package/packages/builder-api/src/external-system/external-system.module.ts +5 -0
  379. package/packages/builder-api/src/main.ts +16 -0
  380. package/packages/builder-api/tsconfig.json +15 -0
  381. package/scripts/check-builder-api-architecture-grep.js +79 -0
  382. package/scripts/docker_image_content_gate.js +47 -0
  383. package/scripts/docker_image_content_gate.sh +5 -0
  384. package/scripts/export-builder-api-evidence.js +262 -0
  385. package/scripts/lib/builder-api-docker-staging-copy.js +60 -0
  386. package/scripts/lib/builder-api-docker-staging-core.js +183 -0
  387. package/scripts/lib/docker-image-content-gate-core.js +166 -0
  388. package/scripts/lib/plan-actor.js +109 -0
  389. package/scripts/lib/plan-config.js +20 -0
  390. package/scripts/lib/plan-gates.js +154 -0
  391. package/scripts/lib/plan-meta.js +104 -0
  392. package/scripts/lib/plan-parse.js +162 -0
  393. package/scripts/lib/plan-prevalidate-gates.js +337 -0
  394. package/scripts/lib/plan-run-core.js +125 -0
  395. package/scripts/lib/plan-run-report.js +119 -0
  396. package/scripts/plan-approve.js +24 -0
  397. package/scripts/plan-archive.js +49 -0
  398. package/scripts/plan-run.js +13 -0
  399. package/scripts/plan-set-actor.js +21 -0
  400. package/scripts/plan-validate.js +80 -0
  401. package/scripts/pnpm/af.mjs +110 -0
  402. package/scripts/pnpm/check-quiet.mjs +32 -0
  403. package/scripts/pnpm/dev-install.mjs +29 -0
  404. package/scripts/pnpm/dev-reload.mjs +18 -0
  405. package/scripts/pnpm/help.mjs +55 -0
  406. package/scripts/pnpm/lib/dev-reload-core.mjs +189 -0
  407. package/scripts/pnpm/lib/dev-reload-log-capture.mjs +67 -0
  408. package/scripts/pnpm/lib/dev-reload-log-utils.mjs +32 -0
  409. package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +124 -0
  410. package/scripts/pnpm/lib/resolve-app-url.mjs +183 -0
  411. package/scripts/pnpm/lib/spinner.mjs +42 -0
  412. package/scripts/stage_builder_api_for_docker.js +65 -0
  413. package/scripts/sync-builder-api-template.js +44 -0
  414. package/templates/README.md +3 -0
  415. package/templates/applications/builder-api/Dockerfile +38 -0
  416. package/templates/applications/builder-api/application.yaml +75 -0
  417. package/templates/applications/builder-api/env.template +48 -0
  418. package/templates/applications/dataplane/application.yaml +27 -5
  419. package/templates/applications/dataplane/env.template +38 -15
  420. package/templates/applications/dataplane/rbac.yaml +85 -3
  421. package/templates/applications/miso-controller/application.yaml +10 -1
  422. package/templates/applications/miso-controller/env.template +11 -10
  423. package/templates/applications/miso-controller/rbac.yaml +72 -0
  424. package/templates/channels/README.md +18 -0
  425. package/templates/channels/ai-fabrix-icon.jpg +0 -0
  426. package/templates/channels/chatgpt/install.template.md.hbs +21 -24
  427. package/templates/channels/chatgpt/integration/README.md +11 -0
  428. package/templates/channels/chatgpt/integration/application.json +15 -0
  429. package/templates/channels/chatgpt/integration/chatgpt-system.json +29 -0
  430. package/templates/channels/chatgpt/integration/env.template +4 -0
  431. package/templates/channels/microsoft-copilot/install.template.md.hbs +20 -25
  432. package/templates/channels/microsoft-copilot/integration/README.md +11 -0
  433. package/templates/channels/microsoft-copilot/integration/application.json +15 -0
  434. package/templates/channels/microsoft-copilot/integration/env.template +6 -0
  435. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +34 -0
  436. package/templates/channels/slack/install.template.md.hbs +48 -18
  437. package/templates/channels/slack/integration/README.md +38 -0
  438. package/templates/channels/slack/integration/application.json +18 -0
  439. package/templates/channels/slack/integration/env.template +29 -0
  440. package/templates/channels/slack/integration/slack-datasource-conversations.json +226 -0
  441. package/templates/channels/slack/integration/slack-datasource-messages.json +269 -0
  442. package/templates/channels/slack/integration/slack-system.json +144 -0
  443. package/templates/channels/slack/manifest.template.json.hbs +20 -10
  444. package/templates/channels/teams-bot/install.template.md.hbs +31 -17
  445. package/templates/channels/teams-bot/integration/README.md +18 -0
  446. package/templates/channels/teams-bot/integration/application.json +17 -0
  447. package/templates/channels/teams-bot/integration/env.template +5 -0
  448. package/templates/channels/teams-bot/integration/teams-bot-system.json +55 -0
  449. package/templates/channels/teams-bot/manifest.template.json.hbs +27 -0
  450. package/templates/channels/web-embed/install.template.md.hbs +16 -26
  451. package/templates/channels/web-embed/integration/README.md +11 -0
  452. package/templates/channels/web-embed/integration/application.json +15 -0
  453. package/templates/channels/web-embed/integration/env.template +4 -0
  454. package/templates/channels/web-embed/integration/web-embed-system.json +29 -0
  455. package/templates/openapi/redoc_page.html +86 -0
  456. package/templates/python/docker-compose.hbs +11 -0
  457. package/templates/python/requirements.txt +2 -2
  458. package/templates/typescript/docker-compose.hbs +11 -0
  459. package/lib/certification/cli-cert-sync-skip.js +0 -21
@@ -6,18 +6,49 @@
6
6
 
7
7
  const nodeFsLib = require('../internal/node-fs');
8
8
  const path = require('path');
9
- const { ensureSshDir } = require('./ssh-key-helper');
9
+ const { ensureSshDir, getDefaultEd25519PrivateKeyPath } = require('./ssh-key-helper');
10
10
 
11
11
  /**
12
- * Derive SSH config Host alias: sync user + real hostname (e.g. dev01.builder02.local).
13
- * @param {string} sshUser - sync-ssh-user
14
- * @param {string} sshHost - sync-ssh-host (HostName)
12
+ * Legacy SSH Host alias: sync user + builder API hostname (e.g. dev03.builder01.aifabrix.dev).
13
+ * @param {string} sshUser
14
+ * @param {string} sshHost
15
15
  * @returns {string}
16
16
  */
17
17
  function getDevSshHostAlias(sshUser, sshHost) {
18
18
  return `${sshUser}.${sshHost}`;
19
19
  }
20
20
 
21
+ /**
22
+ * @param {string|number} developerId
23
+ * @returns {string}
24
+ */
25
+ function formatDeveloperNumericId(developerId) {
26
+ const trimmed = String(developerId ?? '').trim();
27
+ if (/^\d+$/.test(trimmed)) {
28
+ return String(parseInt(trimmed, 10)).padStart(2, '0');
29
+ }
30
+ return trimmed.replace(/^dev/i, '');
31
+ }
32
+
33
+ /**
34
+ * Preferred SSH config Host alias — matches per-developer app host when developer-root-domain is set.
35
+ *
36
+ * @param {Object} p
37
+ * @param {string} p.syncUser
38
+ * @param {string} p.syncHost - sync-ssh-host (HostName for TCP connect)
39
+ * @param {string|number} [p.developerId]
40
+ * @param {string} [p.developerRootDomain] - e.g. aifabrix.dev → dev03.aifabrix.dev; dev.aifabrix → dev03.dev.aifabrix
41
+ * @returns {string}
42
+ */
43
+ function resolveDevSshHostAlias(p) {
44
+ const root = String(p.developerRootDomain || '').trim().replace(/^\.+|\.+$/g, '');
45
+ const id = p.developerId !== undefined && p.developerId !== null ? String(p.developerId).trim() : '';
46
+ if (root && id) {
47
+ return `dev${formatDeveloperNumericId(id)}.${root}`;
48
+ }
49
+ return getDevSshHostAlias(p.syncUser, p.syncHost);
50
+ }
51
+
21
52
  /**
22
53
  * Parse ssh config into Host blocks (lines before the first Host are ignored).
23
54
  * @param {string} content
@@ -91,6 +122,48 @@ function resolveConnectAlias(matchedBlock, canonicalAlias) {
91
122
  return matchedBlock.aliases[0] || canonicalAlias;
92
123
  }
93
124
 
125
+ /**
126
+ * @param {string[]} body
127
+ * @param {string} hostname
128
+ * @param {string} user
129
+ * @returns {boolean}
130
+ */
131
+ function isSshHostBlockForUserHost(body, hostname, user) {
132
+ return (
133
+ getHostBlockDirective(body, 'HostName') === hostname &&
134
+ getHostBlockDirective(body, 'User') === user
135
+ );
136
+ }
137
+
138
+ /**
139
+ * Drop Host blocks that target the same HostName + User (legacy alias migration).
140
+ * @param {string} content
141
+ * @param {string} hostname
142
+ * @param {string} user
143
+ * @returns {string}
144
+ */
145
+ function removeSshHostBlocksForUserHost(content, hostname, user) {
146
+ const lines = (content || '').split(/\r?\n/);
147
+ const out = [];
148
+ for (let i = 0; i < lines.length; i++) {
149
+ const m = lines[i].match(/^Host\s+(.+?)\s*$/i);
150
+ if (!m) {
151
+ out.push(lines[i]);
152
+ continue;
153
+ }
154
+ const body = [];
155
+ i++;
156
+ while (i < lines.length && !/^Host\s/i.test(lines[i])) {
157
+ body.push(lines[i++]);
158
+ }
159
+ if (!isSshHostBlockForUserHost(body, hostname, user)) {
160
+ out.push(`Host ${m[1].trim()}`, ...body);
161
+ }
162
+ i--;
163
+ }
164
+ return out.join('\n').replace(/\s+$/, '');
165
+ }
166
+
94
167
  /**
95
168
  * Replace an existing Host block for hostAlias, or append a new block at EOF.
96
169
  * @param {string} content - Existing ssh config (may be empty)
@@ -100,7 +173,8 @@ function resolveConnectAlias(matchedBlock, canonicalAlias) {
100
173
  * @returns {string} Updated config
101
174
  */
102
175
  function upsertSshHostBlock(content, hostAlias, hostname, user) {
103
- const lines = (content || '').split(/\r?\n/);
176
+ const withoutDupes = removeSshHostBlocksForUserHost(content, hostname, user);
177
+ const lines = (withoutDupes || '').split(/\r?\n/);
104
178
  const out = [];
105
179
  let i = 0;
106
180
  while (i < lines.length) {
@@ -123,6 +197,7 @@ function upsertSshHostBlock(content, hostAlias, hostname, user) {
123
197
  `Host ${hostAlias}`,
124
198
  ` HostName ${hostname}`,
125
199
  ` User ${user}`,
200
+ ` IdentityFile ${getDefaultEd25519PrivateKeyPath().replace(/\\/g, '/')}`,
126
201
  ' IdentitiesOnly yes'
127
202
  ].join('\n');
128
203
  const trimmed = out.join('\n').replace(/\s+$/, '');
@@ -130,12 +205,27 @@ function upsertSshHostBlock(content, hostAlias, hostname, user) {
130
205
  return `${prefix}${block}\n`;
131
206
  }
132
207
 
208
+ function listHostAliasesForUserHost(content, hostname, user) {
209
+ const aliases = [];
210
+ for (const block of parseSshHostBlocks(content)) {
211
+ const hn = getHostBlockDirective(block.body, 'HostName');
212
+ const u = getHostBlockDirective(block.body, 'User');
213
+ if (hn === hostname && u === user) {
214
+ aliases.push(...block.aliases);
215
+ }
216
+ }
217
+ return aliases;
218
+ }
219
+
133
220
  /**
134
221
  * @param {string} sshUser
135
222
  * @param {string} sshHost
136
- * @returns {{ error: string }|{ user: string, host: string, hostAlias: string }}
223
+ * @param {Object} [options]
224
+ * @param {string|number} [options.developerId]
225
+ * @param {string} [options.developerRootDomain]
226
+ * @returns {{ error: string }|{ user: string, host: string, hostAlias: string, legacyHostAlias: string }}
137
227
  */
138
- function parseEnsureSshInputs(sshUser, sshHost) {
228
+ function parseEnsureSshInputs(sshUser, sshHost, options = {}) {
139
229
  if (!sshUser || typeof sshUser !== 'string' || !sshUser.trim()) {
140
230
  return { error: 'missing ssh user' };
141
231
  }
@@ -144,7 +234,53 @@ function parseEnsureSshInputs(sshUser, sshHost) {
144
234
  }
145
235
  const user = sshUser.trim();
146
236
  const host = sshHost.trim();
147
- return { user, host, hostAlias: getDevSshHostAlias(user, host) };
237
+ const hostAlias = resolveDevSshHostAlias({
238
+ syncUser: user,
239
+ syncHost: host,
240
+ developerId: options.developerId,
241
+ developerRootDomain: options.developerRootDomain
242
+ });
243
+ return {
244
+ user,
245
+ host,
246
+ hostAlias,
247
+ legacyHostAlias: getDevSshHostAlias(user, host)
248
+ };
249
+ }
250
+
251
+ /**
252
+ * @param {string} configPath
253
+ * @returns {Promise<{ content: string }|{ error: string }>}
254
+ */
255
+ async function readExistingSshConfig(configPath) {
256
+ try {
257
+ const content = await nodeFsLib.nodeFs().promises.readFile(configPath, 'utf8');
258
+ return { content };
259
+ } catch (e) {
260
+ if (e.code === 'ENOENT') {
261
+ return { content: '' };
262
+ }
263
+ return { error: e.message || String(e) };
264
+ }
265
+ }
266
+
267
+ /**
268
+ * @param {{ aliases: string[], body: string[] }|null} matched
269
+ * @param {string} hostAlias
270
+ * @param {string} rootDomain
271
+ * @returns {{ skip: true, hostAlias: string }|{ skip: false, matched: typeof matched }}
272
+ */
273
+ function resolveExistingSshBlock(matched, hostAlias, rootDomain) {
274
+ if (!matched) {
275
+ return { skip: false, matched: null };
276
+ }
277
+ const matchedAlias = resolveConnectAlias(matched, hostAlias);
278
+ const keepExisting =
279
+ !rootDomain || (matched.aliases.includes(hostAlias) && matchedAlias === hostAlias);
280
+ if (keepExisting) {
281
+ return { skip: true, hostAlias: matchedAlias };
282
+ }
283
+ return { skip: false, matched };
148
284
  }
149
285
 
150
286
  /**
@@ -152,44 +288,52 @@ function parseEnsureSshInputs(sshUser, sshHost) {
152
288
  * @param {string} sshUser - SSH user (sync-ssh-user)
153
289
  * @param {string} sshHost - Real hostname (sync-ssh-host)
154
290
  * @param {string} [sshDir] - SSH directory (default ~/.ssh)
155
- * @returns {Promise<{ ok: boolean, configPath?: string, hostAlias?: string, error?: string, skippedDuplicate?: boolean }>}
291
+ * @param {Object} [options]
292
+ * @param {string|number} [options.developerId]
293
+ * @param {string} [options.developerRootDomain]
294
+ * @returns {Promise<{ ok: boolean, configPath?: string, hostAlias?: string, error?: string, skippedDuplicate?: boolean, updated?: boolean }>}
156
295
  */
157
- async function ensureDevSshConfigBlock(sshUser, sshHost, sshDir) {
158
- const parsed = parseEnsureSshInputs(sshUser, sshHost);
296
+ async function ensureDevSshConfigBlock(sshUser, sshHost, sshDir, options = {}) {
297
+ const parsed = parseEnsureSshInputs(sshUser, sshHost, options);
159
298
  if ('error' in parsed) {
160
299
  return { ok: false, error: parsed.error };
161
300
  }
162
- const { user, host, hostAlias } = parsed;
163
- const dir = ensureSshDir(sshDir);
164
- const configPath = path.join(dir, 'config');
165
- let existing = '';
166
- try {
167
- existing = await nodeFsLib.nodeFs().promises.readFile(configPath, 'utf8');
168
- } catch (e) {
169
- if (e.code !== 'ENOENT') {
170
- return { ok: false, error: e.message || String(e) };
171
- }
301
+ const { user, host, hostAlias, legacyHostAlias } = parsed;
302
+ const configPath = path.join(ensureSshDir(sshDir), 'config');
303
+ const readResult = await readExistingSshConfig(configPath);
304
+ if ('error' in readResult) {
305
+ return { ok: false, error: readResult.error };
306
+ }
307
+ const rootDomain = String(options.developerRootDomain || '').trim();
308
+ const matched = findMatchingHostBlockForUserHost(readResult.content, host, user);
309
+ const existing = resolveExistingSshBlock(matched, hostAlias, rootDomain);
310
+ if (existing.skip) {
311
+ return { ok: true, configPath, hostAlias: existing.hostAlias, skippedDuplicate: true };
172
312
  }
173
- const matched = findMatchingHostBlockForUserHost(existing, host, user);
174
- if (matched) {
175
- return {
176
- ok: true,
177
- configPath,
178
- hostAlias: resolveConnectAlias(matched, hostAlias),
179
- skippedDuplicate: true
180
- };
181
- }
182
- const next = upsertSshHostBlock(existing, hostAlias, host, user);
183
- if (next === existing) {
313
+ const next = upsertSshHostBlock(readResult.content, hostAlias, host, user);
314
+ if (next === readResult.content) {
184
315
  return { ok: true, configPath, hostAlias };
185
316
  }
186
317
  await nodeFsLib.nodeFs().promises.writeFile(configPath, next, { mode: 0o600 });
187
- return { ok: true, configPath, hostAlias };
318
+ const migratedFrom = existing.matched
319
+ ? resolveConnectAlias(existing.matched, hostAlias)
320
+ : legacyHostAlias;
321
+ return {
322
+ ok: true,
323
+ configPath,
324
+ hostAlias,
325
+ updated: true,
326
+ migratedFrom: migratedFrom !== hostAlias ? migratedFrom : undefined
327
+ };
188
328
  }
189
329
 
190
330
  module.exports = {
331
+ formatDeveloperNumericId,
191
332
  getDevSshHostAlias,
333
+ resolveDevSshHostAlias,
192
334
  findMatchingHostBlockForUserHost,
335
+ listHostAliasesForUserHost,
336
+ removeSshHostBlocksForUserHost,
193
337
  resolveConnectAlias,
194
338
  upsertSshHostBlock,
195
339
  ensureDevSshConfigBlock
@@ -110,25 +110,15 @@ function buildDockerCliArgs(imageName, tag, dockerfilePath, contextPath, buildAr
110
110
  return args;
111
111
  }
112
112
 
113
- function runDockerBuildProcess(buildOpts) {
114
- const {
115
- imageName,
116
- tag,
117
- dockerfilePath,
118
- contextPath,
119
- spinner,
120
- resolve,
121
- reject,
122
- env = {},
123
- buildArgs = {},
124
- noCache = false
125
- } = buildOpts;
126
- const spawnEnv = { ...process.env, ...env };
127
- const args = buildDockerCliArgs(imageName, tag, dockerfilePath, contextPath, buildArgs, noCache);
128
- const dockerProcess = spawn('docker', args, {
129
- shell: process.platform === 'win32',
130
- env: spawnEnv
131
- });
113
+ function createDockerSpawnParams(options) {
114
+ const { imageName, tag, dockerfilePath, contextPath, buildArgs, noCache, env } = options;
115
+ const spawnEnv = { ...process.env, ...(env || {}) };
116
+ const args = buildDockerCliArgs(imageName, tag, dockerfilePath, contextPath, buildArgs || {}, noCache);
117
+ return { spawnEnv, args };
118
+ }
119
+
120
+ function attachDockerBuildListeners(dockerProcess, context) {
121
+ const { imageName, tag, spinner, resolve, reject } = context;
132
122
  let stdoutBuffer = '';
133
123
  let stderrBuffer = '';
134
124
  const lastProgressUpdateRef = { current: Date.now() };
@@ -162,6 +152,35 @@ function runDockerBuildProcess(buildOpts) {
162
152
  });
163
153
  }
164
154
 
155
+ function runDockerBuildProcess(buildOpts) {
156
+ const {
157
+ imageName,
158
+ tag,
159
+ dockerfilePath,
160
+ contextPath,
161
+ spinner,
162
+ resolve,
163
+ reject,
164
+ env = {},
165
+ buildArgs = {},
166
+ noCache = false
167
+ } = buildOpts;
168
+ const { spawnEnv, args } = createDockerSpawnParams({
169
+ imageName,
170
+ tag,
171
+ dockerfilePath,
172
+ contextPath,
173
+ buildArgs,
174
+ noCache,
175
+ env
176
+ });
177
+ const dockerProcess = spawn('docker', args, {
178
+ shell: process.platform === 'win32',
179
+ env: spawnEnv
180
+ });
181
+ attachDockerBuildListeners(dockerProcess, { imageName, tag, spinner, resolve, reject });
182
+ }
183
+
165
184
  /**
166
185
  * Executes Docker build command with progress indicator
167
186
  * @param {string} imageName - Image name to build
@@ -236,12 +255,10 @@ async function executeBuild(imageName, dockerfilePath, contextPath, tag, options
236
255
 
237
256
  // Tag image if additional tag provided
238
257
  if (options && options.tag && options.tag !== 'latest') {
239
- const { promisify } = require('util');
240
- const { exec } = require('child_process');
241
- const run = promisify(exec);
258
+ const { execFileWithDockerEnv } = require('./docker-exec');
242
259
  const { getDockerExecEnv } = require('./remote-docker-env');
243
260
  const env = await getDockerExecEnv();
244
- await run(`docker tag ${imageName}:${tag} ${imageName}:latest`, { env });
261
+ await execFileWithDockerEnv('docker', ['tag', `${imageName}:${tag}`, `${imageName}:latest`], { env });
245
262
  }
246
263
  }
247
264
 
@@ -270,12 +287,14 @@ async function executeDockerBuildWithTag(effectiveImageName, imageName, dockerfi
270
287
  }
271
288
 
272
289
  try {
273
- const { promisify } = require('util');
274
- const { exec } = require('child_process');
275
- const run = promisify(exec);
290
+ const { execFileWithDockerEnv } = require('./docker-exec');
276
291
  const { getDockerExecEnv } = require('./remote-docker-env');
277
292
  const env = await getDockerExecEnv();
278
- await run(`docker tag ${effectiveImageName}:${tag} ${imageName}:${tag}`, { env });
293
+ await execFileWithDockerEnv(
294
+ 'docker',
295
+ ['tag', `${effectiveImageName}:${tag}`, `${imageName}:${tag}`],
296
+ { env }
297
+ );
279
298
  logger.log(formatSuccessLine(`Tagged image: ${imageName}:${tag}`));
280
299
  } catch (err) {
281
300
  logger.log(
@@ -183,7 +183,7 @@ function fetchDockerDaemonTlsCaPem(dockerEndpoint, opts) {
183
183
  host: parsed.host,
184
184
  port: parsed.port,
185
185
  servername: parsed.servername,
186
- rejectUnauthorized: false
186
+ rejectUnauthorized: true
187
187
  },
188
188
  () => {
189
189
  try {
@@ -9,9 +9,85 @@
9
9
  'use strict';
10
10
 
11
11
  const { promisify } = require('util');
12
- const { exec } = require('child_process');
12
+ const childProcess = require('child_process');
13
+ const execFileAsync = childProcess.execFile ? promisify(childProcess.execFile) : null;
13
14
 
14
- const execAsync = promisify(exec);
15
+ /**
16
+ * Parse a command string into argv tokens without invoking a shell.
17
+ * Supports simple single/double quoted segments and escaping quotes within double quotes.
18
+ * @param {string} command
19
+ * @returns {string[]}
20
+ */
21
+ // eslint-disable-next-line max-statements, complexity -- tokenizer intentionally handles quoted token edge-cases in one place
22
+ function parseCommandTokens(command) {
23
+ const input = String(command || '');
24
+ if (!input.trim()) {
25
+ throw new Error('Command must be a non-empty string');
26
+ }
27
+
28
+ /** @type {string[]} */
29
+ const tokens = [];
30
+ let current = '';
31
+ let quote = null;
32
+
33
+ for (let i = 0; i < input.length; i += 1) {
34
+ const ch = input[i];
35
+ if (quote === null && (ch === '"' || ch === '\'')) {
36
+ quote = ch;
37
+ continue;
38
+ }
39
+ if (quote !== null && ch === quote) {
40
+ quote = null;
41
+ continue;
42
+ }
43
+ // Bash double-quote escapes: \", \\, \$, \`, and escaped newlines.
44
+ if (quote === '"' && ch === '\\') {
45
+ const next = input[i + 1];
46
+ if (next === '"' || next === '\\' || next === '$' || next === '`' || next === '\n') {
47
+ current += next;
48
+ i += 1;
49
+ continue;
50
+ }
51
+ }
52
+ if (quote === null && /\s/.test(ch)) {
53
+ if (current) {
54
+ tokens.push(current);
55
+ current = '';
56
+ }
57
+ continue;
58
+ }
59
+ current += ch;
60
+ }
61
+
62
+ if (quote !== null) {
63
+ throw new Error('Unterminated quote in command');
64
+ }
65
+ if (current) {
66
+ tokens.push(current);
67
+ }
68
+ if (!tokens.length) {
69
+ throw new Error('Command produced no executable token');
70
+ }
71
+ return tokens;
72
+ }
73
+
74
+ /**
75
+ * Run an executable with argv and remote Docker env settings.
76
+ * @param {string} file
77
+ * @param {string[]} [args]
78
+ * @param {import('child_process').ExecFileOptions} [options]
79
+ * @returns {Promise<{ stdout: string, stderr: string }>}
80
+ */
81
+ async function execFileWithDockerEnv(file, args = [], options = {}) {
82
+ const { getDockerExecEnv } = require('./remote-docker-env');
83
+ const env = { ...(await getDockerExecEnv()), ...(options.env || {}) };
84
+ if (execFileAsync) {
85
+ return execFileAsync(file, args, { ...options, env });
86
+ }
87
+ const execAsync = promisify(childProcess.exec);
88
+ const command = [file, ...args.map((arg) => String(arg))].join(' ');
89
+ return execAsync(command, { ...options, env });
90
+ }
15
91
 
16
92
  /**
17
93
  * Run a shell command with process.env merged with remote Docker client settings when docker-endpoint is set.
@@ -20,9 +96,18 @@ const execAsync = promisify(exec);
20
96
  * @returns {Promise<{ stdout: string, stderr: string }>}
21
97
  */
22
98
  async function execWithDockerEnv(command, options = {}) {
23
- const { getDockerExecEnv } = require('./remote-docker-env');
24
- const env = { ...(await getDockerExecEnv()), ...(options.env || {}) };
25
- return execAsync(command, { ...options, env });
99
+ if (!execFileAsync || process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID !== undefined) {
100
+ const { getDockerExecEnv } = require('./remote-docker-env');
101
+ const env = { ...(await getDockerExecEnv()), ...(options.env || {}) };
102
+ const execAsync = promisify(childProcess.exec);
103
+ return execAsync(command, { ...options, env });
104
+ }
105
+ const [file, ...args] = parseCommandTokens(command);
106
+ return execFileWithDockerEnv(file, args, options);
26
107
  }
27
108
 
28
- module.exports = { execWithDockerEnv };
109
+ module.exports = {
110
+ execWithDockerEnv,
111
+ execFileWithDockerEnv,
112
+ parseCommandTokens
113
+ };
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Enterprise Knowledge workspace path helpers (456.5).
3
+ *
4
+ * @fileoverview Paths under enterprise-knowledge/ for Enterprise Knowledge anchors
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const path = require('path');
12
+ const os = require('os');
13
+ const { nodeFs } = require('../internal/node-fs');
14
+
15
+ const WORKSPACE_ENTERPRISE_KNOWLEDGE = 'enterprise-knowledge';
16
+ const SYSTEM_KIND_ENTERPRISE_KNOWLEDGE = 'enterpriseKnowledge';
17
+
18
+ /**
19
+ * Materialization parent without importing paths.js (avoids circular deps in tests).
20
+ * @returns {string}
21
+ */
22
+ function getMaterializationParent() {
23
+ const work = process.env.AIFABRIX_WORK;
24
+ if (work && typeof work === 'string' && work.trim()) {
25
+ return path.resolve(work.trim());
26
+ }
27
+ if (process.env.AIFABRIX_HOME && typeof process.env.AIFABRIX_HOME === 'string') {
28
+ return path.resolve(process.env.AIFABRIX_HOME.trim());
29
+ }
30
+ return path.join(os.homedir(), '.aifabrix');
31
+ }
32
+
33
+ /**
34
+ * Absolute enterprise-knowledge/ next to process.cwd when present.
35
+ * @returns {string|null}
36
+ */
37
+ function getCwdEnterpriseKnowledgeRoot() {
38
+ const p = path.join(path.resolve(process.cwd()), WORKSPACE_ENTERPRISE_KNOWLEDGE);
39
+ try {
40
+ const disk = nodeFs();
41
+ if (disk.existsSync(p)) {
42
+ const st = disk.statSync(p);
43
+ if (st && typeof st.isDirectory === 'function' && st.isDirectory()) {
44
+ return p;
45
+ }
46
+ }
47
+ } catch {
48
+ // ignore
49
+ }
50
+ return null;
51
+ }
52
+
53
+ /**
54
+ * Default enterprise-knowledge root under materialization parent.
55
+ * @returns {string}
56
+ */
57
+ function getEnterpriseKnowledgeRoot() {
58
+ const cwdRoot = getCwdEnterpriseKnowledgeRoot();
59
+ if (cwdRoot) {
60
+ return cwdRoot;
61
+ }
62
+ return path.join(getMaterializationParent(), WORKSPACE_ENTERPRISE_KNOWLEDGE);
63
+ }
64
+
65
+ /**
66
+ * Resolves enterprise-knowledge/<anchorKey> (cwd-first, then materialization parent).
67
+ * @param {string} anchorKey - Enterprise Knowledge anchor key
68
+ * @returns {string}
69
+ */
70
+ function getEnterpriseKnowledgePath(anchorKey) {
71
+ if (!anchorKey || typeof anchorKey !== 'string') {
72
+ throw new Error('Anchor key is required and must be a string');
73
+ }
74
+ const cwdHit = path.join(path.resolve(process.cwd()), WORKSPACE_ENTERPRISE_KNOWLEDGE, anchorKey);
75
+ try {
76
+ const disk = nodeFs();
77
+ if (disk.existsSync(cwdHit)) {
78
+ const st = disk.statSync(cwdHit);
79
+ if (st && typeof st.isDirectory === 'function' && st.isDirectory()) {
80
+ return cwdHit;
81
+ }
82
+ }
83
+ } catch {
84
+ // ignore
85
+ }
86
+ return path.join(getMaterializationParent(), WORKSPACE_ENTERPRISE_KNOWLEDGE, anchorKey);
87
+ }
88
+
89
+ function isEnterpriseKnowledgeDirectory(disk, fullPath) {
90
+ try {
91
+ const child = disk.statSync(fullPath);
92
+ return Boolean(child && typeof child.isDirectory === 'function' && child.isDirectory());
93
+ } catch {
94
+ return false;
95
+ }
96
+ }
97
+
98
+ function collectAnchorNamesInRoot(disk, root, names) {
99
+ if (!root || !disk.existsSync(root) || !isEnterpriseKnowledgeDirectory(disk, root)) {
100
+ return;
101
+ }
102
+ let entries;
103
+ try {
104
+ entries = disk.readdirSync(root);
105
+ } catch {
106
+ return;
107
+ }
108
+ for (const name of entries) {
109
+ const full = path.join(root, name);
110
+ if (isEnterpriseKnowledgeDirectory(disk, full)) {
111
+ names.add(name);
112
+ }
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Lists anchor folder names under enterprise-knowledge/.
118
+ * @returns {string[]}
119
+ */
120
+ function listEnterpriseKnowledgeAnchors() {
121
+ const disk = nodeFs();
122
+ const names = new Set();
123
+ const roots = new Set();
124
+ const cwdRoot = getCwdEnterpriseKnowledgeRoot();
125
+ if (cwdRoot) {
126
+ roots.add(path.resolve(cwdRoot));
127
+ }
128
+ roots.add(path.resolve(path.join(getMaterializationParent(), WORKSPACE_ENTERPRISE_KNOWLEDGE)));
129
+ for (const root of roots) {
130
+ collectAnchorNamesInRoot(disk, root, names);
131
+ }
132
+ return [...names].sort();
133
+ }
134
+
135
+ module.exports = {
136
+ WORKSPACE_ENTERPRISE_KNOWLEDGE,
137
+ SYSTEM_KIND_ENTERPRISE_KNOWLEDGE,
138
+ getCwdEnterpriseKnowledgeRoot,
139
+ getEnterpriseKnowledgeRoot,
140
+ getEnterpriseKnowledgePath,
141
+ listEnterpriseKnowledgeAnchors
142
+ };
@@ -123,7 +123,8 @@ async function writeEnvOutputForReload(outputPath, runEnvPath, appName) {
123
123
  } else {
124
124
  baseContent = runContent;
125
125
  }
126
- const toWrite = mergeEnvMapIntoContent(baseContent, runMap, { appendMissingFromNewMap: false });
126
+ let toWrite = mergeEnvMapIntoContent(baseContent, runMap, { appendMissingFromNewMap: false });
127
+ toWrite = substituteMntDataForLocal(toWrite, outputPath);
127
128
  await fsp.writeFile(outputPath, toWrite, { mode: 0o600 });
128
129
  logger.log(
129
130
  formatSuccessLine(
@@ -384,9 +385,7 @@ async function processEnvVariables(envPath, variablesPath, appName, secretsPath,
384
385
  }
385
386
 
386
387
  const label = variables.build.envOutputPath;
387
- const appPathForLocal =
388
- (copyOptions && copyOptions.appPath) ||
389
- (variablesPath ? path.dirname(variablesPath) : null);
388
+ const appPathForLocal = (copyOptions && copyOptions.appPath) || path.dirname(variablesPath);
390
389
  const preferLocal =
391
390
  copyOptions && typeof copyOptions === 'object' && copyOptions.preferLocalEnvOutputPath === true;
392
391
  const freshEnv = copyOptions && typeof copyOptions === 'object' && copyOptions.freshEnv === true;