@aifabrix/builder 2.45.0 → 2.45.5

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 (180) hide show
  1. package/.cursor/rules/docs-rules.mdc +3 -1
  2. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
  3. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
  4. package/integration/hubspot-test/wizard-hubspot-e2e.yaml +1 -1
  5. package/jest.projects.js +44 -1
  6. package/lib/api/agent-metadata-validation.api.js +93 -0
  7. package/lib/api/audit-api-helpers.js +68 -0
  8. package/lib/api/audit.api.js +119 -0
  9. package/lib/api/auth-cache.api.js +44 -0
  10. package/lib/api/certificates.api.js +4 -4
  11. package/lib/api/credential.api.js +2 -2
  12. package/lib/api/dataplane-health.api.js +137 -0
  13. package/lib/api/dataplane-sync.api.js +27 -0
  14. package/lib/api/datasources-core.api.js +21 -18
  15. package/lib/api/datasources-extended.api.js +22 -22
  16. package/lib/api/dimensions.api.js +3 -0
  17. package/lib/api/external-systems.api.js +13 -13
  18. package/lib/api/governance-scenarios.api.js +39 -0
  19. package/lib/api/groups.api.js +79 -0
  20. package/lib/api/index.js +45 -2
  21. package/lib/api/pipeline.api.js +4 -4
  22. package/lib/api/protection.api.js +157 -0
  23. package/lib/api/records-bulk.api.js +30 -0
  24. package/lib/api/records-search-parse.js +49 -0
  25. package/lib/api/records-search.api.js +29 -0
  26. package/lib/api/types/agent-metadata-validation.types.js +67 -0
  27. package/lib/api/types/audit.types.js +72 -0
  28. package/lib/api/types/dataplane-health.types.js +27 -0
  29. package/lib/api/types/dimensions.types.js +2 -0
  30. package/lib/api/types/governance-scenarios.types.js +39 -0
  31. package/lib/api/types/protection.types.js +69 -0
  32. package/lib/api/types/records-bulk.types.js +35 -0
  33. package/lib/api/types/records-search.types.js +28 -0
  34. package/lib/api/user-groups.api.js +50 -0
  35. package/lib/api/users.api.js +95 -0
  36. package/lib/api/validation-run.api.js +3 -3
  37. package/lib/api/validation-runner.js +3 -3
  38. package/lib/api/wizard-platform.api.js +3 -3
  39. package/lib/api/wizard.api.js +21 -21
  40. package/lib/app/deploy.js +34 -19
  41. package/lib/cli/index.js +4 -2
  42. package/lib/cli/infra-guided.js +22 -3
  43. package/lib/cli/setup-app.help.js +50 -2
  44. package/lib/cli/setup-app.js +33 -24
  45. package/lib/cli/setup-app.test-commands.js +80 -21
  46. package/lib/cli/setup-auth.js +30 -3
  47. package/lib/cli/setup-external-system.js +37 -3
  48. package/lib/cli/setup-utility-help-after.js +45 -0
  49. package/lib/cli/setup-utility-resolve.js +2 -2
  50. package/lib/cli/setup-utility.js +99 -81
  51. package/lib/commands/auth-status-dataplane-version.js +231 -0
  52. package/lib/commands/auth-status-display.js +94 -0
  53. package/lib/commands/auth-status.js +70 -6
  54. package/lib/commands/credential-push.js +10 -5
  55. package/lib/commands/datasource-load-export-cli.js +178 -0
  56. package/lib/commands/datasource-test-trust-cli.js +114 -0
  57. package/lib/commands/datasource-unified-test-cli.js +25 -17
  58. package/lib/commands/datasource-unified-test-cli.options.js +18 -3
  59. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +5 -5
  60. package/lib/commands/datasource-verify-audit-cli.js +96 -0
  61. package/lib/commands/datasource.js +68 -1
  62. package/lib/commands/dimension-value.js +43 -13
  63. package/lib/commands/dimension.js +38 -7
  64. package/lib/commands/identity-apply-sync.js +131 -0
  65. package/lib/commands/identity-group-cli.js +146 -0
  66. package/lib/commands/identity-membership-role-cache.js +175 -0
  67. package/lib/commands/identity-shared.js +94 -0
  68. package/lib/commands/identity-user-cli.js +158 -0
  69. package/lib/commands/identity.js +43 -0
  70. package/lib/commands/login.js +46 -16
  71. package/lib/commands/protection-cli-leaves.js +286 -0
  72. package/lib/commands/protection.js +50 -0
  73. package/lib/commands/repair.js +13 -3
  74. package/lib/commands/test-e2e-external.js +40 -9
  75. package/lib/commands/test-governance-cli-options.js +47 -0
  76. package/lib/commands/test-governance-command-action.js +55 -0
  77. package/lib/commands/test-governance-external.js +88 -0
  78. package/lib/commands/test-trust-cli-options.js +32 -0
  79. package/lib/commands/test-trust-command-action.js +118 -0
  80. package/lib/commands/test-trust-external.js +127 -0
  81. package/lib/commands/upload.js +34 -13
  82. package/lib/commands/wizard-core.js +3 -0
  83. package/lib/core/config-device-dataplane.js +185 -0
  84. package/lib/datasource/agent-trust-debug-log.js +45 -0
  85. package/lib/datasource/agent-trust-fetch.js +115 -0
  86. package/lib/datasource/agent-trust-map.js +101 -0
  87. package/lib/datasource/agent-trust-mock.js +44 -0
  88. package/lib/datasource/agent-trust-run.js +93 -0
  89. package/lib/datasource/agent-trust-timeout.js +25 -0
  90. package/lib/datasource/audit-evidence-display.js +80 -0
  91. package/lib/datasource/audit-evidence-extract-debug.js +103 -0
  92. package/lib/datasource/audit-evidence-extract.js +177 -0
  93. package/lib/datasource/audit-evidence-matrix-rows.js +158 -0
  94. package/lib/datasource/audit-evidence-operation-aliases.js +63 -0
  95. package/lib/datasource/audit-evidence-poll.js +109 -0
  96. package/lib/datasource/audit-evidence-run.js +177 -0
  97. package/lib/datasource/audit-evidence-verify-helpers.js +167 -0
  98. package/lib/datasource/audit-evidence-verify-matrix.js +177 -0
  99. package/lib/datasource/audit-evidence-verify.js +108 -0
  100. package/lib/datasource/bulk-loader-run-batches.js +88 -0
  101. package/lib/datasource/bulk-loader-service-retry.js +52 -0
  102. package/lib/datasource/bulk-loader-service.js +127 -0
  103. package/lib/datasource/capability/run-capability-dimension.js +2 -1
  104. package/lib/datasource/datasource-exporter-resolve.js +82 -0
  105. package/lib/datasource/datasource-exporter-service.js +144 -0
  106. package/lib/datasource/datasource-identifier.js +148 -0
  107. package/lib/datasource/datasource-load-export-context.js +92 -0
  108. package/lib/datasource/integration-context.js +6 -4
  109. package/lib/datasource/local-data-paths.js +145 -0
  110. package/lib/datasource/log-cleaner.js +241 -0
  111. package/lib/datasource/log-viewer.js +111 -6
  112. package/lib/datasource/record-file-parser.js +85 -0
  113. package/lib/datasource/record-mapper.js +129 -0
  114. package/lib/datasource/resolve-app.js +74 -55
  115. package/lib/datasource/test-e2e.js +26 -2
  116. package/lib/datasource/unified-validation-run-resolve.js +45 -12
  117. package/lib/datasource/unified-validation-run.js +43 -17
  118. package/lib/datasource/validate.js +37 -20
  119. package/lib/external-system/test-system-level.js +25 -4
  120. package/lib/external-system/test.js +3 -1
  121. package/lib/governance/governance-pack-loader.js +70 -0
  122. package/lib/governance/governance-run-display.js +119 -0
  123. package/lib/identity/identity-apply-core.js +108 -0
  124. package/lib/identity/identity-apply-phases.js +244 -0
  125. package/lib/identity/identity-apply-service.js +77 -0
  126. package/lib/identity/identity-csv-parser.js +114 -0
  127. package/lib/internal/fs-real-sync.js +29 -1
  128. package/lib/protection/auth-context.js +45 -0
  129. package/lib/protection/convert-batch.js +90 -0
  130. package/lib/protection/load.js +41 -0
  131. package/lib/protection/paths.js +158 -0
  132. package/lib/protection/preflight-datasource-ready.js +46 -0
  133. package/lib/protection/protection-create-probe-lines.js +142 -0
  134. package/lib/protection/protection-create-probes.js +95 -0
  135. package/lib/protection/protection-create-scaffold.js +281 -0
  136. package/lib/protection/protection-display-helpers.js +445 -0
  137. package/lib/protection/protection-display.js +215 -0
  138. package/lib/protection/protection-preset-registry.js +97 -0
  139. package/lib/protection/report-exit.js +62 -0
  140. package/lib/protection/resolve.js +202 -0
  141. package/lib/protection/run-commands-validate.js +130 -0
  142. package/lib/protection/run-commands.js +216 -0
  143. package/lib/protection/run-protection-create-helpers.js +134 -0
  144. package/lib/protection/run-protection-create-probes-flow.js +43 -0
  145. package/lib/protection/run-protection-create.js +191 -0
  146. package/lib/protection/scope.js +22 -0
  147. package/lib/protection/sync-after-upload.js +64 -0
  148. package/lib/protection/upload-batch.js +127 -0
  149. package/lib/protection/validate-batch.js +113 -0
  150. package/lib/protection/validate-local.js +65 -0
  151. package/lib/resolvers/dimension-file.js +29 -4
  152. package/lib/schema/external-datasource.schema.json +47 -13
  153. package/lib/schema/flag-map-validation-run.json +2 -2
  154. package/lib/schema/protection.schema.json +374 -0
  155. package/lib/schema/type/credential-field-registry.json +636 -0
  156. package/lib/schema/wizard-config.schema.json +1 -1
  157. package/lib/utils/agent-trust-run-display.js +231 -0
  158. package/lib/utils/agent-trust-run-exit.js +59 -0
  159. package/lib/utils/agent-trust-wait-ui.js +94 -0
  160. package/lib/utils/cli-exit-codes.js +30 -0
  161. package/lib/utils/cli-sync-options.js +33 -0
  162. package/lib/utils/credential-push-ui.js +90 -0
  163. package/lib/utils/dataplane-cli-version-gate.js +202 -0
  164. package/lib/utils/dataplane-cli-version-help.js +74 -0
  165. package/lib/utils/datasource-export-display.js +137 -0
  166. package/lib/utils/datasource-load-display.js +174 -0
  167. package/lib/utils/datasource-load-export-ui.js +120 -0
  168. package/lib/utils/datasource-test-run-capability-scope.js +3 -3
  169. package/lib/utils/datasource-test-run-display.js +3 -3
  170. package/lib/utils/datasource-test-run-tty-log.js +5 -1
  171. package/lib/utils/help-builder.js +30 -24
  172. package/lib/utils/manifest-source-emit.js +22 -0
  173. package/lib/utils/semver-compare.js +127 -0
  174. package/lib/utils/upload-pipeline-ui.js +91 -0
  175. package/lib/utils/validation-poll-ui.js +14 -7
  176. package/lib/validation/wizard-config-validator.js +58 -19
  177. package/package.json +1 -1
  178. package/templates/applications/dataplane/env.template +13 -1
  179. package/templates/applications/dataplane/rbac.yaml +4 -0
  180. package/templates/external-system/README.md.hbs +56 -8
