@aifabrix/builder 2.45.0 → 2.46.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 (352) 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/docs-rules.mdc +3 -1
  4. package/.cursor/rules/project-rules.mdc +1 -0
  5. package/README.md +43 -17
  6. package/integration/hubspot-test/wizard-hubspot-e2e.yaml +1 -1
  7. package/jest.config.default.js +2 -1
  8. package/jest.config.isolated.js +2 -1
  9. package/jest.global-live-fabrix-hooks.js +36 -0
  10. package/jest.isolated-projects.js +130 -0
  11. package/jest.projects.js +69 -121
  12. package/lib/api/agent-metadata-validation.api.js +93 -0
  13. package/lib/api/api-response-errors.js +124 -0
  14. package/lib/api/audit-api-helpers.js +68 -0
  15. package/lib/api/audit.api.js +119 -0
  16. package/lib/api/auth-cache.api.js +44 -0
  17. package/lib/api/certificates.api.js +4 -4
  18. package/lib/api/credential.api.js +2 -2
  19. package/lib/api/dataplane-health.api.js +137 -0
  20. package/lib/api/dataplane-sync.api.js +27 -0
  21. package/lib/api/datasources-core.api.js +21 -18
  22. package/lib/api/datasources-extended.api.js +22 -22
  23. package/lib/api/dimensions.api.js +3 -0
  24. package/lib/api/external-systems.api.js +13 -13
  25. package/lib/api/governance-scenario-pack.api.js +159 -0
  26. package/lib/api/governance-scenarios.api.js +39 -0
  27. package/lib/api/groups.api.js +79 -0
  28. package/lib/api/index.js +88 -5
  29. package/lib/api/lifecycle.api.js +77 -0
  30. package/lib/api/pipeline.api.js +7 -5
  31. package/lib/api/protection.api.js +157 -0
  32. package/lib/api/records-bulk.api.js +43 -0
  33. package/lib/api/records-search-parse.js +49 -0
  34. package/lib/api/records-search.api.js +29 -0
  35. package/lib/api/types/agent-metadata-validation.types.js +67 -0
  36. package/lib/api/types/audit.types.js +72 -0
  37. package/lib/api/types/dataplane-health.types.js +27 -0
  38. package/lib/api/types/dimensions.types.js +2 -0
  39. package/lib/api/types/governance-scenarios.types.js +39 -0
  40. package/lib/api/types/protection.types.js +69 -0
  41. package/lib/api/types/records-bulk.types.js +35 -0
  42. package/lib/api/types/records-search.types.js +28 -0
  43. package/lib/api/user-groups.api.js +50 -0
  44. package/lib/api/users.api.js +95 -0
  45. package/lib/api/validation-run.api.js +3 -3
  46. package/lib/api/validation-runner.js +5 -3
  47. package/lib/api/wizard-platform.api.js +3 -3
  48. package/lib/api/wizard.api.js +21 -21
  49. package/lib/app/deploy-config.js +4 -1
  50. package/lib/app/deploy.js +34 -19
  51. package/lib/app/down.js +20 -1
  52. package/lib/app/push.js +4 -5
  53. package/lib/app/register.js +7 -4
  54. package/lib/app/run-env-compose.js +84 -30
  55. package/lib/build/index.js +5 -0
  56. package/lib/certification/sync-system-certification.js +13 -6
  57. package/lib/cli/index.js +8 -2
  58. package/lib/cli/infra-guided-auth.js +109 -0
  59. package/lib/cli/infra-guided.js +91 -69
  60. package/lib/cli/setup-app.help.js +19 -2
  61. package/lib/cli/setup-app.js +58 -23
  62. package/lib/cli/setup-app.test-commands.js +28 -21
  63. package/lib/cli/setup-auth.js +55 -3
  64. package/lib/cli/setup-certification-commands.js +147 -0
  65. package/lib/cli/setup-certification.help.js +141 -0
  66. package/lib/cli/setup-environment.js +19 -2
  67. package/lib/cli/setup-external-system-help.js +62 -0
  68. package/lib/cli/setup-external-system.js +62 -6
  69. package/lib/cli/setup-infra.js +9 -1
  70. package/lib/cli/setup-platform.js +6 -1
  71. package/lib/cli/setup-secrets.js +33 -1
  72. package/lib/cli/setup-utility-help-after.js +65 -0
  73. package/lib/cli/setup-utility-repair.js +198 -0
  74. package/lib/cli/setup-utility-resolve.js +42 -6
  75. package/lib/cli/setup-utility-validate.js +197 -0
  76. package/lib/cli/setup-utility.js +41 -258
  77. package/lib/commands/auth-status-client-tokens.js +214 -0
  78. package/lib/commands/auth-status-dataplane-version.js +269 -0
  79. package/lib/commands/auth-status-display.js +94 -0
  80. package/lib/commands/auth-status.js +111 -53
  81. package/lib/commands/credential-push.js +10 -5
  82. package/lib/commands/datasource-load-export-cli.js +178 -0
  83. package/lib/commands/datasource-test-trust-cli.js +118 -0
  84. package/lib/commands/datasource-unified-test-cli.js +31 -20
  85. package/lib/commands/datasource-unified-test-cli.options.js +22 -3
  86. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +5 -5
  87. package/lib/commands/datasource-verify-audit-cli.js +96 -0
  88. package/lib/commands/datasource.js +68 -1
  89. package/lib/commands/dev-show-display.js +8 -1
  90. package/lib/commands/dimension-value.js +43 -13
  91. package/lib/commands/dimension.js +38 -7
  92. package/lib/commands/governance-cli-shared.js +94 -0
  93. package/lib/commands/governance-command-action.js +132 -0
  94. package/lib/commands/governance-download-external.js +34 -0
  95. package/lib/commands/governance-generate-external.js +71 -0
  96. package/lib/commands/governance-upload-external.js +36 -0
  97. package/lib/commands/governance-verify-external.js +64 -0
  98. package/lib/commands/governance.js +144 -0
  99. package/lib/commands/identity-apply-sync.js +131 -0
  100. package/lib/commands/identity-group-cli.js +146 -0
  101. package/lib/commands/identity-membership-role-cache.js +175 -0
  102. package/lib/commands/identity-shared.js +94 -0
  103. package/lib/commands/identity-user-cli.js +158 -0
  104. package/lib/commands/identity.js +43 -0
  105. package/lib/commands/lifecycle-command-action.js +123 -0
  106. package/lib/commands/lifecycle-external.js +268 -0
  107. package/lib/commands/login.js +56 -17
  108. package/lib/commands/protection-cli-leaves.js +286 -0
  109. package/lib/commands/protection.js +50 -0
  110. package/lib/commands/repair-auth-apply.js +127 -0
  111. package/lib/commands/repair-changed-files.js +41 -0
  112. package/lib/commands/repair-datasource-keys.js +4 -1
  113. package/lib/commands/repair-datasource-run.js +59 -0
  114. package/lib/commands/repair-datasource-test-payload.js +259 -0
  115. package/lib/commands/repair-datasource.js +1 -51
  116. package/lib/commands/repair-env-template.js +64 -13
  117. package/lib/commands/repair-external-run.js +216 -0
  118. package/lib/commands/repair-openapi-sync.js +23 -0
  119. package/lib/commands/repair-persist.js +4 -0
  120. package/lib/commands/repair-rbac.js +52 -1
  121. package/lib/commands/repair-steps.js +145 -0
  122. package/lib/commands/repair.js +29 -286
  123. package/lib/commands/secrets-get.js +184 -0
  124. package/lib/commands/secrets-remove-all.js +3 -1
  125. package/lib/commands/setup-image-refresh.js +146 -0
  126. package/lib/commands/setup-modes.js +158 -162
  127. package/lib/commands/setup-platform-auth.js +76 -0
  128. package/lib/commands/setup-prompts-admin.js +244 -0
  129. package/lib/commands/setup-prompts-platform-mode.js +67 -0
  130. package/lib/commands/setup-prompts-validators.js +36 -0
  131. package/lib/commands/setup-prompts.js +24 -76
  132. package/lib/commands/setup-run-context.js +45 -0
  133. package/lib/commands/setup-spinners.js +39 -0
  134. package/lib/commands/setup.js +27 -5
  135. package/lib/commands/teardown.js +39 -0
  136. package/lib/commands/test-e2e-external.js +61 -14
  137. package/lib/commands/test-governance-cli-options.js +47 -0
  138. package/lib/commands/test-governance-external.js +67 -0
  139. package/lib/commands/test-trust-cli-options.js +32 -0
  140. package/lib/commands/test-trust-external.js +126 -0
  141. package/lib/commands/up-common.js +25 -13
  142. package/lib/commands/up-dataplane.js +50 -13
  143. package/lib/commands/upload-publish-context.js +75 -0
  144. package/lib/commands/upload-sidecar-followups.js +89 -0
  145. package/lib/commands/upload.js +108 -105
  146. package/lib/commands/verify-governance-combined-external.js +61 -0
  147. package/lib/commands/verify-governance-command-action.js +64 -0
  148. package/lib/commands/verify-governance-db.js +102 -0
  149. package/lib/commands/verify-governance-external.js +77 -0
  150. package/lib/commands/verify-governance-result-builders.js +71 -0
  151. package/lib/commands/verify-operations-command-action.js +68 -0
  152. package/lib/commands/verify-operations-external.js +268 -0
  153. package/lib/commands/verify-operations-persist.js +75 -0
  154. package/lib/commands/verify-operations-step-plan.js +68 -0
  155. package/lib/commands/verify-operations-steps.js +111 -0
  156. package/lib/commands/verify-trust-command-action.js +70 -0
  157. package/lib/commands/verify-trust-external.js +67 -0
  158. package/lib/commands/wizard-config-normalizer.js +43 -23
  159. package/lib/commands/wizard-core.js +5 -0
  160. package/lib/core/admin-password-generator.js +38 -0
  161. package/lib/core/admin-secrets-bundle.js +111 -0
  162. package/lib/core/admin-secrets-env-overlay.js +62 -0
  163. package/lib/core/admin-secrets.js +32 -4
  164. package/lib/core/config-attach-extensions.js +3 -0
  165. package/lib/core/config-device-dataplane.js +185 -0
  166. package/lib/core/config-platform-controller.js +44 -0
  167. package/lib/core/config-setup-installation-profile.js +42 -0
  168. package/lib/core/config-setup-platform-mode.js +46 -0
  169. package/lib/core/config.js +46 -36
  170. package/lib/core/secrets-admin-env.js +6 -2
  171. package/lib/core/secrets-ensure.js +4 -0
  172. package/lib/core/secrets-env-content.js +54 -48
  173. package/lib/core/secrets-env-write.js +10 -1
  174. package/lib/core/secrets-infra-placeholder-sync.js +2 -0
  175. package/lib/core/setup-installation-profile.js +43 -0
  176. package/lib/core/setup-platform-mode.js +55 -0
  177. package/lib/datasource/agent-trust-debug-log.js +45 -0
  178. package/lib/datasource/agent-trust-fetch.js +115 -0
  179. package/lib/datasource/agent-trust-map.js +101 -0
  180. package/lib/datasource/agent-trust-mock.js +44 -0
  181. package/lib/datasource/agent-trust-run.js +95 -0
  182. package/lib/datasource/agent-trust-timeout.js +25 -0
  183. package/lib/datasource/audit-evidence-display.js +80 -0
  184. package/lib/datasource/audit-evidence-extract-debug.js +115 -0
  185. package/lib/datasource/audit-evidence-extract.js +180 -0
  186. package/lib/datasource/audit-evidence-matrix-rows.js +158 -0
  187. package/lib/datasource/audit-evidence-operation-aliases.js +63 -0
  188. package/lib/datasource/audit-evidence-poll.js +109 -0
  189. package/lib/datasource/audit-evidence-run.js +177 -0
  190. package/lib/datasource/audit-evidence-verify-helpers.js +167 -0
  191. package/lib/datasource/audit-evidence-verify-matrix.js +205 -0
  192. package/lib/datasource/audit-evidence-verify.js +108 -0
  193. package/lib/datasource/bulk-loader-run-batches.js +100 -0
  194. package/lib/datasource/bulk-loader-service-retry.js +52 -0
  195. package/lib/datasource/bulk-loader-service.js +127 -0
  196. package/lib/datasource/capability/run-capability-dimension.js +2 -1
  197. package/lib/datasource/datasource-exporter-resolve.js +82 -0
  198. package/lib/datasource/datasource-exporter-service.js +144 -0
  199. package/lib/datasource/datasource-identifier.js +148 -0
  200. package/lib/datasource/datasource-load-export-context.js +95 -0
  201. package/lib/datasource/integration-context.js +6 -4
  202. package/lib/datasource/local-data-paths.js +145 -0
  203. package/lib/datasource/log-cleaner.js +241 -0
  204. package/lib/datasource/log-viewer.js +111 -6
  205. package/lib/datasource/record-file-parser.js +85 -0
  206. package/lib/datasource/record-mapper.js +129 -0
  207. package/lib/datasource/resolve-app.js +74 -55
  208. package/lib/datasource/test-e2e.js +29 -2
  209. package/lib/datasource/unified-validation-run-body.js +3 -1
  210. package/lib/datasource/unified-validation-run-resolve.js +45 -12
  211. package/lib/datasource/unified-validation-run.js +47 -18
  212. package/lib/datasource/validate.js +37 -20
  213. package/lib/deployment/environment-poll-status.js +138 -0
  214. package/lib/deployment/environment.js +42 -34
  215. package/lib/external-system/download.js +21 -20
  216. package/lib/external-system/generator.js +5 -1
  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-system-level.js +25 -4
  220. package/lib/external-system/test.js +9 -7
  221. package/lib/generator/external-controller-manifest.js +15 -0
  222. package/lib/governance/governance-cli-errors.js +96 -0
  223. package/lib/governance/governance-download-display.js +38 -0
  224. package/lib/governance/governance-pack-loader.js +70 -0
  225. package/lib/governance/governance-run-display.js +309 -0
  226. package/lib/identity/identity-apply-core.js +108 -0
  227. package/lib/identity/identity-apply-phases.js +244 -0
  228. package/lib/identity/identity-apply-service.js +77 -0
  229. package/lib/identity/identity-csv-parser.js +114 -0
  230. package/lib/infrastructure/admin-secrets-apply.js +84 -0
  231. package/lib/infrastructure/admin-secrets-ensure.js +130 -0
  232. package/lib/infrastructure/admin-secrets-resolve.js +95 -0
  233. package/lib/infrastructure/admin-secrets-sync.js +91 -0
  234. package/lib/infrastructure/helpers.js +23 -129
  235. package/lib/infrastructure/index.js +5 -6
  236. package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
  237. package/lib/internal/fs-real-sync.js +29 -1
  238. package/lib/lifecycle/certification-progress.js +231 -0
  239. package/lib/lifecycle/dataplane-ui-url.js +145 -0
  240. package/lib/lifecycle/exit-codes.js +24 -0
  241. package/lib/lifecycle/json-envelope.js +25 -0
  242. package/lib/lifecycle/lifecycle-governance-options.js +51 -0
  243. package/lib/lifecycle/logger-quiet.js +29 -0
  244. package/lib/lifecycle/open-api-published.js +59 -0
  245. package/lib/lifecycle/operations-readiness-metrics.js +101 -0
  246. package/lib/lifecycle/product-model.js +196 -0
  247. package/lib/lifecycle/report-display.js +471 -0
  248. package/lib/lifecycle/scenario-upload.js +191 -0
  249. package/lib/lifecycle/verify-step-progress.js +87 -0
  250. package/lib/parameters/infra-kv-discovery.js +27 -2
  251. package/lib/protection/auth-context.js +51 -0
  252. package/lib/protection/convert-batch.js +90 -0
  253. package/lib/protection/load.js +41 -0
  254. package/lib/protection/paths.js +158 -0
  255. package/lib/protection/preflight-datasource-ready.js +46 -0
  256. package/lib/protection/protection-create-probe-lines.js +142 -0
  257. package/lib/protection/protection-create-probes.js +95 -0
  258. package/lib/protection/protection-create-scaffold.js +281 -0
  259. package/lib/protection/protection-display-helpers.js +445 -0
  260. package/lib/protection/protection-display.js +215 -0
  261. package/lib/protection/protection-preset-registry.js +97 -0
  262. package/lib/protection/report-exit.js +62 -0
  263. package/lib/protection/resolve.js +202 -0
  264. package/lib/protection/run-commands-validate.js +130 -0
  265. package/lib/protection/run-commands.js +216 -0
  266. package/lib/protection/run-protection-create-helpers.js +134 -0
  267. package/lib/protection/run-protection-create-probes-flow.js +43 -0
  268. package/lib/protection/run-protection-create.js +191 -0
  269. package/lib/protection/scope.js +22 -0
  270. package/lib/protection/sync-after-upload.js +64 -0
  271. package/lib/protection/upload-batch.js +127 -0
  272. package/lib/protection/validate-batch.js +113 -0
  273. package/lib/protection/validate-local.js +65 -0
  274. package/lib/resolvers/dimension-file.js +29 -4
  275. package/lib/schema/application-schema.json +1 -1
  276. package/lib/schema/datasource-test-run.schema.json +89 -6
  277. package/lib/schema/external-datasource.schema.json +2636 -2588
  278. package/lib/schema/external-system.schema.json +1089 -761
  279. package/lib/schema/flag-map-validation-run.json +2 -2
  280. package/lib/schema/infra.parameter.yaml +45 -0
  281. package/lib/schema/protection.schema.json +374 -0
  282. package/lib/schema/type/credential-field-registry.json +642 -0
  283. package/lib/schema/wizard-config.schema.json +1 -1
  284. package/lib/utils/agent-trust-run-display.js +231 -0
  285. package/lib/utils/agent-trust-run-exit.js +59 -0
  286. package/lib/utils/agent-trust-wait-ui.js +94 -0
  287. package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
  288. package/lib/utils/api.js +55 -31
  289. package/lib/utils/app-relative-path-env.js +112 -0
  290. package/lib/utils/cli-exit-codes.js +30 -0
  291. package/lib/utils/cli-secrets-error-format.js +83 -21
  292. package/lib/utils/cli-sync-options.js +33 -0
  293. package/lib/utils/cli-utils.js +16 -4
  294. package/lib/utils/compose-generate-docker-compose.js +4 -0
  295. package/lib/utils/compose-traefik-ingress-base.js +16 -1
  296. package/lib/utils/config-secrets-path.js +46 -0
  297. package/lib/utils/controller-url.js +88 -1
  298. package/lib/utils/credential-push-ui.js +90 -0
  299. package/lib/utils/credential-secrets-env.js +137 -9
  300. package/lib/utils/dataplane-cli-version-gate.js +202 -0
  301. package/lib/utils/dataplane-cli-version-help.js +74 -0
  302. package/lib/utils/dataplane-resolver.js +129 -2
  303. package/lib/utils/datasource-export-display.js +137 -0
  304. package/lib/utils/datasource-load-display.js +174 -0
  305. package/lib/utils/datasource-load-export-ui.js +120 -0
  306. package/lib/utils/datasource-test-run-capability-scope.js +3 -3
  307. package/lib/utils/datasource-test-run-display.js +3 -3
  308. package/lib/utils/datasource-test-run-tty-log.js +5 -1
  309. package/lib/utils/declarative-url-ports.js +3 -3
  310. package/lib/utils/deployment-auth-mode.js +41 -0
  311. package/lib/utils/developer-volume-id.js +33 -0
  312. package/lib/utils/env-copy.js +14 -9
  313. package/lib/utils/env-kv-orphan-lines.js +43 -0
  314. package/lib/utils/error-formatters/network-errors.js +13 -4
  315. package/lib/utils/external-env-template.js +1 -0
  316. package/lib/utils/external-system-readiness-core.js +10 -0
  317. package/lib/utils/external-system-readiness-display.js +80 -23
  318. package/lib/utils/health-check.js +4 -1
  319. package/lib/utils/help-builder.js +35 -26
  320. package/lib/utils/keycloak-realm-ready.js +101 -0
  321. package/lib/utils/load-cip-capacity-display-config.js +61 -15
  322. package/lib/utils/manifest-source-emit.js +24 -0
  323. package/lib/utils/pipeline-upload-auth-retry.js +82 -0
  324. package/lib/utils/platform-controller-url.js +156 -0
  325. package/lib/utils/postgres-platform-bootstrap.js +199 -0
  326. package/lib/utils/postgres-wipe.js +9 -2
  327. package/lib/utils/resolve-env-mode.js +47 -0
  328. package/lib/utils/secrets-generator.js +31 -25
  329. package/lib/utils/secrets-missing-error.js +164 -0
  330. package/lib/utils/semver-compare.js +127 -0
  331. package/lib/utils/service-url-label.js +81 -0
  332. package/lib/utils/setup-quiet-output.js +25 -0
  333. package/lib/utils/template-helpers.js +15 -0
  334. package/lib/utils/token-manager-client-credentials.js +201 -0
  335. package/lib/utils/token-manager-messages.js +8 -0
  336. package/lib/utils/token-manager-refresh.js +12 -2
  337. package/lib/utils/token-manager.js +86 -105
  338. package/lib/utils/upload-pipeline-ui.js +98 -0
  339. package/lib/utils/upload-sync-options.js +42 -0
  340. package/lib/utils/url-declarative-public-base.js +21 -3
  341. package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
  342. package/lib/utils/validation-poll-ui.js +22 -7
  343. package/lib/utils/validation-run-stage.js +45 -0
  344. package/lib/validation/wizard-config-validator.js +58 -19
  345. package/package.json +1 -1
  346. package/templates/applications/dataplane/application.yaml +2 -1
  347. package/templates/applications/dataplane/env.template +36 -1
  348. package/templates/applications/dataplane/rbac.yaml +4 -0
  349. package/templates/applications/miso-controller/env.template +16 -0
  350. package/templates/external-system/README.md.hbs +116 -11
  351. package/templates/python/docker-compose.hbs +19 -18
  352. package/templates/typescript/docker-compose.hbs +18 -17
