@aifabrix/builder 2.42.1 → 2.44.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 (392) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/README.md +2 -2
  3. package/anchor-docs/README.md +10 -0
  4. package/anchor-docs/_TEMPLATE +24 -0
  5. package/bin/aifabrix.js +13 -4
  6. package/integration/hubspot-test/README.md +157 -0
  7. package/integration/{hubspot → hubspot-test}/application.json +6 -6
  8. package/integration/{hubspot → hubspot-test}/create-hubspot.js +10 -10
  9. package/integration/hubspot-test/env.template +4 -0
  10. package/integration/hubspot-test/hubspot-test-datasource-company.json +138 -0
  11. package/integration/hubspot-test/hubspot-test-datasource-contact.json +146 -0
  12. package/integration/hubspot-test/hubspot-test-datasource-deal.json +146 -0
  13. package/integration/hubspot-test/hubspot-test-datasource-users.json +76 -0
  14. package/integration/{hubspot/hubspot-deploy.json → hubspot-test/hubspot-test-deploy.json} +201 -24
  15. package/integration/{hubspot/hubspot-system.json → hubspot-test/hubspot-test-system.json} +8 -7
  16. package/integration/hubspot-test/rbac.json +166 -0
  17. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-hubspot-credential-real.yaml +3 -3
  18. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-hubspot-env-vars.yaml +2 -2
  19. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-add-datasource.yaml +1 -1
  20. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-credential-create.yaml +1 -1
  21. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-credential-select.yaml +1 -1
  22. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-known-platform.yaml +1 -1
  23. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +2 -0
  24. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-mode.yaml +1 -1
  25. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-openapi-file.yaml +1 -1
  26. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-openapi-url.yaml +1 -1
  27. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-source.yaml +1 -1
  28. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-dimension-array-test.yaml +1 -1
  29. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +5 -0
  30. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +5 -0
  31. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-dimension-test.yaml +1 -1
  32. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-rbac-test.yaml +1 -1
  33. package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +1 -1
  34. package/integration/{hubspot → hubspot-test}/test-dataplane-down-tests.js +1 -7
  35. package/integration/{hubspot → hubspot-test}/test-dataplane-down.js +3 -3
  36. package/integration/{hubspot → hubspot-test}/test.js +137 -102
  37. package/integration/{hubspot → hubspot-test}/wizard-hubspot-e2e.yaml +2 -2
  38. package/integration/{hubspot → hubspot-test}/wizard-hubspot-platform.yaml +1 -1
  39. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  40. package/integration/roundtrip-test-local/README.md +144 -0
  41. package/integration/roundtrip-test-local/application.yaml +13 -0
  42. package/integration/roundtrip-test-local/env.template +15 -0
  43. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  44. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  45. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  46. package/integration/roundtrip-test-local2/README.md +144 -0
  47. package/integration/roundtrip-test-local2/application.yaml +13 -0
  48. package/integration/roundtrip-test-local2/env.template +15 -0
  49. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  50. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  51. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  52. package/integration/test/wizard.yaml +8 -0
  53. package/jest.config.default.js +10 -0
  54. package/jest.config.integration.fixtures.js +22 -0
  55. package/jest.config.integration.js +21 -18
  56. package/jest.config.isolated.js +10 -0
  57. package/jest.projects.js +288 -0
  58. package/lib/api/datasources-core.api.js +3 -3
  59. package/lib/api/dev-mtls-request.js +110 -0
  60. package/lib/api/dev-server-https.js +145 -0
  61. package/lib/api/dev.api.js +133 -144
  62. package/lib/api/index.js +0 -1
  63. package/lib/api/pipeline.api.js +67 -20
  64. package/lib/api/service-users.api.js +111 -2
  65. package/lib/api/types/dev.types.js +4 -3
  66. package/lib/api/types/pipeline.types.js +8 -5
  67. package/lib/api/types/service-users.types.js +41 -0
  68. package/lib/api/types/validation-run.types.js +56 -0
  69. package/lib/api/validation-run.api.js +99 -0
  70. package/lib/api/validation-runner.js +99 -0
  71. package/lib/app/config.js +1 -1
  72. package/lib/app/deploy-status-display.js +2 -2
  73. package/lib/app/deploy.js +7 -6
  74. package/lib/app/display.js +2 -1
  75. package/lib/app/dockerfile.js +3 -2
  76. package/lib/app/down.js +2 -1
  77. package/lib/app/helpers.js +6 -5
  78. package/lib/app/index.js +27 -8
  79. package/lib/app/list.js +7 -6
  80. package/lib/app/push.js +4 -3
  81. package/lib/app/register.js +19 -8
  82. package/lib/app/rotate-secret.js +17 -13
  83. package/lib/app/run-container-start.js +184 -0
  84. package/lib/app/run-docker-fallback.js +108 -0
  85. package/lib/app/run-env-compose.js +30 -42
  86. package/lib/app/run-helpers.js +49 -126
  87. package/lib/app/run-infra-requirements.js +30 -0
  88. package/lib/app/run-resolve-image.js +21 -0
  89. package/lib/app/run.js +74 -21
  90. package/lib/app/show-display.js +1 -1
  91. package/lib/app/show.js +1 -1
  92. package/lib/build/index.js +13 -10
  93. package/lib/cli/index.js +2 -0
  94. package/lib/cli/setup-app.help.js +67 -0
  95. package/lib/cli/setup-app.js +59 -123
  96. package/lib/cli/setup-app.test-commands.js +179 -0
  97. package/lib/cli/setup-auth.js +36 -14
  98. package/lib/cli/setup-credential-deployment.js +22 -8
  99. package/lib/cli/setup-dev-path-commands.js +124 -0
  100. package/lib/cli/setup-dev.js +190 -103
  101. package/lib/cli/setup-environment.js +11 -20
  102. package/lib/cli/setup-external-system.js +62 -22
  103. package/lib/cli/setup-infra.js +139 -47
  104. package/lib/cli/setup-parameters.js +32 -0
  105. package/lib/cli/setup-secrets.js +147 -10
  106. package/lib/cli/setup-service-user.js +146 -20
  107. package/lib/cli/setup-utility.js +47 -19
  108. package/lib/commands/app-down.js +5 -7
  109. package/lib/commands/app-install.js +14 -7
  110. package/lib/commands/app-logs.js +13 -10
  111. package/lib/commands/app-shell.js +4 -1
  112. package/lib/commands/app-test.js +25 -19
  113. package/lib/commands/app.js +22 -10
  114. package/lib/commands/auth-config.js +10 -14
  115. package/lib/commands/auth-status.js +4 -3
  116. package/lib/commands/credential-env.js +4 -3
  117. package/lib/commands/credential-list.js +5 -4
  118. package/lib/commands/credential-push.js +4 -3
  119. package/lib/commands/datasource-unified-test-cli.js +495 -0
  120. package/lib/commands/datasource-unified-test-cli.options.js +149 -0
  121. package/lib/commands/datasource-validation-cli.js +129 -0
  122. package/lib/commands/datasource.js +123 -71
  123. package/lib/commands/deployment-list.js +6 -5
  124. package/lib/commands/dev-cli-handlers.js +122 -18
  125. package/lib/commands/dev-down.js +4 -3
  126. package/lib/commands/dev-init.js +231 -116
  127. package/lib/commands/dev-show-display.js +473 -0
  128. package/lib/commands/login-credentials.js +3 -2
  129. package/lib/commands/login-device.js +4 -3
  130. package/lib/commands/login.js +5 -4
  131. package/lib/commands/logout.js +8 -7
  132. package/lib/commands/parameters-validate.js +54 -0
  133. package/lib/commands/repair-datasource.js +314 -68
  134. package/lib/commands/repair-env-template.js +16 -10
  135. package/lib/commands/repair-rbac.js +25 -19
  136. package/lib/commands/repair.js +116 -32
  137. package/lib/commands/secrets-list.js +23 -12
  138. package/lib/commands/secrets-remove-all.js +220 -0
  139. package/lib/commands/secrets-remove.js +22 -13
  140. package/lib/commands/secrets-set.js +21 -12
  141. package/lib/commands/secrets-validate.js +20 -7
  142. package/lib/commands/secure.js +10 -9
  143. package/lib/commands/service-user.js +243 -13
  144. package/lib/commands/test-e2e-external.js +27 -1
  145. package/lib/commands/up-common.js +28 -2
  146. package/lib/commands/up-dataplane.js +31 -18
  147. package/lib/commands/up-miso.js +19 -29
  148. package/lib/commands/upload.js +138 -39
  149. package/lib/commands/wizard-core-helpers.js +1 -1
  150. package/lib/commands/wizard-dataplane.js +4 -3
  151. package/lib/commands/wizard-helpers.js +3 -3
  152. package/lib/commands/wizard.js +2 -2
  153. package/lib/core/admin-secrets.js +16 -5
  154. package/lib/core/audit-logger.js +12 -4
  155. package/lib/core/config-attach-extensions.js +46 -0
  156. package/lib/core/config-runtime-paths.js +29 -0
  157. package/lib/core/config.js +59 -58
  158. package/lib/core/diff.js +3 -2
  159. package/lib/core/ensure-encryption-key.js +2 -4
  160. package/lib/core/secrets-ensure-infra.js +77 -0
  161. package/lib/core/secrets-ensure.js +120 -64
  162. package/lib/core/secrets-env-write.js +35 -7
  163. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  164. package/lib/core/secrets.js +228 -42
  165. package/lib/core/templates-env.js +4 -3
  166. package/lib/core/templates.js +1 -1
  167. package/lib/datasource/abac-validator.js +148 -0
  168. package/lib/datasource/deploy.js +75 -53
  169. package/lib/datasource/field-reference-validator.js +77 -36
  170. package/lib/datasource/integration-context.js +63 -0
  171. package/lib/datasource/list.js +8 -7
  172. package/lib/datasource/log-viewer.js +252 -0
  173. package/lib/datasource/resolve-app.js +109 -0
  174. package/lib/datasource/test-e2e.js +95 -155
  175. package/lib/datasource/test-integration.js +121 -109
  176. package/lib/datasource/unified-validation-run-body.js +65 -0
  177. package/lib/datasource/unified-validation-run-post.js +23 -0
  178. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  179. package/lib/datasource/unified-validation-run.js +92 -0
  180. package/lib/datasource/validate.js +162 -15
  181. package/lib/deployment/deployer.js +4 -3
  182. package/lib/deployment/environment.js +7 -6
  183. package/lib/deployment/push.js +17 -8
  184. package/lib/external-system/delete.js +4 -3
  185. package/lib/external-system/deploy.js +131 -53
  186. package/lib/external-system/download-helpers.js +1 -1
  187. package/lib/external-system/download.js +7 -6
  188. package/lib/external-system/generator.js +104 -14
  189. package/lib/external-system/integration-test-dispatch.js +26 -0
  190. package/lib/external-system/test-execution.js +5 -1
  191. package/lib/external-system/test-helpers.js +0 -4
  192. package/lib/external-system/test-system-level-helpers.js +110 -0
  193. package/lib/external-system/test-system-level.js +83 -44
  194. package/lib/external-system/test.js +59 -8
  195. package/lib/generator/builders.js +23 -11
  196. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  197. package/lib/generator/external-controller-manifest.js +3 -3
  198. package/lib/generator/external.js +23 -11
  199. package/lib/generator/helpers.js +71 -12
  200. package/lib/generator/index.js +8 -4
  201. package/lib/generator/split-readme.js +12 -7
  202. package/lib/generator/split-variables.js +2 -1
  203. package/lib/generator/split.js +46 -11
  204. package/lib/generator/wizard-readme.js +3 -3
  205. package/lib/generator/wizard.js +16 -13
  206. package/lib/infrastructure/compose.js +60 -6
  207. package/lib/infrastructure/helpers.js +238 -51
  208. package/lib/infrastructure/index.js +64 -37
  209. package/lib/infrastructure/services.js +21 -15
  210. package/lib/internal/fs-real-sync.js +104 -0
  211. package/lib/internal/node-fs.js +98 -0
  212. package/lib/parameters/database-secret-values.js +173 -0
  213. package/lib/parameters/infra-kv-discovery.js +121 -0
  214. package/lib/parameters/infra-parameter-catalog.js +458 -0
  215. package/lib/parameters/infra-parameter-validate.js +64 -0
  216. package/lib/schema/application-schema.json +37 -17
  217. package/lib/schema/datasource-test-run.schema.json +493 -0
  218. package/lib/schema/deployment-rules.yaml +102 -63
  219. package/lib/schema/external-datasource.schema.json +1201 -433
  220. package/lib/schema/external-system.schema.json +181 -5
  221. package/lib/schema/flag-map-validation-run.json +31 -0
  222. package/lib/schema/infra-parameter.schema.json +106 -0
  223. package/lib/schema/infra.parameter.yaml +421 -0
  224. package/lib/schema/type/credential-auth-templates.json +40 -0
  225. package/lib/schema/type/document-storage.json +213 -0
  226. package/lib/schema/type/message-service.json +123 -0
  227. package/lib/schema/type/vector-store.json +88 -0
  228. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  229. package/lib/utils/api-error-handler.js +2 -2
  230. package/lib/utils/api.js +49 -14
  231. package/lib/utils/app-config-resolver.js +23 -1
  232. package/lib/utils/app-register-api.js +3 -2
  233. package/lib/utils/app-register-auth.js +1 -1
  234. package/lib/utils/app-register-config.js +4 -4
  235. package/lib/utils/app-register-display.js +3 -2
  236. package/lib/utils/app-register-validator.js +3 -2
  237. package/lib/utils/app-run-containers.js +26 -22
  238. package/lib/utils/app-scoped-config.js +31 -0
  239. package/lib/utils/app-service-env-from-builder.js +164 -0
  240. package/lib/utils/build-copy.js +1 -1
  241. package/lib/utils/build-helpers.js +20 -20
  242. package/lib/utils/build-resolve-image.js +165 -0
  243. package/lib/utils/cli-layout-chalk.js +8 -0
  244. package/lib/utils/cli-test-layout-chalk.js +267 -0
  245. package/lib/utils/cli-utils.js +88 -11
  246. package/lib/utils/compose-db-passwords.js +138 -0
  247. package/lib/utils/compose-generate-docker-compose.js +216 -0
  248. package/lib/utils/compose-generator.js +197 -291
  249. package/lib/utils/compose-miso-env.js +18 -0
  250. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  251. package/lib/utils/config-paths.js +209 -6
  252. package/lib/utils/config-scoped-resources-preference.js +41 -0
  253. package/lib/utils/controller-deployment-outcome.js +68 -0
  254. package/lib/utils/credential-display.js +2 -2
  255. package/lib/utils/credential-secrets-env.js +16 -1
  256. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  257. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  258. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  259. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  260. package/lib/utils/datasource-test-run-display.js +442 -0
  261. package/lib/utils/datasource-test-run-exit.js +58 -0
  262. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  263. package/lib/utils/datasource-test-run-report-version.js +51 -0
  264. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  265. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  266. package/lib/utils/datasource-validation-watch.js +266 -0
  267. package/lib/utils/declarative-url-ports.js +47 -0
  268. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  269. package/lib/utils/dev-ca-install.js +185 -23
  270. package/lib/utils/dev-cert-helper.js +266 -17
  271. package/lib/utils/dev-hosts-helper.js +307 -0
  272. package/lib/utils/dev-init-cert-hints.js +37 -0
  273. package/lib/utils/dev-init-health-messages.js +52 -0
  274. package/lib/utils/dev-init-resolve.js +86 -0
  275. package/lib/utils/dev-init-ssh-merge.js +65 -0
  276. package/lib/utils/dev-ssh-config-helper.js +196 -0
  277. package/lib/utils/dev-user-groups.js +93 -0
  278. package/lib/utils/docker-build.js +42 -17
  279. package/lib/utils/docker-exec.js +28 -0
  280. package/lib/utils/docker-manifest-public-port.js +116 -0
  281. package/lib/utils/docker-not-running-hint.js +52 -0
  282. package/lib/utils/docker.js +98 -11
  283. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  284. package/lib/utils/env-config-loader.js +10 -91
  285. package/lib/utils/env-copy.js +19 -10
  286. package/lib/utils/env-map.js +42 -11
  287. package/lib/utils/env-template.js +2 -2
  288. package/lib/utils/environment-scoped-resources.js +144 -0
  289. package/lib/utils/error-formatter.js +125 -9
  290. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  291. package/lib/utils/error-formatters/network-errors.js +2 -1
  292. package/lib/utils/error-formatters/permission-errors.js +2 -1
  293. package/lib/utils/error-formatters/validation-errors.js +2 -1
  294. package/lib/utils/external-env-template.js +180 -0
  295. package/lib/utils/external-readme.js +8 -1
  296. package/lib/utils/external-system-display.js +277 -136
  297. package/lib/utils/external-system-local-test-tty.js +389 -0
  298. package/lib/utils/external-system-readiness-core.js +377 -0
  299. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  300. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  301. package/lib/utils/external-system-readiness-display.js +186 -0
  302. package/lib/utils/external-system-test-helpers.js +24 -6
  303. package/lib/utils/external-system-validators.js +32 -14
  304. package/lib/utils/health-check-url.js +119 -0
  305. package/lib/utils/health-check.js +59 -25
  306. package/lib/utils/help-builder.js +14 -13
  307. package/lib/utils/image-version.js +4 -8
  308. package/lib/utils/infra-containers.js +4 -7
  309. package/lib/utils/infra-env-defaults.js +162 -0
  310. package/lib/utils/infra-status-display.js +167 -0
  311. package/lib/utils/infra-status.js +16 -8
  312. package/lib/utils/local-secrets.js +29 -7
  313. package/lib/utils/paths.js +136 -48
  314. package/lib/utils/port-resolver.js +10 -23
  315. package/lib/utils/redis-env-scope.js +62 -0
  316. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  317. package/lib/utils/remote-builder-validation.js +99 -0
  318. package/lib/utils/remote-dev-auth.js +117 -21
  319. package/lib/utils/remote-docker-env.js +67 -15
  320. package/lib/utils/remote-secrets-loader.js +13 -4
  321. package/lib/utils/resolve-docker-image-ref.js +124 -0
  322. package/lib/utils/schema-loader.js +22 -9
  323. package/lib/utils/secrets-bash-kv.js +25 -0
  324. package/lib/utils/secrets-generator.js +171 -51
  325. package/lib/utils/secrets-helpers.js +70 -59
  326. package/lib/utils/secrets-kv-scope.js +60 -0
  327. package/lib/utils/secrets-utils.js +35 -37
  328. package/lib/utils/secrets-validation.js +3 -1
  329. package/lib/utils/secrets-yaml-preserve.js +109 -0
  330. package/lib/utils/secure-file-permissions.js +91 -0
  331. package/lib/utils/ssh-key-helper.js +4 -2
  332. package/lib/utils/template-helpers.js +2 -2
  333. package/lib/utils/test-log-writer.js +3 -3
  334. package/lib/utils/token-manager.js +37 -5
  335. package/lib/utils/url-declarative-public-base.js +188 -0
  336. package/lib/utils/url-declarative-resolve-build.js +493 -0
  337. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  338. package/lib/utils/url-declarative-resolve.js +220 -0
  339. package/lib/utils/url-declarative-token-parse.js +74 -0
  340. package/lib/utils/url-declarative-url-flags.js +50 -0
  341. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  342. package/lib/utils/url-public-path-prefix.js +34 -0
  343. package/lib/utils/urls-local-registry.js +220 -0
  344. package/lib/utils/validation-report-tty-kit.js +77 -0
  345. package/lib/utils/validation-run-poll.js +89 -0
  346. package/lib/utils/validation-run-post-retry.js +73 -0
  347. package/lib/utils/validation-run-request.js +98 -0
  348. package/lib/utils/variable-transformer.js +21 -4
  349. package/lib/utils/yaml-preserve.js +78 -1
  350. package/lib/validation/datasource-warnings.js +56 -0
  351. package/lib/validation/env-template-auth.js +50 -2
  352. package/lib/validation/external-manifest-validator.js +35 -7
  353. package/lib/validation/validate-display.js +37 -31
  354. package/lib/validation/validate.js +9 -10
  355. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  356. package/lib/validation/validator.js +32 -78
  357. package/lib/validation/wizard-config-validator.js +2 -1
  358. package/package.json +11 -3
  359. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  360. package/scripts/diagnose-cli.js +150 -0
  361. package/scripts/install-local.js +304 -55
  362. package/templates/README.md +15 -2
  363. package/templates/applications/dataplane/application.yaml +52 -2
  364. package/templates/applications/dataplane/env.template +80 -18
  365. package/templates/applications/dataplane/rbac.yaml +8 -0
  366. package/templates/applications/keycloak/application.yaml +9 -1
  367. package/templates/applications/keycloak/env.template +15 -6
  368. package/templates/applications/miso-controller/application.yaml +10 -2
  369. package/templates/applications/miso-controller/env.template +55 -14
  370. package/templates/applications/miso-controller/rbac.yaml +5 -0
  371. package/templates/external-system/README.md.hbs +20 -7
  372. package/templates/external-system/deploy.js.hbs +5 -5
  373. package/templates/external-system/env.template.hbs +22 -0
  374. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  375. package/templates/infra/compose.yaml.hbs +20 -4
  376. package/templates/python/docker-compose.hbs +16 -0
  377. package/templates/typescript/docker-compose.hbs +16 -0
  378. package/integration/hubspot/README.md +0 -102
  379. package/integration/hubspot/env.template +0 -4
  380. package/integration/hubspot/hubspot-datasource-company.json +0 -541
  381. package/integration/hubspot/hubspot-datasource-contact.json +0 -639
  382. package/integration/hubspot/hubspot-datasource-deal.json +0 -588
  383. package/integration/hubspot/hubspot-datasource-users.json +0 -116
  384. package/integration/hubspot/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
  385. package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
  386. package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
  387. package/lib/api/external-test.api.js +0 -111
  388. package/lib/schema/env-config.yaml +0 -43
  389. /package/integration/{hubspot → hubspot-test}/companies.json +0 -0
  390. /package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-app-name.yaml +0 -0
  391. /package/integration/{hubspot → hubspot-test}/test-artifacts/wizard-invalid-missing-app.yaml +0 -0
  392. /package/integration/{hubspot → hubspot-test}/test-dataplane-down-helpers.js +0 -0