@@ -5,10 +5,12 @@ alwaysApply: true
5
5
 
6
6
  ## Audience
7
7
 
8
- Documents under **docs/** (including **docs/commands/**) are **CLI developer / user documentation**. The audience is people who use the AI Fabrix Builder CLI or integrate it into workflows. They do not need to know how the CLI talks to the Controller or Dataplane over HTTP.
8
+ Documents under **docs/** (including **docs/commands/**) are **public CLI user documentation**. The audience is people who use the AI Fabrix Builder CLI or integrate it into workflows—they may **not** have access to private monorepos (dataplane, miso-controller, internal plans). They do not need to know how the CLI talks to the Controller or Dataplane over HTTP.
9
9
 
10
10
  ## Do Not Include in CLI User Docs
11
11
 
12
+ - **Links or paths into other product repos (FORBIDDEN)** – No markdown links, examples, or prerequisites that point at private/sibling repositories or their trees: `../../../aifabrix-dataplane/...`, `../../aifabrix-miso/...`, `packages/miso-controller/...`, `integration/<fixture>/README.md` in another repo, `.cursor/plans/` anywhere, `/workspace/...` monorepo layouts, or “see the dataplane/miso-controller repo”. **Only** cross-link within **`docs/`** and use on-disk paths the user owns (`integration/<systemKey>/...`, `builder/<appKey>/...`, `~/.aifabrix/...`).
13
+ - **Internal plan or ticket IDs** – No “Plan 407.1”, “plan section 2.3”, or similar; describe behavior in user terms.
12
14
  - **REST API details** – No HTTP methods, URL paths, or endpoint names (e.g. `GET /api/v1/...`, `POST .../pipeline/upload`).
13
15
  - **Request/response shapes** – No payload structures, status codes, or field names from backend APIs.
14
16
  - **Backend implementation terms** – Avoid referring to “pipeline config endpoint”, “upload endpoint”, or similar; describe what the **command** does from the user’s perspective.
@@ -2,7 +2,7 @@ appName: wizard-e2e-credential-real
2
2
  mode: create-system
3
3
  source:
4
4
  type: openapi-file
5
- filePath: /workspace/aifabrix-builder/integration/hubspot-test/companies.json
5
+ filePath: ./integration/hubspot-test/companies.json
6
6
  credential:
7
7
  action: create
8
8
  config:
@@ -2,7 +2,7 @@ appName: wizard-e2e-env-vars
2
2
  mode: create-system
3
3
  source:
4
4
  type: openapi-file
5
- filePath: /workspace/aifabrix-builder/integration/hubspot-test/companies.json
5
+ filePath: ./integration/hubspot-test/companies.json
6
6
  deployment:
7
7
  controller: ${CONTROLLER_URL}
8
8
  dataplane: ${DATAPLANE_URL}
@@ -2,7 +2,7 @@ appName: wizard-e2e-e2e
2
2
  mode: create-system
3
3
  source:
4
4
  type: openapi-file
5
- filePath: /workspace/aifabrix-builder/integration/hubspot-test/companies.json
5
+ filePath: ./integration/hubspot-test/companies.json
6
6
  credential:
7
7
  action: skip
8
8
  preferences:
package/jest.projects.js CHANGED
@@ -278,7 +278,35 @@ const defaultProject = {
278
278
  '/tests/lib/datasource/run-capability-remove.test.js',
279
279
  '\\\\tests\\\\lib\\\\datasource\\\\run-capability-remove.test.js',
280
280
  'lib/datasource/run-capability-remove.test.js',
281
- 'run-capability-remove\\.test\\.js'
281
+ 'run-capability-remove\\.test\\.js',
282
+ '/tests/lib/datasource/log-cleaner.test.js',
283
+ '\\\\tests\\\\lib\\\\datasource\\\\log-cleaner.test.js',
284
+ 'lib/datasource/log-cleaner.test.js',
285
+ 'log-cleaner\\.test\\.js',
286
+ '/tests/lib/datasource/datasource-exporter-service.test.js',
287
+ '\\\\tests\\\\lib\\\\datasource\\\\datasource-exporter-service.test.js',
288
+ 'lib/datasource/datasource-exporter-service.test.js',
289
+ 'datasource-exporter-service\\.test\\.js',
290
+ '/tests/lib/protection/paths.test.js',
291
+ '\\\\tests\\\\lib\\\\protection\\\\paths.test.js',
292
+ 'lib/protection/paths.test.js',
293
+ 'protection/paths\\.test\\.js',
294
+ '/tests/lib/protection/protection-resolve.test.js',
295
+ '\\\\tests\\\\lib\\\\protection\\\\protection-resolve.test.js',
296
+ 'lib/protection/protection-resolve.test.js',
297
+ 'protection-resolve\\.test\\.js',
298
+ '/tests/lib/protection/run-protection-create-helpers.test.js',
299
+ '\\\\tests\\\\lib\\\\protection\\\\run-protection-create-helpers.test.js',
300
+ 'lib/protection/run-protection-create-helpers.test.js',
301
+ 'run-protection-create-helpers\\.test\\.js',
302
+ '/tests/lib/governance/governance-pack-loader.test.js',
303
+ '\\\\tests\\\\lib\\\\governance\\\\governance-pack-loader.test.js',
304
+ 'lib/governance/governance-pack-loader.test.js',
305
+ 'governance-pack-loader\\.test\\.js',
306
+ '/tests/lib/protection/validate-batch.test.js',
307
+ '\\\\tests\\\\lib\\\\protection\\\\validate-batch.test.js',
308
+ 'lib/protection/validate-batch.test.js',
309
+ 'validate-batch\\.test\\.js'
282
310
  ];
283
311
  if (process.env.INCLUDE_LOCAL_TESTS !== 'true') {
284
312
  patterns.push('/tests/local/');
@@ -404,6 +432,21 @@ const isolatedProjects = [
404
432
  '**/tests/lib/datasource/run-capability-diff.test.js',
