@aifabrix/builder 2.45.5 → 2.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) hide show
  1. package/.cursor/rules/cli-layout.mdc +2 -0
  2. package/.cursor/rules/cli-product-neutral.mdc +43 -0
  3. package/.cursor/rules/project-rules.mdc +1 -0
  4. package/.npmrc.token +1 -0
  5. package/.temp/jest-protection-convert/run-IFN2nv/.protection/hubspot-companies.json +1 -0
  6. package/.temp/jest-protection-convert/run-IvmKLO/.protection/hubspot-companies.yaml +17 -0
  7. package/.temp/jest-protection-convert/run-SdvblF/.protection/hubspot-companies.json +1 -0
  8. package/.temp/jest-protection-convert/run-b51TsW/.protection/hubspot-companies.json +1 -0
  9. package/.temp/jest-protection-convert/run-fiLmb1/.protection/hubspot-companies.json +1 -0
  10. package/.temp/jest-protection-convert/run-qYGHMU/.protection/hubspot-companies.yaml +17 -0
  11. package/.temp/jest-protection-fixtures/hubspot-Mq5re8/hubspot-companies.yaml +17 -0
  12. package/.temp/jest-protection-fixtures/hubspot-f3u4YL/hubspot-companies.yaml +17 -0
  13. package/.temp/jest-protection-fixtures/hubspot-iQtd1O/hubspot-companies.yaml +17 -0
  14. package/.temp/jest-protection-fixtures/hubspot-mdmz5M/hubspot-companies.yaml +17 -0
  15. package/.temp/jest-protection-fixtures/hubspot-qbKYxQ/hubspot-companies.yaml +17 -0
  16. package/.temp/jest-protection-fixtures/hubspot-yzlJy6/hubspot-companies.yaml +17 -0
  17. package/.temp/validation/summary.txt +5 -0
  18. package/README.md +43 -17
  19. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
  20. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
  21. package/jest.config.default.js +2 -1
  22. package/jest.config.isolated.js +2 -1
  23. package/jest.global-live-fabrix-hooks.js +36 -0
  24. package/jest.isolated-projects.js +146 -0
  25. package/jest.projects.js +65 -136
  26. package/lib/api/api-response-errors.js +124 -0
  27. package/lib/api/dataplane-health.api.js +19 -7
  28. package/lib/api/governance-scenario-pack.api.js +159 -0
  29. package/lib/api/index.js +43 -3
  30. package/lib/api/lifecycle.api.js +98 -0
  31. package/lib/api/pipeline.api.js +3 -1
  32. package/lib/api/records-bulk.api.js +14 -1
  33. package/lib/api/resource-types.api.js +107 -0
  34. package/lib/api/runtime-configuration.api.js +72 -0
  35. package/lib/api/types/resource-types.types.js +45 -0
  36. package/lib/api/user-groups.api.js +9 -9
  37. package/lib/api/users.api.js +8 -8
  38. package/lib/api/validation-runner.js +3 -1
  39. package/lib/api/wizard.api.js +10 -2
  40. package/lib/app/deploy-config.js +4 -1
  41. package/lib/app/down.js +78 -27
  42. package/lib/app/index.js +2 -2
  43. package/lib/app/push.js +4 -5
  44. package/lib/app/register.js +7 -4
  45. package/lib/app/run-env-compose.js +84 -30
  46. package/lib/app/run-resolve-image.js +2 -1
  47. package/lib/app/run-stop-containers.js +113 -0
  48. package/lib/app/run.js +1 -31
  49. package/lib/app/show-display.js +35 -0
  50. package/lib/app/show.js +32 -1
  51. package/lib/build/index.js +22 -5
  52. package/lib/build/miso-controller-npm-sdk-guard.js +25 -0
  53. package/lib/certification/sync-system-certification.js +13 -6
  54. package/lib/channels/add-channel.js +348 -0
  55. package/lib/channels/channel-artifact-generator.js +141 -0
  56. package/lib/channels/channel-audit.js +101 -0
  57. package/lib/channels/channel-auth-context.js +37 -0
  58. package/lib/channels/channel-credential.js +200 -0
  59. package/lib/channels/channel-display-name.js +64 -0
  60. package/lib/channels/channel-external-system.js +106 -0
  61. package/lib/channels/channel-integration-generator.js +274 -0
  62. package/lib/channels/channel-probe.js +89 -0
  63. package/lib/channels/channel-runtime-resolver.js +152 -0
  64. package/lib/channels/channel-status-display.js +141 -0
  65. package/lib/channels/channel-targets.js +115 -0
  66. package/lib/cli/index.js +20 -4
  67. package/lib/cli/infra-guided-auth.js +109 -0
  68. package/lib/cli/infra-guided.js +84 -81
  69. package/lib/cli/setup-app.help.js +0 -31
  70. package/lib/cli/setup-app.js +82 -5
  71. package/lib/cli/setup-app.test-commands.js +5 -57
  72. package/lib/cli/setup-auth.js +25 -0
  73. package/lib/cli/setup-certification-commands.js +147 -0
  74. package/lib/cli/setup-certification.help.js +141 -0
  75. package/lib/cli/setup-environment.js +19 -2
  76. package/lib/cli/setup-external-system-help.js +62 -0
  77. package/lib/cli/setup-external-system.js +25 -3
  78. package/lib/cli/setup-infra-up-dataplane-action.js +2 -2
  79. package/lib/cli/setup-infra-up-platform-action.js +2 -1
  80. package/lib/cli/setup-infra.js +9 -1
  81. package/lib/cli/setup-platform.js +6 -1
  82. package/lib/cli/setup-secrets.js +33 -1
  83. package/lib/cli/setup-utility-help-after.js +25 -2
  84. package/lib/cli/setup-utility-repair.js +198 -0
  85. package/lib/cli/setup-utility-resolve.js +44 -5
  86. package/lib/cli/setup-utility-validate.js +197 -0
  87. package/lib/cli/setup-utility.js +4 -239
  88. package/lib/commands/app-logs.js +54 -26
  89. package/lib/commands/app.js +41 -0
  90. package/lib/commands/auth-status-client-tokens.js +214 -0
  91. package/lib/commands/auth-status-dataplane-version.js +142 -68
  92. package/lib/commands/auth-status.js +43 -54
  93. package/lib/commands/channel.js +58 -0
  94. package/lib/commands/datasource-test-trust-cli.js +27 -23
  95. package/lib/commands/datasource-unified-test-cli.js +6 -3
  96. package/lib/commands/datasource-unified-test-cli.options.js +5 -1
  97. package/lib/commands/datasource.js +8 -8
  98. package/lib/commands/dev-show-display.js +8 -1
  99. package/lib/commands/governance-cli-shared.js +94 -0
  100. package/lib/commands/governance-command-action.js +132 -0
  101. package/lib/commands/governance-download-external.js +34 -0
  102. package/lib/commands/governance-generate-external.js +71 -0
  103. package/lib/commands/governance-upload-external.js +36 -0
  104. package/lib/commands/governance-verify-external.js +64 -0
  105. package/lib/commands/governance.js +144 -0
  106. package/lib/commands/identity-apply-sync.js +49 -8
  107. package/lib/commands/identity-group-cli.js +66 -26
  108. package/lib/commands/identity-membership-role-cache.js +58 -37
  109. package/lib/commands/identity-shared.js +22 -1
  110. package/lib/commands/identity-user-cli.js +80 -34
  111. package/lib/commands/lifecycle-command-action.js +123 -0
  112. package/lib/commands/lifecycle-external.js +268 -0
  113. package/lib/commands/login.js +11 -2
  114. package/lib/commands/repair-auth-apply.js +153 -0
  115. package/lib/commands/repair-auth-config.js +8 -13
  116. package/lib/commands/repair-changed-files.js +41 -0
  117. package/lib/commands/repair-datasource-com-v2.js +15 -0
  118. package/lib/commands/repair-datasource-keys.js +4 -1
  119. package/lib/commands/repair-datasource-run.js +59 -0
  120. package/lib/commands/repair-datasource-service-contract.js +206 -0
  121. package/lib/commands/repair-datasource-test-payload.js +259 -0
  122. package/lib/commands/repair-datasource.js +49 -64
  123. package/lib/commands/repair-env-template.js +76 -25
  124. package/lib/commands/repair-external-run.js +216 -0
  125. package/lib/commands/repair-openapi-sync.js +49 -4
  126. package/lib/commands/repair-persist.js +4 -0
  127. package/lib/commands/repair-rbac.js +52 -1
  128. package/lib/commands/repair-steps.js +160 -0
  129. package/lib/commands/repair-system-alignment.js +7 -4
  130. package/lib/commands/repair.js +29 -296
  131. package/lib/commands/resource-type.js +371 -0
  132. package/lib/commands/secrets-get.js +184 -0
  133. package/lib/commands/secrets-remove-all.js +3 -1
  134. package/lib/commands/setup-image-refresh.js +146 -0
  135. package/lib/commands/setup-modes.js +158 -162
  136. package/lib/commands/setup-platform-auth.js +76 -0
  137. package/lib/commands/setup-prompts-admin.js +244 -0
  138. package/lib/commands/setup-prompts-platform-mode.js +70 -0
  139. package/lib/commands/setup-prompts-validators.js +36 -0
  140. package/lib/commands/setup-prompts.js +24 -76
  141. package/lib/commands/setup-run-context.js +45 -0
  142. package/lib/commands/setup-spinners.js +39 -0
  143. package/lib/commands/setup.js +27 -5
  144. package/lib/commands/teardown.js +39 -0
  145. package/lib/commands/test-e2e-external.js +24 -8
  146. package/lib/commands/test-governance-external.js +3 -24
  147. package/lib/commands/test-trust-external.js +48 -100
  148. package/lib/commands/up-common.js +57 -13
  149. package/lib/commands/up-dataplane.js +56 -15
  150. package/lib/commands/upload-publish-context.js +75 -0
  151. package/lib/commands/upload-sidecar-followups.js +89 -0
  152. package/lib/commands/upload.js +113 -110
  153. package/lib/commands/verify-governance-combined-external.js +61 -0
  154. package/lib/commands/verify-governance-command-action.js +64 -0
  155. package/lib/commands/verify-governance-db.js +102 -0
  156. package/lib/commands/verify-governance-external.js +77 -0
  157. package/lib/commands/verify-governance-result-builders.js +71 -0
  158. package/lib/commands/verify-operations-command-action.js +68 -0
  159. package/lib/commands/verify-operations-external.js +268 -0
  160. package/lib/commands/verify-operations-persist.js +75 -0
  161. package/lib/commands/verify-operations-step-plan.js +68 -0
  162. package/lib/commands/verify-operations-steps.js +111 -0
  163. package/lib/commands/verify-trust-command-action.js +73 -0
  164. package/lib/commands/verify-trust-external.js +59 -0
  165. package/lib/commands/wizard-config-normalizer.js +43 -23
  166. package/lib/commands/wizard-core.js +2 -0
  167. package/lib/core/admin-password-generator.js +38 -0
  168. package/lib/core/admin-secrets-bundle.js +111 -0
  169. package/lib/core/admin-secrets-env-overlay.js +62 -0
  170. package/lib/core/admin-secrets.js +32 -4
  171. package/lib/core/config-attach-extensions.js +3 -0
  172. package/lib/core/config-platform-controller.js +44 -0
  173. package/lib/core/config-setup-installation-profile.js +42 -0
  174. package/lib/core/config-setup-platform-mode.js +46 -0
  175. package/lib/core/config.js +46 -36
  176. package/lib/core/secrets-admin-env.js +6 -2
  177. package/lib/core/secrets-ensure.js +4 -0
  178. package/lib/core/secrets-env-content.js +54 -48
  179. package/lib/core/secrets-env-write.js +10 -1
  180. package/lib/core/secrets-infra-placeholder-sync.js +2 -0
  181. package/lib/core/setup-installation-profile.js +43 -0
  182. package/lib/core/setup-platform-mode.js +90 -0
  183. package/lib/datasource/agent-trust-debug-log.js +1 -1
  184. package/lib/datasource/agent-trust-run.js +5 -3
  185. package/lib/datasource/audit-evidence-extract-debug.js +30 -18
  186. package/lib/datasource/audit-evidence-extract.js +7 -4
  187. package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
  188. package/lib/datasource/bulk-loader-run-batches.js +15 -3
  189. package/lib/datasource/capability/capability-diff-slice.js +2 -2
  190. package/lib/datasource/capability/capability-manifest.js +254 -0
  191. package/lib/datasource/capability/capability-resolve.js +3 -4
  192. package/lib/datasource/capability/copy-operations.js +5 -3
  193. package/lib/datasource/capability/remove-operations.js +2 -1
  194. package/lib/datasource/capability/run-capability-copy.js +32 -4
  195. package/lib/datasource/capability/run-capability-diff.js +3 -3
  196. package/lib/datasource/capability/run-capability-dimension.js +2 -4
  197. package/lib/datasource/capability/run-capability-edit.js +4 -7
  198. package/lib/datasource/capability/run-capability-relate.js +2 -4
  199. package/lib/datasource/capability/run-capability-remove.js +2 -4
  200. package/lib/datasource/capability/validate-capability-slice.js +2 -1
  201. package/lib/datasource/datasource-identifier.js +2 -1
  202. package/lib/datasource/datasource-load-export-context.js +3 -0
  203. package/lib/datasource/datasource-validate-display.js +1 -1
  204. package/lib/datasource/field-reference-validator.js +24 -3
  205. package/lib/datasource/log-cleaner.js +2 -2
  206. package/lib/datasource/log-viewer.js +8 -8
  207. package/lib/datasource/orphan-profiles-validator.js +98 -0
  208. package/lib/datasource/test-e2e.js +4 -1
  209. package/lib/datasource/unified-validation-run-body.js +3 -1
  210. package/lib/datasource/unified-validation-run.js +5 -2
  211. package/lib/datasource/validate.js +41 -23
  212. package/lib/deployment/environment-poll-status.js +138 -0
  213. package/lib/deployment/environment.js +42 -34
  214. package/lib/external-system/download-helpers.js +87 -0
  215. package/lib/external-system/download.js +78 -138
  216. package/lib/external-system/generator.js +1 -55
  217. package/lib/external-system/integration-auth-context.js +45 -0
  218. package/lib/external-system/test-auth.js +12 -5
  219. package/lib/external-system/test.js +16 -21
  220. package/lib/generator/builders.js +11 -1
  221. package/lib/generator/external-controller-manifest.js +18 -0
  222. package/lib/generator/split.js +3 -1
  223. package/lib/generator/wizard.js +1 -28
  224. package/lib/governance/governance-cli-errors.js +96 -0
  225. package/lib/governance/governance-download-display.js +38 -0
  226. package/lib/governance/governance-run-display.js +215 -25
  227. package/lib/identity/fk-reference.js +65 -0
  228. package/lib/identity/identity-apply-core.js +13 -58
  229. package/lib/identity/identity-apply-phases.js +5 -1
  230. package/lib/identity/identity-display.js +243 -0
  231. package/lib/identity/identity-response-helpers.js +52 -0
  232. package/lib/identity/identity-sync-errors.js +62 -0
  233. package/lib/identity/resolve-user-id.js +129 -0
  234. package/lib/identity/username-default.js +31 -0
  235. package/lib/infrastructure/admin-secrets-apply.js +84 -0
  236. package/lib/infrastructure/admin-secrets-ensure.js +130 -0
  237. package/lib/infrastructure/admin-secrets-resolve.js +95 -0
  238. package/lib/infrastructure/admin-secrets-sync.js +91 -0
  239. package/lib/infrastructure/helpers.js +23 -129
  240. package/lib/infrastructure/index.js +5 -6
  241. package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
  242. package/lib/lifecycle/certification-progress.js +231 -0
  243. package/lib/lifecycle/dataplane-ui-url.js +145 -0
  244. package/lib/lifecycle/exit-codes.js +24 -0
  245. package/lib/lifecycle/json-envelope.js +25 -0
  246. package/lib/lifecycle/lifecycle-governance-options.js +51 -0
  247. package/lib/lifecycle/logger-quiet.js +29 -0
  248. package/lib/lifecycle/open-api-published.js +59 -0
  249. package/lib/lifecycle/operations-readiness-metrics.js +101 -0
  250. package/lib/lifecycle/product-model.js +196 -0
  251. package/lib/lifecycle/report-display-trust.js +70 -0
  252. package/lib/lifecycle/report-display.js +472 -0
  253. package/lib/lifecycle/scenario-upload.js +191 -0
  254. package/lib/lifecycle/verify-step-progress.js +87 -0
  255. package/lib/parameters/infra-kv-discovery.js +27 -2
  256. package/lib/protection/auth-context.js +10 -4
  257. package/lib/resolvers/datasource-resolver.js +2 -3
  258. package/lib/resolvers/resource-type-file.js +159 -0
  259. package/lib/schema/application-schema.json +17 -1
  260. package/lib/schema/datasource-test-run.schema.json +89 -6
  261. package/lib/schema/deployment-rules.yaml +2 -1
  262. package/lib/schema/external-datasource.schema.json +2947 -2619
  263. package/lib/schema/external-system.schema.json +1418 -761
  264. package/lib/schema/infra.parameter.yaml +45 -0
  265. package/lib/schema/type/credential-field-registry.json +103 -97
  266. package/lib/schema/type/document-storage.json +9 -5
  267. package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
  268. package/lib/utils/api.js +55 -31
  269. package/lib/utils/app-relative-path-env.js +112 -0
  270. package/lib/utils/app-run-containers.js +25 -2
  271. package/lib/utils/authentication-shape.js +224 -0
  272. package/lib/utils/build-copy.js +36 -5
  273. package/lib/utils/build-resolve-image.js +66 -12
  274. package/lib/utils/celery-companion-apps.js +53 -0
  275. package/lib/utils/cli-secrets-error-format.js +83 -21
  276. package/lib/utils/cli-utils.js +20 -4
  277. package/lib/utils/compose-celery-worker.js +23 -0
  278. package/lib/utils/compose-generate-docker-compose.js +13 -1
  279. package/lib/utils/compose-traefik-ingress-base.js +16 -1
  280. package/lib/utils/config-secrets-path.js +46 -0
  281. package/lib/utils/configuration-env-resolver.js +36 -0
  282. package/lib/utils/controller-url.js +88 -1
  283. package/lib/utils/credential-secrets-env-kv.js +216 -0
  284. package/lib/utils/credential-secrets-env.js +175 -257
  285. package/lib/utils/dataplane-resolver.js +18 -2
  286. package/lib/utils/declarative-url-ports.js +27 -4
  287. package/lib/utils/deployment-auth-mode.js +41 -0
  288. package/lib/utils/developer-volume-id.js +33 -0
  289. package/lib/utils/docker-build.js +1 -4
  290. package/lib/utils/env-copy.js +14 -9
  291. package/lib/utils/env-kv-orphan-lines.js +43 -0
  292. package/lib/utils/error-formatters/network-errors.js +13 -4
  293. package/lib/utils/external-env-template.js +11 -3
  294. package/lib/utils/external-system-readiness-core.js +10 -0
  295. package/lib/utils/external-system-readiness-display.js +80 -23
  296. package/lib/utils/external-system-validators.js +8 -2
  297. package/lib/utils/health-check.js +4 -1
  298. package/lib/utils/help-builder.js +13 -8
  299. package/lib/utils/keycloak-realm-ready.js +101 -0
  300. package/lib/utils/load-cip-capacity-display-config.js +61 -15
  301. package/lib/utils/manifest-source-emit.js +2 -0
  302. package/lib/utils/paths.js +25 -0
  303. package/lib/utils/pipeline-upload-auth-retry.js +82 -0
  304. package/lib/utils/platform-controller-url.js +157 -0
  305. package/lib/utils/platform-kv-ref.js +57 -0
  306. package/lib/utils/postgres-platform-bootstrap.js +199 -0
  307. package/lib/utils/postgres-wipe.js +9 -2
  308. package/lib/utils/resolve-env-mode.js +47 -0
  309. package/lib/utils/runtime-configuration-download.js +189 -0
  310. package/lib/utils/runtime-configuration-values.js +119 -0
  311. package/lib/utils/schema-loader.js +19 -4
  312. package/lib/utils/secrets-generator.js +31 -25
  313. package/lib/utils/secrets-missing-error.js +164 -0
  314. package/lib/utils/service-url-label.js +81 -0
  315. package/lib/utils/setup-quiet-output.js +25 -0
  316. package/lib/utils/template-helpers.js +15 -0
  317. package/lib/utils/token-manager-client-credentials.js +201 -0
  318. package/lib/utils/token-manager-messages.js +8 -0
  319. package/lib/utils/token-manager-refresh.js +12 -2
  320. package/lib/utils/token-manager.js +86 -105
  321. package/lib/utils/upload-pipeline-ui.js +12 -5
  322. package/lib/utils/upload-sync-options.js +42 -0
  323. package/lib/utils/url-declarative-public-base.js +21 -3
  324. package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
  325. package/lib/utils/validation-poll-ui.js +8 -0
  326. package/lib/utils/validation-run-stage.js +45 -0
  327. package/lib/utils/worker-sidecars.js +142 -0
  328. package/lib/validation/external-manifest-validator.js +2 -0
  329. package/lib/validation/runtime-configuration-rules.js +98 -0
  330. package/lib/validation/validate-display-dimensions.js +154 -0
  331. package/lib/validation/validate-display-sections.js +276 -0
  332. package/lib/validation/validate-display-steps.js +67 -0
  333. package/lib/validation/validate-display.js +24 -402
  334. package/package.json +1 -1
  335. package/templates/applications/dataplane/application.yaml +7 -1
  336. package/templates/applications/dataplane/env.template +50 -14
  337. package/templates/applications/dataplane/rbac.yaml +108 -1
  338. package/templates/applications/miso-controller/application.yaml +2 -2
  339. package/templates/applications/miso-controller/env.template +53 -122
  340. package/templates/applications/miso-controller/rbac.yaml +28 -13
  341. package/templates/channels/chatgpt/install.template.md.hbs +49 -0
  342. package/templates/channels/chatgpt/manifest.template.json.hbs +9 -0
  343. package/templates/channels/microsoft-copilot/install.template.md.hbs +49 -0
  344. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +8 -0
  345. package/templates/channels/slack/install.template.md.hbs +49 -0
  346. package/templates/channels/slack/manifest.template.json.hbs +66 -0
  347. package/templates/channels/teams-bot/install.template.md.hbs +49 -0
  348. package/templates/channels/teams-bot/manifest.template.json.hbs +13 -0
  349. package/templates/channels/web-embed/install.template.md.hbs +49 -0
  350. package/templates/channels/web-embed/manifest.template.json.hbs +8 -0
  351. package/templates/external-system/README.md.hbs +74 -17
  352. package/templates/python/docker-compose.hbs +75 -18
  353. package/templates/typescript/docker-compose.hbs +70 -17
  354. package/lib/commands/test-governance-command-action.js +0 -55
  355. package/lib/commands/test-trust-command-action.js +0 -118