@@ -0,0 +1,377 @@
1
+ /**
2
+ * Pure helpers for external system readiness (Tier A publish / Tier B probe).
3
+ * No I/O; safe for unit tests.
4
+ *
5
+ * @fileoverview Readiness classification and manifest-derived identity/credential intent
6
+ * @author AI Fabrix Team
7
+ * @version 2.0.0
8
+ */
9
+
10
+ /**
11
+ * Unwraps `{ success, data }` API envelope or returns object if already body.
12
+ * @param {*} res - ApiClient / makeApiCall response
13
+ * @returns {Object|null}
14
+ */
15
+ function unwrapApiData(res) {
16
+ if (!res || typeof res !== 'object') return null;
17
+ if (res.success === false) return null;
18
+ if (res.data !== undefined && res.data !== null) return res.data;
19
+ return res;
20
+ }
21
+
22
+ /**
23
+ * True if object looks like dataplane PublicationResult.
24
+ * @param {*} obj - Parsed JSON
25
+ * @returns {boolean}
26
+ */
27
+ function isPublicationResultShape(obj) {
28
+ return !!(obj && typeof obj === 'object' && (obj.uploadId || obj.system) && Array.isArray(obj.datasources));
29
+ }
30
+
31
+ /**
32
+ * Returns publication payload from upload API response.
33
+ * @param {*} res - Response from uploadApplicationViaPipeline
34
+ * @returns {Object|null}
35
+ */
36
+ function unwrapPublicationResult(res) {
37
+ const d = unwrapApiData(res);
38
+ return isPublicationResultShape(d) ? d : null;
39
+ }
40
+
41
+ /**
42
+ * Tier A: readiness from published datasource row + MCP expectation.
43
+ * Rules: inactive/archived → Failed; MCP expected but missing → Partial; draft → Partial; published/deployed + active → Ready.
44
+ * @param {Object} ds - ExternalDataSourceResponse-like
45
+ * @param {boolean} generateMcpContract - From application config
46
+ * @returns {'ready'|'partial'|'failed'}
47
+ */
48
+ function classifyDatasourceTierA(ds, generateMcpContract) {
49
+ const active = ds.isActive !== false;
50
+ const status = String(ds.status || '').toLowerCase();
51
+ if (!active || status === 'archived') {
52
+ return 'failed';
53
+ }
54
+ if (generateMcpContract === true && !ds.mcpContract) {
55
+ return 'partial';
56
+ }
57
+ if (status === 'draft') {
58
+ return 'partial';
59
+ }
60
+ if (status === 'published' || status === 'deployed') {
61
+ return 'ready';
62
+ }
63
+ return 'partial';
64
+ }
65
+
66
+ /**
67
+ * @param {Array<Object>} datasources - Datasource list
68
+ * @param {boolean} generateMcpContract
69
+ * @returns {{ rows: Array<{ key: string, tier: string }>, ready: number, partial: number, failed: number }}
70
+ */
71
+ function summarizeDatasourceTiersA(datasources, generateMcpContract) {
72
+ const rows = [];
73
+ let ready = 0;
74
+ let partial = 0;
75
+ let failed = 0;
76
+ for (const ds of datasources || []) {
77
+ const key = ds.key || ds.sourceKey || 'unknown';
78
+ const tier = classifyDatasourceTierA(ds, generateMcpContract);
79
+ rows.push({ key, tier });
80
+ if (tier === 'ready') ready += 1;
81
+ else if (tier === 'partial') partial += 1;
82
+ else failed += 1;
83
+ }
84
+ return { rows, ready, partial, failed };
85
+ }
86
+
87
+ /**
88
+ * Aggregate verdict label for system readiness line.
89
+ * @param {{ ready: number, partial: number, failed: number }} counts
90
+ * @returns {'READY'|'PARTIAL'|'FAILED'}
91
+ */
92
+ function aggregateVerdictFromCounts(counts) {
93
+ const { ready, partial, failed } = counts;
94
+ const total = ready + partial + failed;
95
+ if (total === 0) return 'PARTIAL';
96
+ if (failed === total) return 'FAILED';
97
+ if (failed === 0 && partial === 0) return 'READY';
98
+ return 'PARTIAL';
99
+ }
100
+
101
+ /**
102
+ * Tier B: map validation/run per-datasource result.
103
+ * @param {Object} row - ExternalDataSourceTestResponse-like
104
+ * @returns {'ready'|'partial'|'failed'}
105
+ */
106
+ function classifyDatasourceTierB(row) {
107
+ if (!row || row.skipped) return 'partial';
108
+ if (row.success === false) return 'failed';
109
+ const vr = row.validationResults || {};
110
+ if (vr.isValid === false) return 'failed';
111
+ const warnings = vr.warnings || row.fieldMappingResults?.warnings;
112
+ const etr = row.endpointTestResults || {};
113
+ if (etr.success === false || etr.endpointReachable === false) return 'failed';
114
+ if ((Array.isArray(warnings) && warnings.length > 0) || etr.warning) return 'partial';
115
+ return 'ready';
116
+ }
117
+
118
+ /**
119
+ * True if body matches dataplane **DatasourceTestRun** (POST /validation/run success shape).
120
+ * @param {*} obj
121
+ * @returns {boolean}
122
+ */
123
+ function isDatasourceTestRunEnvelope(obj) {
124
+ if (!obj || typeof obj !== 'object') return false;
125
+ const ver = obj.reportVersion;
126
+ return typeof ver === 'string' && ver.length > 0 && 'datasourceKey' in obj;
127
+ }
128
+
129
+ const CONNECTIVITY_STEP_MARKERS = ['credential', 'endpoint', 'connectivity', 'live'];
130
+
131
+ /**
132
+ * @param {Array<*>} issues
133
+ * @returns {{ errors: string[], warnings: string[] }}
134
+ */
135
+ function partitionDatasourceTestRunIssues(issues) {
136
+ const errors = [];
137
+ const warnings = [];
138
+ for (const i of issues) {
139
+ if (!i || typeof i !== 'object') continue;
140
+ const msg = i.message || i.code || '';
141
+ const sev = String(i.severity || '').toLowerCase();
142
+ if (sev === 'blocking') errors.push(String(msg));
143
+ else warnings.push(String(msg));
144
+ }
145
+ return { errors, warnings };
146
+ }
147
+
148
+ /**
149
+ * @param {Object} step
150
+ * @returns {boolean}
151
+ */
152
+ function stepFailureAffectsConnectivity(step) {
153
+ if (!step || typeof step !== 'object' || step.success !== false) return false;
154
+ const n = String(step.name || '').toLowerCase();
155
+ return CONNECTIVITY_STEP_MARKERS.some(m => n.includes(m));
156
+ }
157
+
158
+ /**
159
+ * Endpoint flags from integration + root status (legacy probe row shape).
160
+ * @param {Object} run - DatasourceTestRun
161
+ * @returns {{ endpointSuccess: boolean, endpointReachable: boolean, endpointWarning: boolean, endpointMessage: string|null, rootStatus: string }}
162
+ */
163
+ function datasourceTestRunEndpointFlags(run) {
164
+ let endpointSuccess = true;
165
+ let endpointReachable = true;
166
+ let endpointWarning = false;
167
+ let endpointMessage = null;
168
+ const integration = run.integration;
169
+ if (integration && typeof integration === 'object') {
170
+ const ist = String(integration.status || '').toLowerCase();
171
+ if (ist === 'fail') {
172
+ endpointSuccess = false;
173
+ endpointReachable = false;
174
+ }
175
+ if (ist === 'warn') endpointWarning = true;
176
+ if (integration.summary) endpointMessage = String(integration.summary);
177
+ const steps = integration.stepResults;
178
+ if (Array.isArray(steps) && steps.some(stepFailureAffectsConnectivity)) {
179
+ endpointSuccess = false;
180
+ endpointReachable = false;
181
+ }
182
+ }
183
+ const rootStatus = run.status && typeof run.status === 'string' ? run.status.toLowerCase() : '';
184
+ if (rootStatus === 'fail') {
185
+ endpointSuccess = false;
186
+ }
187
+ return { endpointSuccess, endpointReachable, endpointWarning, endpointMessage, rootStatus };
188
+ }
189
+
190
+ /**
191
+ * Map canonical DatasourceTestRun JSON into a legacy probe row for {@link summarizeProbeResults}.
192
+ * @param {Object} run
193
+ * @returns {Object}
194
+ */
195
+ function datasourceTestRunToLegacyRow(run) {
196
+ const v = run.validation;
197
+ const vStatus = v && typeof v.status === 'string' ? v.status.toLowerCase() : '';
198
+ const issues = Array.isArray(v?.issues) ? v.issues : [];
199
+ const { errors, warnings } = partitionDatasourceTestRunIssues(issues);
200
+ const isValid = vStatus !== 'fail' && errors.length === 0;
201
+ const ep = datasourceTestRunEndpointFlags(run);
202
+ return {
203
+ sourceKey: run.datasourceKey,
204
+ key: run.datasourceKey,
205
+ success: ep.rootStatus !== 'fail',
206
+ skipped: ep.rootStatus === 'skipped',
207
+ validationResults: { isValid, errors, warnings },
208
+ endpointTestResults: {
209
+ success: ep.endpointSuccess,
210
+ endpointReachable: ep.endpointReachable,
211
+ message: ep.endpointMessage,
212
+ warning: ep.endpointWarning
213
+ }
214
+ };
215
+ }
216
+
217
+ /**
218
+ * Normalize runtime probe body for Tier B display.
219
+ *
220
+ * Mapping note (plan 127: "align examples to API"):
221
+ * - **Upload** uses dataplane pipeline upload and returns **PublicationResult** with:
222
+ * - `uploadId`, `uploadStatus`, `system`, `datasources[]`, `generateMcpContract`
223
+ * - **Server validation (upload --verbose)** uses pipeline validate and returns:
224
+ * - `warnings[]` (dry-run; no publish)
225
+ * - **Runtime probe (--probe)** uses validation run and returns either:
226
+ * - legacy `{ results: ExternalDataSourceTestResponse[] }`, or
227
+ * - canonical **DatasourceTestRun** envelope (single success shape) which we coerce into a legacy row
228
+ *
229
+ * This helper intentionally accepts multiple shapes so the CLI output stays truthful across dataplane versions.
230
+ *
231
+ * @param {*} probeRaw - Unwrapped API data
232
+ * @returns {Object[]}
233
+ */
234
+ function coerceProbeRunToResultRows(probeRaw) {
235
+ if (!probeRaw || typeof probeRaw !== 'object') return [];
236
+ if (Array.isArray(probeRaw.results) && probeRaw.results.length > 0) return probeRaw.results;
237
+ if (isDatasourceTestRunEnvelope(probeRaw)) return [datasourceTestRunToLegacyRow(probeRaw)];
238
+ return [];
239
+ }
240
+
241
+ /**
242
+ * @param {Array<Object>} results - ExternalSystemTestResponse.results
243
+ * @returns {{ rows: Array<{ key: string, tier: string }>, ready: number, partial: number, failed: number, issues: Array<{ key: string, lines: string[] }> }}
244
+ */
245
+ function summarizeProbeResults(results) {
246
+ const rows = [];
247
+ const issues = [];
248
+ let ready = 0;
249
+ let partial = 0;
250
+ let failed = 0;
251
+ for (const r of results || []) {
252
+ const key = r.sourceKey || r.key || 'unknown';
253
+ const tier = classifyDatasourceTierB(r);
254
+ rows.push({ key, tier });
255
+ if (tier === 'ready') ready += 1;
256
+ else if (tier === 'partial') partial += 1;
257
+ else failed += 1;
258
+ const lines = [];
259
+ if (r.error) lines.push(r.error);
260
+ const vr = r.validationResults || {};
261
+ if (Array.isArray(vr.errors)) vr.errors.forEach(e => lines.push(String(e)));
262
+ const etr = r.endpointTestResults || {};
263
+ if (etr.message && (tier === 'failed' || tier === 'partial')) lines.push(String(etr.message));
264
+ if (lines.length) issues.push({ key, lines });
265
+ }
266
+ return { rows, ready, partial, failed, issues };
267
+ }
268
+
269
+ /**
270
+ * Identity summary from external system manifest `system` object.
271
+ * @param {Object} system - manifest.system
272
+ * @returns {{ mode: string, attribution: string, tokenBroker: string }}
273
+ */
274
+ function extractIdentitySummary(system) {
275
+ const ip = system?.identityPropagation || {};
276
+ const mode = ip.mode || ip.executionMode || 'system';
277
+ const attr = ip.attribution;
278
+ let attribution = 'disabled';
279
+ if (attr && typeof attr === 'object' && attr.enabled === true) attribution = 'enabled';
280
+ else if (attr === true) attribution = 'enabled';
281
+ const tb = ip.tokenBroker;
282
+ let tokenBroker = 'not configured';
283
+ if (tb && typeof tb === 'object' && Object.keys(tb).length > 0) {
284
+ tokenBroker = 'configured';
285
+ }
286
+ return { mode: String(mode), attribution, tokenBroker };
287
+ }
288
+
289
+ /**
290
+ * Resolves GET test URL display from authentication.variables (apikey, oauth2, etc.).
291
+ * @param {Object} system - manifest.system
292
+ * @returns {string|null} Full URL or null
293
+ */
294
+ function resolveCredentialTestEndpointDisplay(system) {
295
+ const auth = system?.authentication;
296
+ if (!auth || typeof auth !== 'object') return null;
297
+ const vars = auth.variables || {};
298
+ const baseUrl = typeof vars.baseUrl === 'string' ? vars.baseUrl.replace(/\/$/, '') : '';
299
+ const testPath = vars.testEndpoint;
300
+ if (!testPath) return baseUrl ? `${baseUrl}/health` : null;
301
+ if (/^https?:\/\//i.test(testPath)) return testPath;
302
+ if (!baseUrl) return testPath;
303
+ const path = testPath.startsWith('/') ? testPath : `/${testPath}`;
304
+ return `${baseUrl}${path}`;
305
+ }
306
+
307
+ /**
308
+ * Human-readable reason for dataplane fetch errors (no stack).
309
+ * @param {Error} err - Network or API error
310
+ * @param {string} dataplaneUrl - Base URL for context
311
+ * @returns {string}
312
+ */
313
+ function formatDataplaneFetchReason(err, dataplaneUrl) {
314
+ const msg = err && err.message ? err.message : String(err);
315
+ const lower = msg.toLowerCase();
316
+ if (lower.includes('econnrefused') || lower.includes('connection refused')) {
317
+ return `connection refused (${dataplaneUrl})`;
318
+ }
319
+ if (lower.includes('enotfound') || lower.includes('getaddrinfo')) {
320
+ return `host not reachable (${dataplaneUrl})`;
321
+ }
322
+ if (lower.includes('401') || lower.includes('unauthorized')) {
323
+ return 'authentication failed (401)';
324
+ }
325
+ if (lower.includes('403') || lower.includes('forbidden')) {
326
+ return 'forbidden (403)';
327
+ }
328
+ if (lower.includes('404')) {
329
+ return 'not found (404)';
330
+ }
331
+ return msg.split('\n')[0].slice(0, 200);
332
+ }
333
+
334
+ /**
335
+ * Next-action hints from Tier A summary.
336
+ * @param {string} systemKey
337
+ * @param {{ rows: Array<{ key: string, tier: string }> }} summary
338
+ * @param {boolean} generateMcpContract
339
+ * @returns {string[]}
340
+ */
341
+ function buildNextActionsTierA(systemKey, summary, generateMcpContract) {
342
+ const lines = [];
343
+ const failed = summary.rows.filter(r => r.tier === 'failed').map(r => r.key);
344
+ const partial = summary.rows.filter(r => r.tier === 'partial').map(r => r.key);
345
+ if (failed.length > 0) {
346
+ lines.push(`Investigate failed datasource: ${failed.join(', ')}`);
347
+ lines.push(`Run: aifabrix datasource test-e2e ${failed[0]} --app ${systemKey}`);
348
+ } else if (partial.length > 0) {
349
+ lines.push(`Review partial datasource(s): ${partial.join(', ')}`);
350
+ lines.push('Run: aifabrix upload ' + systemKey + ' --probe');
351
+ }
352
+ if (generateMcpContract && partial.length > 0) {
353
+ lines.push('If MCP is missing on a datasource, check generateMcpContract and datasource config.');
354
+ }
355
+ if (lines.length === 0) {
356
+ lines.push('Use --probe for runtime verification against the live API.');
357
+ }
358
+ return lines;
359
+ }
360
+
361
+ module.exports = {
362
+ unwrapApiData,
363
+ unwrapPublicationResult,
364
+ isPublicationResultShape,
365
+ classifyDatasourceTierA,
366
+ summarizeDatasourceTiersA,
367
+ aggregateVerdictFromCounts,
368
+ classifyDatasourceTierB,
369
+ summarizeProbeResults,
370
+ coerceProbeRunToResultRows,
371
+ isDatasourceTestRunEnvelope,
372
+ datasourceTestRunToLegacyRow,
373
+ extractIdentitySummary,
374
+ resolveCredentialTestEndpointDisplay,
375
+ formatDataplaneFetchReason,
376
+ buildNextActionsTierA
377
+ };
@@ -0,0 +1,270 @@
1
+ const { formatBlockingError, formatSuccessLine } = require('./cli-test-layout-chalk');
2
+ /**
3
+ * Deploy readiness CLI output (config / deployment / runtime layers).
4
+ * Kept separate from upload display to satisfy file/function size rules.
5
+ *
6
+ * @fileoverview Deploy external system readiness logging
7
+ * @author AI Fabrix Team
8
+ * @version 2.0.0
9
+ */
10
+
11
+ const chalk = require('chalk');
12
+ const logger = require('./logger');
13
+ const {
14
+ summarizeDatasourceTiersA,
15
+ aggregateVerdictFromCounts,
16
+ summarizeProbeResults,
17
+ coerceProbeRunToResultRows,
18
+ formatDataplaneFetchReason,
19
+ buildNextActionsTierA
20
+ } = require('./external-system-readiness-core');
21
+ const {
22
+ logSeparator,
23
+ logSectionTitle,
24
+ logDatasourceTable,
25
+ verdictLine,
26
+ logIdentityBlock,
27
+ logCredentialIntentBlock,
28
+ logDocsBlock,
29
+ logNextActions
30
+ } = require('./external-system-readiness-display-internals');
31
+
32
+ /**
33
+ * @param {Array<Object>|undefined} dsFromCtx
34
+ * @param {Object} manifest
35
+ * @returns {Object[]}
36
+ */
37
+ function resolveDeployDatasources(dsFromCtx, manifest) {
38
+ let datasources = Array.isArray(dsFromCtx) ? dsFromCtx : [];
39
+ if (datasources.length === 0 && Array.isArray(manifest.dataSources)) {
40
+ datasources = manifest.dataSources.map(d => ({
41
+ key: d.key,
42
+ status: d.status || 'published',
43
+ isActive: d.isActive !== false,
44
+ mcpContract: d.mcpContract
45
+ }));
46
+ }
47
+ return datasources;
48
+ }
49
+
50
+ /**
51
+ * @param {Object} probeData
52
+ */
53
+ function logDeployProbeDatasourceSection(probeData) {
54
+ const results = coerceProbeRunToResultRows(probeData);
55
+ const probeSummary = summarizeProbeResults(results);
56
+ logSectionTitle('Runtime Readiness:');
57
+ logDatasourceTable(probeSummary.rows, probeSummary);
58
+ if (probeSummary.issues.length > 0) {
59
+ logSeparator();
60
+ logSectionTitle('Key Issues:');
61
+ for (const { key, lines } of probeSummary.issues) {
62
+ logger.log(chalk.white(key));
63
+ for (const line of lines) {
64
+ logger.log(chalk.red(`- ${line}`));
65
+ }
66
+ }
67
+ }
68
+ logSeparator();
69
+ logSectionTitle('Credential Test:');
70
+ const anyEndpointFail = results.some(row => row?.endpointTestResults?.success === false);
71
+ if (anyEndpointFail) {
72
+ logger.log(formatBlockingError('Failed (see Key Issues / endpoint test)'));
73
+ } else if (probeSummary.failed > 0) {
74
+ logger.log(formatBlockingError('Some datasource checks failed'));
75
+ } else if (probeSummary.partial > 0) {
76
+ logger.log(chalk.yellow('⚠ Completed with warnings'));
77
+ } else {
78
+ logger.log(formatSuccessLine('Passed'));
79
+ }
80
+ }
81
+
82
+ /**
83
+ * @param {Object|null} systemFromDataplane
84
+ * @param {boolean} genMcp
85
+ */
86
+ function logDeployContractsSection(systemFromDataplane, genMcp) {
87
+ if (!systemFromDataplane) return;
88
+ logSeparator();
89
+ logSectionTitle('Contracts:');
90
+ const mcpOk = genMcp !== false;
91
+ logger.log(mcpOk ? formatSuccessLine('MCP generation enabled') : chalk.gray('○ MCP generation not enabled'));
92
+ if (systemFromDataplane.openApiDocsPageUrl || systemFromDataplane.apiDocumentUrl) {
93
+ logger.log(formatSuccessLine('OpenAPI available'));
94
+ } else {
95
+ logger.log(chalk.gray('○ OpenAPI docs URL not available'));
96
+ }
97
+ logDocsBlock(systemFromDataplane);
98
+ }
99
+
100
+ /**
101
+ * @param {string} systemKey
102
+ * @param {Object|null} probeData
103
+ * @param {Object} summary
104
+ * @param {boolean} genMcp
105
+ */
106
+ function logDeployNextActionsSection(systemKey, probeData, summary, genMcp) {
107
+ logSeparator();
108
+ if (probeData) {
109
+ logNextActions(
110
+ ['Fix API credentials or permissions if endpoint tests failed'],
111
+ `Run: aifabrix datasource test-e2e <datasourceKey> --app ${systemKey}`
112
+ );
113
+ return;
114
+ }
115
+ const hints = buildNextActionsTierA(systemKey, summary, genMcp);
116
+ const deployHints = hints.filter(h => !h.includes('aifabrix upload'));
117
+ const probeCmd = `Run: aifabrix deploy ${systemKey} --probe`;
118
+ if (!deployHints.some(h => h.includes('--probe'))) {
119
+ deployHints.push(probeCmd);
120
+ }
121
+ logNextActions(deployHints.slice(0, 6));
122
+ }
123
+
124
+ /**
125
+ * @param {Object} ctx
126
+ * @param {string} ctx.environment
127
+ * @param {string} ctx.dataplaneUrl
128
+ * @param {string} systemKey
129
+ * @param {Error} fetchError
130
+ */
131
+ function logDeployReadinessFetchError(ctx, systemKey, fetchError) {
132
+ const { dataplaneUrl } = ctx;
133
+ logSeparator();
134
+ logger.log(chalk.yellow('⚠ Unable to fetch system details from dataplane'));
135
+ logger.log(chalk.yellow(`Reason: ${formatDataplaneFetchReason(fetchError, dataplaneUrl || '')}`));
136
+ logger.log(chalk.white('\nDeployment succeeded, but readiness could not be verified.'));
137
+ logSeparator();
138
+ logNextActions(
139
+ ['Verify dataplane is running', 'Check network / authentication'],
140
+ `Retry: aifabrix deploy ${systemKey}`
141
+ );
142
+ }
143
+
144
+ /**
145
+ * @param {Object} systemCfg
146
+ * @param {boolean} deploymentOk
147
+ * @param {Object|null} probeData
148
+ * @param {Object} summary
149
+ * @param {Object|null} [deploymentDetail] - from parseControllerDeploymentOutcome when !deploymentOk
150
+ */
151
+ function logDeployDeploymentSubsection(deploymentOk, deploymentDetail) {
152
+ logSectionTitle('Deployment:');
153
+ if (deploymentOk) {
154
+ logger.log(formatSuccessLine('Controller deployment OK'));
155
+ return;
156
+ }
157
+ logger.log(formatBlockingError('Controller deployment failed'));
158
+ if (!deploymentDetail) {
159
+ logger.log(chalk.gray(' No deployment status payload was available after polling.'));
160
+ return;
161
+ }
162
+ if (deploymentDetail.statusLabel) {
163
+ logger.log(chalk.gray(` Status: ${deploymentDetail.statusLabel}`));
164
+ }
165
+ if (deploymentDetail.error) {
166
+ logger.log(chalk.red(` Error: ${deploymentDetail.error}`));
167
+ }
168
+ if (deploymentDetail.message) {
169
+ logger.log(chalk.yellow(` Message: ${deploymentDetail.message}`));
170
+ }
171
+ if (!deploymentDetail.error && !deploymentDetail.message && !deploymentDetail.statusLabel) {
172
+ logger.log(chalk.gray(' No error details in the deployment status response; check controller logs.'));
173
+ }
174
+ }
175
+
176
+ function logDeployConfigDeploymentRuntime(systemCfg, deploymentOk, probeData, summary, deploymentDetail) {
177
+ const verdict = aggregateVerdictFromCounts(summary);
178
+ logSeparator();
179
+ logger.log(verdictLine(verdict));
180
+ logSectionTitle('Config:');
181
+ logger.log(formatSuccessLine('Manifest valid'));
182
+ const method = systemCfg.authentication?.method || 'unknown';
183
+ logger.log(formatSuccessLine(`Authentication configured (${method})`));
184
+ logDeployDeploymentSubsection(deploymentOk, deploymentDetail);
185
+ logSectionTitle('Runtime:');
186
+ if (!probeData) {
187
+ logger.log(chalk.gray('⏭ Skipped (use --probe to verify)'));
188
+ } else {
189
+ logger.log(formatSuccessLine('Runtime checks completed (--probe)'));
190
+ }
191
+ }
192
+
193
+ /**
194
+ * @param {string} environment
195
+ * @param {string} dataplaneUrl
196
+ */
197
+ function logDeployEnvironmentAndDataplane(environment, dataplaneUrl) {
198
+ logger.log('');
199
+ logger.log(chalk.gray(`Environment: ${environment}`));
200
+ logger.log(chalk.gray(`Dataplane: ${dataplaneUrl || '(unknown)'}`));
201
+ }
202
+
203
+ /**
204
+ * @param {Object} systemCfg
205
+ * @param {boolean} withProbe
206
+ */
207
+ function logDeployIdentityAndCredentialBlocks(systemCfg, withProbe) {
208
+ logSeparator();
209
+ logIdentityBlock(systemCfg);
210
+ if (!withProbe) {
211
+ logSeparator();
212
+ logCredentialIntentBlock(systemCfg, false);
213
+ }
214
+ }
215
+
216
+ /**
217
+ * @param {Object} ctx
218
+ * @param {string} ctx.environment
219
+ * @param {string} ctx.dataplaneUrl
220
+ * @param {Object} ctx.manifest
221
+ * @param {Array<Object>} [ctx.datasources]
222
+ * @param {Object|null} ctx.systemFromDataplane
223
+ * @param {Error|null} ctx.fetchError
224
+ * @param {boolean} ctx.deploymentOk
225
+ * @param {Object|null} [ctx.deploymentDetail]
226
+ * @param {Object|null} ctx.probeData
227
+ */
228
+ function logDeployReadinessSummary(ctx) {
229
+ const {
230
+ environment,
231
+ dataplaneUrl,
232
+ manifest,
233
+ datasources: dsFromCtx,
234
+ systemFromDataplane,
235
+ fetchError,
236
+ deploymentOk,
237
+ deploymentDetail,
238
+ probeData
239
+ } = ctx;
240
+ const systemKey = manifest.key;
241
+ const systemCfg = manifest.system || {};
242
+ const genMcp = systemCfg.generateMcpContract !== false;
243
+
244
+ logDeployEnvironmentAndDataplane(environment, dataplaneUrl);
245
+
246
+ if (fetchError) {
247
+ logDeployReadinessFetchError(ctx, systemKey, fetchError);
248
+ return;
249
+ }
250
+
251
+ const datasources = resolveDeployDatasources(dsFromCtx, manifest);
252
+ const summary = summarizeDatasourceTiersA(datasources, genMcp);
253
+ logDeployConfigDeploymentRuntime(systemCfg, deploymentOk, probeData, summary, deploymentDetail || null);
254
+
255
+ logSeparator();
256
+ if (probeData) {
257
+ logDeployProbeDatasourceSection(probeData);
258
+ } else {
259
+ logDatasourceTable(summary.rows, summary);
260
+ }
261
+
262
+ logDeployIdentityAndCredentialBlocks(systemCfg, !!probeData);
263
+
264
+ logDeployContractsSection(systemFromDataplane, genMcp);
265
+ logDeployNextActionsSection(systemKey, probeData, summary, genMcp);
266
+ }
267
+
268
+ module.exports = {
269
+ logDeployReadinessSummary
270
+ };