@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
@@ -27,6 +27,10 @@ const {
27
27
  logCapabilitiesOverview: logCapabilitiesOverviewSection,
28
28
  logIntegrationHealthSection: logIntegrationHealthSectionBlock
29
29
  } = require('./external-system-system-test-tty-overview');
30
+ const {
31
+ systemCertStatus,
32
+ logCertificationSection
33
+ } = require('./external-system-system-test-tty-certification');
30
34
 
31
35
  /**
32
36
  * @param {'ok'|'warn'|'fail'|'skipped'|null} st
@@ -220,24 +224,6 @@ function collectKeyIssues(rows, cap) {
220
224
  return out.slice(0, Math.max(0, cap));
221
225
  }
222
226
 
223
- function certificateBucket(env) {
224
- const cert = env && env.certificate;
225
- if (!cert || typeof cert !== 'object') return { status: null, level: null };
226
- return {
227
- status: cert.status ? String(cert.status) : null,
228
- level: cert.level ? String(cert.level) : null
229
- };
230
- }
231
-
232
- function systemCertStatus(rows) {
233
- const certs = rows
234
- .map(r => (r && r.datasourceTestRun ? certificateBucket(r.datasourceTestRun) : { status: null, level: null }))
235
- .filter(c => c.status !== null);
236
- if (certs.length === 0) return null;
237
- if (certs.some(c => c.status === 'not_passed')) return 'not_passed';
238
- return 'passed';
239
- }
240
-
241
227
  function drillDownCommand(runType, datasourceKey) {
242
228
  if (!datasourceKey) return null;
243
229
  if (runType === 'e2e') return `aifabrix datasource test-e2e ${datasourceKey}`;
@@ -359,28 +345,6 @@ function logKeyIssuesSection(rows) {
359
345
  return true;
360
346
  }
361
347
 
362
- function logCertificationSection(rows) {
363
- const certSt = systemCertStatus(rows);
364
- if (!certSt) return;
365
- logger.log('');
366
- logger.log(metaGray(SEP));
367
- logger.log('');
368
- logger.log(sectionTitle('Certification:'));
369
- logger.log('');
370
- logger.log(chalk.white(`System level: ${certSt === 'passed' ? '✔ Achieved' : '✖ Not achieved'}`));
371
- logger.log('');
372
- logger.log(chalk.white('Breakdown:'));
373
- for (const r of rows) {
374
- const env = r && r.datasourceTestRun;
375
- if (!env) continue;
376
- const cert = certificateBucket(env);
377
- if (!cert.status) continue;
378
- const g = cert.status === 'passed' ? '✔' : '✖';
379
- const tier = cert.level ? cert.level : '(no level)';
380
- logger.log(chalk.white(`- ${env.datasourceKey}: ${g} ${tier}`));
381
- }
382
- }
383
-
384
348
  function logUseAndFooter(results, runType, systemStatus, blocking) {
385
349
  logger.log('');
386
350
  logger.log(metaGray(SEP));
@@ -422,7 +386,7 @@ function displaySystemAggregateDatasourceTestRuns(results, opts) {
422
386
  const ttyIo = { log: logger.log.bind(logger), chalk, metaGray, sectionTitle, statusGlyph, SEP };
423
387
  logCapabilitiesOverviewSection(rows, ttyIo);
424
388
  logIntegrationHealthSectionBlock(rows, runType, ttyIo);
425
- logCertificationSection(rows);
389
+ logCertificationSection(rows, { debug: opts.debug, verbose: opts.verbose });
426
390
  logUseAndFooter(results, runType, systemStatus, drillDownKey);
427
391
  }
428
392
 
@@ -26,6 +26,7 @@ const CATEGORIES = [
26
26
  { name: 'up-platform' },
27
27
  { name: 'up-miso' },
28
28
  { name: 'up-dataplane' },
29
+ { name: 'up-builder-api' },
29
30
  { name: 'down-infra', term: 'down-infra [service|appKey]' },
30
31
  { name: 'doctor' },
31
32
  { name: 'status' },
@@ -77,8 +78,10 @@ const CATEGORIES = [
77
78
  { name: 'dimension' },
78
79
  { name: 'dimension value', term: 'dimension value <command>' },
79
80
  { name: 'resource-type' },
81
+ { name: 'enterprise-knowledge' },
80
82
  { name: 'identity' },
81
- { name: 'protection' }
83
+ { name: 'protection' },
84
+ { name: 'evidence' }
82
85
  ]
83
86
  },
84
87
  {
@@ -97,11 +100,13 @@ const CATEGORIES = [
97
100
  {
98
101
  name: 'External Systems',
99
102
  commands: [
103
+ { name: 'list', term: 'list' },
100
104
  { name: 'wizard', term: 'wizard [systemKey]' },
101
105
  { name: 'download', term: 'download <systemKey>' },
102
106
  { name: 'upload', term: 'upload <systemKey>' },
103
107
  { name: 'delete', term: 'delete <systemKey>' },
104
108
  { name: 'repair', term: 'repair <systemKey>' },
109
+ { name: 'manifest', term: 'manifest get-section <systemKey> <sectionKey>' },
105
110
  { name: 'channel', term: 'channel scaffold <channelTarget>' },
106
111
  { name: 'datasource' },
107
112
  { name: 'datasource load', term: 'datasource load <datasourceKey>' },
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Human-readable labels for host-ops job polling output.
3
+ *
4
+ * @fileoverview Host-ops job type → user-facing action text
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /** @type {Record<string, { action: string, durationHint: string, pendingDetail?: string, runningDetail?: string }>} */
12
+ const HOST_OPS_JOB_LABELS = {
13
+ 'remove-dev-user': {
14
+ action: 'Removing developer',
15
+ durationHint: 'usually 1–2 min',
16
+ pendingDetail: 'waiting for host job',
17
+ runningDetail: 'stopping platform, removing OS user and database'
18
+ },
19
+ 'provision-dev-user': {
20
+ action: 'Provisioning developer',
21
+ durationHint: 'usually 2–3 min',
22
+ pendingDetail: 'waiting for host job',
23
+ runningDetail: 'creating OS user, installing CLI and platform'
24
+ },
25
+ 'install-dev-platform': {
26
+ action: 'Installing platform for',
27
+ durationHint: 'usually 3–5 min',
28
+ pendingDetail: 'waiting for host job',
29
+ runningDetail: 'pulling images and starting containers'
30
+ },
31
+ 'reinstall-dev-platform': {
32
+ action: 'Re-installing platform for',
33
+ durationHint: 'usually 3–5 min',
34
+ pendingDetail: 'waiting for host job',
35
+ runningDetail: 'replacing platform containers'
36
+ },
37
+ 'update-dev-platform': {
38
+ action: 'Updating platform for',
39
+ durationHint: 'usually 2–4 min',
40
+ pendingDetail: 'waiting for host job',
41
+ runningDetail: 'refreshing platform images'
42
+ },
43
+ 'install-builder-cli': {
44
+ action: 'Installing Builder CLI for',
45
+ durationHint: 'usually 1–2 min',
46
+ pendingDetail: 'waiting for host job',
47
+ runningDetail: 'installing CLI on dev host'
48
+ },
49
+ 'remove-dev-platform': {
50
+ action: 'Removing platform for',
51
+ durationHint: 'usually 1–2 min',
52
+ pendingDetail: 'waiting for host job',
53
+ runningDetail: 'stopping platform containers'
54
+ }
55
+ };
56
+
57
+ /**
58
+ * @param {string|number|undefined} developerId
59
+ * @returns {string}
60
+ */
61
+ function formatDevLinuxUserLabel(developerId) {
62
+ const trimmed = String(developerId ?? '').trim();
63
+ if (!trimmed) {
64
+ return 'developer';
65
+ }
66
+ if (/^\d+$/.test(trimmed)) {
67
+ return `dev${String(parseInt(trimmed, 10)).padStart(2, '0')}`;
68
+ }
69
+ return trimmed.startsWith('dev') ? trimmed : `dev${trimmed}`;
70
+ }
71
+
72
+ /**
73
+ * @param {string|undefined} include
74
+ * @returns {string[]}
75
+ */
76
+ function parseHostOpsIncludeList(include) {
77
+ return String(include ?? '')
78
+ .split(',')
79
+ .map((part) => part.trim())
80
+ .filter(Boolean);
81
+ }
82
+
83
+ /**
84
+ * Resolve human-readable target(s) from host-ops job params.
85
+ *
86
+ * @param {Object} [params]
87
+ * @param {string|number} [params.developerId]
88
+ * @param {string} [params.include]
89
+ * @param {string} [params.exclude]
90
+ * @returns {string}
91
+ */
92
+ function resolveHostOpsTargetLabel(params = {}) {
93
+ if (params.developerId) {
94
+ return formatDevLinuxUserLabel(params.developerId);
95
+ }
96
+ const included = parseHostOpsIncludeList(params.include);
97
+ if (included.length === 1) {
98
+ return formatDevLinuxUserLabel(included[0]);
99
+ }
100
+ if (included.length > 1) {
101
+ return included.map(formatDevLinuxUserLabel).join(', ');
102
+ }
103
+ if (params.exclude) {
104
+ return 'selected developers';
105
+ }
106
+ return 'all developers';
107
+ }
108
+
109
+ /**
110
+ * @param {Object} [params]
111
+ * @returns {number}
112
+ */
113
+ function countHostOpsTargets(params = {}) {
114
+ if (params.developerId) {
115
+ return 1;
116
+ }
117
+ const included = parseHostOpsIncludeList(params.include);
118
+ if (included.length > 0) {
119
+ return included.length;
120
+ }
121
+ return 0;
122
+ }
123
+
124
+ /**
125
+ * @param {number} ms
126
+ * @returns {string}
127
+ */
128
+ function formatHostOpsElapsed(ms) {
129
+ const totalSec = Math.max(0, Math.floor(ms / 1000));
130
+ if (totalSec < 60) {
131
+ return `${totalSec}s`;
132
+ }
133
+ const min = Math.floor(totalSec / 60);
134
+ const sec = totalSec % 60;
135
+ return sec > 0 ? `${min}m ${sec}s` : `${min}m`;
136
+ }
137
+
138
+ /**
139
+ * @param {string} jobType
140
+ * @param {string|number|undefined} targetLabel
141
+ * @returns {string}
142
+ */
143
+ function buildHostOpsActionLabel(jobType, targetLabel) {
144
+ const meta = HOST_OPS_JOB_LABELS[jobType];
145
+ const userLabel = targetLabel ? String(targetLabel) : 'developer';
146
+ if (!meta) {
147
+ return `Host job for ${userLabel}`;
148
+ }
149
+ return `${meta.action} ${userLabel}`;
150
+ }
151
+
152
+ /**
153
+ * @param {string} jobType
154
+ * @param {string} status
155
+ * @returns {string}
156
+ */
157
+ function buildHostOpsStatusDetail(jobType, status) {
158
+ const meta = HOST_OPS_JOB_LABELS[jobType];
159
+ if (!meta) {
160
+ return status || 'pending';
161
+ }
162
+ if (status === 'running') {
163
+ return meta.runningDetail || 'running on server';
164
+ }
165
+ return meta.pendingDetail || 'queued on server';
166
+ }
167
+
168
+ /**
169
+ * @param {string} jobType
170
+ * @param {Object} [params]
171
+ * @returns {string}
172
+ */
173
+ function getHostOpsDurationHint(jobType, params) {
174
+ const meta = HOST_OPS_JOB_LABELS[jobType];
175
+ const base = (meta && meta.durationHint) || 'may take several minutes';
176
+ const count = countHostOpsTargets(params);
177
+ if (count > 1) {
178
+ return `${base} per developer (${count} selected)`;
179
+ }
180
+ return base;
181
+ }
182
+
183
+ /**
184
+ * Single-line poll text (spinner or throttled log).
185
+ *
186
+ * @param {Object} ctx
187
+ * @param {string} ctx.jobType
188
+ * @param {string} [ctx.targetLabel]
189
+ * @param {Object} [ctx.params]
190
+ * @param {string} ctx.status
191
+ * @param {number} ctx.elapsedMs
192
+ * @param {string} [ctx.transientNote]
193
+ * @returns {string}
194
+ */
195
+ function buildHostOpsPollLine(ctx) {
196
+ const targetLabel = ctx.targetLabel || resolveHostOpsTargetLabel(ctx.params);
197
+ const action = buildHostOpsActionLabel(ctx.jobType, targetLabel);
198
+ const durationHint = getHostOpsDurationHint(ctx.jobType, ctx.params);
199
+ const elapsed = formatHostOpsElapsed(ctx.elapsedMs);
200
+ if (ctx.transientNote) {
201
+ return `${action}: ${ctx.transientNote} (${elapsed}, ${durationHint})`;
202
+ }
203
+ const detail = buildHostOpsStatusDetail(ctx.jobType, ctx.status);
204
+ return `${action}: ${detail} (${elapsed}, ${durationHint})`;
205
+ }
206
+
207
+ /**
208
+ * Gray intro line printed once when polling starts.
209
+ *
210
+ * @param {string} jobType
211
+ * @param {string|Object} [targetLabelOrParams]
212
+ * @returns {string}
213
+ */
214
+ function buildHostOpsPollIntroLine(jobType, targetLabelOrParams) {
215
+ const targetLabel =
216
+ typeof targetLabelOrParams === 'string'
217
+ ? targetLabelOrParams
218
+ : resolveHostOpsTargetLabel(targetLabelOrParams);
219
+ const params = typeof targetLabelOrParams === 'object' ? targetLabelOrParams : undefined;
220
+ const action = buildHostOpsActionLabel(jobType, targetLabel);
221
+ const durationHint = getHostOpsDurationHint(jobType, params);
222
+ return `⏳ ${action} — ${durationHint} on the builder host`;
223
+ }
224
+
225
+ module.exports = {
226
+ HOST_OPS_JOB_LABELS,
227
+ formatDevLinuxUserLabel,
228
+ parseHostOpsIncludeList,
229
+ resolveHostOpsTargetLabel,
230
+ countHostOpsTargets,
231
+ formatHostOpsElapsed,
232
+ buildHostOpsActionLabel,
233
+ buildHostOpsPollLine,
234
+ buildHostOpsPollIntroLine,
235
+ getHostOpsDurationHint
236
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @fileoverview Host-ops job success/failure interpretation for CLI polling
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ /**
8
+ * @param {Object|null|undefined} job
9
+ * @returns {boolean}
10
+ */
11
+ function isHostOpsJobFailed(job) {
12
+ if (!job) return true;
13
+ if (job.status === 'failed') return true;
14
+ if (job.error) return true;
15
+ if (!Array.isArray(job.outcomes)) return false;
16
+ return job.outcomes.some((row) => {
17
+ if (!row || typeof row !== 'object') return false;
18
+ const overall = row.overall || row.status;
19
+ return overall === 'FAIL' || overall === 'BLOCKED';
20
+ });
21
+ }
22
+
23
+ /**
24
+ * @param {Object} job
25
+ * @returns {string}
26
+ */
27
+ function formatHostOpsJobFailure(job) {
28
+ const parts = [];
29
+ if (job.error) {
30
+ parts.push(String(job.error));
31
+ }
32
+ if (Array.isArray(job.outcomes)) {
33
+ for (const row of job.outcomes) {
34
+ if (!row || typeof row !== 'object') continue;
35
+ const overall = row.overall || row.status;
36
+ if (overall !== 'FAIL' && overall !== 'BLOCKED') continue;
37
+ const label = row.linuxUser || row.developerId || 'target';
38
+ const detail = row.detail ? ` — ${row.detail}` : '';
39
+ parts.push(`${label}: ${overall}${detail}`);
40
+ }
41
+ }
42
+ if (parts.length > 0) {
43
+ return parts.join('\n');
44
+ }
45
+ return `Host-ops job ${job.jobId || '(unknown)'} failed`;
46
+ }
47
+
48
+ /**
49
+ * @param {Object} job
50
+ * @throws {Error}
51
+ */
52
+ function assertHostOpsJobSucceeded(job) {
53
+ if (!isHostOpsJobFailed(job)) return;
54
+ throw new Error(formatHostOpsJobFailure(job));
55
+ }
56
+
57
+ module.exports = {
58
+ isHostOpsJobFailed,
59
+ formatHostOpsJobFailure,
60
+ assertHostOpsJobSucceeded
61
+ };
@@ -0,0 +1,163 @@
1
+ /**
2
+ * TTY ora spinner + throttled non-TTY lines for host-ops job polling.
3
+ *
4
+ * @fileoverview Host-ops job poll presentation helpers
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const chalk = require('chalk');
12
+ const logger = require('./logger');
13
+ const {
14
+ buildHostOpsPollLine,
15
+ buildHostOpsPollIntroLine
16
+ } = require('./host-ops-job-labels');
17
+
18
+ const SILENT_POLL_HANDLERS = {
19
+ onPollProgress: () => {},
20
+ onTransientError: () => {},
21
+ finish: () => {}
22
+ };
23
+
24
+ function shouldUseHostOpsPollSpinner() {
25
+ return Boolean(process && process.stdout && process.stdout.isTTY);
26
+ }
27
+
28
+ /**
29
+ * @deprecated Use buildHostOpsPollLine via createHostOpsPollHandlers context.
30
+ * @param {string} jobId
31
+ * @param {string} status
32
+ * @param {number} attemptIndex
33
+ * @param {number} maxAttempts
34
+ * @returns {string}
35
+ */
36
+ function buildHostOpsPollSpinnerText(jobId, status, attemptIndex, maxAttempts) {
37
+ const safeStatus = status || 'pending';
38
+ return `host-ops job ${jobId}: ${safeStatus} (${attemptIndex + 1}/${maxAttempts})`;
39
+ }
40
+
41
+ const NON_TTY_THROTTLE_MS = 5000;
42
+
43
+ /**
44
+ * @param {Object} pollContext
45
+ * @returns {Function}
46
+ */
47
+ function createPollLineBuilder(pollContext) {
48
+ const jobType = pollContext.jobType || 'host-ops';
49
+ const params = pollContext.params;
50
+ const targetLabel = pollContext.targetLabel;
51
+ return (status, elapsedMs, transientNote) =>
52
+ buildHostOpsPollLine({
53
+ jobType,
54
+ targetLabel,
55
+ params,
56
+ status,
57
+ elapsedMs,
58
+ transientNote
59
+ });
60
+ }
61
+
62
+ /**
63
+ * @param {Object} pollContext
64
+ * @returns {Function}
65
+ */
66
+ function createPollIntroLogger(pollContext) {
67
+ const jobType = pollContext.jobType || 'host-ops';
68
+ const params = pollContext.params;
69
+ const targetLabel = pollContext.targetLabel;
70
+ let introLogged = false;
71
+ return () => {
72
+ if (introLogged) {
73
+ return;
74
+ }
75
+ introLogged = true;
76
+ logger.log(
77
+ chalk.gray(` ${buildHostOpsPollIntroLine(jobType, targetLabel || params || undefined)}`)
78
+ );
79
+ };
80
+ }
81
+
82
+ /**
83
+ * @param {Object} pollContext
84
+ * @returns {{ onPollProgress: Function, onTransientError: Function, finish: () => void }}
85
+ */
86
+ function createSpinnerHostOpsPollHandlers(pollContext) {
87
+ const startedAt = pollContext.startedAt || Date.now();
88
+ const buildLine = createPollLineBuilder(pollContext);
89
+ const logIntroOnce = createPollIntroLogger(pollContext);
90
+ const ora = require('ora');
91
+ logIntroOnce();
92
+ const spinner = ora({
93
+ text: buildLine('pending', 0),
94
+ spinner: 'dots'
95
+ }).start();
96
+ return {
97
+ onPollProgress: (status) => {
98
+ spinner.text = buildLine(status, Date.now() - startedAt);
99
+ },
100
+ onTransientError: (_err, elapsedMs) => {
101
+ spinner.text = buildLine('pending', elapsedMs, 'server temporarily unavailable, retrying');
102
+ },
103
+ finish: () => {
104
+ spinner.stop();
105
+ }
106
+ };
107
+ }
108
+
109
+ /**
110
+ * @param {Object} pollContext
111
+ * @returns {{ onPollProgress: Function, onTransientError: Function, finish: () => void }}
112
+ */
113
+ function createNonTtyHostOpsPollHandlers(pollContext) {
114
+ const startedAt = pollContext.startedAt || Date.now();
115
+ const buildLine = createPollLineBuilder(pollContext);
116
+ const logIntroOnce = createPollIntroLogger(pollContext);
117
+ let lastNonTtyLogAt = 0;
118
+ return {
119
+ onPollProgress: (status) => {
120
+ logIntroOnce();
121
+ const now = Date.now();
122
+ const elapsedMs = now - startedAt;
123
+ if (now - lastNonTtyLogAt < NON_TTY_THROTTLE_MS && elapsedMs > 0) {
124
+ return;
125
+ }
126
+ lastNonTtyLogAt = now;
127
+ logger.log(chalk.gray(` ${buildLine(status, elapsedMs)}`));
128
+ },
129
+ onTransientError: (_err, elapsedMs) => {
130
+ logIntroOnce();
131
+ logger.log(
132
+ chalk.gray(` ${buildLine('pending', elapsedMs, 'server temporarily unavailable, retrying')}`)
133
+ );
134
+ },
135
+ finish: () => {}
136
+ };
137
+ }
138
+
139
+ /**
140
+ * @param {string} jobId
141
+ * @param {Object} [pollContext]
142
+ * @param {string} [pollContext.jobType]
143
+ * @param {string} [pollContext.targetLabel]
144
+ * @param {Object} [pollContext.params]
145
+ * @param {number} [pollContext.startedAt]
146
+ * @param {{ silent?: boolean }} [options]
147
+ * @returns {{ onPollProgress: Function, onTransientError: Function, finish: () => void }}
148
+ */
149
+ function createHostOpsPollHandlers(jobId, pollContext = {}, options = {}) {
150
+ if (options && options.silent === true) {
151
+ return SILENT_POLL_HANDLERS;
152
+ }
153
+ if (shouldUseHostOpsPollSpinner()) {
154
+ return createSpinnerHostOpsPollHandlers(pollContext);
155
+ }
156
+ return createNonTtyHostOpsPollHandlers(pollContext);
157
+ }
158
+
159
+ module.exports = {
160
+ buildHostOpsPollSpinnerText,
161
+ createHostOpsPollHandlers,
162
+ shouldUseHostOpsPollSpinner
163
+ };
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Find integration/<systemKey> under aifabrix-work (sibling repos).
3
+ *
4
+ * @fileoverview Worktree integration discovery for dev layouts (sibling repos under aifabrix-work)
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const { getAifabrixWork } = require('./paths');
14
+ const { resolveApplicationConfigPath } = require('./app-config-resolver');
15
+ const { discoverIntegrationFiles } = require('../commands/repair-internal');
16
+
17
+ /**
18
+ * @param {string} appPath
19
+ * @returns {boolean}
20
+ */
21
+ function integrationFolderHasContent(appPath) {
22
+ if (!fs.existsSync(appPath)) {
23
+ return false;
24
+ }
25
+ try {
26
+ const st = fs.statSync(appPath);
27
+ if (!st.isDirectory()) {
28
+ return false;
29
+ }
30
+ } catch {
31
+ return false;
32
+ }
33
+ const { systemFiles, datasourceFiles } = discoverIntegrationFiles(appPath);
34
+ if (systemFiles.length > 0 || datasourceFiles.length > 0) {
35
+ return true;
36
+ }
37
+ try {
38
+ resolveApplicationConfigPath(appPath);
39
+ return true;
40
+ } catch {
41
+ return false;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * @param {string} work
47
+ * @param {string} systemKey
48
+ * @returns {{ integrationPath: string, tier: string }[]}
49
+ */
50
+ function collectWorkRepoIntegrationHits(work, systemKey) {
51
+ /** @type {{ integrationPath: string, tier: string }[]} */
52
+ const hits = [];
53
+ let entries;
54
+ try {
55
+ entries = fs.readdirSync(work, { withFileTypes: true });
56
+ } catch {
57
+ return hits;
58
+ }
59
+ for (const ent of entries) {
60
+ if (!ent.isDirectory() || ent.name.startsWith('.')) {
61
+ continue;
62
+ }
63
+ const candidate = path.join(work, ent.name, 'integration', systemKey);
64
+ if (integrationFolderHasContent(candidate)) {
65
+ hits.push({ integrationPath: path.resolve(candidate), tier: 'work-repo-integration' });
66
+ }
67
+ }
68
+ return hits;
69
+ }
70
+
71
+ /**
72
+ * @param {{ integrationPath: string, tier: string }[]} hits
73
+ * @param {string} systemKey
74
+ * @returns {{ integrationPath: string, tier: string }|null}
75
+ */
76
+ function resolveUniqueIntegrationHit(hits, systemKey) {
77
+ if (hits.length === 1) {
78
+ return hits[0];
79
+ }
80
+ if (hits.length > 1) {
81
+ const err = new Error(
82
+ `Integration "${systemKey}" found in multiple repos under aifabrix-work: ${hits.map((h) => h.integrationPath).join(', ')}. ` +
83
+ 'Run from the target repo or narrow with cwd.'
84
+ );
85
+ err.statusCode = 409;
86
+ throw err;
87
+ }
88
+ return null;
89
+ }
90
+
91
+ /**
92
+ * @param {string} systemKey
93
+ * @returns {{ integrationPath: string, tier: string }|null}
94
+ */
95
+ function findIntegrationPathAcrossWorkTree(systemKey) {
96
+ const work = getAifabrixWork();
97
+ if (!work) {
98
+ return null;
99
+ }
100
+
101
+ const direct = path.join(work, 'integration', systemKey);
102
+ if (integrationFolderHasContent(direct)) {
103
+ return { integrationPath: path.resolve(direct), tier: 'work-integration' };
104
+ }
105
+
106
+ return resolveUniqueIntegrationHit(collectWorkRepoIntegrationHits(work, systemKey), systemKey);
107
+ }
108
+
109
+ module.exports = {
110
+ findIntegrationPathAcrossWorkTree,
111
+ integrationFolderHasContent
112
+ };