@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
@@ -9,50 +9,30 @@ const chalk = require('chalk');
9
9
  const logger = require('../utils/logger');
10
10
  const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
11
11
  const { getRemoteDevAuth } = require('../utils/remote-dev-auth');
12
+ const { createHostOpsPollHandlers } = require('../utils/host-ops-poll-ui');
13
+ const { buildHostOpsActionLabel, resolveHostOpsTargetLabel } = require('../utils/host-ops-job-labels');
14
+ const { pollHostOpsJobUntilTerminal } = require('./dev-host-ops-poll');
15
+ const { buildJobParams } = require('./dev-host-ops-params');
12
16
  const hostOpsApi = require('../api/host-ops.api');
17
+ const { assertHostOpsJobSucceeded } = require('../utils/host-ops-job-result');
13
18
 
14
19
  const REMOTE_NOT_CONFIGURED_MSG =
15
20
  'Remote server is not configured. Set remote-server and run "aifabrix dev init" first.';
16
21
 
17
- const POLL_INTERVAL_MS = 3000;
18
- const POLL_TIMEOUT_MS = 3 * 60 * 60 * 1000;
19
-
20
- function sleep(ms) {
21
- return new Promise((resolve) => setTimeout(resolve, ms));
22
- }
23
-
24
22
  /**
25
- * Build job params from Commander options.
23
+ * @param {string} type
24
+ * @param {Object} params
26
25
  * @param {Object} options
27
- * @param {string} [developerId]
28
26
  * @returns {Object}
29
27
  */
