@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
@@ -0,0 +1,368 @@
1
+ /**
2
+ * @fileoverview Deploy pre-promote baseline tests and optional --gate steps (456.9).
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const chalk = require('chalk');
10
+ const { sectionTitle } = require('../utils/cli-test-layout-chalk');
11
+ const logger = require('../utils/logger');
12
+ const { formatDeployGateFailure } = require('./deploy-gate-failure-details');
13
+ const { testExternalSystem, testExternalSystemIntegration } = require('../external-system/test');
14
+ const { runWithVerifyStepProgress } = require('../lifecycle/verify-step-progress');
15
+ const { runTestE2EForExternalSystem, syncLocalIfRequested, resolveExternalIntegrationContext } = require('./test-e2e-external');
16
+ const { cliOptsSkipPublish } = require('../utils/cli-sync-options');
17
+ const { resolveE2eSyncModeWhenPopulated } = require('./datasource-sync-policy');
18
+ const { runVerifyTrustForExternalSystem } = require('./verify-trust-external');
19
+ const { runVerifyGovernanceForExternalSystem } = require('./verify-governance-external');
20
+ const { runGovernanceGenerateForExternalSystem } = require('./governance-generate-external');
21
+ const { resolveGovernanceFixtureSubjectEmails } = require('./governance-fixture-subjects');
22
+ const { runVerifyGovernanceCombined } = require('./verify-governance-combined-external');
23
+ const { VERDICT } = require('../lifecycle/product-model');
24
+
25
+ const KNOWN_GATES = ['operations', 'trust', 'governance'];
26
+
27
+ /**
28
+ * @param {string|undefined} gateRaw
29
+ * @returns {string[]}
30
+ */
31
+ function parseDeployGateTokens(gateRaw) {
32
+ if (!gateRaw || typeof gateRaw !== 'string') {
33
+ return [];
34
+ }
35
+ const tokens = gateRaw
36
+ .split(',')
37
+ .map((part) => part.trim().toLowerCase())
38
+ .filter(Boolean);
39
+ if (tokens.includes('full')) {
40
+ return [...KNOWN_GATES];
41
+ }
42
+ return tokens.filter((token) => KNOWN_GATES.includes(token));
43
+ }
44
+
45
+ /**
46
+ * Strict promote posture suggests full optional gates when caller requests profile resolution.
47
+ * @returns {string[]}
48
+ */
49
+ function resolveStrictPromoteGateProfile() {
50
+ const level = (process.env.TRUST_CUSTOMER_POLICY_LEVEL || 'standard').trim().toLowerCase();
51
+ if (level === 'strict') {
52
+ return [...KNOWN_GATES];
53
+ }
54
+ return [];
55
+ }
56
+
57
+ /**
58
+ * @param {string|undefined} gateRaw
59
+ * @param {Object} [options]
60
+ * @returns {Set<string>}
61
+ */
62
+ function resolveDeployGateSet(gateRaw, options = {}) {
63
+ const explicit = parseDeployGateTokens(gateRaw);
64
+ if (explicit.length > 0) {
65
+ return new Set(explicit);
66
+ }
67
+ if (options.useStrictPromoteProfile === true) {
68
+ return new Set(resolveStrictPromoteGateProfile());
69
+ }
70
+ return new Set();
71
+ }
72
+
73
+ /**
74
+ * @param {Object} options
75
+ * @param {Object|null|undefined} uploadCtx
76
+ * @returns {Object}
77
+ */
78
+ function mergeUploadAuthOptions(options, uploadCtx) {
79
+ if (!uploadCtx?.authConfig || !uploadCtx?.dataplaneUrl) {
80
+ return { ...options, noPublish: true, verbose: false };
81
+ }
82
+ return {
83
+ ...options,
84
+ noPublish: true,
85
+ verbose: false,
86
+ authConfig: uploadCtx.authConfig,
87
+ dataplaneUrl: uploadCtx.dataplaneUrl,
88
+ silentResolve: true
89
+ };
90
+ }
91
+
92
+ /**
93
+ * @async
94
+ * @param {string} label
95
+ * @param {Function} runner
96
+ * @param {Function} isOk
97
+ * @param {Object} [stepOptions]
98
+ */
99
+ async function runRequiredDeployStep(label, runner, isOk, stepOptions = {}) {
100
+ return runWithVerifyStepProgress(
101
+ label,
102
+ async() => {
103
+ const outcome = await runner();
104
+ if (!isOk(outcome)) {
105
+ const detail = formatDeployGateFailure(label, outcome);
106
+ if (stepOptions.quietDeployUi !== true) {
107
+ logger.log(chalk.red(`✖ ${detail}`));
108
+ }
109
+ const err = new Error(`${label} failed: ${detail}`);
110
+ err.gateFailure = true;
111
+ err.gateDetail = detail;
112
+ err.gateLabel = label;
113
+ if (stepOptions.gatePillar) {
114
+ err.gatePillar = stepOptions.gatePillar;
115
+ }
116
+ throw err;
117
+ }
118
+ return outcome;
119
+ },
120
+ { json: false, quietProgress: stepOptions.quietDeployUi === true }
121
+ );
122
+ }
123
+
124
+ /**
125
+ * @async
126
+ * @param {string} systemKey
127
+ * @param {Object} options
128
+ * @returns {Promise<{ unitPassed: boolean, integrationPassed: boolean }>}
129
+ */
130
+ async function runDeployBaselineSteps(systemKey, options) {
131
+ await runRequiredDeployStep(
132
+ 'Running unit tests',
133
+ () => testExternalSystem(systemKey, { verbose: false }),
134
+ (result) => result.valid === true,
135
+ options
136
+ );
137
+
138
+ let stepOptions = { ...options, noPublish: true, verbose: false, uploadStatus: 'published' };
139
+ if (!cliOptsSkipPublish(options)) {
140
+ const uploadCtx = await syncLocalIfRequested(systemKey, {
141
+ ...options,
142
+ uploadStatus: 'published',
143
+ minimal: true,
144
+ suppressSummary: true,
145
+ suppressPipelineSpinner: true,
146
+ uploadContext: 'deploy-preflight'
147
+ });
148
+ stepOptions = mergeUploadAuthOptions({ ...options, uploadStatus: 'published' }, uploadCtx);
149
+ }
150
+
151
+ await runRequiredDeployStep(
152
+ 'Running integration tests',
153
+ () => testExternalSystemIntegration(systemKey, stepOptions),
154
+ (result) => result.success === true,
155
+ options
156
+ );
157
+
158
+ return { unitPassed: true, integrationPassed: true };
159
+ }
160
+
161
+ /**
162
+ * @async
163
+ * @param {string} systemKey
164
+ * @param {Object} options
165
+ * @returns {Promise<Object>}
166
+ */
167
+ async function runOperationsGate(systemKey, options) {
168
+ let stepOptions = mergeUploadAuthOptions(options, null);
169
+ if (!stepOptions.dataplaneUrl || !stepOptions.authConfig) {
170
+ try {
171
+ const uploadCtx = await syncLocalIfRequested(systemKey, { ...options, noPublish: true });
172
+ stepOptions = mergeUploadAuthOptions(options, uploadCtx);
173
+ } catch {
174
+ stepOptions = mergeUploadAuthOptions(options, null);
175
+ }
176
+ }
177
+
178
+ let e2eSyncMode = options.syncMode;
179
+ if (!e2eSyncMode && stepOptions.dataplaneUrl && stepOptions.authConfig) {
180
+ try {
181
+ const { keys } = resolveExternalIntegrationContext(systemKey);
182
+ e2eSyncMode = await resolveE2eSyncModeWhenPopulated(
183
+ stepOptions.dataplaneUrl,
184
+ stepOptions.authConfig,
185
+ keys
186
+ );
187
+ } catch {
188
+ e2eSyncMode = 'auto';
189
+ }
190
+ }
191
+
192
+ await runRequiredDeployStep(
193
+ 'Running operations gate (E2E)',
194
+ () =>
195
+ runTestE2EForExternalSystem(systemKey, {
196
+ ...stepOptions,
197
+ env: options.env,
198
+ async: options.async !== false,
199
+ quietPollUi: true,
200
+ syncMode: e2eSyncMode || stepOptions.syncMode
201
+ }),
202
+ (result) => result.success === true,
203
+ { ...options, gatePillar: 'operations' }
204
+ );
205
+
206
+ return { pillar: 'operations', verdict: VERDICT.VERIFIED };
207
+ }
208
+
209
+ /**
210
+ * @async
211
+ * @param {string} systemKey
212
+ * @param {Object} options
213
+ * @returns {Promise<Object>}
214
+ */
215
+ async function runTrustGate(systemKey, options) {
216
+ const result = await runRequiredDeployStep(
217
+ 'Running trust gate',
218
+ () => runVerifyTrustForExternalSystem(systemKey, { ...options, noPublish: true }),
219
+ (outcome) => outcome.verdict === VERDICT.VERIFIED,
220
+ { ...options, gatePillar: 'trust' }
221
+ );
222
+ return {
223
+ pillar: 'trust',
224
+ verdict: result.verdict,
225
+ percent: result.aiTrustPercent ?? undefined
226
+ };
227
+ }
228
+
229
+ /**
230
+ * @param {Object} options
231
+ * @returns {boolean}
232
+ */
233
+ function governanceSubjectsProvided(options) {
234
+ return Boolean(options.subjectEmail);
235
+ }
236
+
237
+ /**
238
+ * @async
239
+ * @param {string} systemKey
240
+ * @param {Object} options
241
+ * @returns {Promise<Object>}
242
+ */
243
+ async function runGovernanceGate(systemKey, options) {
244
+ const gateOptions = { ...options, noPublish: true };
245
+ let runner;
246
+ if (governanceSubjectsProvided(gateOptions)) {
247
+ runner = () => runVerifyGovernanceCombined(systemKey, gateOptions);
248
+ } else {
249
+ const fixtureEmails = resolveGovernanceFixtureSubjectEmails(systemKey);
250
+ if (fixtureEmails.length > 0) {
251
+ runner = async() => {
252
+ await runGovernanceGenerateForExternalSystem(systemKey, {
253
+ ...gateOptions,
254
+ subjectEmails: fixtureEmails
255
+ });
256
+ return runVerifyGovernanceForExternalSystem(systemKey, gateOptions);
257
+ };
258
+ } else {
259
+ runner = () => runVerifyGovernanceForExternalSystem(systemKey, gateOptions);
260
+ }
261
+ }
262
+ const result = await runRequiredDeployStep(
263
+ 'Running governance gate',
264
+ runner,
265
+ (outcome) => outcome.verdict === VERDICT.VERIFIED,
266
+ { ...options, gatePillar: 'governance' }
267
+ );
268
+ const scenarios = result.enforcementScenarios || {};
269
+ return {
270
+ pillar: 'governance',
271
+ verdict: result.verdict,
272
+ scenariosPassed: scenarios.passed,
273
+ scenariosTotal: scenarios.total
274
+ };
275
+ }
276
+
277
+ /**
278
+ * @async
279
+ * @param {string} systemKey
280
+ * @param {Set<string>} gates
281
+ * @param {Object} options
282
+ * @returns {Promise<Object[]>}
283
+ */
284
+ async function runDeployOptionalGates(systemKey, gates, options) {
285
+ const outcomes = [];
286
+ try {
287
+ if (gates.has('operations')) {
288
+ outcomes.push(await runOperationsGate(systemKey, options));
289
+ }
290
+ if (gates.has('trust')) {
291
+ outcomes.push(await runTrustGate(systemKey, options));
292
+ }
293
+ if (gates.has('governance')) {
294
+ outcomes.push(await runGovernanceGate(systemKey, options));
295
+ }
296
+ } catch (err) {
297
+ if (err && err.gateFailure === true) {
298
+ err.gatesSoFar = outcomes;
299
+ }
300
+ throw err;
301
+ }
302
+ return outcomes;
303
+ }
304
+
305
+ /**
306
+ * @param {string|undefined} label
307
+ * @returns {string}
308
+ */
309
+ function inferGatePillarFromLabel(label) {
310
+ const text = String(label || '').toLowerCase();
311
+ if (text.includes('operations')) return 'operations';
312
+ if (text.includes('trust')) return 'trust';
313
+ if (text.includes('governance')) return 'governance';
314
+ return 'operations';
315
+ }
316
+
317
+ /**
318
+ * Baseline validate + test + test-integration, then optional --gate steps before controller deploy.
319
+ * @async
320
+ * @param {string} systemKey
321
+ * @param {Object} [options]
322
+ * @returns {Promise<{ baseline: { unitPassed: boolean, integrationPassed: boolean }, gates: Object[] }>}
323
+ */
324
+ async function runDeployGateOrchestrator(systemKey, options = {}) {
325
+ const quiet = options.quietDeployUi === true || options.verbose !== true;
326
+ if (!quiet) {
327
+ logger.log('');
328
+ logger.log(sectionTitle('Deploy preflight'));
329
+ }
330
+ const baseline = await runDeployBaselineSteps(systemKey, { ...options, quietDeployUi: quiet });
331
+ const gates = resolveDeployGateSet(options.gate, options);
332
+ if (gates.size === 0) {
333
+ return { baseline, gates: [] };
334
+ }
335
+ try {
336
+ const gateOutcomes = await runDeployOptionalGates(systemKey, gates, {
337
+ ...options,
338
+ quietDeployUi: quiet
339
+ });
340
+ return { baseline, gates: gateOutcomes };
341
+ } catch (err) {
342
+ if (err && err.gateFailure === true && quiet) {
343
+ const { logDeployGateAbortCompact } = require('../utils/external-system-readiness-compact-blocks');
344
+ const failedPillar = err.gatePillar || inferGatePillarFromLabel(err.gateLabel);
345
+ logDeployGateAbortCompact({
346
+ systemKey,
347
+ environment: options.environment || options.env || 'dev',
348
+ dataplaneUrl: options.dataplaneUrl || options.knownDataplaneUrl,
349
+ baseline,
350
+ gatesSoFar: err.gatesSoFar || [],
351
+ failedPillar,
352
+ failedDetail: err.gateDetail || err.message
353
+ });
354
+ err.compactGateAbortLogged = true;
355
+ }
356
+ throw err;
357
+ }
358
+ }
359
+
360
+ module.exports = {
361
+ KNOWN_GATES,
362
+ parseDeployGateTokens,
363
+ resolveStrictPromoteGateProfile,
364
+ resolveDeployGateSet,
365
+ runDeployBaselineSteps,
366
+ runDeployOptionalGates,
367
+ runDeployGateOrchestrator
368
+ };
@@ -17,6 +17,8 @@ const {
17
17
  augmentDevUserGroupsServerError
18
18
  } = require('../utils/dev-user-groups');
