@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
package/lib/api/index.js CHANGED
@@ -14,13 +14,15 @@ const { makeApiCall, authenticatedApiCall } = require('../utils/api');
14
14
  class ApiClient {
15
15
  /**
16
16
  * Create an API client instance.
17
- * App endpoints receive token-only auth (Bearer). x-client-id/x-client-secret are not sent to app endpoints.
17
+ * App endpoints receive token-only auth (Bearer). x-client-id/x-client-secret are used only for the controller token endpoint.
18
18
  * @param {string} baseUrl - Base URL for the API (controller URL)
19
19
  * @param {Object} [authConfig] - Authentication configuration
20
- * @param {string} [authConfig.type] - Auth type ('bearer' | 'client-token')
20
+ * @param {string} [authConfig.type] - Auth type ('bearer' | 'client-token' | 'client-credentials')
21
21
  * @param {string} [authConfig.token] - Bearer token
22
+ * @param {string} [authConfig.clientId] - Client ID (client-credentials)
23
+ * @param {string} [authConfig.clientSecret] - Client secret (client-credentials)
22
24
  */
23
- constructor(baseUrl, authConfig = {}) {
25
+ constructor(baseUrl, authConfig = {}, clientOptions = {}) {
24
26
  if (baseUrl === null || baseUrl === undefined || typeof baseUrl !== 'string') {
25
27
  throw new Error('baseUrl is required and must be a string');
26
28
  }
@@ -30,6 +32,25 @@ class ApiClient {
30
32
  }
31
33
  this.baseUrl = trimmedUrl;
32
34
  this.authConfig = authConfig;
35
+ const opts = clientOptions && typeof clientOptions === 'object' ? clientOptions : {};
36
+ this.enforceCliVersion = Boolean(opts.enforceCliVersion);
37
+ this.controllerUrlForGate = opts.controllerUrl || null;
38
+ }
39
+
40
+ /**
41
+ * Plan 142.0: block dataplane mutations when Builder CLI is below minimum.
42
+ * @private
43
+ * @async
44
+ * @returns {Promise<void>}
45
+ */
46
+ async _ensureDataplaneCliVersionGate() {
47
+ if (!this.enforceCliVersion) {
48
+ return;
49
+ }
50
+ const { assertDataplaneCliVersionCompatible } = require('../utils/dataplane-cli-version-gate');
51
+ await assertDataplaneCliVersionCompatible(this.baseUrl, {
52
+ controllerUrl: this.controllerUrlForGate
53
+ });
33
54
  }
34
55
 
35
56
  /**
@@ -68,6 +89,41 @@ class ApiClient {
68
89
  return headers;
69
90
  }
70
91
 
92
+ /**
93
+ * True when endpoint is the controller client-credentials token exchange.
94
+ * @private
95
+ * @param {string} endpoint - API endpoint path
96
+ * @returns {boolean}
97
+ */
98
+ _isClientCredentialsTokenEndpoint(endpoint) {
99
+ const path = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
100
+ return path === '/api/v1/auth/token';
101
+ }
102
+
103
+ /**
104
+ * Add x-client-id/x-client-secret only for POST /api/v1/auth/token (never for app endpoints).
105
+ * @private
106
+ * @param {string} endpoint - API endpoint path
107
+ * @param {Object} headers - Request headers built by _buildHeaders
108
+ * @returns {Object}
109
+ */
110
+ _applyClientCredentialHeadersForTokenEndpoint(endpoint, headers) {
111
+ if (this.authConfig.type !== 'client-credentials') {
112
+ return headers;
113
+ }
114
+ if (!this._isClientCredentialsTokenEndpoint(endpoint)) {
115
+ return headers;
116
+ }
117
+ const out = { ...headers };
118
+ if (this.authConfig.clientId) {
119
+ out['x-client-id'] = String(this.authConfig.clientId);
120
+ }
121
+ if (this.authConfig.clientSecret) {
122
+ out['x-client-secret'] = String(this.authConfig.clientSecret);
123
+ }
124
+ return out;
125
+ }
126
+
71
127
  /**
72
128
  * Make a GET request
73
129
  * @async
@@ -78,6 +134,7 @@ class ApiClient {
78
134
  * @returns {Promise<Object>} API response
79
135
  */
80
136
  async get(endpoint, options = {}) {
137
+ await this._ensureDataplaneCliVersionGate();
81
138
  let url = this._buildUrl(endpoint);
82
139
  const headers = this._buildHeaders(options.headers);
83
140
 
@@ -119,8 +176,12 @@ class ApiClient {
119
176
  * @returns {Promise<Object>} API response
120
177
  */
121
178
  async post(endpoint, options = {}) {
179
+ await this._ensureDataplaneCliVersionGate();
122
180
  let url = this._buildUrl(endpoint);
123
- const headers = this._buildHeaders(options.headers);
181
+ const headers = this._applyClientCredentialHeadersForTokenEndpoint(
182
+ endpoint,
183
+ this._buildHeaders(options.headers)
184
+ );
124
185
 
125
186
  // Add query parameters if provided
126
187
  if (options.params) {
@@ -167,6 +228,7 @@ class ApiClient {
167
228
  * @returns {Promise<Object>} API response
168
229
  */
169
230
  async postFormData(endpoint, formData, options = {}) {
231
+ await this._ensureDataplaneCliVersionGate();
170
232
  const url = this._buildUrl(endpoint);
171
233
  const headers = this._buildHeaders(options.headers || {}, { skipContentType: true });
172
234
 
@@ -194,6 +256,7 @@ class ApiClient {
194
256
  * @returns {Promise<Object>} API response
195
257
  */
196
258
  async patch(endpoint, options = {}) {
259
+ await this._ensureDataplaneCliVersionGate();
197
260
  const url = this._buildUrl(endpoint);
198
261
  const headers = this._buildHeaders(options.headers);
199
262
 
@@ -224,6 +287,7 @@ class ApiClient {
224
287
  * @returns {Promise<Object>} API response
225
288
  */
226
289
  async put(endpoint, options = {}) {
290
+ await this._ensureDataplaneCliVersionGate();
227
291
  const url = this._buildUrl(endpoint);
228
292
  const headers = this._buildHeaders(options.headers);
229
293
 
@@ -253,6 +317,7 @@ class ApiClient {
253
317
  * @returns {Promise<Object>} API response
254
318
  */
255
319
  async delete(endpoint, options = {}) {
320
+ await this._ensureDataplaneCliVersionGate();
256
321
  const url = this._buildUrl(endpoint);
257
322
  const headers = this._buildHeaders(options.headers);
258
323
 
@@ -270,7 +335,25 @@ class ApiClient {
270
335
  }
271
336
  }
272
337
 
338
+ /**
339
+ * Dataplane-scoped client — enforces Builder CLI version gate before each request.
340
+ * Do not use for `fetchDataplaneGeneralHealth` (health must stay ungated).
341
+ *
342
+ * @param {string} dataplaneUrl - Dataplane base URL
343
+ * @param {Object} authConfig - Authentication configuration
344
+ * @param {Object} [options]
345
+ * @param {string} [options.controllerUrl] - Controller URL for device cache lookup
346
+ * @returns {ApiClient}
347
+ */
348
+ function createDataplaneApiClient(dataplaneUrl, authConfig, options = {}) {
349
+ return new ApiClient(dataplaneUrl, authConfig, {
350
+ enforceCliVersion: true,
351
+ controllerUrl: options.controllerUrl
352
+ });
353
+ }
354
+
273
355
  module.exports = {
274
- ApiClient
356
+ ApiClient,
357
+ createDataplaneApiClient
275
358
  };
276
359
 
@@ -0,0 +1,77 @@
1
+ /**
2
+ * @fileoverview Dataplane Enterprise AI Certification lifecycle API client (419.0).
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { createDataplaneApiClient } = require('./index');
10
+ const { unwrapApiData } = require('../utils/external-system-readiness-core');
11
+
12
+ /**
13
+ * GET /api/v1/external/systems/{systemKey}/lifecycle
14
+ * @requiresPermission {Dataplane} external-system:read
15
+ * @async
16
+ * @param {string} dataplaneUrl
17
+ * @param {Object} authConfig
18
+ * @param {string} systemKey
19
+ * @param {{ details?: boolean, summary?: boolean }} [opts]
20
+ * @returns {Promise<Object>}
21
+ */
22
+ async function getSystemLifecycleReport(dataplaneUrl, authConfig, systemKey, opts = {}) {
23
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
24
+ const params = {};
25
+ if (opts.details === true) params.details = true;
26
+ if (opts.summary === true) params.summary = true;
27
+ const res = await client.get(`/api/v1/external/systems/${encodeURIComponent(systemKey)}/lifecycle`, {
28
+ params
29
+ });
30
+ if (res && res.success === false) {
31
+ const msg =
32
+ (res.error && (res.error.formattedError || res.error.error || res.error.message)) ||
33
+ res.formattedError ||
34
+ 'Lifecycle report request failed';
35
+ throw new Error(msg);
36
+ }
37
+ const unwrapped = unwrapApiData(res);
38
+ if (!unwrapped || !unwrapped.systemKey) {
39
+ throw new Error('Lifecycle report returned an unexpected response shape');
40
+ }
41
+ return unwrapped;
42
+ }
43
+
44
+ /**
45
+ * POST /api/v1/external/systems/{systemKey}/lifecycle/run
46
+ * @requiresPermission {Dataplane} external-system:update
47
+ * @async
48
+ * @param {string} dataplaneUrl
49
+ * @param {Object} authConfig
50
+ * @param {string} systemKey
51
+ * @param {Object} [body]
52
+ * @returns {Promise<Object>}
53
+ */
54
+ async function runSystemLifecycle(dataplaneUrl, authConfig, systemKey, body = {}) {
55
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
56
+ const res = await client.post(
57
+ `/api/v1/external/systems/${encodeURIComponent(systemKey)}/lifecycle/run`,
58
+ { body }
59
+ );
60
+ if (res && res.success === false) {
61
+ const msg =
62
+ (res.error && (res.error.formattedError || res.error.error || res.error.message)) ||
63
+ res.formattedError ||
64
+ 'Lifecycle run request failed';
65
+ throw new Error(msg);
66
+ }
67
+ const unwrapped = unwrapApiData(res);
68
+ if (!unwrapped || !unwrapped.report) {
69
+ throw new Error('Lifecycle run returned an unexpected response shape');
70
+ }
71
+ return unwrapped;
72
+ }
73
+
74
+ module.exports = {
75
+ getSystemLifecycleReport,
76
+ runSystemLifecycle
77
+ };
@@ -4,8 +4,9 @@
4
4
  * @version 2.0.0
5
5
  */
6
6
 
7
- const { ApiClient } = require('./index');
7
+ const { ApiClient, createDataplaneApiClient } = require('./index');
8
8
  const { postValidationRunAndOptionalPoll } = require('./validation-runner');
9
+ const { withStageOnValidationRunBody } = require('../utils/validation-run-stage');
9
10
 
10
11
  /**
11
12
  * @param {Object} opts
@@ -30,7 +31,7 @@ function buildValidationRunPayloadTestBody({ validationScope, systemKey, datasou
30
31
  if (validationScope === 'externalDataSource') {
31
32
  body.datasourceKey = datasourceKey;
32
33
  }
33
- return body;
34
+ return withStageOnValidationRunBody(body, body.runType);
34
35
  }
35
36
 
36
37
  /**
@@ -127,7 +128,7 @@ async function getPipelineHealth(controllerUrl, envKey) {
127
128
  * @throws {Error} If publish fails
128
129
  */
129
130
  async function publishDatasourceViaPipeline(dataplaneUrl, systemKey, authConfig, datasourceConfig) {
130
- const client = new ApiClient(dataplaneUrl, authConfig);
131
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
131
132
  return await client.post(`/api/v1/pipeline/${systemKey}/upload`, {
132
133
  body: datasourceConfig
133
134
  });
@@ -147,7 +148,7 @@ async function publishDatasourceViaPipeline(dataplaneUrl, systemKey, authConfig,
147
148
  * @throws {Error} If request fails
148
149
  */
149
150
  async function validatePipelineConfig(dataplaneUrl, authConfig, { config }) {
150
- const client = new ApiClient(dataplaneUrl, authConfig);
151
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
151
152
  return await client.post('/api/v1/pipeline/validate', {
152
153
  body: { config }
153
154
  });
@@ -242,12 +243,13 @@ async function testDatasourceViaPipeline({ dataplaneUrl, systemKey, datasourceKe
242
243
  * @param {Object} authConfig - Authentication configuration (must include token for Bearer; client id/secret rejected)
243
244
  * @param {Object} payload - { version, application, dataSources }; optional status (default "draft")
244
245
  * @param {string} [payload.status="draft"] - "draft" or "published"; Builder uses "draft"
246
+ * @param {boolean} [payload.force=false] - When true, bypass guards on active datasource publish
245
247
  * @returns {Promise<Object>} API envelope `{ success, data }` where `data` is PublicationResult (uploadId, system, datasources, generateMcpContract, …)
246
248
  * @throws {Error} If upload fails
247
249
  */
248
250
  async function uploadApplicationViaPipeline(dataplaneUrl, authConfig, payload) {
249
251
  const body = { ...payload, status: payload.status ?? 'draft' };
250
- const client = new ApiClient(dataplaneUrl, authConfig);
252
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
251
253
  return await client.post('/api/v1/pipeline/upload', {
252
254
  body
253
255
  });
@@ -0,0 +1,157 @@
1
+ /**
2
+ * @fileoverview Protection manifest API (dataplane /api/v1/protection/*).
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { createDataplaneApiClient } = require('./index');
10
+ const { unwrapApiData } = require('../utils/external-system-readiness-core');
11
+
12
+ const BASE = '/api/v1/protection';
13
+
14
+ /**
15
+ * @param {*} res
16
+ * @returns {*}
17
+ */
18
+ function unwrapBody(res) {
19
+ return unwrapApiData(res) ?? res;
20
+ }
21
+
22
+ /**
23
+ * POST /api/v1/protection/validate
24
+ * @requiresPermission {Dataplane} external-system:read
25
+ */
26
+ async function validateProtection(dataplaneUrl, authConfig, manifest, opts = {}) {
27
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
28
+ const params = {};
29
+ if (opts.strict === true) params.strict = true;
30
+ if (opts.explain === true) params.explain = true;
31
+ const res = await client.post(`${BASE}/validate`, {
32
+ body: { manifest },
33
+ params
34
+ });
35
+ return unwrapBody(res);
36
+ }
37
+
38
+ /**
39
+ * POST /api/v1/protection/simulate
40
+ * @requiresPermission {Dataplane} external-system:read
41
+ */
42
+ async function simulateProtection(dataplaneUrl, authConfig, manifest, opts = {}) {
43
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
44
+ const params = {};
45
+ if (opts.strict === true) params.strict = true;
46
+ if (opts.explain === true) params.explain = true;
47
+ if (opts.sampleSize !== undefined && opts.sampleSize !== null) {
48
+ params.sampleSize = opts.sampleSize;
49
+ }
50
+ const res = await client.post(`${BASE}/simulate`, {
51
+ body: { manifest },
52
+ params
53
+ });
54
+ return unwrapBody(res);
55
+ }
56
+
57
+ /**
58
+ * POST /api/v1/protection/upload
59
+ * @requiresPermission {Dataplane} external-system:publish
60
+ */
61
+ async function uploadProtection(dataplaneUrl, authConfig, manifest) {
62
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
63
+ const res = await client.post(`${BASE}/upload`, { body: { manifest } });
64
+ return unwrapBody(res);
65
+ }
66
+
67
+ /**
68
+ * GET /api/v1/protection/{key}
69
+ * @requiresPermission {Dataplane} external-system:read
70
+ */
71
+ async function getProtection(dataplaneUrl, authConfig, key) {
72
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
73
+ const res = await client.get(`${BASE}/${encodeURIComponent(key)}`);
74
+ return unwrapBody(res);
75
+ }
76
+
77
+ /**
78
+ * GET /api/v1/protection/{key}/status
79
+ * @requiresPermission {Dataplane} external-system:read
80
+ */
81
+ async function getProtectionStatus(dataplaneUrl, authConfig, key) {
82
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
83
+ const res = await client.get(`${BASE}/${encodeURIComponent(key)}/status`);
84
+ return unwrapBody(res);
85
+ }
86
+
87
+ /**
88
+ * @param {*} body
89
+ * @returns {Object[]}
90
+ */
91
+ function extractProtectionListItems(body) {
92
+ if (!body || typeof body !== 'object') {
93
+ return [];
94
+ }
95
+ if (Array.isArray(body.data)) {
96
+ return body.data;
97
+ }
98
+ if (Array.isArray(body.items)) {
99
+ return body.items;
100
+ }
101
+ if (Array.isArray(body)) {
102
+ return body;
103
+ }
104
+ return [];
105
+ }
106
+
107
+ /**
108
+ * GET /api/v1/protection
109
+ * @requiresPermission {Dataplane} external-system:read
110
+ * @returns {Promise<{ items: Object[], meta: Object|null, raw: * }>}
111
+ */
112
+ async function listProtectionManifests(dataplaneUrl, authConfig, options = {}) {
113
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
114
+ const res = await client.get(BASE, { params: options });
115
+ const body = unwrapBody(res);
116
+ return {
117
+ items: extractProtectionListItems(body),
118
+ meta: body && typeof body === 'object' && body.meta ? body.meta : null,
119
+ raw: body
120
+ };
121
+ }
122
+
123
+ /**
124
+ * DELETE /api/v1/protection/{key}
125
+ * @requiresPermission {Dataplane} external-system:delete
126
+ */
127
+ async function deleteProtection(dataplaneUrl, authConfig, key) {
128
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
129
+ return await client.delete(`${BASE}/${encodeURIComponent(key)}`);
130
+ }
131
+
132
+ /**
133
+ * Find deployed protection key by datasource key (client-side scan).
134
+ * @param {string} dataplaneUrl
135
+ * @param {Object} authConfig
136
+ * @param {string} datasourceKey
137
+ * @returns {Promise<string|null>}
138
+ */
139
+ async function findProtectionKeyByDatasource(dataplaneUrl, authConfig, datasourceKey) {
140
+ const { items } = await listProtectionManifests(dataplaneUrl, authConfig, {
141
+ page: 1,
142
+ pageSize: 100
143
+ });
144
+ const match = items.find((row) => String(row?.datasourceKey || '').trim() === datasourceKey);
145
+ return match?.key ? String(match.key) : null;
146
+ }
147
+
148
+ module.exports = {
149
+ validateProtection,
150
+ simulateProtection,
151
+ uploadProtection,
152
+ getProtection,
153
+ getProtectionStatus,
154
+ listProtectionManifests,
155
+ deleteProtection,
156
+ findProtectionKeyByDatasource
157
+ };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @fileoverview Dataplane bulk record sync API (data-storage records/bulk)
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ const { createDataplaneApiClient } = require('./index');
8
+ const { unwrapApiData } = require('../utils/external-system-readiness-core');
9
+
10
+ /**
11
+ * Bulk sync external records for a datasource.
12
+ * POST /api/v1/data-storage/{sourceIdOrKey}/records/bulk
13
+ * @requiresPermission {Dataplane} external-data-source:sync
14
+ * @async
15
+ * @param {string} dataplaneUrl
16
+ * @param {string} sourceIdOrKey
17
+ * @param {Object} authConfig
18
+ * @param {import('./types/records-bulk.types').ExternalRecordBulkRequest} body
19
+ * @returns {Promise<import('./types/records-bulk.types').ExternalRecordBulkResponse>}
20
+ */
21
+ async function bulkSyncRecords(dataplaneUrl, sourceIdOrKey, authConfig, body) {
22
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
23
+ const res = await client.post(
24
+ `/api/v1/data-storage/${encodeURIComponent(sourceIdOrKey)}/records/bulk`,
25
+ { body }
26
+ );
27
+ if (res && res.success === false) {
28
+ const msg =
29
+ res.formattedError ||
30
+ res.error ||
31
+ `Bulk sync failed (HTTP ${res.status || 0})`;
32
+ throw new Error(msg);
33
+ }
34
+ const payload = unwrapApiData(res);
35
+ if (!payload || typeof payload !== 'object') {
36
+ throw new Error('Bulk sync returned an unexpected response shape');
37
+ }
38
+ return payload;
39
+ }
40
+
41
+ module.exports = {
42
+ bulkSyncRecords
43
+ };
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @fileoverview Normalize dataplane Records Search client responses
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ /**
10
+ * Unwrap ApiClient `{ success, data: { data, meta, links } }` to a flat search result.
11
+ * @param {Object} response - Raw client.post result
12
+ * @returns {{ success: boolean, data: Array, meta: Object, links?: Object, status?: number, error?: string, formattedError?: string }}
13
+ */
14
+ function normalizeRecordsSearchClientResponse(response) {
15
+ if (!response || response.success !== true) {
16
+ return response || { success: false, data: [], meta: {} };
17
+ }
18
+
19
+ const body = response.data;
20
+ if (body && typeof body === 'object' && Array.isArray(body.data)) {
21
+ return {
22
+ success: true,
23
+ data: body.data,
24
+ meta: body.meta && typeof body.meta === 'object' ? body.meta : {},
25
+ links: body.links,
26
+ status: response.status
27
+ };
28
+ }
29
+
30
+ if (Array.isArray(body)) {
31
+ return {
32
+ success: true,
33
+ data: body,
34
+ meta: response.meta && typeof response.meta === 'object' ? response.meta : {},
35
+ status: response.status
36
+ };
37
+ }
38
+
39
+ return {
40
+ success: true,
41
+ data: [],
42
+ meta: body && typeof body === 'object' && body.meta ? body.meta : {},
43
+ status: response.status
44
+ };
45
+ }
46
+
47
+ module.exports = {
48
+ normalizeRecordsSearchClientResponse
49
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @fileoverview Dataplane Records Search API
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ const { createDataplaneApiClient } = require('./index');
8
+ const { normalizeRecordsSearchClientResponse } = require('./records-search-parse');
9
+
10
+ /**
11
+ * Search records across datasources (governed read path).
12
+ * POST /api/v1/records/search
13
+ * @requiresPermission {Dataplane} record:search
14
+ * @async
15
+ * @param {string} dataplaneUrl
16
+ * @param {Object} authConfig
17
+ * @param {import('./types/records-search.types').RecordsSearchRequest} body
18
+ * @returns {Promise<{ success: boolean, data: Array, meta: Object, links?: Object, status?: number }>}
19
+ */
20
+ async function searchRecords(dataplaneUrl, authConfig, body) {
21
+ const client = createDataplaneApiClient(dataplaneUrl, authConfig);
22
+ const raw = await client.post('/api/v1/records/search', { body });
23
+ return normalizeRecordsSearchClientResponse(raw);
24
+ }
25
+
26
+ module.exports = {
27
+ searchRecords,
28
+ normalizeRecordsSearchClientResponse
29
+ };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @fileoverview Agent metadata validation API types (dataplane 404.5)
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ /**
8
+ * @typedef {'info' | 'warning' | 'error'} AgentValidationFindingSeverity
9
+ */
10
+
11
+ /**
12
+ * @typedef {Object} AgentValidationFinding
13
+ * @property {AgentValidationFindingSeverity} severity
14
+ * @property {string} code
15
+ * @property {string} message
16
+ * @property {string} [field]
17
+ * @property {string} [recommendation]
18
+ */
19
+
20
+ /**
21
+ * @typedef {'pending' | 'passed' | 'warning' | 'failed'} AgentValidationStatus
22
+ */
23
+
24
+ /**
25
+ * @typedef {'trusted' | 'usableWithWarnings' | 'notTrusted' | 'pending'} AgentTrustDecision
26
+ */
27
+
28
+ /**
29
+ * @typedef {Object} AgentMetadataValidationResult
30
+ * @property {AgentValidationStatus} status
31
+ * @property {AgentTrustDecision} trustDecision
32
+ * @property {number} confidence
33
+ * @property {string} summary
34
+ * @property {AgentValidationFinding[]} findings
35
+ * @property {string} validatedAt - ISO 8601
36
+ * @property {string} inputHash
37
+ * @property {string} contractVersion
38
+ */
39
+
40
+ /**
41
+ * @typedef {Object} AgentMetadataValidationRunRequest
42
+ * @property {boolean} [forceRevalidate]
43
+ * @property {Object<string, Object>} [peerDatasourceConfigs]
44
+ */
45
+
46
+ /**
47
+ * @typedef {Object} AgentMetadataValidationRunResponse
48
+ * @property {string} id
49
+ * @property {string} externalDataSourceId
50
+ * @property {string} datasourceKey
51
+ * @property {AgentMetadataValidationResult} result
52
+ * @property {boolean} [reused]
53
+ */
54
+
55
+ /**
56
+ * @typedef {Object} AgentMetadataValidationHistoryItem
57
+ * @property {string} id
58
+ * @property {string} inputHash
59
+ * @property {string} contractVersion
60
+ * @property {AgentTrustDecision} trustDecision
61
+ * @property {AgentValidationStatus} validationStatus
62
+ * @property {number} confidence
63
+ * @property {string} validatedAt
64
+ * @property {boolean} isLatest
65
+ */
66
+
67
+ module.exports = {};