30
- function buildJobParams(options, developerId) {
31
- const params = {};
32
- const id = developerId || options.developerId || options['developer-id'];
33
- if (id) params.developerId = String(id).trim();
34
- if (options.include) params.include = options.include;
35
- if (options.exclude) params.exclude = options.exclude;
36
- if (options.builderVersion || options['builder-version']) {
37
- params.builderVersion = options.builderVersion || options['builder-version'];
38
- }
39
- if (options.adminEmail || options['admin-email']) {
40
- params.adminEmail = options.adminEmail || options['admin-email'];
41
- }
42
- if (options.adminPassword || options['admin-password']) {
43
- params.adminPassword = options.adminPassword || options['admin-password'];
44
- }
45
- if (options.platform) params.platform = options.platform;
46
- if (options.installation) params.installation = options.installation;
47
- if (options.skipCert || options['skip-cert']) params.skipCert = true;
48
- if (options.skipPlatform || options['skip-platform']) params.skipPlatform = true;
49
- if (options.skipCli || options['skip-cli']) params.skipCli = true;
50
- if (options.check) params.check = true;
51
- if (options.failOnBlocked) params.failOnBlocked = true;
52
- if (options.timeoutMinutes || options['timeout-minutes']) {
53
- params.timeoutMinutes = parseInt(options.timeoutMinutes || options['timeout-minutes'], 10);
54
- }
55
- return params;
28
+ function buildHostOpsWaitOpts(type, params, options) {
29
+ return {
30
+ wait: options.wait !== false,
31
+ json: Boolean(options.json),
32
+ jobType: type,
33
+ targetLabel: resolveHostOpsTargetLabel(params),
34
+ params
35
+ };
56
36
  }
57
37
 
58
38
  /**
@@ -70,26 +50,20 @@ async function waitForHostOpsJob(auth, jobId, opts = {}) {
70
50
  if (!wait) {
71
51
  return { jobId, status: 'pending' };
72
52
  }
73
- const started = Date.now();
74
- while (Date.now() - started < POLL_TIMEOUT_MS) {
75
- const job = await hostOpsApi.getHostOpsJob(
76
- auth.serverUrl,
77
- auth.clientCertPem,
78
- jobId,
79
- auth.serverCaPem || undefined
80
- );
81
- if (!json) {
82
- logger.log(chalk.gray(` host-ops job ${jobId}: ${job.status}`));
83
- }
84
- if (job.status === 'completed' || job.status === 'failed') {
85
- if (job.status === 'failed') {
86
- throw new Error(job.error || `Host-ops job ${jobId} failed`);
87
- }
88
- return job;
89
- }
90
- await sleep(POLL_INTERVAL_MS);
53
+ const pollContext = {
54
+ jobType: opts.jobType,
55
+ targetLabel: opts.targetLabel,
56
+ params: opts.params,
57
+ startedAt: Date.now()
58
+ };
59
+ const pollUi = json
60
+ ? { onPollProgress: () => {}, onTransientError: () => {}, finish: () => {} }
61
+ : createHostOpsPollHandlers(jobId, pollContext);
62
+ try {
63
+ return await pollHostOpsJobUntilTerminal(auth, jobId, pollUi, json);
64
+ } finally {
65
+ pollUi.finish();
91
66
  }
92
- throw new Error(`Timed out waiting for host-ops job ${jobId}`);
93
67
  }
94
68
 
95
69
  /**
@@ -135,13 +109,26 @@ async function runHostOpsJob(type, params, options = {}) {
135
109
  { type, params },
136
110
  auth.serverCaPem || undefined
137
111
  );
112
+ const waitOpts = buildHostOpsWaitOpts(type, params, options);
113
+ if (options.wait === false) {
114
+ if (options.json) {
115
+ logger.log(JSON.stringify({ jobId, status: 'pending', type }, null, 2));
116
+ } else {
117
+ const action = buildHostOpsActionLabel(type, waitOpts.targetLabel);
118
+ logger.log(formatSuccessLine(`${action} queued (job ${jobId}).`));
119
+ }
120
+ return { jobId, status: 'pending' };
121
+ }
138
122
  if (options.json) {
139
- const job = await waitForHostOpsJob(auth, jobId, { wait: options.wait !== false, json: true });
123
+ const job = await waitForHostOpsJob(auth, jobId, waitOpts);
124
+ assertHostOpsJobSucceeded(job);
140
125
  logger.log(JSON.stringify(job, null, 2));
141
126
  return job;
142
127
  }
143
- const job = await waitForHostOpsJob(auth, jobId, { wait: options.wait !== false, json: false });
144
- logger.log(formatSuccessLine(`Host-ops job ${jobId} completed (${type}).`));
128
+ const job = await waitForHostOpsJob(auth, jobId, waitOpts);
129
+ assertHostOpsJobSucceeded(job);
130
+ const action = buildHostOpsActionLabel(type, waitOpts.targetLabel);
131
+ logger.log(formatSuccessLine(`${action} completed.`));
145
132
  return job;
146
133
  }
147
134
 
@@ -161,6 +148,63 @@ async function handlePlatformUpdate(developerId, options) {
161
148
  await runHostOpsJob('update-dev-platform', params, options);
162
149
  }
163
150
 
151
+ function logPlatformInstallOutcomes(developerId, job, json) {
152
+ if (json) {
153
+ logger.log(JSON.stringify(job, null, 2));
154
+ return;
155
+ }
156
+ if (!Array.isArray(job.outcomes)) {
157
+ return;
158
+ }
159
+ job.outcomes.forEach((row) => {
160
+ logger.log(` ${row.linuxUser || developerId}: ${row.overall || row.status}${row.detail ? ` — ${row.detail}` : ''}`);
161
+ });
162
+ }
163
+
164
+ async function runPlatformInstallPreflight(auth, params) {
165
+ const { jobId } = await hostOpsApi.preflightHostOps(
166
+ auth.serverUrl,
167
+ auth.clientCertPem,
168
+ { type: 'install-dev-platform', params },
169
+ auth.serverCaPem || undefined
170
+ );
171
+ return waitForHostOpsJob(auth, jobId, buildHostOpsWaitOpts('install-dev-platform', params, {}));
172
+ }
173
+
174
+ async function handlePlatformInstallCheck(developerId, params, options) {
175
+ const auth = await getRemoteDevAuth();
176
+ if (!auth) throw new Error(REMOTE_NOT_CONFIGURED_MSG);
177
+ params.check = true;
178
+ const { jobId } = await hostOpsApi.preflightHostOps(
179
+ auth.serverUrl,
180
+ auth.clientCertPem,
181
+ { type: 'install-dev-platform', params },
182
+ auth.serverCaPem || undefined
183
+ );
184
+ const job = await waitForHostOpsJob(auth, jobId, buildHostOpsWaitOpts('install-dev-platform', params, options));
185
+ logPlatformInstallOutcomes(developerId, job, options.json);
186
+ assertHostOpsJobSucceeded(job);
187
+ return job;
188
+ }
189
+
190
+ async function confirmPlatformReinstall(developerId, params, options) {
191
+ const auth = await getRemoteDevAuth();
192
+ if (!auth) throw new Error(REMOTE_NOT_CONFIGURED_MSG);
193
+ const preflight = await runPlatformInstallPreflight(auth, { ...params, developerId });
194
+ if (!platformAlreadyInstalled(preflight.outcomes)) {
195
+ return null;
196
+ }
197
+ const ok = await promptYesNo(
198
+ `Platform already installed for dev${String(developerId).padStart(2, '0')}. Re-install?`
199
+ );
200
+ if (!ok) {
201
+ logger.log(chalk.gray('Cancelled.'));
202
+ return preflight;
203
+ }
204
+ await runHostOpsJob('reinstall-dev-platform', params, options);
205
+ return undefined;
206
+ }
207
+
164
208
  async function handlePlatformInstall(developerId, options) {
165
209
  if (!developerId) {
166
210
  throw new Error('Developer ID is required (positional argument).');
@@ -168,46 +212,13 @@ async function handlePlatformInstall(developerId, options) {
168
212
  const params = buildJobParams(options, developerId);
169
213
 
170
214
  if (options.check) {
171
- params.check = true;
172
- const auth = await getRemoteDevAuth();
173
- if (!auth) throw new Error(REMOTE_NOT_CONFIGURED_MSG);
174
- const { jobId } = await hostOpsApi.preflightHostOps(
175
- auth.serverUrl,
176
- auth.clientCertPem,
177
- { type: 'install-dev-platform', params },
178
- auth.serverCaPem || undefined
179
- );
180
- const job = await waitForHostOpsJob(auth, jobId, options);
181
- if (options.json) {
182
- logger.log(JSON.stringify(job, null, 2));
183
- } else if (Array.isArray(job.outcomes)) {
184
- job.outcomes.forEach((row) => {
185
- logger.log(` ${row.linuxUser || developerId}: ${row.overall || row.status}${row.detail ? ` — ${row.detail}` : ''}`);
186
- });
187
- }
188
- return job;
215
+ return handlePlatformInstallCheck(developerId, params, options);
189
216
  }
190
217
 
191
218
  if (!options.force && !options.yes) {
192
- const auth = await getRemoteDevAuth();
193
- if (!auth) throw new Error(REMOTE_NOT_CONFIGURED_MSG);
194
- const { jobId } = await hostOpsApi.preflightHostOps(
195
- auth.serverUrl,
196
- auth.clientCertPem,
197
- { type: 'install-dev-platform', params: { ...params, developerId } },
198
- auth.serverCaPem || undefined
199
- );
200
- const preflight = await waitForHostOpsJob(auth, jobId, { ...options, json: false });
201
- if (platformAlreadyInstalled(preflight.outcomes)) {
202
- const ok = await promptYesNo(
203
- `Platform already installed for dev${String(developerId).padStart(2, '0')}. Re-install?`
204
- );
205
- if (!ok) {
206
- logger.log(chalk.gray('Cancelled.'));
207
- return preflight;
208
- }
209
- await runHostOpsJob('reinstall-dev-platform', params, options);
210
- return;
219
+ const cancelled = await confirmPlatformReinstall(developerId, params, options);
220
+ if (cancelled) {
221
+ return cancelled;
211
222
  }
212
223
  }
213
224
 
@@ -230,7 +241,9 @@ async function handleRemoveDevUser(developerId, options) {
230
241
 
231
242
  module.exports = {
232
243
  buildJobParams,
244
+ buildHostOpsWaitOpts,
233
245
  waitForHostOpsJob,
246
+ runHostOpsJob,
234
247
  handlePlatformInstallCli,
235
248
  handlePlatformUpdate,
236
249
  handlePlatformInstall,
@@ -14,10 +14,6 @@ const { getConfigDirForPaths } = require('../utils/paths');
14
14
  const {
15
15
  generateCSR,
16
16
  getCertDir,
17
- readClientCertPem,
18
- readClientKeyPem,
19
- readServerCaPem,
20
- getCertValidNotAfter,
21
17
  normalizePemNewlines,
22
18
  mergeCaPemBlocks
23
19
  } = require('../utils/dev-cert-helper');
@@ -35,7 +31,6 @@ const {
35
31
  const { runOptionalHostsSetup } = require('../utils/dev-hosts-helper');
36
32
  const { mergeDevSshConfigAfterInit } = require('../utils/dev-init-ssh-merge');
37
33
  const { resolveInitOptions } = require('../utils/dev-init-resolve');
38
- const { displayDevConfig } = require('./dev-show-display');
39
34
  const {
40
35
  isHealthHttpServerError,
41
36
  formatEnsureServerTrustedFailure
@@ -383,104 +378,9 @@ async function runDevInit(options) {
383
378
  logOnboardingFinished(sshInfo);
384
379
  }
385
380
 
386
- /** Days before cert expiry at which we auto-refresh on dev refresh. */
387
- const CERT_REFRESH_DAYS = 14;
388
-
389
- /**
390
- * True if the cert in certDir expires within CERT_REFRESH_DAYS (or we cannot read expiry).
391
- * @param {string} certDir - Certificate directory
392
- * @returns {boolean}
393
- */
394
- function shouldRefreshDevCert(certDir) {
395
- const validNotAfter = getCertValidNotAfter(certDir);
396
- if (!validNotAfter) return true;
397
- const now = Date.now();
398
- const threshold = now + CERT_REFRESH_DAYS * 24 * 60 * 60 * 1000;
399
- return validNotAfter.getTime() < threshold;
400
- }
401
-
402
- /**
403
- * Refresh developer certificate: create PIN (with current cert), issue new cert, save and apply settings.
404
- * @param {{ serverUrl: string, clientCertPem: string, serverCaPem?: string|null }} auth - Current auth from getRemoteDevAuth
405
- * @returns {Promise<void>}
406
- */
407
- async function runCertificateRefresh(auth) {
408
- const devId = await config.getDeveloperId();
409
- if (!devId) throw new Error('developer-id not set in config.');
410
- const configDir = getConfigDirForPaths();
411
- const serverCaPem = auth.serverCaPem || undefined;
412
- logger.log(chalk.blue('\nšŸ”„ Refreshing certificate (create PIN + issue-cert)...\n'));
413
- const pinRes = await devApi.createPin(auth.serverUrl, auth.clientCertPem, devId, serverCaPem);
414
- const pin = pinRes.pin;
415
- if (!pin || typeof pin !== 'string') throw new Error('Server did not return a PIN.');
416
- logger.log(chalk.gray(' Generating new certificate request...'));
417
- const { csrPem, keyPem } = generateCSR(devId);
418
- logger.log(chalk.gray(' Requesting new certificate (issue-cert)...'));
419
- const issueResponse = await requestCertificate(auth.serverUrl, devId, pin, csrPem, serverCaPem);
420
- const caPem = mergeCaPemBlocks(serverCaPem, issueResponse.caCertificate, issueResponse.ca);
421
- await saveCertAndConfig(configDir, devId, issueResponse.certificate, keyPem, caPem);
422
- await applySettingsFromServer(auth.serverUrl, devId, issueResponse, keyPem, serverCaPem);
423
- await augmentAndSaveCaPemForRemoteDocker(configDir, devId, caPem, {
424
- settings: issueResponse.settings,
425
- remoteServerUrl: auth.serverUrl,
426
- warn: (msg) => logger.log(chalk.yellow(` ⚠ ${msg}`))
427
- });
428
- logger.log(formatSuccessLine('Certificate refreshed and config updated from server.\n'));
429
- }
430
-
431
- /**
432
- * GET /api/dev/settings and merge into local config (used by dev refresh when cert is still valid).
433
- * @param {{ serverUrl: string, serverCaPem?: string|null }} auth
434
- * @param {string} clientCertPem
435
- * @param {string|null|undefined} clientKeyPem
436
- * @param {string} devId
437
- * @returns {Promise<void>}
438
- */
439
- async function fetchAndMergeRemoteSettings(auth, clientCertPem, clientKeyPem, devId) {
440
- logger.log(chalk.blue('\nšŸ”„ Fetching settings from Builder Server...\n'));
441
- const settings = await devApi.getSettings(
442
- auth.serverUrl,
443
- clientCertPem,
444
- clientKeyPem || undefined,
445
- auth.serverCaPem || undefined
446
- );
447
- await config.mergeRemoteSettings(settings);
448
- const existingCa = readServerCaPem(getCertDir(getConfigDirForPaths(), devId));
449
- await augmentAndSaveCaPemForRemoteDocker(getConfigDirForPaths(), devId, existingCa, {
450
- settings,
451
- remoteServerUrl: auth.serverUrl,
452
- warn: (msg) => logger.log(chalk.yellow(` ⚠ ${msg}`))
453
- });
454
- logger.log(formatSuccessLine('Config updated from server.\n'));
455
- await displayDevConfig(devId);
456
- }
457
-
458
- /**
459
- * Fetch settings from Builder Server and merge into config (GET /api/dev/settings).
460
- * If certificate expires within CERT_REFRESH_DAYS (or --cert), refresh cert first (create PIN + issue-cert).
461
- * @param {Object} [options] - Commander options; options.cert = true forces cert refresh
462
- * @returns {Promise<void>}
463
- * @throws {Error} If remote server or certificate not configured, or getSettings fails
464
- */
465
- async function runDevRefresh(options = {}) {
466
- const { getRemoteDevAuth } = require('../utils/remote-dev-auth');
467
- const auth = await getRemoteDevAuth();
468
- if (!auth) {
469
- throw new Error('Remote server is not configured. Set remote-server and run "aifabrix dev init" first.');
470
- }
471
- const devId = await config.getDeveloperId();
472
- const certDir = getCertDir(getConfigDirForPaths(), devId);
473
- const clientCertPem = readClientCertPem(certDir);
474
- const clientKeyPem = readClientKeyPem(certDir);
475
- if (!clientCertPem) {
476
- throw new Error('Client certificate not found. Run "aifabrix dev init" first.');
477
- }
478
- if (Boolean(options.cert) || shouldRefreshDevCert(certDir)) {
479
- await runCertificateRefresh(auth);
480
- await displayDevConfig(devId);
481
- return;
482
- }
483
- await fetchAndMergeRemoteSettings(auth, clientCertPem, clientKeyPem, devId);
484
- }
485
-
486
- module.exports = { runDevInit, runDevRefresh };
381
+ module.exports = {
382
+ runDevInit,
383
+ requestCertificate,
384
+ saveCertAndConfig,
385
+ applySettingsFromServer
386
+ };
@@ -0,0 +1,197 @@
1
+ /**
2
+ * @fileoverview aifabrix dev refresh – sync remote settings and renew client cert when due
3
+ * @author AI Fabrix Team
4
+ * @version 2.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const chalk = require('chalk');
10
+ const config = require('../core/config');
11
+ const { getConfigDirForPaths } = require('../utils/paths');
12
+ const {
13
+ generateCSR,
14
+ getCertDir,
15
+ readClientCertPem,
16
+ readClientKeyPem,
17
+ readServerCaPem,
18
+ getCertValidNotAfter,
19
+ mergeCaPemBlocks
20
+ } = require('../utils/dev-cert-helper');
21
+ const devApi = require('../api/dev.api');
22
+ const logger = require('../utils/logger');
23
+ const { mergeDevSshConfigAfterInit, logDevSshConnectHint } = require('../utils/dev-init-ssh-merge');
24
+ const { displayDevConfig } = require('./dev-show-display');
25
+ const { augmentAndSaveCaPemForRemoteDocker } = require('../utils/dev-ca-docker-augment');
26
+ const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
27
+ const {
28
+ requestCertificate,
29
+ saveCertAndConfig,
30
+ applySettingsFromServer
31
+ } = require('./dev-init');
32
+
33
+ /** Days before cert expiry at which we auto-refresh on dev refresh / auto-renew. */
34
+ const CERT_REFRESH_DAYS = 14;
35
+
36
+ /**
37
+ * True if the cert expires within CERT_REFRESH_DAYS (or expiry cannot be read).
38
+ * Used by explicit `dev refresh` (also attempts when expiry is unknown).
39
+ * @param {string} certDir
40
+ * @returns {boolean}
41
+ */
42
+ function shouldRefreshDevCert(certDir) {
43
+ const validNotAfter = getCertValidNotAfter(certDir);
44
+ if (!validNotAfter) return true;
45
+ const now = Date.now();
46
+ const threshold = now + CERT_REFRESH_DAYS * 24 * 60 * 60 * 1000;
47
+ return validNotAfter.getTime() < threshold;
48
+ }
49
+
50
+ /**
51
+ * True when cert is still valid but expires within CERT_REFRESH_DAYS.
52
+ * Used for automatic renew (never tries when already expired).
53
+ * @param {string} certDir
54
+ * @returns {boolean}
55
+ */
56
+ function isDevCertAutoRenewalDue(certDir) {
57
+ const validNotAfter = getCertValidNotAfter(certDir);
58
+ if (!validNotAfter) return false;
59
+ const now = Date.now();
60
+ if (validNotAfter.getTime() <= now) return false;
61
+ const threshold = now + CERT_REFRESH_DAYS * 24 * 60 * 60 * 1000;
62
+ return validNotAfter.getTime() < threshold;
63
+ }
64
+
65
+ /**
66
+ * Refresh developer certificate: create PIN (with current cert), issue new cert, save and apply settings.
67
+ * @param {{ serverUrl: string, clientCertPem: string, serverCaPem?: string|null }} auth
68
+ * @returns {Promise<void>}
69
+ */
70
+ async function runCertificateRefresh(auth) {
71
+ const devId = await config.getDeveloperId();
72
+ if (!devId) throw new Error('developer-id not set in config.');
73
+ const configDir = getConfigDirForPaths();
74
+ const serverCaPem = auth.serverCaPem || undefined;
75
+ logger.log(chalk.blue('\nšŸ”„ Refreshing certificate (create PIN + issue-cert)...\n'));
76
+ const pinRes = await devApi.createPin(auth.serverUrl, auth.clientCertPem, devId, serverCaPem);
77
+ const pin = pinRes.pin;
78
+ if (!pin || typeof pin !== 'string') throw new Error('Server did not return a PIN.');
79
+ logger.log(chalk.gray(' Generating new certificate request...'));
80
+ const { csrPem, keyPem } = generateCSR(devId);
81
+ logger.log(chalk.gray(' Requesting new certificate (issue-cert)...'));
82
+ const issueResponse = await requestCertificate(auth.serverUrl, devId, pin, csrPem, serverCaPem);
83
+ const caPem = mergeCaPemBlocks(serverCaPem, issueResponse.caCertificate, issueResponse.ca);
84
+ await saveCertAndConfig(configDir, devId, issueResponse.certificate, keyPem, caPem);
85
+ await applySettingsFromServer(auth.serverUrl, devId, issueResponse, keyPem, serverCaPem);
86
+ await augmentAndSaveCaPemForRemoteDocker(configDir, devId, caPem, {
87
+ settings: issueResponse.settings,
88
+ remoteServerUrl: auth.serverUrl,
89
+ warn: (msg) => logger.log(chalk.yellow(` ⚠ ${msg}`))
90
+ });
91
+ logger.log(formatSuccessLine('Certificate refreshed and config updated from server.\n'));
92
+ logDevSshConnectHint(await mergeDevSshConfigAfterInit(auth.serverUrl, devId));
93
+ }
94
+
95
+ /**
96
+ * GET /api/dev/settings and merge into local config (when cert is still valid).
97
+ * @param {{ serverUrl: string, serverCaPem?: string|null }} auth
98
+ * @param {string} clientCertPem
99
+ * @param {string|null|undefined} clientKeyPem
100
+ * @param {string} devId
101
+ * @returns {Promise<void>}
102
+ */
103
+ async function fetchAndMergeRemoteSettings(auth, clientCertPem, clientKeyPem, devId) {
104
+ logger.log(chalk.blue('\nšŸ”„ Fetching settings from Builder Server...\n'));
105
+ const settings = await devApi.getSettings(
106
+ auth.serverUrl,
107
+ clientCertPem,
108
+ clientKeyPem || undefined,
109
+ auth.serverCaPem || undefined
110
+ );
111
+ await config.mergeRemoteSettings(settings);
112
+ const existingCa = readServerCaPem(getCertDir(getConfigDirForPaths(), devId));
113
+ await augmentAndSaveCaPemForRemoteDocker(getConfigDirForPaths(), devId, existingCa, {
114
+ settings,
115
+ remoteServerUrl: auth.serverUrl,
116
+ warn: (msg) => logger.log(chalk.yellow(` ⚠ ${msg}`))
117
+ });
118
+ logger.log(formatSuccessLine('Config updated from server.\n'));
119
+ await displayDevConfig(devId);
120
+ }
121
+
122
+ /**
123
+ * Fetch settings from Builder Server and merge into config.
124
+ * If certificate expires within CERT_REFRESH_DAYS (or --cert), refresh cert first.
125
+ * @param {Object} [options] - Commander options; options.cert = true forces cert refresh
126
+ * @returns {Promise<void>}
127
+ */
128
+ async function runDevRefresh(options = {}) {
129
+ const { readRemoteDevAuth } = require('../utils/remote-dev-auth');
130
+ const auth = await readRemoteDevAuth();
131
+ if (!auth) {
132
+ throw new Error('Remote server is not configured. Set remote-server and run "aifabrix dev init" first.');
133
+ }
134
+ const devId = await config.getDeveloperId();
135
+ const certDir = getCertDir(getConfigDirForPaths(), devId);
136
+ const clientCertPem = readClientCertPem(certDir);
137
+ const clientKeyPem = readClientKeyPem(certDir);
138
+ if (!clientCertPem) {
139
+ throw new Error('Client certificate not found. Run "aifabrix dev init" first.');
140
+ }
141
+ if (Boolean(options.cert) || shouldRefreshDevCert(certDir)) {
142
+ await runCertificateRefresh(auth);
143
+ await displayDevConfig(devId);
144
+ return;
145
+ }
146
+ await fetchAndMergeRemoteSettings(auth, clientCertPem, clientKeyPem, devId);
147
+ logDevSshConnectHint(await mergeDevSshConfigAfterInit(auth.serverUrl, devId));
148
+ }
149
+
150
+ /**
151
+ * Automatically renew the developer client certificate when still valid but due within
152
+ * CERT_REFRESH_DAYS. Safe for any cert-using command: no-op when not due / offline.
153
+ * Uses readRemoteDevAuth (not getRemoteDevAuth) to avoid recursion with auto-renew.
154
+ * Does not display config (caller shows status afterward).
155
+ *
156
+ * @param {{ quiet?: boolean }} [opts] - quiet=true suppresses failure warnings
157
+ * @returns {Promise<{ refreshed: boolean, reason?: string, error?: Error }>}
158
+ */
159
+ async function ensureDevCertFreshIfDue(opts = {}) {
160
+ const quiet = opts.quiet === true;
161
+ const { readRemoteDevAuth } = require('../utils/remote-dev-auth');
162
+ const auth = await readRemoteDevAuth();
163
+ if (!auth) {
164
+ return { refreshed: false, reason: 'no-remote-auth' };
165
+ }
166
+ const devId = await config.getDeveloperId();
167
+ if (!devId) {
168
+ return { refreshed: false, reason: 'no-developer-id' };
169
+ }
170
+ const certDir = getCertDir(getConfigDirForPaths(), devId);
171
+ if (!readClientCertPem(certDir)) {
172
+ return { refreshed: false, reason: 'no-cert' };
173
+ }
174
+ if (!isDevCertAutoRenewalDue(certDir)) {
175
+ return { refreshed: false, reason: 'not-due' };
176
+ }
177
+ try {
178
+ await runCertificateRefresh(auth);
179
+ return { refreshed: true };
180
+ } catch (error) {
181
+ if (!quiet) {
182
+ logger.warn(
183
+ chalk.yellow(`Could not auto-refresh developer certificate: ${error.message}`)
184
+ );
185
+ logger.warn(chalk.gray(' Run: aifabrix dev refresh --cert'));
186
+ }
187
+ return { refreshed: false, reason: 'refresh-failed', error };
188
+ }
189
+ }
190
+
191
+ module.exports = {
192
+ runDevRefresh,
193
+ ensureDevCertFreshIfDue,
194
+ isDevCertAutoRenewalDue,
195
+ shouldRefreshDevCert,
196
+ CERT_REFRESH_DAYS
197
+ };