19
19
  const { handleProvisionDevUser, handleRemoveDevUser } = require('./dev-host-ops');
20
+ const { logDevPinShareInstructions } = require('../utils/dev-pin-share-instructions');
21
+ const { sortDevUsers } = require('../utils/dev-list-sort');
20
22
 
21
23
  const REMOTE_NOT_CONFIGURED_MSG = 'Remote server is not configured. Set remote-server and run "aifabrix dev init" first.';
22
24
 
@@ -51,10 +53,12 @@ function formatCertUntil(iso) {
51
53
  }
52
54
 
53
55
  /**
54
- * Handle dev list – list developer users (remote only). Table format, sorted by name.
56
+ * Handle dev list – list developer users (remote only). Table format; default sort by name.
57
+ * @param {Object} [options] - Commander options
58
+ * @param {string} [options.sort] - Sort field/direction (id|name|email|until; prefix - for descending)
55
59
  * @returns {Promise<void>}
56
60
  */
57
- async function handleDevList() {
61
+ async function handleDevList(options = {}) {
58
62
  const auth = await getRemoteDevAuth();
59
63
  if (!auth) {
60
64
  logger.log(chalk.yellow(REMOTE_NOT_CONFIGURED_MSG));
@@ -68,7 +72,7 @@ async function handleDevList() {
68
72
  logger.log(chalk.bold('\n📋 Developers:\n'));
69
73
  logger.log(chalk.gray('ID'.padEnd(ID_WIDTH) + 'Name'.padEnd(NAME_WIDTH) + 'Email'.padEnd(EMAIL_WIDTH) + 'Cert'.padEnd(CERT_WIDTH) + 'Until'.padEnd(UNTIL_WIDTH) + 'Groups'));
70
74
  logger.log(chalk.gray('-'.repeat(TABLE_SEPARATOR_LENGTH)));
71
- const sorted = [...users].sort((a, b) => (a.name || '').localeCompare(b.name || '', undefined, { sensitivity: 'base' }));
75
+ const sorted = sortDevUsers(users, options.sort);
72
76
  sorted.forEach(u => {
73
77
  const certLabel = u.certificateIssued ? 'yes' : 'no cert';
74
78
  const untilRaw = u.certificateIssued && u.certificateValidNotAfter ? u.certificateValidNotAfter : null;
@@ -149,64 +153,6 @@ async function handleDevUpdate(developerId, options) {
149
153
  }
150
154
  }
151
155
 
152
- function logPinHostsVariantLines(baseInit, id, hostsIp) {
153
- logger.log(
154
- chalk.cyan('2) Hosts file / administrator')
155
- + chalk.gray(
156
- ' — use when the hostname does not resolve and your organisation does not publish DNS for it. '
157
- + 'Run in an elevated terminal so the hosts file can be updated, or add the entry manually:'
158
- )
159
- );
160
- if (hostsIp) {
161
- logger.log(` ${baseInit} --add-hosts --hosts-ip ${hostsIp}`);
162
- } else {
163
- logger.log(` ${baseInit} --add-hosts --hosts-ip <server-LAN-IPv4>`);
164
- logger.log(
165
- chalk.gray(
166
- ` Replace <server-LAN-IPv4> with the Builder Server IPv4, or re-run: aifabrix dev pin ${id} --hosts-ip <ip>`
167
- )
168
- );
169
- }
170
- }
171
-
172
- /**
173
- * Log copy-paste dev init commands for the developer (standard vs hosts-file).
174
- * @param {Object} p
175
- * @param {string} p.id - Developer ID
176
- * @param {string} p.serverUrl - Builder Server base URL
177
- * @param {string} p.pin - One-time PIN
178
- * @param {string} p.expiresAt - PIN expiry (API string)
179
- * @param {string} [p.hostsIp] - Optional IPv4 for the hosts variant
180
- * @returns {void}
181
- */
182
- function logDevPinShareInstructions(p) {
183
- const { id, serverUrl, pin, expiresAt, hostsIp } = p;
184
- const baseInit = `aifabrix dev init --developer-id ${id} --server ${serverUrl} --pin ${pin}`;
185
- const pinOnly = `aifabrix dev init --pin ${pin}`;
186
- logger.log(formatSuccessLine(`PIN created for ${id}, expires ${expiresAt}.`));
187
- logger.log('');
188
- logger.log(
189
- chalk.bold('Share with the developer — they run one command (the PIN is one-time):')
190
- );
191
- logger.log('');
192
- logger.log(
193
- chalk.cyan('1) Standard')
194
- + chalk.gray(' — use when this machine can resolve the server hostname (DNS or hosts already set):')
195
- );
196
- logger.log(` ${baseInit}`);
197
- logger.log('');
198
- logPinHostsVariantLines(baseInit, id, hostsIp);
199
- logger.log('');
200
- logger.log(
201
- chalk.cyan('3) Config already has remote-server + developer-id')
202
- + chalk.gray(
203
- ' — e.g. second machine / SSH session after settings were merged; same onboarding, PIN only:'
204
- )
205
- );
206
- logger.log(` ${pinOnly}`);
207
- logger.log('');
208
- }
209
-
210
156
  /**
211
157
  * Handle dev pin – create/regenerate PIN (remote only).
212
158
  * @param {string} [developerId] - Developer ID (optional; uses config if omitted)
@@ -294,7 +240,6 @@ async function handleDevDelete(developerId, options = {}) {
294
240
  }
295
241
  }
296
242
  await handleRemoveDevUser(id, { ...options, developerId: id });
297
- logger.log(formatSuccessLine(`Developer ${id} removal queued and completed.`));
298
243
  }
299
244
 
300
245
  module.exports = {
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @fileoverview Map Commander options to host-ops job params
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ /**
8
+ * @param {Object} options
9
+ * @param {string[]} keys
10
+ * @returns {string|undefined}
11
+ */
12
+ function firstOption(options, ...keys) {
13
+ for (const key of keys) {
14
+ const value = options[key];
15
+ if (value !== undefined && value !== null && value !== '') {
16
+ return value;
17
+ }
18
+ }
19
+ return undefined;
20
+ }
21
+
22
+ /**
23
+ * @param {Object} params
24
+ * @param {Object} options
25
+ * @param {Array<[string, ...string[]]>} mappings
26
+ */
27
+ function assignStringParams(params, options, mappings) {
28
+ for (const [paramKey, ...optionKeys] of mappings) {
29
+ const value = firstOption(options, ...optionKeys);
30
+ if (value !== undefined) {
31
+ params[paramKey] = value;
32
+ }
33
+ }
34
+ }
35
+
36
+ /**
37
+ * @param {Object} params
38
+ * @param {Object} options
39
+ * @param {Array<[string, ...string[]]>} mappings
40
+ */
41
+ function assignFlagParams(params, options, mappings) {
42
+ for (const [paramKey, ...optionKeys] of mappings) {
43
+ if (optionKeys.some((k) => Boolean(options[k]))) {
44
+ params[paramKey] = true;
45
+ }
46
+ }
47
+ }
48
+
49
+ const STRING_PARAM_MAPPINGS = [
50
+ ['include', 'include'],
51
+ ['exclude', 'exclude'],
52
+ ['builderVersion', 'builderVersion', 'builder-version'],
53
+ ['adminEmail', 'adminEmail', 'admin-email'],
54
+ ['adminPassword', 'adminPassword', 'admin-password'],
55
+ ['platform', 'platform'],
56
+ ['installation', 'installation']
57
+ ];
58
+
59
+ const FLAG_PARAM_MAPPINGS = [
60
+ ['skipCert', 'skipCert', 'skip-cert'],
61
+ ['skipPlatform', 'skipPlatform', 'skip-platform'],
62
+ ['skipCli', 'skipCli', 'skip-cli'],
63
+ ['check', 'check'],
64
+ ['failOnBlocked', 'failOnBlocked']
65
+ ];
66
+
67
+ /**
68
+ * Build job params from Commander options.
69
+ * @param {Object} options
70
+ * @param {string} [developerId]
71
+ * @returns {Object}
72
+ */
73
+ function buildJobParams(options, developerId) {
74
+ const params = {};
75
+ const id = developerId || firstOption(options, 'developerId', 'developer-id');
76
+ if (id) {
77
+ params.developerId = String(id).trim();
78
+ }
79
+ assignStringParams(params, options, STRING_PARAM_MAPPINGS);
80
+ assignFlagParams(params, options, FLAG_PARAM_MAPPINGS);
81
+ const timeoutMinutes = firstOption(options, 'timeoutMinutes', 'timeout-minutes');
82
+ if (timeoutMinutes) {
83
+ params.timeoutMinutes = parseInt(timeoutMinutes, 10);
84
+ }
85
+ return params;
86
+ }
87
+
88
+ module.exports = {
89
+ buildJobParams,
90
+ firstOption
91
+ };
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @fileoverview Host-ops job polling loop
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ const hostOpsApi = require('../api/host-ops.api');
8
+ const { assertHostOpsJobSucceeded } = require('../utils/host-ops-job-result');
9
+
10
+ const POLL_INTERVAL_MS = 3000;
11
+ const POLL_TIMEOUT_MS = 3 * 60 * 60 * 1000;
12
+ const TRANSIENT_HTTP_STATUSES = new Set([502, 503, 504]);
13
+ /** Allow ~3 min of consecutive gateway errors (container restart during remove-dev-user). */
14
+ const MAX_TRANSIENT_POLL_ERRORS = 60;
15
+
16
+ function sleep(ms) {
17
+ return new Promise((resolve) => setTimeout(resolve, ms));
18
+ }
19
+
20
+ /**
21
+ * @param {Error} err
22
+ * @returns {boolean}
23
+ */
24
+ function isTransientHostOpsPollError(err) {
25
+ return Boolean(err && TRANSIENT_HTTP_STATUSES.has(err.status));
26
+ }
27
+
28
+ /**
29
+ * @param {Error} err
30
+ * @param {string} jobId
31
+ * @returns {Error}
32
+ */
33
+ function enhanceTransientHostOpsPollError(err, jobId) {
34
+ const status = err && err.status;
35
+ const base =
36
+ status === 502
37
+ ? 'Builder server returned Bad Gateway while waiting for the host job.'
38
+ : `Builder server returned HTTP ${status} while waiting for the host job.`;
39
+ const hint =
40
+ 'The job may still be running on the host (common during platform teardown or container restart). ' +
41
+ 'Wait 1–2 minutes, then run "aifabrix dev list" to verify. ' +
42
+ `Job id: ${jobId}`;
43
+ return new Error(`${base} ${hint}`);
44
+ }
45
+
46
+ /**
47
+ * @param {Object} auth
48
+ * @param {string} jobId
49
+ * @param {Object} pollUi
50
+ * @returns {Promise<Object>}
51
+ */
52
+ async function fetchHostOpsJobWithRetry(auth, jobId, pollUi) {
53
+ const started = Date.now();
54
+ for (let attempt = 0; attempt <= MAX_TRANSIENT_POLL_ERRORS; attempt += 1) {
55
+ try {
56
+ return await hostOpsApi.getHostOpsJob(
57
+ auth.serverUrl,
58
+ auth.clientCertPem,
59
+ jobId,
60
+ auth.serverCaPem || undefined
61
+ );
62
+ } catch (err) {
63
+ if (!isTransientHostOpsPollError(err)) {
64
+ throw err;
65
+ }
66
+ if (attempt >= MAX_TRANSIENT_POLL_ERRORS) {
67
+ throw enhanceTransientHostOpsPollError(err, jobId);
68
+ }
69
+ if (pollUi && typeof pollUi.onTransientError === 'function') {
70
+ pollUi.onTransientError(err, Date.now() - started);
71
+ }
72
+ await sleep(POLL_INTERVAL_MS);
73
+ }
74
+ }
75
+ throw new Error(`Failed to fetch host-ops job ${jobId} after transient retries`);
76
+ }
77
+
78
+ /**
79
+ * @param {Object} auth
80
+ * @param {string} jobId
81
+ * @param {Object} pollUi
82
+ * @param {boolean} json
83
+ * @returns {Promise<Object>}
84
+ */
85
+ async function pollHostOpsJobUntilTerminal(auth, jobId, pollUi, json) {
86
+ const started = Date.now();
87
+ while (Date.now() - started < POLL_TIMEOUT_MS) {
88
+ const job = await fetchHostOpsJobWithRetry(auth, jobId, pollUi);
89
+ if (!json) {
90
+ pollUi.onPollProgress(job.status);
91
+ }
92
+ if (job.status === 'failed') {
93
+ throw new Error(job.error || `Host-ops job ${jobId} failed`);
94
+ }
95
+ if (job.status === 'completed') {
96
+ assertHostOpsJobSucceeded(job);
97
+ return job;
98
+ }
99
+ await sleep(POLL_INTERVAL_MS);
100
+ }
101
+ throw new Error(`Timed out waiting for host-ops job ${jobId}`);
102
+ }
103
+
104
+ module.exports = {
105
+ POLL_INTERVAL_MS,
106
+ POLL_TIMEOUT_MS,
107
+ isTransientHostOpsPollError,
108
+ enhanceTransientHostOpsPollError,
109
+ fetchHostOpsJobWithRetry,
110
+ pollHostOpsJobUntilTerminal
111
+ };