@aifabrix/builder 2.45.5 → 2.47.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 (355) hide show
  1. package/.cursor/rules/cli-layout.mdc +2 -0
  2. package/.cursor/rules/cli-product-neutral.mdc +43 -0
  3. package/.cursor/rules/project-rules.mdc +1 -0
  4. package/.npmrc.token +1 -0
  5. package/.temp/jest-protection-convert/run-IFN2nv/.protection/hubspot-companies.json +1 -0
  6. package/.temp/jest-protection-convert/run-IvmKLO/.protection/hubspot-companies.yaml +17 -0
  7. package/.temp/jest-protection-convert/run-SdvblF/.protection/hubspot-companies.json +1 -0
  8. package/.temp/jest-protection-convert/run-b51TsW/.protection/hubspot-companies.json +1 -0
  9. package/.temp/jest-protection-convert/run-fiLmb1/.protection/hubspot-companies.json +1 -0
  10. package/.temp/jest-protection-convert/run-qYGHMU/.protection/hubspot-companies.yaml +17 -0
  11. package/.temp/jest-protection-fixtures/hubspot-Mq5re8/hubspot-companies.yaml +17 -0
  12. package/.temp/jest-protection-fixtures/hubspot-f3u4YL/hubspot-companies.yaml +17 -0
  13. package/.temp/jest-protection-fixtures/hubspot-iQtd1O/hubspot-companies.yaml +17 -0
  14. package/.temp/jest-protection-fixtures/hubspot-mdmz5M/hubspot-companies.yaml +17 -0
  15. package/.temp/jest-protection-fixtures/hubspot-qbKYxQ/hubspot-companies.yaml +17 -0
  16. package/.temp/jest-protection-fixtures/hubspot-yzlJy6/hubspot-companies.yaml +17 -0
  17. package/.temp/validation/summary.txt +5 -0
  18. package/README.md +43 -17
  19. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
  20. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
  21. package/jest.config.default.js +2 -1
  22. package/jest.config.isolated.js +2 -1
  23. package/jest.global-live-fabrix-hooks.js +36 -0
  24. package/jest.isolated-projects.js +146 -0
  25. package/jest.projects.js +65 -136
  26. package/lib/api/api-response-errors.js +124 -0
  27. package/lib/api/dataplane-health.api.js +19 -7
  28. package/lib/api/governance-scenario-pack.api.js +159 -0
  29. package/lib/api/index.js +43 -3
  30. package/lib/api/lifecycle.api.js +98 -0
  31. package/lib/api/pipeline.api.js +3 -1
  32. package/lib/api/records-bulk.api.js +14 -1
  33. package/lib/api/resource-types.api.js +107 -0
  34. package/lib/api/runtime-configuration.api.js +72 -0
  35. package/lib/api/types/resource-types.types.js +45 -0
  36. package/lib/api/user-groups.api.js +9 -9
  37. package/lib/api/users.api.js +8 -8
  38. package/lib/api/validation-runner.js +3 -1
  39. package/lib/api/wizard.api.js +10 -2
  40. package/lib/app/deploy-config.js +4 -1
  41. package/lib/app/down.js +78 -27
  42. package/lib/app/index.js +2 -2
  43. package/lib/app/push.js +4 -5
  44. package/lib/app/register.js +7 -4
  45. package/lib/app/run-env-compose.js +84 -30
  46. package/lib/app/run-resolve-image.js +2 -1
  47. package/lib/app/run-stop-containers.js +113 -0
  48. package/lib/app/run.js +1 -31
  49. package/lib/app/show-display.js +35 -0
  50. package/lib/app/show.js +32 -1
  51. package/lib/build/index.js +22 -5
  52. package/lib/build/miso-controller-npm-sdk-guard.js +25 -0
  53. package/lib/certification/sync-system-certification.js +13 -6
  54. package/lib/channels/add-channel.js +348 -0
  55. package/lib/channels/channel-artifact-generator.js +141 -0
  56. package/lib/channels/channel-audit.js +101 -0
  57. package/lib/channels/channel-auth-context.js +37 -0
  58. package/lib/channels/channel-credential.js +200 -0
  59. package/lib/channels/channel-display-name.js +64 -0
  60. package/lib/channels/channel-external-system.js +106 -0
  61. package/lib/channels/channel-integration-generator.js +274 -0
  62. package/lib/channels/channel-probe.js +89 -0
  63. package/lib/channels/channel-runtime-resolver.js +152 -0
  64. package/lib/channels/channel-status-display.js +141 -0
  65. package/lib/channels/channel-targets.js +115 -0
  66. package/lib/cli/index.js +20 -4
  67. package/lib/cli/infra-guided-auth.js +109 -0
  68. package/lib/cli/infra-guided.js +84 -81
  69. package/lib/cli/setup-app.help.js +0 -31
  70. package/lib/cli/setup-app.js +82 -5
  71. package/lib/cli/setup-app.test-commands.js +5 -57
  72. package/lib/cli/setup-auth.js +25 -0
  73. package/lib/cli/setup-certification-commands.js +147 -0
  74. package/lib/cli/setup-certification.help.js +141 -0
  75. package/lib/cli/setup-environment.js +19 -2
  76. package/lib/cli/setup-external-system-help.js +62 -0
  77. package/lib/cli/setup-external-system.js +25 -3
  78. package/lib/cli/setup-infra-up-dataplane-action.js +2 -2
  79. package/lib/cli/setup-infra-up-platform-action.js +2 -1
  80. package/lib/cli/setup-infra.js +9 -1
  81. package/lib/cli/setup-platform.js +6 -1
  82. package/lib/cli/setup-secrets.js +33 -1
  83. package/lib/cli/setup-utility-help-after.js +25 -2
  84. package/lib/cli/setup-utility-repair.js +198 -0
  85. package/lib/cli/setup-utility-resolve.js +44 -5
  86. package/lib/cli/setup-utility-validate.js +197 -0
  87. package/lib/cli/setup-utility.js +4 -239
  88. package/lib/commands/app-logs.js +54 -26
  89. package/lib/commands/app.js +41 -0
  90. package/lib/commands/auth-status-client-tokens.js +214 -0
  91. package/lib/commands/auth-status-dataplane-version.js +142 -68
  92. package/lib/commands/auth-status.js +43 -54
  93. package/lib/commands/channel.js +58 -0
  94. package/lib/commands/datasource-test-trust-cli.js +27 -23
  95. package/lib/commands/datasource-unified-test-cli.js +6 -3
  96. package/lib/commands/datasource-unified-test-cli.options.js +5 -1
  97. package/lib/commands/datasource.js +8 -8
  98. package/lib/commands/dev-show-display.js +8 -1
  99. package/lib/commands/governance-cli-shared.js +94 -0
  100. package/lib/commands/governance-command-action.js +132 -0
  101. package/lib/commands/governance-download-external.js +34 -0
  102. package/lib/commands/governance-generate-external.js +71 -0
  103. package/lib/commands/governance-upload-external.js +36 -0
  104. package/lib/commands/governance-verify-external.js +64 -0
  105. package/lib/commands/governance.js +144 -0
  106. package/lib/commands/identity-apply-sync.js +49 -8
  107. package/lib/commands/identity-group-cli.js +66 -26
  108. package/lib/commands/identity-membership-role-cache.js +58 -37
  109. package/lib/commands/identity-shared.js +22 -1
  110. package/lib/commands/identity-user-cli.js +80 -34
  111. package/lib/commands/lifecycle-command-action.js +123 -0
  112. package/lib/commands/lifecycle-external.js +268 -0
  113. package/lib/commands/login.js +11 -2
  114. package/lib/commands/repair-auth-apply.js +153 -0
  115. package/lib/commands/repair-auth-config.js +8 -13
  116. package/lib/commands/repair-changed-files.js +41 -0
  117. package/lib/commands/repair-datasource-com-v2.js +15 -0
  118. package/lib/commands/repair-datasource-keys.js +4 -1
  119. package/lib/commands/repair-datasource-run.js +59 -0
  120. package/lib/commands/repair-datasource-service-contract.js +206 -0
  121. package/lib/commands/repair-datasource-test-payload.js +259 -0
  122. package/lib/commands/repair-datasource.js +49 -64
  123. package/lib/commands/repair-env-template.js +76 -25
  124. package/lib/commands/repair-external-run.js +216 -0
  125. package/lib/commands/repair-openapi-sync.js +49 -4
  126. package/lib/commands/repair-persist.js +4 -0
  127. package/lib/commands/repair-rbac.js +52 -1
  128. package/lib/commands/repair-steps.js +160 -0
  129. package/lib/commands/repair-system-alignment.js +7 -4
  130. package/lib/commands/repair.js +29 -296
  131. package/lib/commands/resource-type.js +371 -0
  132. package/lib/commands/secrets-get.js +184 -0
  133. package/lib/commands/secrets-remove-all.js +3 -1
  134. package/lib/commands/setup-image-refresh.js +146 -0
  135. package/lib/commands/setup-modes.js +158 -162
  136. package/lib/commands/setup-platform-auth.js +76 -0
  137. package/lib/commands/setup-prompts-admin.js +244 -0
  138. package/lib/commands/setup-prompts-platform-mode.js +70 -0
  139. package/lib/commands/setup-prompts-validators.js +36 -0
  140. package/lib/commands/setup-prompts.js +24 -76
  141. package/lib/commands/setup-run-context.js +45 -0
  142. package/lib/commands/setup-spinners.js +39 -0
  143. package/lib/commands/setup.js +27 -5
  144. package/lib/commands/teardown.js +39 -0
  145. package/lib/commands/test-e2e-external.js +24 -8
  146. package/lib/commands/test-governance-external.js +3 -24
  147. package/lib/commands/test-trust-external.js +48 -100
  148. package/lib/commands/up-common.js +57 -13
  149. package/lib/commands/up-dataplane.js +56 -15
  150. package/lib/commands/upload-publish-context.js +75 -0
  151. package/lib/commands/upload-sidecar-followups.js +89 -0
  152. package/lib/commands/upload.js +113 -110
  153. package/lib/commands/verify-governance-combined-external.js +61 -0
  154. package/lib/commands/verify-governance-command-action.js +64 -0
  155. package/lib/commands/verify-governance-db.js +102 -0
  156. package/lib/commands/verify-governance-external.js +77 -0
  157. package/lib/commands/verify-governance-result-builders.js +71 -0
  158. package/lib/commands/verify-operations-command-action.js +68 -0
  159. package/lib/commands/verify-operations-external.js +268 -0
  160. package/lib/commands/verify-operations-persist.js +75 -0
  161. package/lib/commands/verify-operations-step-plan.js +68 -0
  162. package/lib/commands/verify-operations-steps.js +111 -0
  163. package/lib/commands/verify-trust-command-action.js +73 -0
  164. package/lib/commands/verify-trust-external.js +59 -0
  165. package/lib/commands/wizard-config-normalizer.js +43 -23
  166. package/lib/commands/wizard-core.js +2 -0
  167. package/lib/core/admin-password-generator.js +38 -0
  168. package/lib/core/admin-secrets-bundle.js +111 -0
  169. package/lib/core/admin-secrets-env-overlay.js +62 -0
  170. package/lib/core/admin-secrets.js +32 -4
  171. package/lib/core/config-attach-extensions.js +3 -0
  172. package/lib/core/config-platform-controller.js +44 -0
  173. package/lib/core/config-setup-installation-profile.js +42 -0
  174. package/lib/core/config-setup-platform-mode.js +46 -0
  175. package/lib/core/config.js +46 -36
  176. package/lib/core/secrets-admin-env.js +6 -2
  177. package/lib/core/secrets-ensure.js +4 -0
  178. package/lib/core/secrets-env-content.js +54 -48
  179. package/lib/core/secrets-env-write.js +10 -1
  180. package/lib/core/secrets-infra-placeholder-sync.js +2 -0
  181. package/lib/core/setup-installation-profile.js +43 -0
  182. package/lib/core/setup-platform-mode.js +90 -0
  183. package/lib/datasource/agent-trust-debug-log.js +1 -1
  184. package/lib/datasource/agent-trust-run.js +5 -3
  185. package/lib/datasource/audit-evidence-extract-debug.js +30 -18
  186. package/lib/datasource/audit-evidence-extract.js +7 -4
  187. package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
  188. package/lib/datasource/bulk-loader-run-batches.js +15 -3
  189. package/lib/datasource/capability/capability-diff-slice.js +2 -2
  190. package/lib/datasource/capability/capability-manifest.js +254 -0
  191. package/lib/datasource/capability/capability-resolve.js +3 -4
  192. package/lib/datasource/capability/copy-operations.js +5 -3
  193. package/lib/datasource/capability/remove-operations.js +2 -1
  194. package/lib/datasource/capability/run-capability-copy.js +32 -4
  195. package/lib/datasource/capability/run-capability-diff.js +3 -3
  196. package/lib/datasource/capability/run-capability-dimension.js +2 -4
  197. package/lib/datasource/capability/run-capability-edit.js +4 -7
  198. package/lib/datasource/capability/run-capability-relate.js +2 -4
  199. package/lib/datasource/capability/run-capability-remove.js +2 -4
  200. package/lib/datasource/capability/validate-capability-slice.js +2 -1
  201. package/lib/datasource/datasource-identifier.js +2 -1
  202. package/lib/datasource/datasource-load-export-context.js +3 -0
  203. package/lib/datasource/datasource-validate-display.js +1 -1
  204. package/lib/datasource/field-reference-validator.js +24 -3
  205. package/lib/datasource/log-cleaner.js +2 -2
  206. package/lib/datasource/log-viewer.js +8 -8
  207. package/lib/datasource/orphan-profiles-validator.js +98 -0
  208. package/lib/datasource/test-e2e.js +4 -1
  209. package/lib/datasource/unified-validation-run-body.js +3 -1
  210. package/lib/datasource/unified-validation-run.js +5 -2
  211. package/lib/datasource/validate.js +41 -23
  212. package/lib/deployment/environment-poll-status.js +138 -0
  213. package/lib/deployment/environment.js +42 -34
  214. package/lib/external-system/download-helpers.js +87 -0
  215. package/lib/external-system/download.js +78 -138
  216. package/lib/external-system/generator.js +1 -55
  217. package/lib/external-system/integration-auth-context.js +45 -0
  218. package/lib/external-system/test-auth.js +12 -5
  219. package/lib/external-system/test.js +16 -21
  220. package/lib/generator/builders.js +11 -1
  221. package/lib/generator/external-controller-manifest.js +18 -0
  222. package/lib/generator/split.js +3 -1
  223. package/lib/generator/wizard.js +1 -28
  224. package/lib/governance/governance-cli-errors.js +96 -0
  225. package/lib/governance/governance-download-display.js +38 -0
  226. package/lib/governance/governance-run-display.js +215 -25
  227. package/lib/identity/fk-reference.js +65 -0
  228. package/lib/identity/identity-apply-core.js +13 -58
  229. package/lib/identity/identity-apply-phases.js +5 -1
  230. package/lib/identity/identity-display.js +243 -0
  231. package/lib/identity/identity-response-helpers.js +52 -0
  232. package/lib/identity/identity-sync-errors.js +62 -0
  233. package/lib/identity/resolve-user-id.js +129 -0
  234. package/lib/identity/username-default.js +31 -0
  235. package/lib/infrastructure/admin-secrets-apply.js +84 -0
  236. package/lib/infrastructure/admin-secrets-ensure.js +130 -0
  237. package/lib/infrastructure/admin-secrets-resolve.js +95 -0
  238. package/lib/infrastructure/admin-secrets-sync.js +91 -0
  239. package/lib/infrastructure/helpers.js +23 -129
  240. package/lib/infrastructure/index.js +5 -6
  241. package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
  242. package/lib/lifecycle/certification-progress.js +231 -0
  243. package/lib/lifecycle/dataplane-ui-url.js +145 -0
  244. package/lib/lifecycle/exit-codes.js +24 -0
  245. package/lib/lifecycle/json-envelope.js +25 -0
  246. package/lib/lifecycle/lifecycle-governance-options.js +51 -0
  247. package/lib/lifecycle/logger-quiet.js +29 -0
  248. package/lib/lifecycle/open-api-published.js +59 -0
  249. package/lib/lifecycle/operations-readiness-metrics.js +101 -0
  250. package/lib/lifecycle/product-model.js +196 -0
  251. package/lib/lifecycle/report-display-trust.js +70 -0
  252. package/lib/lifecycle/report-display.js +472 -0
  253. package/lib/lifecycle/scenario-upload.js +191 -0
  254. package/lib/lifecycle/verify-step-progress.js +87 -0
  255. package/lib/parameters/infra-kv-discovery.js +27 -2
  256. package/lib/protection/auth-context.js +10 -4
  257. package/lib/resolvers/datasource-resolver.js +2 -3
  258. package/lib/resolvers/resource-type-file.js +159 -0
  259. package/lib/schema/application-schema.json +17 -1
  260. package/lib/schema/datasource-test-run.schema.json +89 -6
  261. package/lib/schema/deployment-rules.yaml +2 -1
  262. package/lib/schema/external-datasource.schema.json +2947 -2619
  263. package/lib/schema/external-system.schema.json +1418 -761
  264. package/lib/schema/infra.parameter.yaml +45 -0
  265. package/lib/schema/type/credential-field-registry.json +103 -97
  266. package/lib/schema/type/document-storage.json +9 -5
  267. package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
  268. package/lib/utils/api.js +55 -31
  269. package/lib/utils/app-relative-path-env.js +112 -0
  270. package/lib/utils/app-run-containers.js +25 -2
  271. package/lib/utils/authentication-shape.js +224 -0
  272. package/lib/utils/build-copy.js +36 -5
  273. package/lib/utils/build-resolve-image.js +66 -12
  274. package/lib/utils/celery-companion-apps.js +53 -0
  275. package/lib/utils/cli-secrets-error-format.js +83 -21
  276. package/lib/utils/cli-utils.js +20 -4
  277. package/lib/utils/compose-celery-worker.js +23 -0
  278. package/lib/utils/compose-generate-docker-compose.js +13 -1
  279. package/lib/utils/compose-traefik-ingress-base.js +16 -1
  280. package/lib/utils/config-secrets-path.js +46 -0
  281. package/lib/utils/configuration-env-resolver.js +36 -0
  282. package/lib/utils/controller-url.js +88 -1
  283. package/lib/utils/credential-secrets-env-kv.js +216 -0
  284. package/lib/utils/credential-secrets-env.js +175 -257
  285. package/lib/utils/dataplane-resolver.js +18 -2
  286. package/lib/utils/declarative-url-ports.js +27 -4
  287. package/lib/utils/deployment-auth-mode.js +41 -0
  288. package/lib/utils/developer-volume-id.js +33 -0
  289. package/lib/utils/docker-build.js +1 -4
  290. package/lib/utils/env-copy.js +14 -9
  291. package/lib/utils/env-kv-orphan-lines.js +43 -0
  292. package/lib/utils/error-formatters/network-errors.js +13 -4
  293. package/lib/utils/external-env-template.js +11 -3
  294. package/lib/utils/external-system-readiness-core.js +10 -0
  295. package/lib/utils/external-system-readiness-display.js +80 -23
  296. package/lib/utils/external-system-validators.js +8 -2
  297. package/lib/utils/health-check.js +4 -1
  298. package/lib/utils/help-builder.js +13 -8
  299. package/lib/utils/keycloak-realm-ready.js +101 -0
  300. package/lib/utils/load-cip-capacity-display-config.js +61 -15
  301. package/lib/utils/manifest-source-emit.js +2 -0
  302. package/lib/utils/paths.js +25 -0
  303. package/lib/utils/pipeline-upload-auth-retry.js +82 -0
  304. package/lib/utils/platform-controller-url.js +157 -0
  305. package/lib/utils/platform-kv-ref.js +57 -0
  306. package/lib/utils/postgres-platform-bootstrap.js +199 -0
  307. package/lib/utils/postgres-wipe.js +9 -2
  308. package/lib/utils/resolve-env-mode.js +47 -0
  309. package/lib/utils/runtime-configuration-download.js +189 -0
  310. package/lib/utils/runtime-configuration-values.js +119 -0
  311. package/lib/utils/schema-loader.js +19 -4
  312. package/lib/utils/secrets-generator.js +31 -25
  313. package/lib/utils/secrets-missing-error.js +164 -0
  314. package/lib/utils/service-url-label.js +81 -0
  315. package/lib/utils/setup-quiet-output.js +25 -0
  316. package/lib/utils/template-helpers.js +15 -0
  317. package/lib/utils/token-manager-client-credentials.js +201 -0
  318. package/lib/utils/token-manager-messages.js +8 -0
  319. package/lib/utils/token-manager-refresh.js +12 -2
  320. package/lib/utils/token-manager.js +86 -105
  321. package/lib/utils/upload-pipeline-ui.js +12 -5
  322. package/lib/utils/upload-sync-options.js +42 -0
  323. package/lib/utils/url-declarative-public-base.js +21 -3
  324. package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
  325. package/lib/utils/validation-poll-ui.js +8 -0
  326. package/lib/utils/validation-run-stage.js +45 -0
  327. package/lib/utils/worker-sidecars.js +142 -0
  328. package/lib/validation/external-manifest-validator.js +2 -0
  329. package/lib/validation/runtime-configuration-rules.js +98 -0
  330. package/lib/validation/validate-display-dimensions.js +154 -0
  331. package/lib/validation/validate-display-sections.js +276 -0
  332. package/lib/validation/validate-display-steps.js +67 -0
  333. package/lib/validation/validate-display.js +24 -402
  334. package/package.json +1 -1
  335. package/templates/applications/dataplane/application.yaml +7 -1
  336. package/templates/applications/dataplane/env.template +50 -14
  337. package/templates/applications/dataplane/rbac.yaml +108 -1
  338. package/templates/applications/miso-controller/application.yaml +2 -2
  339. package/templates/applications/miso-controller/env.template +53 -122
  340. package/templates/applications/miso-controller/rbac.yaml +28 -13
  341. package/templates/channels/chatgpt/install.template.md.hbs +49 -0
  342. package/templates/channels/chatgpt/manifest.template.json.hbs +9 -0
  343. package/templates/channels/microsoft-copilot/install.template.md.hbs +49 -0
  344. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +8 -0
  345. package/templates/channels/slack/install.template.md.hbs +49 -0
  346. package/templates/channels/slack/manifest.template.json.hbs +66 -0
  347. package/templates/channels/teams-bot/install.template.md.hbs +49 -0
  348. package/templates/channels/teams-bot/manifest.template.json.hbs +13 -0
  349. package/templates/channels/web-embed/install.template.md.hbs +49 -0
  350. package/templates/channels/web-embed/manifest.template.json.hbs +8 -0
  351. package/templates/external-system/README.md.hbs +74 -17
  352. package/templates/python/docker-compose.hbs +75 -18
  353. package/templates/typescript/docker-compose.hbs +70 -17
  354. package/lib/commands/test-governance-command-action.js +0 -55
  355. package/lib/commands/test-trust-command-action.js +0 -118