@@ -0,0 +1,205 @@
1
+ /**
2
+ * @fileoverview Build matrix rows 1–9 for audit evidence verification
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const {
10
+ queryExecutions,
11
+ queryRbacDecisions,
12
+ queryAbacTraces,
13
+ getExecutionRbac,
14
+ getExecutionAbac,
15
+ getExecutionErrors,
16
+ getExecutionSteps,
17
+ getExecutionTrace
18
+ } = require('../api/audit.api');
19
+ const {
20
+ checkRow1ExecutionsByDatasource,
21
+ checkRow2RbacDecisionsList,
22
+ checkRow3AbacTracesList
23
+ } = require('./audit-evidence-matrix-rows');
24
+ const {
25
+ operationQueryVariants,
26
+ executionsCoverExpectedOperations
27
+ } = require('./audit-evidence-operation-aliases');
28
+ const {
29
+ checkRow8CorrelationGroup,
30
+ resolveRow8Executions,
31
+ checkRow9Traces,
32
+ isRbacSubResourceValid,
33
+ isAbacSubResourceValid,
34
+ isErrorsValid,
35
+ isStepsValid,
36
+ resolveExecutionIdsForChecks,
37
+ checkPerExecutionSub
38
+ } = require('./audit-evidence-verify-helpers');
39
+
40
+ /**
41
+ * @param {string} dataplaneUrl
42
+ * @param {Object} authConfig
43
+ * @param {string} correlationId
44
+ * @param {string[]} expectedOperations
45
+ * @returns {Promise<Array>}
46
+ */
47
+ async function fetchCorrelationExecutionsByOperation(
48
+ dataplaneUrl,
49
+ authConfig,
50
+ correlationId,
51
+ expectedOperations
52
+ ) {
53
+ const deduped = new Map();
54
+ for (const rawOp of expectedOperations) {
55
+ const variants = operationQueryVariants(rawOp);
56
+ for (const op of variants) {
57
+ const res = await queryExecutions(dataplaneUrl, authConfig, {
58
+ correlationId,
59
+ operation: op,
60
+ pageSize: 20
61
+ });
62
+ for (const row of res.data || []) {
63
+ if (row && row.id) deduped.set(String(row.id), row);
64
+ }
65
+ }
66
+ }
67
+ const merged = [...deduped.values()];
68
+ return executionsCoverExpectedOperations(merged, expectedOperations) ? merged : [];
69
+ }
70
+
71
+ /**
72
+ * @param {Object} ctx
73
+ * @param {Object} polled
74
+ * @param {number} minExpected
75
+ * @returns {Promise<import('../api/types/audit.types').AuditEvidenceMatrixRow[]>}
76
+ */
77
+ async function buildListMatrixRows(ctx, polled, minExpected) {
78
+ const executions = polled.data || [];
79
+ const { dataplaneUrl, authConfig } = ctx;
80
+ const totalItems =
81
+ polled.meta && polled.meta.totalItems !== undefined
82
+ ? polled.meta.totalItems
83
+ : executions.length;
84
+ const rows = [
85
+ checkRow1ExecutionsByDatasource({
86
+ executions,
87
+ totalItems,
88
+ minExpected
89
+ })
90
+ ];
91
+ const rbacList = await queryRbacDecisions(dataplaneUrl, authConfig, {
92
+ targetDatasourceKey: ctx.datasourceKey,
93
+ pageSize: 100
94
+ });
95
+ rows.push(
96
+ checkRow2RbacDecisionsList({
97
+ rbacItems: rbacList.data,
98
+ totalItems: rbacList.meta && rbacList.meta.totalItems
99
+ })
100
+ );
101
+ const abacList = await queryAbacTraces(dataplaneUrl, authConfig, {
102
+ datasourceKey: ctx.datasourceKey,
103
+ pageSize: 100
104
+ });
105
+ rows.push(
106
+ checkRow3AbacTracesList({
107
+ abacItems: abacList.data,
108
+ totalItems: abacList.meta && abacList.meta.totalItems
109
+ })
110
+ );
111
+ return rows;
112
+ }
113
+
114
+ /**
115
+ * @param {Object} ctx
116
+ * @param {string[]} execIds
117
+ * @returns {Promise<import('../api/types/audit.types').AuditEvidenceMatrixRow[]>}
118
+ */
119
+ async function buildPerExecutionSubRows(ctx, execIds) {
120
+ const { dataplaneUrl, authConfig } = ctx;
121
+ const base = { dataplaneUrl, authConfig, executionId: execIds[0] };
122
+ return Promise.all([
123
+ checkPerExecutionSub({ ...base, rowNum: 4, label: 'rbac', fetcher: getExecutionRbac, isValid: isRbacSubResourceValid }),
124
+ checkPerExecutionSub({ ...base, rowNum: 5, label: 'abac', fetcher: getExecutionAbac, isValid: isAbacSubResourceValid }),
125
+ checkPerExecutionSub({ ...base, rowNum: 6, label: 'errors', fetcher: getExecutionErrors, isValid: isErrorsValid }),
126
+ checkPerExecutionSub({ ...base, rowNum: 7, label: 'steps', fetcher: getExecutionSteps, isValid: isStepsValid })
127
+ ]);
128
+ }
129
+
130
+ /**
131
+ * @param {Object} ctx
132
+ * @param {Array} executions
133
+ * @returns {Promise<Array>}
134
+ */
135
+ async function resolveRow8PoolForMatrix(ctx, executions) {
136
+ const { dataplaneUrl, authConfig } = ctx;
137
+ let corrQueryRows = [];
138
+ if (ctx.correlationId) {
139
+ const corr = await queryExecutions(dataplaneUrl, authConfig, {
140
+ correlationId: ctx.correlationId,
141
+ pageSize: 100
142
+ });
143
+ corrQueryRows = corr.data || [];
144
+ }
145
+ const row8Pool = corrQueryRows.length ? corrQueryRows : executions;
146
+ const expected = ctx.expectedOperations || [];
147
+ if (!expected.length || !ctx.correlationId) {
148
+ return row8Pool;
149
+ }
150
+ const byOp = await fetchCorrelationExecutionsByOperation(
151
+ dataplaneUrl,
152
+ authConfig,
153
+ ctx.correlationId,
154
+ expected
155
+ );
156
+ return byOp.length ? byOp : row8Pool;
157
+ }
158
+
159
+ /**
160
+ * @param {Object} ctx
161
+ * @param {string[]} execIds
162
+ * @returns {Promise<Set<string>>}
163
+ */
164
+ async function collectTraceIdsForRow9(ctx, execIds) {
165
+ const { dataplaneUrl, authConfig } = ctx;
166
+ const traceIds = new Set();
167
+ const sample = execIds.slice(0, Math.min(execIds.length, 12));
168
+ for (const id of sample) {
169
+ try {
170
+ const tr = await getExecutionTrace(dataplaneUrl, authConfig, id);
171
+ if (tr && tr.executionId) traceIds.add(String(tr.executionId));
172
+ else if (tr && tr.id) traceIds.add(String(tr.id));
173
+ } catch {
174
+ /* row 9 may fail */
175
+ }
176
+ }
177
+ return traceIds;
178
+ }
179
+
180
+ /**
181
+ * @param {Object} ctx
182
+ * @param {Array} executions
183
+ * @param {string[]} executionIds
184
+ * @returns {Promise<{ rows: import('../api/types/audit.types').AuditEvidenceMatrixRow[], execIds: string[] }>}
185
+ */
186
+ async function buildPerExecutionAndTailRows(ctx, executions, executionIds) {
187
+ const execIds = resolveExecutionIdsForChecks(executions, executionIds);
188
+ const rows = await buildPerExecutionSubRows(ctx, execIds);
189
+ const row8Pool = await resolveRow8PoolForMatrix(ctx, executions);
190
+ const row8Executions = resolveRow8Executions(ctx, executions, row8Pool);
191
+ rows.push(
192
+ checkRow8CorrelationGroup({
193
+ correlationId: ctx.correlationId,
194
+ executions: row8Executions,
195
+ expectedOperations: ctx.expectedOperations
196
+ })
197
+ );
198
+ rows.push(checkRow9Traces(await collectTraceIdsForRow9(ctx, execIds), execIds));
199
+ return { rows, execIds };
200
+ }
201
+
202
+ module.exports = {
203
+ buildListMatrixRows,
204
+ buildPerExecutionAndTailRows
205
+ };
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @fileoverview Run Plan 407.1 nine-row audit evidence matrix against dataplane APIs
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { queryExecutions } = require('../api/audit.api');
10
+ const { pollExecutionsUntilReady } = require('./audit-evidence-poll');
11
+ const {
12
+ buildListMatrixRows,
13
+ buildPerExecutionAndTailRows
14
+ } = require('./audit-evidence-verify-matrix');
15
+ const { checkRow8CorrelationGroup, checkRow9Traces } = require('./audit-evidence-verify-helpers');
16
+
17
+ /**
18
+ * @param {Object} ctx
19
+ * @returns {number}
20
+ */
21
+ /**
22
+ * E2E runs tag executions with testRunId as correlationId; prefer that for list poll.
23
+ * @param {Object} ctx
24
+ * @returns {Object}
25
+ */
26
+ function buildExecutionsPollQuery(ctx) {
27
+ const base = { pageSize: 100, sort: '-startedAt' };
28
+ if (ctx.correlationId) {
29
+ return { ...base, correlationId: ctx.correlationId };
30
+ }
31
+ return { ...base, datasourceKey: ctx.datasourceKey };
32
+ }
33
+
34
+ function resolveMinExpected(ctx) {
35
+ const fromOps = ctx.expectedOperations && ctx.expectedOperations.length;
36
+ const fromIds = ctx.executionIds && ctx.executionIds.length;
37
+ if (fromIds && fromOps) {
38
+ return Math.max(1, Math.min(fromOps, fromIds));
39
+ }
40
+ return Math.max(1, fromOps || fromIds || 1);
41
+ }
42
+
43
+ /**
44
+ * @param {string} datasourceKey
45
+ * @param {Object} ctx
46
+ * @returns {import('../api/types/audit.types').AuditEvidenceVerification}
47
+ */
48
+ function failedMissingIds(datasourceKey, ctx) {
49
+ return {
50
+ status: 'failed',
51
+ datasourceKey,
52
+ correlationId: ctx.correlationId || null,
53
+ executionIds: [],
54
+ matrix: [
55
+ {
56
+ row: 0,
57
+ status: 'failed',
58
+ detail: 'missing audit.executionIds in envelope',
59
+ code: 'auditIdsMissing'
60
+ }
61
+ ]
62
+ };
63
+ }
64
+
65
+ /**
66
+ * @param {Object} ctx
67
+ * @returns {Promise<import('../api/types/audit.types').AuditEvidenceVerification>}
68
+ */
69
+ async function verifyAuditEvidenceMatrix(ctx) {
70
+ const datasourceKey = ctx.datasourceKey || '';
71
+ const executionIds = Array.isArray(ctx.executionIds) ? ctx.executionIds : [];
72
+ if (!executionIds.length && !ctx.correlationId) {
73
+ return failedMissingIds(datasourceKey, ctx);
74
+ }
75
+
76
+ const { dataplaneUrl, authConfig } = ctx;
77
+ const minExpected = resolveMinExpected(ctx);
78
+ const execQuery = buildExecutionsPollQuery(ctx);
79
+ const polled = await pollExecutionsUntilReady({
80
+ fetchExecutions: () => queryExecutions(dataplaneUrl, authConfig, execQuery),
81
+ minExpected,
82
+ executionIds,
83
+ maxWaitMs: ctx.maxWaitMs,
84
+ intervalMs: ctx.intervalMs
85
+ });
86
+
87
+ const executions = polled.data || [];
88
+ const matrix = await buildListMatrixRows(ctx, polled, minExpected);
89
+ const tail = await buildPerExecutionAndTailRows(ctx, executions, executionIds);
90
+ matrix.push(...tail.rows);
91
+
92
+ const passed = matrix.every(r => r.status === 'passed');
93
+ return {
94
+ status: passed ? 'passed' : 'failed',
95
+ datasourceKey,
96
+ correlationId: ctx.correlationId || null,
97
+ executionIds: tail.execIds,
98
+ matrix
99
+ };
100
+ }
101
+
102
+ module.exports = {
103
+ verifyAuditEvidenceMatrix,
104
+ buildExecutionsPollQuery,
105
+ resolveMinExpected,
106
+ checkRow8CorrelationGroup,
107
+ checkRow9Traces
108
+ };
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @fileoverview Batch upload loop for datasource load (plan 144)
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { bulkSyncRecords } = require('../api/records-bulk.api');
10
+ const { withTransientRetry, errorStatusCode } = require('./bulk-loader-service-retry');
11
+
12
+ /**
13
+ * @param {Object} state
14
+ * @param {number} index
15
+ * @param {Error} err
16
+ * @param {Object[]} batchRecords
17
+ */
18
+ function recordBatchFailure(state, index, err, batchRecords) {
19
+ state.batches.push({
20
+ index: index + 1,
21
+ total: state.chunkCount,
22
+ error: err.message || String(err),
23
+ statusCode: errorStatusCode(err),
24
+ recordCount: batchRecords.length,
25
+ failed: batchRecords.map(r => ({ key: r.key, message: err.message || String(err) }))
26
+ });
27
+ state.totals.failedCount += batchRecords.length;
28
+ }
29
+
30
+ /**
31
+ * @param {Object} state
32
+ * @param {number} index
33
+ * @param {Object} response
34
+ * @param {Object[]} batchRecords
35
+ */
36
+ function recordBatchSuccess(state, index, response, batchRecords) {
37
+ if (!response || typeof response !== 'object') {
38
+ throw new Error('Bulk sync returned empty response');
39
+ }
40
+ if (response.success === false) {
41
+ throw new Error(
42
+ response.formattedError ||
43
+ response.error ||
44
+ `Bulk sync failed (HTTP ${response.status || 0})`
45
+ );
46
+ }
47
+ const payload =
48
+ response.data !== undefined && response.data !== null ? response.data : response;
49
+ const inserted = payload.insertedCount || 0;
50
+ const updated = payload.updatedCount || 0;
51
+ const processed = payload.totalProcessed || batchRecords.length;
52
+ const failedInBatch = Math.max(0, batchRecords.length - processed);
53
+
54
+ state.batches.push({
55
+ index: index + 1,
56
+ total: state.chunkCount,
57
+ insertedCount: inserted,
58
+ updatedCount: updated,
59
+ totalProcessed: processed,
60
+ failed: failedInBatch > 0 ? [{ message: 'Some records were not processed' }] : []
61
+ });
62
+ state.totals.insertedCount += inserted;
63
+ state.totals.updatedCount += updated;
64
+ state.totals.failedCount += failedInBatch;
65
+ }
66
+
67
+ /**
68
+ * @async
69
+ * @param {Object} params
70
+ * @returns {Promise<{ batches: Object[], totals: Object }>}
71
+ */
72
+ async function uploadRecordBatches(params) {
73
+ const { chunks, syncType, dataplaneUrl, datasourceKey, authConfig } = params;
74
+ const state = {
75
+ batches: [],
76
+ totals: { insertedCount: 0, updatedCount: 0, failedCount: 0 },
77
+ chunkCount: chunks.length
78
+ };
79
+
80
+ for (let i = 0; i < chunks.length; i += 1) {
81
+ const batchRecords = chunks[i];
82
+ const body = { syncType, sync: false, records: batchRecords };
83
+ try {
84
+ const response = await withTransientRetry(() =>
85
+ bulkSyncRecords(dataplaneUrl, datasourceKey, authConfig, body)
86
+ );
87
+ recordBatchSuccess(state, i, response, batchRecords);
88
+ } catch (err) {
89
+ recordBatchFailure(state, i, err, batchRecords);
90
+ }
91
+ }
92
+
93
+ return { batches: state.batches, totals: state.totals };
94
+ }
95
+
96
+ module.exports = {
97
+ uploadRecordBatches,
98
+ recordBatchFailure,
99
+ recordBatchSuccess
100
+ };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @fileoverview Retry helpers for bulk loader (plan 144)
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const MAX_RETRIES = 3;
10
+ const RETRY_STATUS = new Set([429, 500, 502, 503, 504]);
11
+
12
+ /**
13
+ * @param {Error} err
14
+ * @returns {number|null}
15
+ */
16
+ function errorStatusCode(err) {
17
+ if (!err || typeof err !== 'object') return null;
18
+ if (typeof err.statusCode === 'number') return err.statusCode;
19
+ if (err.response && typeof err.response.status === 'number') return err.response.status;
20
+ return null;
21
+ }
22
+
23
+ function sleep(ms) {
24
+ return new Promise(resolve => setTimeout(resolve, ms));
25
+ }
26
+
27
+ /**
28
+ * @async
29
+ * @param {Function} fn
30
+ * @returns {Promise<*>}
31
+ */
32
+ async function withTransientRetry(fn) {
33
+ let lastErr;
34
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt += 1) {
35
+ try {
36
+ return await fn();
37
+ } catch (err) {
38
+ lastErr = err;
39
+ const code = errorStatusCode(err);
40
+ if (!code || !RETRY_STATUS.has(code) || attempt >= MAX_RETRIES - 1) {
41
+ throw err;
42
+ }
43
+ await sleep(500 * (attempt + 1));
44
+ }
45
+ }
46
+ throw lastErr;
47
+ }
48
+
49
+ module.exports = {
50
+ withTransientRetry,
51
+ errorStatusCode
52
+ };
@@ -0,0 +1,127 @@
1
+ /**
2
+ * @fileoverview Load local fixtures via dataplane bulk record sync (plan 144)
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { resolveDataFilePath } = require('./local-data-paths');
10
+ const { parseRecordFile, estimatePayloadBytes } = require('./record-file-parser');
11
+ const { normalizeRecordsForBulk } = require('./record-mapper');
12
+ const { resolveLoadExportContext } = require('./datasource-load-export-context');
13
+ const { uploadRecordBatches } = require('./bulk-loader-run-batches');
14
+ const { runWithDatasourceLoadExportSpinner } = require('../utils/datasource-load-export-ui');
15
+
16
+ const DEFAULT_BATCH_SIZE = 100;
17
+
18
+ /**
19
+ * @param {Object[]} records
20
+ * @param {number} batchSize
21
+ * @returns {Object[][]}
22
+ */
23
+ function chunkRecords(records, batchSize) {
24
+ const size = Math.max(1, batchSize);
25
+ const chunks = [];
26
+ for (let i = 0; i < records.length; i += size) {
27
+ chunks.push(records.slice(i, i + size));
28
+ }
29
+ return chunks;
30
+ }
31
+
32
+ /**
33
+ * @param {Object} params
34
+ * @returns {Object}
35
+ */
36
+ function buildLoadResultBase(params) {
37
+ const { ctx, filePath, format, records, batchSize, syncType, dryRun } = params;
38
+ return {
39
+ datasourceKey: ctx.datasourceKey,
40
+ systemKey: ctx.systemKey,
41
+ appKey: ctx.appKey,
42
+ dryRun,
43
+ file: filePath,
44
+ format,
45
+ recordCount: records.length,
46
+ batchSize,
47
+ syncType,
48
+ estimatedPayloadBytes: estimatePayloadBytes(records),
49
+ batches: [],
50
+ totals: { insertedCount: 0, updatedCount: 0, failedCount: 0 }
51
+ };
52
+ }
53
+
54
+ /**
55
+ * @async
56
+ * @param {Object} params
57
+ * @returns {Promise<Object>}
58
+ */
59
+ async function executeDatasourceLoadWork(params) {
60
+ const { ctx, options, batchSize, syncType, dryRun } = params;
61
+ const { filePath, format } = resolveDataFilePath({
62
+ systemKey: ctx.systemKey,
63
+ entitySuffix: ctx.entitySuffix,
64
+ file: options.file,
65
+ format: options.format
66
+ });
67
+
68
+ const raw = parseRecordFile(filePath, format);
69
+ const records = normalizeRecordsForBulk(raw, ctx.datasource);
70
+ const result = buildLoadResultBase({
71
+ ctx,
72
+ filePath,
73
+ format,
74
+ records,
75
+ batchSize,
76
+ syncType,
77
+ dryRun
78
+ });
79
+
80
+ if (dryRun) {
81
+ return { ...result, context: ctx };
82
+ }
83
+
84
+ const { batches, totals } = await uploadRecordBatches({
85
+ chunks: chunkRecords(records, batchSize),
86
+ syncType,
87
+ dataplaneUrl: ctx.dataplaneUrl,
88
+ datasourceKey: ctx.datasourceKey,
89
+ authConfig: ctx.authConfig
90
+ });
91
+
92
+ return { ...result, batches, totals, context: ctx };
93
+ }
94
+
95
+ /**
96
+ * @async
97
+ * @param {string} datasourceKey
98
+ * @param {Object} options
99
+ * @returns {Promise<Object>}
100
+ */
101
+ async function runDatasourceLoad(datasourceKey, options = {}) {
102
+ const ctx = await resolveLoadExportContext(datasourceKey, options);
103
+ const batchSize = options.batchSize
104
+ ? parseInt(String(options.batchSize), 10)
105
+ : DEFAULT_BATCH_SIZE;
106
+ const syncType = options.syncType || 'incremental';
107
+ const dryRun = options.dryRun === true;
108
+ const startedAt = Date.now();
109
+
110
+ const payload = await runWithDatasourceLoadExportSpinner(
111
+ () => executeDatasourceLoadWork({ ctx, options, batchSize, syncType, dryRun }),
112
+ {
113
+ operation: dryRun ? 'load-dry-run' : 'load',
114
+ datasourceKey: ctx.datasourceKey,
115
+ json: options.json === true
116
+ }
117
+ );
118
+
119
+ return { ...payload, durationMs: Date.now() - startedAt };
120
+ }
121
+
122
+ module.exports = {
123
+ runDatasourceLoad,
124
+ chunkRecords,
125
+ buildLoadResultBase,
126
+ DEFAULT_BATCH_SIZE
127
+ };
@@ -43,7 +43,8 @@ async function maybeLoadDimensionCatalogKeys() {
43
43
  page: 1,
44
44
  pageSize: 500
45
45
  });