405
433
  '**/tests/lib/datasource/run-capability-edit.test.js',
406
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'
407
450
  ])
408
451
  ];
409
452
 
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @fileoverview Agent metadata validation API (dataplane 404.5)
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ const { createDataplaneApiClient } = require('./index');
8
+
9
+ /**
10
+ * Run agent metadata validation for a datasource.
11
+ * POST /api/v1/external/{sourceIdOrKey}/agent-metadata-validation
12
+ * @requiresPermission {Dataplane} external-data-source:update
13
+ * @async
14
+ * @function runAgentMetadataValidation
15
+ * @param {string} dataplaneUrl - Dataplane base URL
16
+ * @param {string} sourceIdOrKey - Datasource key or ID
17
+ * @param {Object} authConfig - Authentication configuration
18
+ * @param {import('./types/agent-metadata-validation.types').AgentMetadataValidationRunRequest} [body]
19
+ * @returns {Promise<import('./types/agent-metadata-validation.types').AgentMetadataValidationRunResponse>}
20
+ */
21
+ async function runAgentMetadataValidation(
22
+ dataplaneUrl,
23
+ sourceIdOrKey,
24
+ authConfig,
25
+ body = {},
26
+ opts = {}
27
+ ) {
28
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
29
+ const requestOpts = { body };
30
+ if (opts.timeoutMs !== undefined && opts.timeoutMs !== null) {
31
+ requestOpts.timeoutMs = opts.timeoutMs;
32
+ }
33
+ return await client.post(
34
+ `/api/v1/external/${encodeURIComponent(sourceIdOrKey)}/agent-metadata-validation`,
35
+ requestOpts
36
+ );
37
+ }
38
+
39
+ /**
40
+ * Get latest agent metadata validation result.
41
+ * GET /api/v1/external/{sourceIdOrKey}/agent-validation
42
+ * @requiresPermission {Dataplane} external-data-source:read
43
+ * @async
44
+ * @function getLatestAgentMetadataValidation
45
+ * @param {string} dataplaneUrl - Dataplane base URL
46
+ * @param {string} sourceIdOrKey - Datasource key or ID
47
+ * @param {Object} authConfig - Authentication configuration
48
+ * @returns {Promise<import('./types/agent-metadata-validation.types').AgentMetadataValidationResult>}
49
+ */
50
+ async function getLatestAgentMetadataValidation(
51
+ dataplaneUrl,
52
+ sourceIdOrKey,
53
+ authConfig,
54
+ opts = {}
55
+ ) {
56
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
57
+ const requestOpts = {};
58
+ if (opts.timeoutMs !== undefined && opts.timeoutMs !== null) {
59
+ requestOpts.timeoutMs = opts.timeoutMs;
60
+ }
61
+ return await client.get(
62
+ `/api/v1/external/${encodeURIComponent(sourceIdOrKey)}/agent-validation`,
63
+ requestOpts
64
+ );
65
+ }
66
+
67
+ /**
68
+ * List agent metadata validation history.
69
+ * GET /api/v1/external/{sourceIdOrKey}/agent-validation/history
70
+ * @requiresPermission {Dataplane} external-data-source:read
71
+ * @async
72
+ * @function listAgentMetadataValidationHistory
73
+ * @param {string} dataplaneUrl - Dataplane base URL
74
+ * @param {string} sourceIdOrKey - Datasource key or ID
75
+ * @param {Object} authConfig - Authentication configuration
76
+ * @returns {Promise<import('./types/agent-metadata-validation.types').AgentMetadataValidationHistoryItem[]>}
77
+ */
78
+ async function listAgentMetadataValidationHistory(
79
+ dataplaneUrl,
80
+ sourceIdOrKey,
81
+ authConfig
82
+ ) {
83
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
84
+ return await client.get(
85
+ `/api/v1/external/${encodeURIComponent(sourceIdOrKey)}/agent-validation/history`
86
+ );
87
+ }
88
+
89
+ module.exports = {
90
+ runAgentMetadataValidation,
91
+ getLatestAgentMetadataValidation,
92
+ listAgentMetadataValidationHistory
93
+ };
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @fileoverview Shared helpers for dataplane audit API responses
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { unwrapApiData } = require('../utils/external-system-readiness-core');
10
+
11
+ /**
12
+ * @param {*} res
13
+ * @throws {Error}
14
+ */
15
+ function assertAuditApiSuccess(res) {
16
+ if (!res || typeof res !== 'object') {
17
+ throw new Error('Audit API returned an empty response');
18
+ }
19
+ if (res.success === false) {
20
+ const msg =
21
+ (res.error && (res.error.formattedError || res.error.error || res.error.message)) ||
22
+ res.formattedError ||
23
+ 'Audit API request failed';
24
+ const err = new Error(msg);
25
+ if (res.status) err.status = res.status;
26
+ throw err;
27
+ }
28
+ }
29
+
30
+ /**
31
+ * @param {*} res
32
+ * @returns {{ data: Array, meta: Object|null, raw: Object|null }}
33
+ */
34
+ function unwrapPaginatedAuditList(res) {
35
+ assertAuditApiSuccess(res);
36
+ const body = unwrapApiData(res);
37
+ if (!body || typeof body !== 'object') {
38
+ return { data: [], meta: null, raw: null };
39
+ }
40
+ const data = Array.isArray(body.data)
41
+ ? body.data
42
+ : Array.isArray(body.items)
43
+ ? body.items
44
+ : [];
45
+ const meta = body.meta && typeof body.meta === 'object' ? body.meta : null;
46
+ return { data, meta, raw: body };
47
+ }
48
+
49
+ /**
50
+ * Unwrap execution sub-resource envelope `{ root: T }`.
51
+ * @param {*} res
52
+ * @returns {*|null}
53
+ */
54
+ function unwrapExecutionSubresource(res) {
55
+ assertAuditApiSuccess(res);
56
+ const body = unwrapApiData(res);
57
+ if (body === null || body === undefined) return null;
58
+ if (typeof body === 'object' && Object.prototype.hasOwnProperty.call(body, 'root')) {
59
+ return body.root;
60
+ }
61
+ return body;
62
+ }
63
+
64
+ module.exports = {
65
+ assertAuditApiSuccess,
66
+ unwrapPaginatedAuditList,
67
+ unwrapExecutionSubresource
68
+ };
@@ -0,0 +1,119 @@
1
+ /**
2
+ * @fileoverview Dataplane audit read API (Plan 407.1 / 407.3 evidence matrix)
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { createDataplaneApiClient } = require('./index');
10
+ const { unwrapPaginatedAuditList, unwrapExecutionSubresource } = require('./audit-api-helpers');
11
+
12
+ const AUDIT_BASE = '/api/v1/audit';
13
+ const DEFAULT_PAGE_SIZE = 100;
14
+
15
+ /**
16
+ * @param {string} dataplaneUrl
17
+ * @param {Object} authConfig
18
+ * @param {Object} [query]
19
+ * @returns {Promise<{ data: import('./types/audit.types').AuditExecutionListItem[], meta: import('./types/audit.types').AuditListMeta|null }>}
20
+ * @requiresPermission {Dataplane} audit:read
21
+ */
22
+ async function queryExecutions(dataplaneUrl, authConfig, query = {}) {
23
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
24
+ const res = await client.get(`${AUDIT_BASE}/executions`, {
25
+ params: {
26
+ page: 1,
27
+ pageSize: DEFAULT_PAGE_SIZE,
28
+ ...query
29
+ }
30
+ });
31
+ return unwrapPaginatedAuditList(res);
32
+ }
33
+
34
+ /**
35
+ * @requiresPermission {Dataplane} audit:read
36
+ */
37
+ async function queryRbacDecisions(dataplaneUrl, authConfig, query = {}) {
38
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
39
+ const res = await client.get(`${AUDIT_BASE}/rbac-decisions`, {
40
+ params: {
41
+ page: 1,
42
+ pageSize: DEFAULT_PAGE_SIZE,
43
+ sort: '-timestamp',
44
+ ...query
45
+ }
46
+ });
47
+ return unwrapPaginatedAuditList(res);
48
+ }
49
+
50
+ /**
51
+ * @requiresPermission {Dataplane} audit:read
52
+ */
53
+ async function queryAbacTraces(dataplaneUrl, authConfig, query = {}) {
54
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
55
+ const res = await client.get(`${AUDIT_BASE}/abac-traces`, {
56
+ params: {
57
+ page: 1,
58
+ pageSize: DEFAULT_PAGE_SIZE,
59
+ ...query
60
+ }
61
+ });
62
+ return unwrapPaginatedAuditList(res);
63
+ }
64
+
65
+ /**
66
+ * @requiresPermission {Dataplane} audit:read
67
+ */
68
+ async function getExecutionRbac(dataplaneUrl, authConfig, executionId) {
69
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
70
+ const res = await client.get(`${AUDIT_BASE}/executions/${executionId}/rbac`);
71
+ return unwrapExecutionSubresource(res);
72
+ }
73
+
74
+ /**
75
+ * @requiresPermission {Dataplane} audit:read
76
+ */
77
+ async function getExecutionAbac(dataplaneUrl, authConfig, executionId) {
78
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
79
+ const res = await client.get(`${AUDIT_BASE}/executions/${executionId}/abac`);
80
+ return unwrapExecutionSubresource(res);
81
+ }
82
+
83
+ /**
84
+ * @requiresPermission {Dataplane} audit:read
85
+ */
86
+ async function getExecutionTrace(dataplaneUrl, authConfig, executionId) {
87
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
88
+ const res = await client.get(`${AUDIT_BASE}/executions/${executionId}/trace`);
89
+ return unwrapExecutionSubresource(res);
90
+ }
91
+
92
+ /**
93
+ * @requiresPermission {Dataplane} audit:read
94
+ */
95
+ async function getExecutionSteps(dataplaneUrl, authConfig, executionId) {
96
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
97
+ const res = await client.get(`${AUDIT_BASE}/executions/${executionId}/steps`);
98
+ return unwrapExecutionSubresource(res);
99
+ }
100
+
101
+ /**
102
+ * @requiresPermission {Dataplane} audit:read
103
+ */
104
+ async function getExecutionErrors(dataplaneUrl, authConfig, executionId) {
105
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
106
+ const res = await client.get(`${AUDIT_BASE}/executions/${executionId}/errors`);
107
+ return unwrapExecutionSubresource(res);
108
+ }
109
+
110
+ module.exports = {
111
+ queryExecutions,
112
+ queryRbacDecisions,
113
+ queryAbacTraces,
114
+ getExecutionRbac,
115
+ getExecutionAbac,
116
+ getExecutionTrace,
117
+ getExecutionSteps,
118
+ getExecutionErrors
119
+ };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @fileoverview Controller auth/RBAC cache API
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { ApiClient } = require('./index');
10
+
11
+ const CLEAR_PATH = '/api/v1/auth/cache/clear';
12
+ const INVALIDATE_PATH = '/api/v1/auth/cache/invalidate';
13
+
14
+ /**
15
+ * Clear all controller cache entries
16
+ * @requiresPermission {Controller} cache:admin
17
+ * @async
18
+ * @param {string} controllerUrl
19
+ * @param {Object} authConfig
20
+ * @returns {Promise<Object>}
21
+ */
22
+ async function clearAuthCache(controllerUrl, authConfig) {
23
+ const client = new ApiClient(controllerUrl, authConfig);
24
+ return await client.post(CLEAR_PATH);
25
+ }
26
+
27
+ /**
28
+ * Invalidate cache entries matching a pattern
29
+ * @requiresPermission {Controller} cache:admin
30
+ * @async
31
+ * @param {string} controllerUrl
32
+ * @param {Object} authConfig
33
+ * @param {string} pattern
34
+ * @returns {Promise<Object>}
35
+ */
36
+ async function invalidateAuthCache(controllerUrl, authConfig, pattern) {
37
+ const client = new ApiClient(controllerUrl, authConfig);
38
+ return await client.post(INVALIDATE_PATH, { body: { pattern } });
39
+ }
40
+
41
+ module.exports = {
42
+ clearAuthCache,
43
+ invalidateAuthCache
44
+ };
@@ -4,7 +4,7 @@
4
4
  * @version 2.0.0