package/jest.projects.js CHANGED
@@ -4,6 +4,9 @@
4
4
  * @fileoverview
5
5
  */
6
6
 
7
+ const { globalLiveFabrixHooks } = require('./jest.global-live-fabrix-hooks');
8
+ const { buildIsolatedProjects } = require('./jest.isolated-projects');
9
+
7
10
  // Detect CI environment (GitHub Actions, CI simulation, etc.)
8
11
  const isCI = process.env.CI === 'true' || process.env.CI_SIMULATION === 'true';
9
12
 
@@ -31,7 +34,7 @@ function makeIsolatedProject(displayName, testMatch) {
31
34
  testPathIgnorePatterns: ['/node_modules/', '\\\\node_modules\\\\'],
32
35
  setupFiles: ['<rootDir>/tests/capture-real-fs.js'],
33
36
  setupFilesAfterEnv: ['<rootDir>/tests/setup.js'],
34
- testTimeout: isCI ? 10000 : 5000,
37
+ testTimeout: isCI ? 15000 : 8000,
35
38
  maxWorkers: 1
36
39
  };
37
40
  }
@@ -79,10 +82,18 @@ const defaultProject = {
79
82
  'lib/datasource/log-viewer-structural.test.js',
80
83
  'lib/datasource/log-viewer-run.test.js',
81
84
  'log-viewer-run\\.test\\.js',
85
+ '/tests/lib/datasource/audit-evidence-extract.test.js',
86
+ '\\\\tests\\\\lib\\\\datasource\\\\audit-evidence-extract.test.js',
87
+ 'lib/datasource/audit-evidence-extract.test.js',
88
+ 'audit-evidence-extract\\.test\\.js',
82
89
  '/tests/lib/commands/parameters-validate.test.js',
83
90
  '\\\\tests\\\\lib\\\\commands\\\\parameters-validate.test.js',
84
91
  'lib/commands/parameters-validate.test.js',
85
92
  'parameters-validate\\.test\\.js',
93
+ '/tests/lib/commands/test-e2e-external.test.js',
94
+ '\\\\tests\\\\lib\\\\commands\\\\test-e2e-external.test.js',
95
+ 'lib/commands/test-e2e-external.test.js',
96
+ 'test-e2e-external\\.test\\.js',
86
97
  '/tests/lib/commands/repair-openapi-sync.test.js',
87
98
  '\\\\tests\\\\lib\\\\commands\\\\repair-openapi-sync.test.js',
88
99
  'lib/commands/repair-openapi-sync.test.js',
@@ -105,6 +116,10 @@ const defaultProject = {
105
116
  '\\\\tests\\\\lib\\\\parameters\\\\infra-parameter-catalog.test.js',
106
117
  'lib/parameters/infra-parameter-catalog.test.js',
107
118
  'infra-parameter-catalog\\.test\\.js',
119
+ '/tests/lib/utils/platform-kv-ref.test.js',
120
+ '\\\\tests\\\\lib\\\\utils\\\\platform-kv-ref.test.js',
121
+ 'lib/utils/platform-kv-ref.test.js',
122
+ 'platform-kv-ref\\.test\\.js',
108
123
  '/tests/lib/utils/urls-local-registry.test.js',
109
124
  '\\\\tests\\\\lib\\\\utils\\\\urls-local-registry.test.js',
110
125
  'lib/utils/urls-local-registry.test.js',
@@ -221,10 +236,6 @@ const defaultProject = {
221
236
  '\\\\tests\\\\lib\\\\utils\\\\secrets-generator.test.js',
222
237
  'lib/utils/secrets-generator.test.js',
223
238
  'secrets-generator\\.test\\.js',
224
- '/tests/lib/app/app-uncovered-lines.test.js',
225
- '\\\\tests\\\\lib\\\\app\\\\app-uncovered-lines.test.js',
226
- 'lib/app/app-uncovered-lines.test.js',
227
- 'app-uncovered-lines\\.test\\.js',
228
239
  '/tests/lib/utils/ensure-dev-certs-for-remote-docker.test.js',
229
240
  '\\\\tests\\\\lib\\\\utils\\\\ensure-dev-certs-for-remote-docker.test.js',
230
241
  'lib/utils/ensure-dev-certs-for-remote-docker.test.js',
@@ -245,6 +256,14 @@ const defaultProject = {
245
256
  '\\\\tests\\\\lib\\\\validation\\\\schema-241-alignment.test.js',
246
257
  'lib/validation/schema-241-alignment.test.js',
247
258
  'schema-241-alignment\\.test\\.js',
259
+ '/tests/lib/validation/hubspot-e2e-com-v2.test.js',
260
+ '\\\\tests\\\\lib\\\\validation\\\\hubspot-e2e-com-v2.test.js',
261
+ 'lib/validation/hubspot-e2e-com-v2.test.js',
262
+ 'hubspot-e2e-com-v2\\.test\\.js',
263
+ '/tests/lib/utils/runtime-configuration-download.test.js',
264
+ '\\\\tests\\\\lib\\\\utils\\\\runtime-configuration-download.test.js',
265
+ 'lib/utils/runtime-configuration-download.test.js',
266
+ 'runtime-configuration-download\\.test\\.js',
248
267
  '/tests/lib/utils/schema-resolver-order.test.js',
249
268
  '\\\\tests\\\\lib\\\\utils\\\\schema-resolver-order.test.js',
250
269
  'lib/utils/schema-resolver-order.test.js',
@@ -303,10 +322,46 @@ const defaultProject = {
303
322
  '\\\\tests\\\\lib\\\\governance\\\\governance-pack-loader.test.js',
304
323
  'lib/governance/governance-pack-loader.test.js',
305
324
  'governance-pack-loader\\.test\\.js',
325
+ '/tests/lib/lifecycle/scenario-upload.test.js',
326
+ '\\\\tests\\\\lib\\\\lifecycle\\\\scenario-upload.test.js',
327
+ 'lib/lifecycle/scenario-upload.test.js',
328
+ 'scenario-upload\\.test\\.js',
329
+ '/tests/lib/commands/governance-generate-external.test.js',
330
+ '\\\\tests\\\\lib\\\\commands\\\\governance-generate-external.test.js',
331
+ 'lib/commands/governance-generate-external.test.js',
332
+ 'governance-generate-external\\.test\\.js',
306
333
  '/tests/lib/protection/validate-batch.test.js',
307
334
  '\\\\tests\\\\lib\\\\protection\\\\validate-batch.test.js',
308
335
  'lib/protection/validate-batch.test.js',
309
- 'validate-batch\\.test\\.js'
336
+ 'validate-batch\\.test\\.js',
337
+ '/tests/helpers/aifabrix-runtime-sandbox.test.js',
338
+ '\\\\tests\\\\helpers\\\\aifabrix-runtime-sandbox.test.js',
339
+ 'helpers/aifabrix-runtime-sandbox\\.test\\.js',
340
+ '/tests/helpers/aifabrix-runtime-backup.test.js',
341
+ '\\\\tests\\\\helpers\\\\aifabrix-runtime-backup.test.js',
342
+ 'helpers/aifabrix-runtime-backup\\.test\\.js',
343
+ '/tests/lib/utils/paths-jest-sandbox-integration.test.js',
344
+ '\\\\tests\\\\lib\\\\utils\\\\paths-jest-sandbox-integration.test.js',
345
+ 'paths-jest-sandbox-integration\\.test\\.js',
346
+ '/tests/lib/commands/secrets-remove-all-guard.test.js',
347
+ '\\\\tests\\\\lib\\\\commands\\\\secrets-remove-all-guard.test.js',
348
+ 'lib/commands/secrets-remove-all-guard.test.js',
349
+ 'secrets-remove-all-guard\\.test\\.js',
350
+ '/tests/lib/commands/app-logs.test.js',
351
+ '\\\\tests\\\\lib\\\\commands\\\\app-logs.test.js',
352
+ 'lib/commands/app-logs.test.js',
353
+ 'app-logs\\.test\\.js',
354
+ '/tests/lib/channels/channel-integration-generator.test.js',
355
+ '\\\\tests\\\\lib\\\\channels\\\\channel-integration-generator.test.js',
356
+ 'lib/channels/channel-integration-generator.test.js',
357
+ 'channel-integration-generator\\.test\\.js',
358
+ '/tests/lib/channels/channel-artifact-generator.test.js',
359
+ '\\\\tests\\\\lib\\\\channels\\\\channel-artifact-generator.test.js',
360
+ 'lib/channels/channel-artifact-generator.test.js',
361
+ 'channel-artifact-generator\\.test\\.js',
362
+ '/tests/setup-ci-live-fabrix-guard.test.js',
363
+ '\\\\tests\\\\setup-ci-live-fabrix-guard.test.js',
364
+ 'setup-ci-live-fabrix-guard\\.test\\.js'
310
365
  ];
311
366
  if (process.env.INCLUDE_LOCAL_TESTS !== 'true') {
312
367
  patterns.push('/tests/local/');
@@ -316,139 +371,12 @@ const defaultProject = {
316
371
  })(),
317
372
  setupFiles: ['<rootDir>/tests/capture-real-fs.js'],
318
373
  setupFilesAfterEnv: ['<rootDir>/tests/setup.js'],
319
- testTimeout: isCI ? 10000 : 5000,
374
+ testTimeout: isCI ? 15000 : 8000,
320
375
  detectOpenHandles: true,
321
376
  maxWorkers: 1
322
377
  };
323
378
 
324
- const isolatedProjects = [
325
- makeIsolatedProject('cli-utils', ['**/tests/lib/utils/cli-utils.test.js']),
326
- makeIsolatedProject('external-system-display', ['**/tests/lib/utils/external-system-display.test.js']),
327
- makeIsolatedProject('dev-hosts-helper', ['**/tests/lib/utils/dev-hosts-helper.test.js']),
328
- makeIsolatedProject('parameters-validate', ['**/tests/lib/commands/parameters-validate.test.js']),
329
- makeIsolatedProject('repair-openapi-sync', ['**/tests/lib/commands/repair-openapi-sync.test.js']),
330
- makeIsolatedProject('paths-app-listing', ['**/tests/lib/utils/paths-app-listing.test.js']),
331
- makeIsolatedProject('paths-system-builder-resolution', [
332
- '**/tests/lib/utils/paths-system-builder-resolution.test.js'
333
- ]),
334
- makeIsolatedProject('manifest-location', ['**/tests/lib/utils/manifest-location.test.js']),
335
- makeIsolatedProject('installation-log', ['**/tests/lib/utils/installation-log.test.js']),
336
- makeIsolatedProject('secrets-ancestor-paths', ['**/tests/lib/utils/secrets-ancestor-paths.test.js']),
337
- makeIsolatedProject('datasource-validation-watch', [
338
- '**/tests/lib/utils/datasource-validation-watch.test.js'
339
- ]),
340
- makeIsolatedProject('log-viewer', [
341
- '**/tests/lib/datasource/log-viewer.test.js',
342
- '**/tests/lib/datasource/log-viewer-structural.test.js',
343
- '**/tests/lib/datasource/log-viewer-run.test.js'
344
- ]),
345
- makeIsolatedProject('manifest-source-emit', ['**/tests/lib/utils/manifest-source-emit.test.js']),
346
- makeIsolatedProject('register-aifabrix-shell-env', [
347
- '**/tests/lib/utils/register-aifabrix-shell-env.test.js'
348
- ]),
349
- makeIsolatedProject('datasource-test-run-schema-sync', [
350
- '**/tests/lib/utils/datasource-test-run-schema-sync.test.js'
351
- ]),
352
- makeIsolatedProject('infra-platform-contract', [
353
- '**/tests/lib/parameters/infra-platform-contract.test.js'
354
- ]),
355
- makeIsolatedProject('application-frontdoor-paths-contract', [
356
- '**/tests/lib/templates/application-frontdoor-paths.contract.test.js'
357
- ]),
358
- makeIsolatedProject('database-secret-values', [
359
- '**/tests/lib/parameters/database-secret-values.test.js'
360
- ]),
361
- makeIsolatedProject('infra-parameter-validate', [
362
- '**/tests/lib/parameters/infra-parameter-validate.test.js'
363
- ]),
364
- makeIsolatedProject('infra-parameter-catalog', [
365
- '**/tests/lib/parameters/infra-parameter-catalog.test.js'
366
- ]),
367
- makeIsolatedProject('urls-local-registry', ['**/tests/lib/utils/urls-local-registry.test.js']),
368
- makeIsolatedProject('aifabrix-runtime-config-dir', [
369
- '**/tests/lib/utils/aifabrix-runtime-config-dir.test.js'
370
- ]),
371
- makeIsolatedProject('platform-env-template-kv-catalog', [
372
- '**/tests/lib/parameters/platform-env-template-kv-catalog.test.js'
373
- ]),
374
- makeIsolatedProject('resolve-infra-state-paths', [
375
- '**/tests/lib/infrastructure/resolve-infra-state-paths.test.js'
376
- ]),
377
- makeIsolatedProject('dev-ssh-config-helper', [
378
- '**/tests/lib/utils/dev-ssh-config-helper.test.js'
379
- ]),
380
- makeIsolatedProject('ssh-key-helper', ['**/tests/lib/utils/ssh-key-helper.test.js']),
381
- makeIsolatedProject('secrets-ensure-catalog-fallback', [
382
- '**/tests/lib/core/secrets-ensure-catalog-fallback.test.js'
383
- ]),
384
- makeIsolatedProject('secrets-ensure', ['**/tests/lib/core/secrets-ensure.test.js']),
385
- makeIsolatedProject('url-declarative-vdir-inactive-env', [
386
- '**/tests/lib/utils/url-declarative-vdir-inactive-env.test.js'
387
- ]),
388
- makeIsolatedProject('url-declarative-user-cfg-per-app-proxy', [
389
- '**/tests/lib/utils/url-declarative-user-cfg-per-app-proxy.test.js'
390
- ]),
391
- makeIsolatedProject('declarative-url-paths-spy-suites', [
392
- '**/tests/lib/utils/url-declarative-expand-traefik-off-no-usercfg.test.js',
393
- '**/tests/lib/core/secrets-env-declarative-show-urls.test.js',
394
- '**/tests/lib/utils/url-declarative-registry-internal-docker-origin.test.js'
395
- ]),
396
- makeIsolatedProject('platform-urls-registry-validation', [
397
- '**/tests/lib/commands/platform-urls-registry.validation.test.js'
398
- ]),
399
- makeIsolatedProject('env-copy-resolve-output', ['**/tests/lib/utils/env-copy-resolve-output.test.js']),
400
- makeIsolatedProject('write-env-output-reload', ['**/tests/lib/utils/write-env-output-reload.test.js']),
401
- makeIsolatedProject('app-service-env-from-builder', [
402
- '**/tests/lib/utils/app-service-env-from-builder.test.js'
403
- ]),
404
- makeIsolatedProject('infra-kv-discovery', ['**/tests/lib/parameters/infra-kv-discovery.test.js']),
405
- makeIsolatedProject('infra-env-defaults', ['**/tests/lib/utils/infra-env-defaults.test.js']),
406
- makeIsolatedProject('compose-traefik-template', [
407
- '**/tests/lib/infrastructure/compose-traefik-template.test.js'
408
- ]),
409
- makeIsolatedProject('generator-external-rbac', [
410
- '**/tests/lib/generator/generator-external-rbac.test.js'
411
- ]),
412
- makeIsolatedProject('helpers-ensure-admin-secrets', [
413
- '**/tests/lib/infrastructure/helpers-ensure-admin-secrets.test.js'
414
- ]),
415
- makeIsolatedProject('secrets-generator', ['**/tests/lib/utils/secrets-generator.test.js']),
416
- makeIsolatedProject('app-uncovered-lines', ['**/tests/lib/app/app-uncovered-lines.test.js']),
417
- makeIsolatedProject('ensure-dev-certs-for-remote-docker', [
418
- '**/tests/lib/utils/ensure-dev-certs-for-remote-docker.test.js'
419
- ]),
420
- makeIsolatedProject('generator-error-paths', ['**/tests/lib/generator/generator-error-paths.test.js']),
421
- makeIsolatedProject('generator-validation', ['**/tests/lib/generator/generator-validation.test.js']),
422
- makeIsolatedProject('secrets-databaselog', ['**/tests/lib/core/secrets-databaselog.test.js']),
423
- makeIsolatedProject('schema-241-alignment', ['**/tests/lib/validation/schema-241-alignment.test.js']),
424
- makeIsolatedProject('schema-resolver-order', ['**/tests/lib/utils/schema-resolver-order.test.js']),
425
- makeIsolatedProject('app-module', ['**/tests/lib/app/app.test.js']),
426
- makeIsolatedProject('admin-secrets', ['**/tests/lib/core/admin-secrets.test.js']),
427
- makeIsolatedProject('validate-datasource-parsed', [
428
- '**/tests/lib/datasource/validate-datasource-parsed.test.js'
429
- ]),
430
- makeIsolatedProject('capability-run-real-fs', [
431
- '**/tests/lib/datasource/run-capability-copy.test.js',
432
- '**/tests/lib/datasource/run-capability-diff.test.js',
433
- '**/tests/lib/datasource/run-capability-edit.test.js',
434
- '**/tests/lib/datasource/run-capability-remove.test.js'
435
- ]),
436
- makeIsolatedProject('log-cleaner', ['**/tests/lib/datasource/log-cleaner.test.js']),
437
- makeIsolatedProject('datasource-exporter-service', [
438
- '**/tests/lib/datasource/datasource-exporter-service.test.js'
439
- ]),
440
- makeIsolatedProject('protection-paths', ['**/tests/lib/protection/paths.test.js']),
441
- makeIsolatedProject('protection-resolve', ['**/tests/lib/protection/protection-resolve.test.js']),
442
- makeIsolatedProject('protection-create-helpers', [
443
- '**/tests/lib/protection/run-protection-create-helpers.test.js'
444
- ]),
445
- makeIsolatedProject('governance-pack-loader', [
446
- '**/tests/lib/governance/governance-pack-loader.test.js'
447
- ]),
448
- makeIsolatedProject('protection-validate-batch', [
449
- '**/tests/lib/protection/validate-batch.test.js'
450
- ])
451
- ];
379
+ const isolatedProjects = buildIsolatedProjects(makeIsolatedProject, isCI, sharedTransform);
452
380
 
453
381
  const allProjects = [defaultProject, ...isolatedProjects];
454
382
 
@@ -458,5 +386,6 @@ module.exports = {
458
386
  makeIsolatedProject,
459
387
  defaultProject,
460
388
  isolatedProjects,
461
- allProjects
389
+ allProjects,
390
+ globalLiveFabrixHooks
462
391
  };
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Throw CLI errors from ApiClient responses with formatted output preserved.
3
+ *
4
+ * @fileoverview Dataplane/controller API failure helpers
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { formatApiError } = require('../utils/api-error-handler');
12
+ const {
13
+ enrichUnresolvableGovernanceSubjectsError
14
+ } = require('../governance/governance-cli-errors');
15
+ const { inferServiceLabelFromUrl } = require('../utils/service-url-label');
16
+
17
+ /**
18
+ * @param {Object|undefined} res - ApiClient response
19
+ * @param {string} fallbackMessage
20
+ * @returns {string}
21
+ */
22
+ function resolveApiErrorMessage(res, fallbackMessage) {
23
+ if (!res) {
24
+ return fallbackMessage;
25
+ }
26
+ const fromError =
27
+ res.error &&
28
+ (res.error.formattedError || res.error.error || res.error.message);
29
+ return (
30
+ res.formattedError ||
31
+ fromError ||
32
+ (typeof res.error === 'string' ? res.error : null) ||
33
+ fallbackMessage
34
+ );
35
+ }
36
+
37
+ /**
38
+ * @param {Object|undefined} res
39
+ * @param {string} endpointUrl
40
+ * @returns {{ endpoint: string, serviceLabel: string }}
41
+ */
42
+ function resolveApiFailureEndpointContext(res, endpointUrl) {
43
+ const endpoint =
44
+ (res && res.errorData && res.errorData.endpointUrl) || endpointUrl || '';
45
+ const serviceLabel =
46
+ (res && res.errorData && res.errorData.serviceLabel) ||
47
+ inferServiceLabelFromUrl(endpoint);
48
+ return { endpoint, serviceLabel };
49
+ }
50
+
51
+ /**
52
+ * @param {Object|undefined} res
53
+ * @param {string} endpoint
54
+ * @param {string} serviceLabel
55
+ * @returns {Object}
56
+ */
57
+ function buildEnrichedApiFailureResponse(res, endpoint, serviceLabel) {
58
+ return {
59
+ ...res,
60
+ errorData: {
61
+ ...(res && res.errorData),
62
+ endpointUrl: endpoint,
63
+ serviceLabel
64
+ }
65
+ };
66
+ }
67
+
68
+ /**
69
+ * @param {Error} err
70
+ * @param {Object|undefined} res
71
+ * @param {string} endpoint
72
+ * @param {string} serviceLabel
73
+ * @param {Object} enriched
74
+ */
75
+ function assignApiFailureErrorFields(err, res, endpoint, serviceLabel, enriched) {
76
+ err.formatted =
77
+ res && res.formattedError ? res.formattedError : formatApiError(enriched, null);
78
+ err.network = Boolean(res && res.network === true);
79
+ err.status = res && typeof res.status === 'number' ? res.status : 0;
80
+ err.endpointUrl = endpoint;
81
+ err.serviceLabel = serviceLabel;
82
+ }
83
+
84
+ /**
85
+ * @param {Object|undefined} res
86
+ * @param {string} endpointUrl
87
+ * @returns {Error}
88
+ */
89
+ function buildApiFailureError(res, endpointUrl, context = {}) {
90
+ const message = resolveApiErrorMessage(res, 'Request failed');
91
+ const err = new Error(message);
92
+ const { endpoint, serviceLabel } = resolveApiFailureEndpointContext(res, endpointUrl);
93
+ const enriched = buildEnrichedApiFailureResponse(res, endpoint, serviceLabel);
94
+ assignApiFailureErrorFields(err, res, endpoint, serviceLabel, enriched);
95
+ if (
96
+ typeof endpoint === 'string' &&
97
+ endpoint.includes('/governance-scenarios/generate')
98
+ ) {
99
+ enrichUnresolvableGovernanceSubjectsError(err, context);
100
+ }
101
+ return err;
102
+ }
103
+
104
+ /**
105
+ * @param {Object} res - ApiClient response (`success: false`)
106
+ * @param {{ fallbackMessage?: string, endpointUrl?: string }} [context]
107
+ * @throws {Error}
108
+ */
109
+ function throwIfApiFailed(res, context = {}) {
110
+ if (!res || res.success !== false) {
111
+ return;
112
+ }
113
+ const endpointUrl =
114
+ context.endpointUrl ||
115
+ (res.errorData && res.errorData.endpointUrl) ||
116
+ '';
117
+ throw buildApiFailureError(res, endpointUrl || context.endpointUrl || '', context);
118
+ }
119
+
120
+ module.exports = {
121
+ throwIfApiFailed,
122
+ buildApiFailureError,
123
+ resolveApiErrorMessage
124
+ };
@@ -90,6 +90,17 @@ function parseGeneralHealthResponse(response, endpoint) {
90
90
  * Snapshot, or null when both endpoints fail
91
91
  * @throws {Error} When dataplaneUrl is missing or not a string
92
92
  */
93
+ /**
94
+ * @param {'v1-first'|'legacy-first'} [endpointOrder]
95
+ * @returns {[string, string]}
96
+ */
97
+ function healthEndpointOrder(endpointOrder) {
98
+ if (endpointOrder === 'legacy-first') {
99
+ return [FALLBACK_ENDPOINT, PRIMARY_ENDPOINT];
100
+ }
101
+ return [PRIMARY_ENDPOINT, FALLBACK_ENDPOINT];
102
+ }
103
+
93
104
  async function fetchDataplaneGeneralHealth(dataplaneUrl, options = {}) {
94
105
  if (!dataplaneUrl || typeof dataplaneUrl !== 'string') {
95
106
  throw new Error('dataplaneUrl is required and must be a string');
@@ -100,13 +111,14 @@ async function fetchDataplaneGeneralHealth(dataplaneUrl, options = {}) {
100
111
  requestOpts.timeoutMs = options.timeoutMs;
101
112
  }
102
113
 
103
- const primary = await safeGet(client, PRIMARY_ENDPOINT, requestOpts);
104
- const primarySnapshot = parseGeneralHealthResponse(primary, PRIMARY_ENDPOINT);
105
- if (primarySnapshot) return primarySnapshot;
106
-
107
- const fallback = await safeGet(client, FALLBACK_ENDPOINT, requestOpts);
108
- const fallbackSnapshot = parseGeneralHealthResponse(fallback, FALLBACK_ENDPOINT);
109
- if (fallbackSnapshot) return fallbackSnapshot;
114
+ const endpoints = healthEndpointOrder(options.endpointOrder);
115
+ for (const endpoint of endpoints) {
116
+ const response = await safeGet(client, endpoint, requestOpts);
117
+ const snapshot = parseGeneralHealthResponse(response, endpoint);
118
+ if (snapshot) {
119
+ return snapshot;
120
+ }
121
+ }
110
122
 
111
123
  return null;
112
124
  }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * @fileoverview Dataplane governance scenario pack CRUD + run API (419.0).
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { createDataplaneApiClient } = require('./index');
10
+ const { throwIfApiFailed } = require('./api-response-errors');
11
+ const { unwrapApiData } = require('../utils/external-system-readiness-core');
12
+ const {
13
+ governanceUploadSchemaHint,
14
+ isGovernanceCoverageSchemaError
15
+ } = require('../governance/governance-cli-errors');
16
+
17
+ /**
18
+ * @param {string} dataplaneUrl
19
+ * @param {string} datasourceKey
20
+ * @param {string} suffix
21
+ * @returns {string}
22
+ */
23
+ function governanceScenarioEndpoint(dataplaneUrl, datasourceKey, suffix) {
24
+ const base = String(dataplaneUrl || '').replace(/\/$/, '');
25
+ return `${base}/api/v1/external/${encodeURIComponent(datasourceKey)}${suffix}`;
26
+ }
27
+
28
+ /**
29
+ * PUT /api/v1/external/{datasourceKey}/governance-scenarios
30
+ * @requiresPermission {Dataplane} external-data-source:update
31
+ * @async
32
+ */
33
+ async function upsertDatasourceGovernancePack(dataplaneUrl, authConfig, datasourceKey, pack) {
34
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
35
+ const res = await client.put(
36
+ `/api/v1/external/${encodeURIComponent(datasourceKey)}/governance-scenarios`,
37
+ { body: { pack } }
38
+ );
39
+ if (res && res.success === false) {
40
+ try {
41
+ throwIfApiFailed(res, {
42
+ endpointUrl: governanceScenarioEndpoint(
43
+ dataplaneUrl,
44
+ datasourceKey,
45
+ '/governance-scenarios'
46
+ )
47
+ });
48
+ } catch (err) {
49
+ if (isGovernanceCoverageSchemaError(err)) {
50
+ err.friendlyHint = governanceUploadSchemaHint(
51
+ (pack && pack.spec && pack.spec.systemKey) || datasourceKey
52
+ );
53
+ }
54
+ throw err;
55
+ }
56
+ }
57
+ return unwrapApiData(res);
58
+ }
59
+
60
+ /**
61
+ * GET /api/v1/external/{datasourceKey}/governance-scenarios
62
+ * @requiresPermission {Dataplane} external-data-source:read
63
+ * @async
64
+ */
65
+ async function getDatasourceGovernancePack(dataplaneUrl, authConfig, datasourceKey) {
66
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
67
+ const res = await client.get(
68
+ `/api/v1/external/${encodeURIComponent(datasourceKey)}/governance-scenarios`
69
+ );
70
+ throwIfApiFailed(res, {
71
+ endpointUrl: governanceScenarioEndpoint(dataplaneUrl, datasourceKey, '/governance-scenarios')
72
+ });
73
+ return unwrapApiData(res);
74
+ }
75
+
76
+ /**
77
+ * POST /api/v1/external/{datasourceKey}/governance-scenarios/run
78
+ * @requiresPermission {Dataplane} governance:evaluate
79
+ * @async
80
+ */
81
+ async function runDatasourceGovernanceScenarios(dataplaneUrl, authConfig, datasourceKey) {
82
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
83
+ const res = await client.post(
84
+ `/api/v1/external/${encodeURIComponent(datasourceKey)}/governance-scenarios/run`,
85
+ { body: {} }
86
+ );
87
+ throwIfApiFailed(res, {
88
+ endpointUrl: governanceScenarioEndpoint(
89
+ dataplaneUrl,
90
+ datasourceKey,
91
+ '/governance-scenarios/run'
92
+ )
93
+ });
94
+ const unwrapped = unwrapApiData(res);
95
+ if (!unwrapped || !unwrapped.summary) {
96
+ throw new Error('Governance scenario run returned an unexpected response shape');
97
+ }
98
+ return unwrapped;
99
+ }
100
+
101
+ /**
102
+ * POST /api/v1/external/{datasourceKey}/governance-scenarios/generate
103
+ * @requiresPermission {Dataplane} external-data-source:update
104
+ * @async
105
+ */
106
+ async function generateDatasourceGovernancePack(
107
+ dataplaneUrl,
108
+ authConfig,
109
+ datasourceKey,
110
+ body
111
+ ) {
112
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
113
+ const res = await client.post(
114
+ `/api/v1/external/${encodeURIComponent(datasourceKey)}/governance-scenarios/generate`,
115
+ { body }
116
+ );
117
+ const subjectEmails = Array.isArray(body.subjects)
118
+ ? body.subjects
119
+ .map(entry => entry && entry.subjectEmail)
120
+ .filter(email => typeof email === 'string' && email.trim())
121
+ : [];
122
+ throwIfApiFailed(res, {
123
+ endpointUrl: governanceScenarioEndpoint(
124
+ dataplaneUrl,
125
+ datasourceKey,
126
+ '/governance-scenarios/generate'
127
+ ),
128
+ subjectEmails
129
+ });
130
+ return unwrapApiData(res);
131
+ }
132
+
133
+ /**
134
+ * GET /api/v1/external/{datasourceKey}/governance-scenarios/versions
135
+ * @requiresPermission {Dataplane} external-data-source:read
136
+ * @async
137
+ */
138
+ async function listDatasourceGovernancePackVersions(dataplaneUrl, authConfig, datasourceKey) {
139
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
140
+ const res = await client.get(
141
+ `/api/v1/external/${encodeURIComponent(datasourceKey)}/governance-scenarios/versions`
142
+ );
143
+ throwIfApiFailed(res, {
144
+ endpointUrl: governanceScenarioEndpoint(
145
+ dataplaneUrl,
146
+ datasourceKey,
147
+ '/governance-scenarios/versions'
148
+ )
149
+ });
150
+ return unwrapApiData(res);
151
+ }
152
+
153
+ module.exports = {
154
+ upsertDatasourceGovernancePack,
155
+ getDatasourceGovernancePack,
156
+ runDatasourceGovernanceScenarios,
157
+ generateDatasourceGovernancePack,
158
+ listDatasourceGovernancePackVersions
159
+ };
package/lib/api/index.js CHANGED
@@ -14,11 +14,13 @@ const { makeApiCall, authenticatedApiCall } = require('../utils/api');
14
14
  class ApiClient {
15
15
  /**
16
16
  * Create an API client instance.
17
- * App endpoints receive token-only auth (Bearer). x-client-id/x-client-secret are not sent to app endpoints.
17
+ * App endpoints receive token-only auth (Bearer). x-client-id/x-client-secret are used only for the controller token endpoint.
18
18
  * @param {string} baseUrl - Base URL for the API (controller URL)
19
19
  * @param {Object} [authConfig] - Authentication configuration
20
- * @param {string} [authConfig.type] - Auth type ('bearer' | 'client-token')
20
+ * @param {string} [authConfig.type] - Auth type ('bearer' | 'client-token' | 'client-credentials')
21
21
  * @param {string} [authConfig.token] - Bearer token
22
+ * @param {string} [authConfig.clientId] - Client ID (client-credentials)
23
+ * @param {string} [authConfig.clientSecret] - Client secret (client-credentials)
22
24
  */
23
25
  constructor(baseUrl, authConfig = {}, clientOptions = {}) {
24
26
  if (baseUrl === null || baseUrl === undefined || typeof baseUrl !== 'string') {
@@ -87,6 +89,41 @@ class ApiClient {
87
89
  return headers;
88
90
  }
89
91
 
92
+ /**
93
+ * True when endpoint is the controller client-credentials token exchange.
94
+ * @private
95
+ * @param {string} endpoint - API endpoint path
96
+ * @returns {boolean}
97
+ */
98
+ _isClientCredentialsTokenEndpoint(endpoint) {
99
+ const path = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
100
+ return path === '/api/v1/auth/token';
101
+ }
102
+
103
+ /**
104
+ * Add x-client-id/x-client-secret only for POST /api/v1/auth/token (never for app endpoints).
105
+ * @private
106
+ * @param {string} endpoint - API endpoint path
107
+ * @param {Object} headers - Request headers built by _buildHeaders
108
+ * @returns {Object}
109
+ */
110
+ _applyClientCredentialHeadersForTokenEndpoint(endpoint, headers) {
111
+ if (this.authConfig.type !== 'client-credentials') {
112
+ return headers;
113
+ }
114
+ if (!this._isClientCredentialsTokenEndpoint(endpoint)) {
115
+ return headers;
116
+ }
117
+ const out = { ...headers };
118
+ if (this.authConfig.clientId) {
119
+ out['x-client-id'] = String(this.authConfig.clientId);
120
+ }
121
+ if (this.authConfig.clientSecret) {
122
+ out['x-client-secret'] = String(this.authConfig.clientSecret);
123
+ }
124
+ return out;
125
+ }
126
+
90
127
  /**
91
128
  * Make a GET request
92
129
  * @async
@@ -141,7 +178,10 @@ class ApiClient {
141
178
  async post(endpoint, options = {}) {
142
179
  await this._ensureDataplaneCliVersionGate();
143
180
  let url = this._buildUrl(endpoint);
144
- const headers = this._buildHeaders(options.headers);
181
+ const headers = this._applyClientCredentialHeadersForTokenEndpoint(
182
+ endpoint,
183
+ this._buildHeaders(options.headers)
184
+ );
145
185
 
146
186
  // Add query parameters if provided
147
187
  if (options.params) {