46
- const items = res?.data?.items || res?.data?.data?.items || res?.items || [];
46
+ const raw = res?.data?.items ?? res?.data?.data ?? res?.items;
47
+ const items = Array.isArray(raw) ? raw : raw?.items || [];
47
48
  const keys = new Set(
48
49
  Array.isArray(items) ? items.map((d) => String(d?.key || '').trim()).filter(Boolean) : []
49
50
  );
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @fileoverview Export path and search body helpers (plan 144)
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const path = require('path');
10
+ const { resolveDefaultDataOutputPath, inferFormatFromPath } = require('./local-data-paths');
11
+
12
+ /**
13
+ * @param {string|undefined} raw
14
+ * @returns {Object|undefined}
15
+ */
16
+ function parseFilterJson(raw) {
17
+ if (!raw || typeof raw !== 'string' || !raw.trim()) {
18
+ return undefined;
19
+ }
20
+ try {
21
+ const parsed = JSON.parse(raw);
22
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
23
+ return parsed;
24
+ }
25
+ throw new Error('filter must be a JSON object');
26
+ } catch (err) {
27
+ throw new Error(`Invalid --filter JSON: ${err.message}`);
28
+ }
29
+ }
30
+
31
+ /**
32
+ * @param {string|undefined} raw
33
+ * @returns {string[]|undefined}
34
+ */
35
+ function parseFieldsCsv(raw) {
36
+ if (!raw || typeof raw !== 'string' || !raw.trim()) {
37
+ return undefined;
38
+ }
39
+ return raw
40
+ .split(',')
41
+ .map(s => s.trim())
42
+ .filter(Boolean);
43
+ }
44
+
45
+ /**
46
+ * @param {Object} opts
47
+ * @returns {{ outputPath: string, format: 'json'|'ndjson', limit: number, intent: string, filters: Object|undefined, fields: string[]|undefined }}
48
+ */
49
+ function resolveExportOptions(opts) {
50
+ let limit = opts.limit ? parseInt(String(opts.limit), 10) : 1000;
51
+ if (Number.isNaN(limit) || limit < 1) {
52
+ limit = 1000;
53
+ }
54
+ limit = Math.min(limit, 10000);
55
+
56
+ const intent = opts.intent || 'validation';
57
+ const filters = parseFilterJson(opts.filter);
58
+ const fields = parseFieldsCsv(opts.fields);
59
+
60
+ let outputPath;
61
+ let format = opts.format;
62
+ if (opts.file && String(opts.file).trim()) {
63
+ outputPath = path.resolve(String(opts.file).trim());
64
+ format = format || inferFormatFromPath(outputPath);
65
+ } else {
66
+ const resolved = resolveDefaultDataOutputPath({
67
+ systemKey: opts.systemKey,
68
+ entitySuffix: opts.entitySuffix,
69
+ format: format || 'json'
70
+ });
71
+ outputPath = resolved.filePath;
72
+ format = opts.format || resolved.format;
73
+ }
74
+
75
+ return { outputPath, format, limit, intent, filters, fields };
76
+ }
77
+
78
+ module.exports = {
79
+ parseFilterJson,
80
+ parseFieldsCsv,
81
+ resolveExportOptions
82
+ };