5
5
  */
6
6
 
7
- const { ApiClient } = require('./index');
7
+ const { createDataplaneApiClient } = require('./index');
8
8
  const { normalizeDataplaneAuth } = require('./validation-run.api');
9
9
 
10
10
  /**
@@ -36,7 +36,7 @@ function dataplaneAuthForBearerGet(authConfig) {
36
36
  * @returns {Promise<Object>} API envelope `{ success, data?, status, ... }`
37
37
  */
38
38
  async function getActiveIntegrationCertificate(dataplaneUrl, authConfig, systemKey, datasourceKey) {
39
- const client = new ApiClient(dataplaneUrl, dataplaneAuthForBearerGet(authConfig));
39
+ const client = createDataplaneApiClient(dataplaneUrl, dataplaneAuthForBearerGet(authConfig));
40
40
  const path = `/api/v1/systems/${encodeURIComponent(systemKey)}/datasources/${encodeURIComponent(
41
41
  datasourceKey
42
42
  )}/certificates/active`;
@@ -54,7 +54,7 @@ async function getActiveIntegrationCertificate(dataplaneUrl, authConfig, systemK
54
54
  * @returns {Promise<Object>}
55
55
  */
56
56
  async function listIntegrationCertificates(dataplaneUrl, authConfig, params = {}) {
57
- const client = new ApiClient(dataplaneUrl, dataplaneAuthForBearerGet(authConfig));
57
+ const client = createDataplaneApiClient(dataplaneUrl, dataplaneAuthForBearerGet(authConfig));
58
58
  return await client.get('/api/v1/certificates', { params });
59
59
  }
60
60
 
@@ -69,7 +69,7 @@ async function listIntegrationCertificates(dataplaneUrl, authConfig, params = {}
69
69
  * @returns {Promise<Object>}
70
70
  */
71
71
  async function verifyIntegrationCertificate(dataplaneUrl, authConfig, body) {
72
- const client = new ApiClient(dataplaneUrl, dataplaneAuthForBearerGet(authConfig));
72
+ const client = createDataplaneApiClient(dataplaneUrl, dataplaneAuthForBearerGet(authConfig));
73
73
  return await client.post('/api/v1/certificates/verify', { body: body || {} });
74
74
  }
75
75
 
@@ -4,7 +4,7 @@
4
4
  * @version 2.0.0
5
5
  */
6
6
 
7
- const { ApiClient } = require('./index');
7
+ const { createDataplaneApiClient } = require('./index');
8
8
 
9
9
  const CREDENTIAL_SECRET_ENDPOINT = '/api/v1/credential/secret';
10
10
 
@@ -29,7 +29,7 @@ async function storeCredentialSecrets(dataplaneUrl, authConfig, items) {
29
29
  if (!items || !Array.isArray(items) || items.length === 0) {
30
30
  return { stored: 0 };
31
31
  }
32
- const client = new ApiClient(dataplaneUrl, authConfig);
32
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
33
33
  return await client.post(CREDENTIAL_SECRET_ENDPOINT, {
34
34
  body: items
35
35
  });
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Dataplane health (public) — read dataplane `version` and optional
3
+ * `minBuilderCliVersion` for the Builder CLI compatibility gate (plan 142.0).
4
+ *
5
+ * Reads `GET /api/v1/health` first (canonical, plan 403.0) and falls back to
6
+ * `GET /health` for older dataplanes during rollout. The endpoint is public
7
+ * (`security: []`); no auth header is sent.
8
+ *
9
+ * @fileoverview Read dataplane health JSON without authentication
10
+ * @author AI Fabrix Team
11
+ * @version 2.0.0
12
+ * @requiresPermission none — public dataplane health endpoint (security: [])
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ require('./types/dataplane-health.types');
18
+ const { ApiClient } = require('./index');
19
+
20
+ const PRIMARY_ENDPOINT = '/api/v1/health';
21
+ const FALLBACK_ENDPOINT = '/health';
22
+
23
+ /**
24
+ * Extract the inner JSON body from the harmonized ApiClient response shape.
25
+ * @private
26
+ * @param {Object} response
27
+ * @returns {Object|null}
28
+ */
29
+ function unwrapBody(response) {
30
+ if (!response || response.success === false || response.data === null || response.data === undefined) {
31
+ return null;
32
+ }
33
+ const outer = response.data;
34
+ if (!outer || typeof outer !== 'object') {
35
+ return null;
36
+ }
37
+ // Some dataplane shapes return `{ data: { ... } }`; the general health route
38
+ // returns the payload directly. Accept both.
39
+ const inner = outer.data !== undefined && outer.data !== null && typeof outer.data === 'object'
40
+ ? outer.data
41
+ : outer;
42
+ if (!inner || typeof inner !== 'object') {
43
+ return null;
44
+ }
45
+ return inner;
46
+ }
47
+
48
+ /**
49
+ * Parse a raw ApiClient response into a normalized health snapshot.
50
+ *
51
+ * @param {Object} response - ApiClient.get response (`{ success, data, ... }`)
52
+ * @param {string} [endpoint] - Endpoint that produced the response (recorded on snapshot)
53
+ * @returns {import('./types/dataplane-health.types').DataplaneHealthSnapshot|null}
54
+ * Snapshot, or null when the response is not parseable
55
+ */
56
+ function parseGeneralHealthResponse(response, endpoint) {
57
+ const body = unwrapBody(response);
58
+ if (!body) return null;
59
+
60
+ const status = typeof body.status === 'string' ? body.status : 'unknown';
61
+ const version = typeof body.version === 'string' && body.version.trim()
62
+ ? body.version.trim()
63
+ : undefined;
64
+
65
+ let minBuilderCliVersion;
66
+ if (typeof body.minBuilderCliVersion === 'string') {
67
+ const trimmed = body.minBuilderCliVersion.trim();
68
+ if (trimmed) minBuilderCliVersion = trimmed;
69
+ }
70
+
71
+ return {
72
+ status,
73
+ version,
74
+ minBuilderCliVersion,
75
+ endpoint: endpoint || null
76
+ };
77
+ }
78
+
79
+ /**
80
+ * Fetch dataplane general health (public endpoint, no auth).
81
+ *
82
+ * Tries `/api/v1/health` first; on failure falls back to `/health` (compatibility
83
+ * with older dataplanes that did not expose the v1 health route during rollout).
84
+ *
85
+ * @async
86
+ * @param {string} dataplaneUrl - Dataplane base URL (e.g. `http://localhost:3201`)
87
+ * @param {Object} [options]
88
+ * @param {number} [options.timeoutMs] - Optional timeout in milliseconds
89
+ * @returns {Promise<import('./types/dataplane-health.types').DataplaneHealthSnapshot|null>}
90
+ * Snapshot, or null when both endpoints fail
91
+ * @throws {Error} When dataplaneUrl is missing or not a string
92
+ */
93
+ async function fetchDataplaneGeneralHealth(dataplaneUrl, options = {}) {
94
+ if (!dataplaneUrl || typeof dataplaneUrl !== 'string') {
95
+ throw new Error('dataplaneUrl is required and must be a string');
96
+ }
97
+ const client = new ApiClient(dataplaneUrl);
98
+ const requestOpts = {};
99
+ if (options.timeoutMs !== undefined && options.timeoutMs !== null) {
100
+ requestOpts.timeoutMs = options.timeoutMs;
101
+ }
102
+
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;
110
+
111
+ return null;
112
+ }
113
+
114
+ /**
115
+ * GET that swallows transport errors (timeouts / DNS / ECONNREFUSED) so callers
116
+ * can attempt a fallback endpoint without try/catch noise.
117
+ * @private
118
+ * @async
119
+ * @param {ApiClient} client
120
+ * @param {string} endpoint
121
+ * @param {Object} options
122
+ * @returns {Promise<Object|null>}
123
+ */
124
+ async function safeGet(client, endpoint, options) {
125
+ try {
126
+ return await client.get(endpoint, options);
127
+ } catch (_error) {
128
+ return null;
129
+ }
130
+ }
131
+
132
+ module.exports = {
133
+ fetchDataplaneGeneralHealth,
134
+ parseGeneralHealthResponse,
135
+ PRIMARY_ENDPOINT,
136
+ FALLBACK_ENDPOINT
137
+ };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @fileoverview Dataplane sync API (Controller)
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { ApiClient } = require('./index');
10
+
11
+ /**
12
+ * Trigger full identity sync to dataplane for an environment
13
+ * @requiresPermission {Controller} admin:sync
14
+ * @async
15
+ * @param {string} controllerUrl
16
+ * @param {Object} authConfig
17
+ * @param {string} envKey
18
+ * @returns {Promise<Object>}
19
+ */
20
+ async function fullSyncToDataplane(controllerUrl, authConfig, envKey) {
21
+ const client = new ApiClient(controllerUrl, authConfig);
22
+ return await client.post(`/api/v1/sync/dataplane/${encodeURIComponent(envKey)}/full`);
23
+ }
24
+
25
+ module.exports = {
26
+ fullSyncToDataplane
27
+ };