@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
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @fileoverview Governance CLI error messages (424.0).
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ /**
8
+ * @param {Error|string} err
9
+ * @returns {boolean}
10
+ */
11
+ function isGovernancePackNotFoundError(err) {
12
+ const raw = (err && err.message) || String(err);
13
+ return /not found/i.test(raw) || /\b404\b/.test(raw);
14
+ }
15
+
16
+ /**
17
+ * @param {Error|string} err
18
+ * @returns {boolean}
19
+ */
20
+ function isGovernanceCoverageSchemaError(err) {
21
+ const raw = (err && err.message) || String(err);
22
+ return (
23
+ raw.includes('\'coverage\' is a required property') || /spec\.coverage/i.test(raw)
24
+ );
25
+ }
26
+
27
+ /**
28
+ * Short, non-duplicative CLI message from a dataplane governance API error.
29
+ * @param {Error|string} err
30
+ * @returns {string}
31
+ */
32
+ function shortGovernanceApiError(err) {
33
+ const raw = ((err && err.message) || String(err)).trim();
34
+ if (isGovernancePackNotFoundError(err)) {
35
+ return 'No active pack on dataplane';
36
+ }
37
+ if (isGovernanceCoverageSchemaError(err)) {
38
+ return 'Pack missing spec.coverage (424.0 schema)';
39
+ }
40
+ const firstLine = raw.split('\n').find(line => line.trim()) || raw;
41
+ if (/^Governance scenario pack not found/i.test(firstLine)) {
42
+ return 'No active pack on dataplane';
43
+ }
44
+ return firstLine.length > 100 ? `${firstLine.slice(0, 97)}...` : firstLine;
45
+ }
46
+
47
+ /**
48
+ * User-facing hint after a failed governance pack upload (validation).
49
+ * @param {string} systemKey
50
+ * @returns {string}
51
+ */
52
+ function governanceUploadSchemaHint(systemKey) {
53
+ return (
54
+ 'Scenario pack does not meet the 424.0 schema. Use dataplane-first generation:\n' +
55
+ ` aifabrix governance generate ${systemKey} --subject-email <email>\n` +
56
+ 'Or: aifabrix verify-governance ' +
57
+ `${systemKey} --subject-email <email>`
58
+ );
59
+ }
60
+
61
+ /**
62
+ * Clarify subject-resolution 400s (dataplane reachable; User row missing).
63
+ * @param {Error} err
64
+ * @param {{ subjectEmails?: string[] }} [context]
65
+ * @returns {Error}
66
+ */
67
+ function enrichUnresolvableGovernanceSubjectsError(err, context = {}) {
68
+ const hay = `${err.message || ''} ${err.formatted || ''}`;
69
+ if (!hay.includes('No resolvable subjects')) {
70
+ return err;
71
+ }
72
+ const emails = Array.isArray(context.subjectEmails)
73
+ ? context.subjectEmails.filter(Boolean)
74
+ : [];
75
+ const lines = [
76
+ '',
77
+ 'The dataplane is reachable. This is not a network or controller error.',
78
+ 'Pack generation needs --subject-email values that match existing dataplane User rows.',
79
+ emails.length > 0 ? `Subject email(s) you passed: ${emails.join(', ')}` : null,
80
+ 'Check:',
81
+ ' aifabrix identity user list --search <email>',
82
+ 'If the user is missing, apply your identity CSV first:',
83
+ ' aifabrix identity apply --file integration/<systemKey>/fixtures/<users>.csv --filter-prefix <systemKey>',
84
+ ' aifabrix identity sync -e dev --purge-cache'
85
+ ].filter(line => line !== null);
86
+ err.formatted = `${err.formatted || err.message}${lines.join('\n')}`;
87
+ return err;
88
+ }
89
+
90
+ module.exports = {
91
+ isGovernancePackNotFoundError,
92
+ isGovernanceCoverageSchemaError,
93
+ shortGovernanceApiError,
94
+ governanceUploadSchemaHint,
95
+ enrichUnresolvableGovernanceSubjectsError
96
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @fileoverview TTY summary when governance download finds no active packs.
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const chalk = require('chalk');
8
+ const { failureGlyph } = require('../utils/cli-test-layout-chalk');
9
+ const logger = require('../utils/logger');
10
+
11
+ /**
12
+ * @param {Array<{ datasourceKey: string, reason: string }>} missing
13
+ */
14
+ function printGovernanceDownloadMisses(missing) {
15
+ if (!missing || missing.length === 0) {
16
+ return;
17
+ }
18
+ for (const row of missing) {
19
+ logger.log(
20
+ chalk.white(`${row.datasourceKey}: ${failureGlyph()} ${row.reason}`)
21
+ );
22
+ }
23
+ logger.log('');
24
+ logger.log(chalk.gray('Next steps:'));
25
+ logger.log(
26
+ chalk.gray(
27
+ ' • Run: aifabrix governance generate <systemKey> --subject-email <email>'
28
+ )
29
+ );
30
+ logger.log(
31
+ chalk.gray(' • Or use: aifabrix verify-governance <systemKey> --subject-email <email>')
32
+ );
33
+ logger.log(chalk.gray(' • Ensure protection is published and identity sync has run'));
34
+ }
35
+
36
+ module.exports = {
37
+ printGovernanceDownloadMisses
38
+ };
@@ -16,7 +16,45 @@ const {
16
16
  formatBlockingError
17
17
  } = require('../utils/cli-test-layout-chalk');
18
18
 
19
- const SEP = '────────────────────────────────';
19
+ const SEP = '────────────────────────';
20
+ const MAX_SAMPLE_KEYS = 5;
21
+
22
+ /**
23
+ * @param {Object|null|undefined} packDocument
24
+ * @returns {Map<string, { mustIncludeKeys: string[], mustExcludeKeys: string[] }>}
25
+ */
26
+ function buildScenarioExpectMap(packDocument) {
27
+ const map = new Map();
28
+ const scenarios = packDocument?.spec?.scenarios;
29
+ if (!Array.isArray(scenarios)) {
30
+ return map;
31
+ }
32
+ for (const scenario of scenarios) {
33
+ if (!scenario || typeof scenario.id !== 'string') {
34
+ continue;
35
+ }
36
+ const expect = scenario.expect || {};
37
+ map.set(scenario.id, {
38
+ mustIncludeKeys: Array.isArray(expect.mustIncludeKeys) ? expect.mustIncludeKeys : [],
39
+ mustExcludeKeys: Array.isArray(expect.mustExcludeKeys) ? expect.mustExcludeKeys : []
40
+ });
41
+ }
42
+ return map;
43
+ }
44
+
45
+ /**
46
+ * @param {string[]} keys
47
+ * @param {number} [maxKeys]
48
+ * @returns {string}
49
+ */
50
+ function formatKeySample(keys, maxKeys = MAX_SAMPLE_KEYS) {
51
+ if (!Array.isArray(keys) || keys.length === 0) {
52
+ return '—';
53
+ }
54
+ const slice = keys.slice(0, maxKeys);
55
+ const suffix = keys.length > maxKeys ? ` (+${keys.length - maxKeys} more)` : '';
56
+ return `${slice.join(', ')}${suffix}`;
57
+ }
20
58
 
21
59
  /**
22
60
  * @param {'pass'|'fail'} status
@@ -28,38 +66,162 @@ function scenarioGlyph(status) {
28
66
 
29
67
  /**
30
68
  * @param {import('../api/types/governance-scenarios.types').GovernanceScenarioResult} scenario
31
- * @param {boolean} verbose
32
69
  */
33
- function logScenarioVerdict(scenario, verbose) {
34
- logger.log(` ${scenarioGlyph(scenario.status)} ${scenario.verdict}`);
35
- if (!verbose) return;
36
- logger.log(
37
- metaGray(
38
- ` Subject: ${scenario.subjectDisplayName} (${scenario.subjectUserId})`
39
- )
40
- );
41
- if (scenario.subjectGroups && scenario.subjectGroups.length > 0) {
42
- logger.log(metaGray(` Groups: ${scenario.subjectGroups.join(', ')}`));
70
+ function logGovernanceScenarioSubjectLines(scenario) {
71
+ logger.log(` ${scenarioGlyph(scenario.status)} ${scenario.id}`);
72
+ logger.log(metaGray(` Subject email: ${scenario.subjectEmail || '—'}`));
73
+ if (scenario.subjectDisplayName) {
74
+ logger.log(
75
+ metaGray(
76
+ ` Subject: ${scenario.subjectDisplayName} (${scenario.subjectUserId || '—'})`
77
+ )
78
+ );
43
79
  }
44
- logger.log(
45
- metaGray(
46
- ` Visible keys: ${scenario.visibleKeyCount} · excluded ABAC: ${scenario.excludedAbac}` +
47
- (scenario.auditRef ? ` · audit: ${scenario.auditRef}` : '')
48
- )
49
- );
50
- if (scenario.unexpectedVisibleKeys && scenario.unexpectedVisibleKeys.length > 0) {
80
+ logger.log(metaGray(` Verdict: ${scenario.verdict || '—'}`));
81
+ }
82
+
83
+ /**
84
+ * @param {import('../api/types/governance-scenarios.types').GovernanceScenarioResult} scenario
85
+ */
86
+ function logGovernanceScenarioCounts(scenario) {
87
+ const visible = typeof scenario.visibleKeyCount === 'number' ? scenario.visibleKeyCount : 0;
88
+ const abac = typeof scenario.excludedAbac === 'number' ? scenario.excludedAbac : 0;
89
+ const filter = typeof scenario.excludedFilter === 'number' ? scenario.excludedFilter : 0;
90
+ logger.log(metaGray(` Visible keys: ${visible} allowed`));
91
+ logger.log(metaGray(` Declined: ${abac} by ABAC · ${filter} by filter`));
92
+ }
93
+
94
+ /**
95
+ * @param {import('../api/types/governance-scenarios.types').GovernanceScenarioResult} scenario
96
+ * @param {{ mustIncludeKeys: string[], mustExcludeKeys: string[] }} expect
97
+ */
98
+ function logGovernanceScenarioPassSamples(expect) {
99
+ const allowed =
100
+ expect.mustIncludeKeys.length > 0 ? formatKeySample(expect.mustIncludeKeys) : '—';
101
+ const blocked =
102
+ expect.mustExcludeKeys.length > 0 ? formatKeySample(expect.mustExcludeKeys) : '—';
103
+ logger.log(metaGray(` Sample allowed: ${allowed}`));
104
+ logger.log(metaGray(` Sample blocked: ${blocked}`));
105
+ }
106
+
107
+ /**
108
+ * @param {import('../api/types/governance-scenarios.types').GovernanceScenarioResult} scenario
109
+ */
110
+ function logGovernanceScenarioFailSamples(scenario) {
111
+ if (scenario.missingRequiredKeys?.length) {
51
112
  logger.log(
52
- metaGray(` Unexpected: ${scenario.unexpectedVisibleKeys.join(', ')}`)
113
+ metaGray(` Missing keys: ${formatKeySample(scenario.missingRequiredKeys)}`)
53
114
  );
54
115
  }
55
- if (scenario.missingRequiredKeys && scenario.missingRequiredKeys.length > 0) {
56
- logger.log(metaGray(` Missing: ${scenario.missingRequiredKeys.join(', ')}`));
116
+ if (scenario.unexpectedVisibleKeys?.length) {
117
+ logger.log(
118
+ metaGray(` Unexpected: ${formatKeySample(scenario.unexpectedVisibleKeys)}`)
119
+ );
57
120
  }
58
121
  if (scenario.fixHint) {
59
- logger.log(metaGray(` Fix: ${scenario.fixHint}`));
122
+ logger.log(metaGray(` Fix: ${scenario.fixHint}`));
60
123
  }
61
124
  }
62
125
 
126
+ /**
127
+ * @param {import('../api/types/governance-scenarios.types').GovernanceScenarioResult} scenario
128
+ * @param {Map<string, { mustIncludeKeys: string[], mustExcludeKeys: string[] }>} expectMap
129
+ */
130
+ function logGovernanceScenarioDetail(scenario, expectMap) {
131
+ const expect = expectMap.get(scenario.id) || {
132
+ mustIncludeKeys: [],
133
+ mustExcludeKeys: []
134
+ };
135
+ logGovernanceScenarioSubjectLines(scenario);
136
+ logGovernanceScenarioCounts(scenario);
137
+ if (scenario.status === 'pass') {
138
+ logGovernanceScenarioPassSamples(expect);
139
+ } else {
140
+ logGovernanceScenarioFailSamples(scenario);
141
+ }
142
+ if (scenario.subjectGroups?.length) {
143
+ logger.log(metaGray(` Groups: ${scenario.subjectGroups.join(', ')}`));
144
+ }
145
+ if (scenario.auditRef) {
146
+ logger.log(metaGray(` Audit: ${scenario.auditRef}`));
147
+ }
148
+ }
149
+
150
+ /**
151
+ * One datasource block for verify-governance -v.
152
+ * @param {Object} row
153
+ * @param {string} row.datasourceKey
154
+ * @param {Object} [row.result]
155
+ * @param {Object} [row.packDocument]
156
+ * @param {string} [row.packPath]
157
+ * @param {string} [row.error]
158
+ */
159
+ function displayGovernanceDatasourceVerbose(row) {
160
+ logger.log('');
161
+ logger.log(chalk.white(`Datasource: ${row.datasourceKey}`));
162
+ if (row.error) {
163
+ logger.log(formatBlockingError(row.error));
164
+ return;
165
+ }
166
+ const run = row.result;
167
+ if (!run || !run.summary) {
168
+ logger.log(metaGray(' No scenario run result (pack missing or run skipped).'));
169
+ return;
170
+ }
171
+ logger.log(headerKeyValue('Pack:', run.packKey || '—'));
172
+ if (row.packPath) {
173
+ logger.log(metaGray(` File: ${row.packPath}`));
174
+ }
175
+ const summary = run.summary;
176
+ logger.log(
177
+ headerKeyValue('Scenarios:', `${summary.passed || 0}/${summary.total || 0} passed`)
178
+ );
179
+ const expectMap = buildScenarioExpectMap(row.packDocument);
180
+ for (const scenario of run.scenarios || []) {
181
+ logGovernanceScenarioDetail(scenario, expectMap);
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Verbose (-v) scenario breakdown for verify-governance / governance verify.
187
+ * @param {Object} result
188
+ */
189
+ function displayGovernanceVerboseDetails(result) {
190
+ if (!result) {
191
+ return;
192
+ }
193
+ logger.log('');
194
+ logger.log(chalk.white('Scenario results'));
195
+ logger.log(metaGray(SEP));
196
+ logger.log(metaGray('Key sets only — no record payloads.'));
197
+
198
+ if (result.legacyResult && result.legacyResult.summary) {
199
+ const dsKey =
200
+ result.packDatasourceKey ||
201
+ primaryDatasourceFromPack(result.packDocument) ||
202
+ 'scenario pack';
203
+ displayGovernanceDatasourceVerbose({
204
+ datasourceKey: dsKey,
205
+ result: result.legacyResult,
206
+ packDocument: result.packDocument,
207
+ packPath: result.packPath
208
+ });
209
+ logger.log('');
210
+ return;
211
+ }
212
+
213
+ const rows = result.datasourceRows || [];
214
+ if (rows.length === 0) {
215
+ logger.log(metaGray(' No datasource scenario packs were run.'));
216
+ logger.log('');
217
+ return;
218
+ }
219
+ for (const row of rows) {
220
+ displayGovernanceDatasourceVerbose(row);
221
+ }
222
+ logger.log('');
223
+ }
224
+
63
225
  /**
64
226
  * @param {string} systemKey
65
227
  * @param {import('../api/types/governance-scenarios.types').GovernanceScenariosRunResponse} result
@@ -82,8 +244,13 @@ function displayGovernanceRunTTY(systemKey, result, opts = {}) {
82
244
  );
83
245
  logger.log(metaGray(' Does not call vendor APIs (use test-e2e for connectivity).'));
84
246
  logger.log('');
247
+ const expectMap = buildScenarioExpectMap(opts.packDocument);
85
248
  for (const scenario of result.scenarios || []) {
86
- logScenarioVerdict(scenario, opts.verbose === true);
249
+ if (opts.verbose === true) {
250
+ logGovernanceScenarioDetail(scenario, expectMap);
251
+ } else {
252
+ logger.log(` ${scenarioGlyph(scenario.status)} ${scenario.verdict}`);
253
+ }
87
254
  }
88
255
  logger.log('');
89
256
  if (agg === 'ok') {
@@ -112,8 +279,31 @@ function exitCodeFromGovernanceSummary(summary) {
112
279
  return 0;
113
280
  }
114
281
 
282
+ /**
283
+ * @param {Object|null|undefined} packDocument
284
+ * @returns {string|null}
285
+ */
286
+ function primaryDatasourceFromPack(packDocument) {
287
+ const scenarios = packDocument?.spec?.scenarios;
288
+ if (!Array.isArray(scenarios)) {
289
+ return null;
290
+ }
291
+ for (const scenario of scenarios) {
292
+ const keys = scenario?.search?.datasourceKeys;
293
+ if (Array.isArray(keys) && keys.length > 0 && typeof keys[0] === 'string') {
294
+ return keys[0];
295
+ }
296
+ }
297
+ return null;
298
+ }
299
+
115
300
  module.exports = {
301
+ buildScenarioExpectMap,
302
+ formatKeySample,
303
+ displayGovernanceDatasourceVerbose,
304
+ displayGovernanceVerboseDetails,
116
305
  displayGovernanceRunTTY,
117
306
  printGovernanceRunJson,
118
- exitCodeFromGovernanceSummary
307
+ exitCodeFromGovernanceSummary,
308
+ primaryDatasourceFromPack
119
309
  };
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @fileoverview Parse ForeignKeyReference objects from controller identity APIs (plan 194)
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ /**
10
+ * @param {string|Object|null|undefined} ref
11
+ * @returns {string}
12
+ */
13
+ function readFkId(ref) {
14
+ if (typeof ref === 'string') {
15
+ return ref;
16
+ }
17
+ return String(ref?.id || '').trim();
18
+ }
19
+
20
+ /**
21
+ * @param {string|Object|null|undefined} ref
22
+ * @returns {string}
23
+ */
24
+ function readFkKey(ref) {
25
+ if (typeof ref === 'string') {
26
+ return ref;
27
+ }
28
+ return String(ref?.key || '').trim();
29
+ }
30
+
31
+ /**
32
+ * @param {string|Object|null|undefined} ref
33
+ * @returns {string}
34
+ */
35
+ function readFkName(ref) {
36
+ if (typeof ref === 'string') {
37
+ return '';
38
+ }
39
+ return String(ref?.name || '').trim();
40
+ }
41
+
42
+ /**
43
+ * @param {string|Object|null|undefined} ref
44
+ * @param {string} [fallback]
45
+ * @returns {string}
46
+ */
47
+ function formatFkLabel(ref, fallback = '—') {
48
+ const name = readFkName(ref);
49
+ if (name) {
50
+ return name;
51
+ }
52
+ const key = readFkKey(ref);
53
+ if (key) {
54
+ return key;
55
+ }
56
+ const id = readFkId(ref);
57
+ return id || fallback;
58
+ }
59
+
60
+ module.exports = {
61
+ readFkId,
62
+ readFkKey,
63
+ readFkName,
64
+ formatFkLabel
65
+ };
@@ -6,46 +6,13 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- const { getUser, listUsers } = require('../api/users.api');
10
-
11
- /**
12
- * @param {Object} response
13
- * @returns {any}
14
- */
15
- function unwrapControllerData(response) {
16
- if (!response || response.success === false) {
17
- return null;
18
- }
19
- return response?.data?.data ?? response?.data ?? response;
20
- }
21
-
22
- /**
23
- * @param {Object} response
24
- * @returns {string}
25
- */
26
- function apiErrorMessage(response) {
27
- if (!response) {
28
- return 'Request failed';
29
- }
30
- const err = response.error;
31
- if (typeof err === 'string') {
32
- return err;
33
- }
34
- if (err && typeof err === 'object') {
35
- return err.formattedError || err.message || err.error || 'Request failed';
36
- }
37
- return response.formattedError || response.message || 'Request failed';
38
- }
39
-
40
- /**
41
- * @param {Object} response
42
- * @throws {Error}
43
- */
44
- function throwIfApiFailed(response) {
45
- if (!response || response.success === false) {
46
- throw new Error(apiErrorMessage(response));
47
- }
48
- }
9
+ const { lookupUserByIdOrEmail } = require('./resolve-user-id');
10
+ const { buildSyncStatsFailureMessage } = require('./identity-sync-errors');
11
+ const {
12
+ unwrapControllerData,
13
+ apiErrorMessage,
14
+ throwIfApiFailed
15
+ } = require('./identity-response-helpers');
49
16
 
50
17
  /**
51
18
  * @param {Object|null|undefined} stats
@@ -55,11 +22,7 @@ function throwIfApiFailed(response) {
55
22
  function assertSyncStatsOk(stats, opts = {}) {
56
23
  const syncErrors = Number(stats?.errors ?? 0);
57
24
  if (syncErrors > 0) {
58
- throw new Error(
59
- `Dataplane full sync reported ${syncErrors} error(s). ` +
60
- `usersProcessed=${stats?.usersProcessed ?? 0} groupsProcessed=${stats?.groupsProcessed ?? 0}. ` +
61
- 'Check miso-controller logs for the sync request.'
62
- );
25
+ throw new Error(buildSyncStatsFailureMessage(stats));
63
26
  }
64
27
  const processed = Number(stats?.usersProcessed ?? 0);
65
28
  if (processed === 0 && !opts.allowEmptySync) {
@@ -79,24 +42,16 @@ function assertSyncStatsOk(stats, opts = {}) {
79
42
  async function findExistingUser(controllerUrl, authConfig, userSpec) {
80
43
  const csvId = String(userSpec.csvId || '').trim();
81
44
  if (csvId) {
82
- const byId = await getUser(controllerUrl, authConfig, csvId);
83
- const row = unwrapControllerData(byId);
84
- if (row && row.id) {
85
- return row;
45
+ const byId = await lookupUserByIdOrEmail(controllerUrl, authConfig, csvId);
46
+ if (byId?.id) {
47
+ return byId;
86
48
  }
87
49
  }
88
50
  const email = String(userSpec.email || '').trim();
89
- const listed = await listUsers(controllerUrl, authConfig, {
90
- search: email,
91
- pageSize: 10,
92
- page: 1
93
- });
94
- const items = unwrapControllerData(listed);
95
- const list = Array.isArray(items) ? items : items?.data;
96
- if (!Array.isArray(list)) {
51
+ if (!email) {
97
52
  return null;
98
53
  }
99
- return list.find((u) => String(u.email || '').toLowerCase() === email.toLowerCase()) || null;
54
+ return lookupUserByIdOrEmail(controllerUrl, authConfig, email);
100
55
  }
101
56
 
102
57
  module.exports = {
@@ -18,6 +18,7 @@ const {
18
18
  apiErrorMessage,
19
19
  findExistingUser
20
20
  } = require('./identity-apply-core');
21
+ const { resolveIdentityUsername } = require('./username-default');
21
22
 
22
23
  /**
23
24
  * @param {string} msg
@@ -75,7 +76,10 @@ async function ensureUser(controllerUrl, authConfig, userSpec, dryRun) {
75
76
  firstName: userSpec.firstName,
76
77
  lastName: userSpec.lastName,
77
78
  displayName: userSpec.displayName,
78
- username: userSpec.username,
79
+ username: resolveIdentityUsername({
80
+ username: userSpec.username,
81
+ email: userSpec.email
82
+ }),
79
83
  status: 'active'
80
84
  };
81
85
  Object.keys(body).forEach((k) => {