@@ -12,6 +12,7 @@
12
12
  const { getDeveloperIdNumber } = require('./env-map');
13
13
  const devConfig = require('./dev-config');
14
14
  const config = require('../core/config');
15
+ const { getDeviceToken, isTokenExpired } = require('./token-manager');
15
16
 
16
17
  /**
17
18
  * Calculate default controller URL based on developer ID
@@ -40,7 +41,6 @@ function normalizeUrl(url) {
40
41
  }
41
42
  return url.trim().replace(/\/+$/, '');
42
43
  }
43
-
44
44
  /**
45
45
  * True when `config.yaml` has a non-expired-looking device entry for this controller URL
46
46
  * (normalized host/path comparison).
@@ -68,6 +68,90 @@ async function hasStoredDeviceTokenForController(controllerUrl) {
68
68
  }
69
69
  }
70
70
 
71
+ /**
72
+ * True when a stored, non-expired device token exists (local config only — no refresh HTTP).
73
+ * Setup uses this to decide whether to skip the device-login step; avoids refresh warnings
74
+ * when the controller is not up yet or `device:` is empty.
75
+ *
76
+ * @async
77
+ * @param {string} controllerUrl
78
+ * @returns {Promise<boolean>}
79
+ */
80
+ async function isDeviceTokenUsableForController(controllerUrl) {
81
+ if (!(await hasStoredDeviceTokenForController(controllerUrl))) {
82
+ return false;
83
+ }
84
+ const want = normalizeUrl(controllerUrl);
85
+ try {
86
+ const tokenInfo = await getDeviceToken(want);
87
+ return Boolean(tokenInfo && tokenInfo.token && !isTokenExpired(tokenInfo.expiresAt));
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+
93
+ /**
94
+ * True when a stored device token can be refreshed (if needed) and validated against the controller API.
95
+ * Prefer this after the controller is reachable (guided platform auth step). Falls back to local expiry-only
96
+ * check when the controller is not reachable yet.
97
+ *
98
+ * @async
99
+ * @param {string} controllerUrl
100
+ * @returns {Promise<boolean>}
101
+ */
102
+ async function isPlatformAuthValidForController(controllerUrl) {
103
+ if (!(await hasStoredDeviceTokenForController(controllerUrl))) {
104
+ return false;
105
+ }
106
+ const want = normalizeUrl(controllerUrl);
107
+
108
+ if (!(await isControllerHealthReachable(want))) {
109
+ return isDeviceTokenUsableForController(controllerUrl);
110
+ }
111
+
112
+ const { getOrRefreshDeviceToken } = require('./token-manager');
113
+ const { getAuthUser } = require('../api/auth.api');
114
+
115
+ let tokenResult = null;
116
+ try {
117
+ tokenResult = await getOrRefreshDeviceToken(want);
118
+ } catch {
119
+ tokenResult = null;
120
+ }
121
+
122
+ if (!tokenResult || !tokenResult.token) {
123
+ return false;
124
+ }
125
+
126
+ try {
127
+ const response = await getAuthUser(want, { type: 'bearer', token: tokenResult.token });
128
+ return Boolean(response.success && response.data && response.data.authenticated !== false);
129
+ } catch {
130
+ return false;
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Best-effort GET /health on the controller (no auth). Used to avoid token refresh HTTP
136
+ * during setup before Miso Controller is running.
137
+ *
138
+ * @async
139
+ * @param {string} controllerUrl
140
+ * @returns {Promise<boolean>}
141
+ */
142
+ async function isControllerHealthReachable(controllerUrl) {
143
+ const base = normalizeUrl(controllerUrl);
144
+ if (!base) {
145
+ return false;
146
+ }
147
+ try {
148
+ const res = await fetch(`${base}/health`, { signal: AbortSignal.timeout(2500) });
149
+ return res.ok;
150
+ } catch {
151
+ return false;
152
+ }
153
+ }
154
+
71
155
  /**
72
156
  * Get controller URL from logged-in user's device tokens.
73
157
  * Prefers the entry under {@link config.controller} when it matches a `device` key; otherwise a
@@ -152,6 +236,9 @@ async function resolveControllerUrl() {
152
236
  module.exports = {
153
237
  getDefaultControllerUrl,
154
238
  hasStoredDeviceTokenForController,
239
+ isDeviceTokenUsableForController,
240
+ isPlatformAuthValidForController,
241
+ isControllerHealthReachable,
155
242
  getControllerUrlFromLoggedInUser,
156
243
  getControllerFromConfig,
157
244
  resolveControllerUrl
@@ -0,0 +1,216 @@
1
+ /**
2
+ * KV_* env key ↔ kv:// path mapping and payload reference scanning.
3
+ *
4
+ * @fileoverview KV path helpers for credential-secrets-env
5
+ * @author AI Fabrix Team
6
+ * @version 2.0.0
7
+ */
8
+
9
+ const KV_PREFIX = 'KV_';
10
+ const KV_REF_PATTERN = /kv:\/\/([a-zA-Z0-9_\-/]+)/g;
11
+
12
+ /**
13
+ * Converts systemKey to KV_* prefix (e.g. hubspot -> HUBSPOT, my-hubspot -> MY_HUBSPOT).
14
+ * @param {string} systemKey - System key
15
+ * @returns {string}
16
+ */
17
+ function systemKeyToKvPrefix(systemKey) {
18
+ if (!systemKey || typeof systemKey !== 'string') return '';
19
+ return systemKey.replace(/-/g, '_').toUpperCase();
20
+ }
21
+
22
+ /**
23
+ * Maps authentication security key (camelCase) to env VAR (UPPERCASE, no underscores).
24
+ * @param {string} securityKey - Security key (e.g. 'clientId', 'clientSecret')
25
+ * @returns {string}
26
+ */
27
+ function securityKeyToVar(securityKey) {
28
+ if (!securityKey || typeof securityKey !== 'string') return '';
29
+ return securityKey.replace(/_/g, '').toUpperCase();
30
+ }
31
+
32
+ /** Known single-segment variable suffixes (uppercase) for inferring var vs namespace in env keys */
33
+ const VAR_SUFFIXES = new Set(['ID', 'SECRET', 'KEY', 'TOKEN', 'URL', 'USERNAME', 'PASSWORD']);
34
+
35
+ /**
36
+ * Converts var segment(s) from env key to path-style camelCase.
37
+ * @param {string[]} varSegments - One or two segments (e.g. ['CLIENT', 'ID'], ['CLIENTID'])
38
+ * @returns {string}
39
+ */
40
+ function varSegmentsToCamelCase(varSegments) {
41
+ if (!varSegments || varSegments.length === 0) return '';
42
+ if (varSegments.length === 1) {
43
+ const s = varSegments[0].toLowerCase();
44
+ if (s.endsWith('id') && s.length > 2) return s.slice(0, -2) + 'Id';
45
+ if (s.endsWith('secret') && s.length > 6) return s.slice(0, -6) + 'Secret';
46
+ if (s.endsWith('key') && s.length > 3) return s.slice(0, -3) + 'Key';
47
+ if (s.endsWith('token') && s.length > 5) return s.slice(0, -5) + 'Token';
48
+ if (s.endsWith('url') && s.length > 3) return s.slice(0, -3) + 'Url';
49
+ return s;
50
+ }
51
+ return varSegments.map((seg, i) => {
52
+ const lower = seg.toLowerCase();
53
+ return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
54
+ }).join('');
55
+ }
56
+
57
+ /**
58
+ * @param {string[]} segments - Parsed segments after KV_ prefix
59
+ * @param {string} systemKey - System key (e.g. 'microsoft-teams')
60
+ * @returns {string|null}
61
+ */
62
+ function kvPathWithSystemKey(segments, systemKey) {
63
+ const prefixInKey = systemKey.replace(/-/g, '_').toUpperCase();
64
+ const prefixSegs = prefixInKey.split('_').filter(Boolean);
65
+ if (segments.length <= prefixSegs.length) return null;
66
+ const prefixMatch = prefixSegs.every((p, i) => segments[i] === p);
67
+ if (!prefixMatch) return null;
68
+ const varSegments = segments.slice(prefixSegs.length);
69
+ const pathVar = varSegmentsToCamelCase(varSegments);
70
+ return pathVar ? `kv://${systemKey}/${pathVar}` : null;
71
+ }
72
+
73
+ /**
74
+ * @param {string[]} segments - Parsed segments after KV_ prefix
75
+ * @returns {string|null}
76
+ */
77
+ function kvPathInferred(segments) {
78
+ if (segments.length === 1) return `kv://${segments[0].toLowerCase()}`;
79
+ const varSegmentCount = (segments.length >= 2 && VAR_SUFFIXES.has(segments[segments.length - 1])) ? 2 : 1;
80
+ const namespace = segments.slice(0, -varSegmentCount).map(s => s.toLowerCase()).join('-');
81
+ const varSegments = segments.slice(-varSegmentCount);
82
+ const pathVar = varSegmentsToCamelCase(varSegments);
83
+ return (namespace && pathVar) ? `kv://${namespace}/${pathVar}` : null;
84
+ }
85
+
86
+ /**
87
+ * @param {string} securityKey - Security key (e.g. 'apiKey', 'clientId')
88
+ * @returns {string}
89
+ */
90
+ function getKvPathSegmentForSecurityKey(securityKey) {
91
+ if (!securityKey || typeof securityKey !== 'string') return '';
92
+ return varSegmentsToCamelCase([securityKeyToVar(securityKey)]);
93
+ }
94
+
95
+ /**
96
+ * @param {string} envKey - Env var name (e.g. KV_MICROSOFT_TEAMS_CLIENT_ID)
97
+ * @param {string} [systemKey] - Optional system key
98
+ * @returns {string|null}
99
+ */
100
+ function kvEnvKeyToPath(envKey, systemKey) {
101
+ if (!envKey || typeof envKey !== 'string' || !envKey.toUpperCase().startsWith(KV_PREFIX)) return null;
102
+ const rest = envKey.slice(KV_PREFIX.length).trim();
103
+ if (!rest) return null;
104
+ const segments = rest.split('_').filter(Boolean);
105
+ if (segments.length === 0) return null;
106
+
107
+ const hasSystemKey = typeof systemKey === 'string' && systemKey.length > 0;
108
+ if (hasSystemKey) return kvPathWithSystemKey(segments, systemKey);
109
+ return kvPathInferred(segments);
110
+ }
111
+
112
+ /**
113
+ * @param {Object.<string, string>} envMap - Key-value map from .env
114
+ * @param {string} [systemKey]
115
+ * @returns {Array<{ key: string, value: string }>}
116
+ */
117
+ function collectKvEnvVarsAsSecretItems(envMap, systemKey) {
118
+ if (!envMap || typeof envMap !== 'object') {
119
+ return [];
120
+ }
121
+ const items = [];
122
+ for (const [envKey, rawValue] of Object.entries(envMap)) {
123
+ const value = typeof rawValue === 'string' ? rawValue.trim() : '';
124
+ if (value === '') continue;
125
+ let kvPath = null;
126
+ if (value.startsWith('kv://') && isValidKvPath(value)) {
127
+ kvPath = value;
128
+ }
129
+ if (!kvPath) kvPath = kvEnvKeyToPath(envKey, systemKey) || kvEnvKeyToPath(envKey);
130
+ if (!kvPath) continue;
131
+ items.push({ key: kvPath, value });
132
+ }
133
+ return items;
134
+ }
135
+
136
+ /**
137
+ * @param {Object} secrets - Loaded secrets object
138
+ * @param {string} value - Value (may be "kv://..." or plain)
139
+ * @returns {string|null}
140
+ */
141
+ function resolveKvValue(secrets, value) {
142
+ if (typeof value !== 'string') return null;
143
+ const trimmed = value.trim();
144
+ if (!trimmed.startsWith('kv://')) {
145
+ return trimmed;
146
+ }
147
+ const pathMatch = trimmed.match(/^kv:\/\/([a-zA-Z0-9_\-/]+)$/);
148
+ if (!pathMatch) return null;
149
+ const pathKey = pathMatch[1];
150
+ const resolved = secrets[pathKey];
151
+ if (resolved === undefined) return null;
152
+ return typeof resolved === 'string' ? resolved : String(resolved);
153
+ }
154
+
155
+ /**
156
+ * @param {Object|Array|string|number|boolean|null} obj
157
+ * @param {Set<string>} [acc]
158
+ * @returns {string[]}
159
+ */
160
+ function collectKvRefsFromPayload(obj, acc = new Set()) {
161
+ if (obj === null || obj === undefined) {
162
+ return Array.from(acc);
163
+ }
164
+ if (typeof obj === 'string') {
165
+ let m;
166
+ KV_REF_PATTERN.lastIndex = 0;
167
+ while ((m = KV_REF_PATTERN.exec(obj)) !== null) {
168
+ acc.add(`kv://${m[1]}`);
169
+ }
170
+ return Array.from(acc);
171
+ }
172
+ if (Array.isArray(obj)) {
173
+ for (const item of obj) {
174
+ collectKvRefsFromPayload(item, acc);
175
+ }
176
+ return Array.from(acc);
177
+ }
178
+ if (typeof obj === 'object') {
179
+ for (const v of Object.values(obj)) {
180
+ collectKvRefsFromPayload(v, acc);
181
+ }
182
+ return Array.from(acc);
183
+ }
184
+ return Array.from(acc);
185
+ }
186
+
187
+ /**
188
+ * @param {string} key - kv:// path
189
+ * @returns {boolean}
190
+ */
191
+ function isValidKvPath(key) {
192
+ return typeof key === 'string' && /^kv:\/\/[a-z0-9][a-z0-9\-/]*$/i.test(key.trim());
193
+ }
194
+
195
+ /**
196
+ * @param {unknown} resolved
197
+ * @returns {boolean}
198
+ */
199
+ function isNonEmptySecretValue(resolved) {
200
+ if (resolved === null || resolved === undefined) {
201
+ return false;
202
+ }
203
+ return String(resolved).trim() !== '';
204
+ }
205
+
206
+ module.exports = {
207
+ collectKvEnvVarsAsSecretItems,
208
+ collectKvRefsFromPayload,
209
+ getKvPathSegmentForSecurityKey,
210
+ isNonEmptySecretValue,
211
+ isValidKvPath,
212
+ kvEnvKeyToPath,
213
+ resolveKvValue,
214
+ securityKeyToVar,
215
+ systemKeyToKvPrefix
216
+ };