@aifabrix/builder 2.53.1 → 2.54.1

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 (321) hide show
  1. package/bin/aifabrix.js +2 -2
  2. package/lib/api/assistants.api.js +8 -5
  3. package/lib/api/channel-identity.api.js +41 -0
  4. package/lib/api/evidence-authoring.api.js +5 -1
  5. package/lib/api/evidence.api.js +2 -0
  6. package/lib/api/types/evidence.types.js +2 -0
  7. package/lib/api/work-search.api.js +136 -0
  8. package/lib/channels/add-channel.js +163 -126
  9. package/lib/channels/approval-guides/chatgpt.js +14 -18
  10. package/lib/channels/approval-guides/claude.js +29 -0
  11. package/lib/channels/approval-guides/index.js +88 -22
  12. package/lib/channels/approval-guides/mcp-client.js +27 -0
  13. package/lib/channels/approval-guides/microsoft-copilot.js +52 -3
  14. package/lib/channels/approval-guides/slack.js +10 -10
  15. package/lib/channels/approval-guides/teams-bot.js +8 -12
  16. package/lib/channels/channel-add-continuations.js +91 -0
  17. package/lib/channels/channel-add-ensure.js +124 -27
  18. package/lib/channels/channel-add-existing.js +160 -28
  19. package/lib/channels/channel-add-failure.js +60 -0
  20. package/lib/channels/channel-add-remaining.js +486 -0
  21. package/lib/channels/channel-add-tty.js +190 -0
  22. package/lib/channels/channel-add-wizard-config.js +138 -0
  23. package/lib/channels/channel-add-wizard.js +250 -0
  24. package/lib/channels/channel-artifact-generator.js +27 -13
  25. package/lib/channels/channel-cardinality.js +83 -0
  26. package/lib/channels/channel-catalog-icon.js +45 -0
  27. package/lib/channels/channel-cli-instructions.js +75 -0
  28. package/lib/channels/channel-configuration-map.js +213 -0
  29. package/lib/channels/channel-credential.js +11 -14
  30. package/lib/channels/channel-definition-project.js +101 -0
  31. package/lib/channels/channel-definition-registry.js +154 -0
  32. package/lib/channels/channel-description.js +59 -2
  33. package/lib/channels/channel-discovery.js +16 -2
  34. package/lib/channels/channel-external-system.js +86 -9
  35. package/lib/channels/channel-install-envelope-actions.js +88 -0
  36. package/lib/channels/channel-install-envelope-microsoft.js +155 -0
  37. package/lib/channels/channel-install-envelope.js +356 -0
  38. package/lib/channels/channel-install-help-md.js +172 -0
  39. package/lib/channels/channel-install-http-payload.js +62 -0
  40. package/lib/channels/channel-install-inventory.js +115 -0
  41. package/lib/channels/channel-install-profiles.js +90 -0
  42. package/lib/channels/channel-instance-collision.js +118 -0
  43. package/lib/channels/channel-instance-key.js +100 -0
  44. package/lib/channels/channel-instance-materialize.js +240 -0
  45. package/lib/channels/channel-integration-generator.js +16 -9
  46. package/lib/channels/channel-integration-template.js +101 -22
  47. package/lib/channels/channel-inventory-fetch.js +79 -0
  48. package/lib/channels/channel-oauth-preflight.js +104 -0
  49. package/lib/channels/channel-package-version.js +76 -0
  50. package/lib/channels/channel-predefined-client.js +154 -0
  51. package/lib/channels/channel-probe.js +7 -2
  52. package/lib/channels/channel-runtime-resolver.js +180 -72
  53. package/lib/channels/channel-status-display.js +86 -16
  54. package/lib/channels/channel-targets.js +106 -92
  55. package/lib/channels/chatgpt-callback.js +318 -0
  56. package/lib/channels/chatgpt-channel-add.js +229 -0
  57. package/lib/channels/chatgpt-preflight.js +396 -0
  58. package/lib/channels/chatgpt-runtime-contract.js +17 -0
  59. package/lib/channels/chatgpt-setup-values.js +124 -0
  60. package/lib/channels/claude-callback.js +67 -0
  61. package/lib/channels/claude-channel-add.js +254 -0
  62. package/lib/channels/claude-runtime-contract.js +40 -0
  63. package/lib/channels/claude-runtime.js +58 -0
  64. package/lib/channels/claude-setup-values.js +89 -0
  65. package/lib/channels/mcp-client/config-merge.js +148 -0
  66. package/lib/channels/mcp-client/ensure-client.js +231 -0
  67. package/lib/channels/mcp-client/paths.js +53 -0
  68. package/lib/channels/mcp-client/profiles.js +122 -0
  69. package/lib/channels/mcp-client/redirect-uris.js +99 -0
  70. package/lib/channels/mcp-client/runtime.js +59 -0
  71. package/lib/channels/mcp-client-channel-add.js +186 -0
  72. package/lib/channels/microsoft-copilot-channel-add.js +117 -7
  73. package/lib/channels/microsoft-copilot-entra-identifier-uris.js +187 -0
  74. package/lib/channels/microsoft-copilot-entra-sso-form.js +106 -18
  75. package/lib/channels/microsoft-copilot-entra-sso.js +31 -2
  76. package/lib/channels/microsoft-copilot-package-prior.js +107 -0
  77. package/lib/channels/microsoft-copilot-package.js +29 -28
  78. package/lib/channels/microsoft-provisioning/a365.js +80 -0
  79. package/lib/channels/microsoft-provisioning/auth-config.js +240 -0
  80. package/lib/channels/microsoft-provisioning/auth.js +179 -0
  81. package/lib/channels/microsoft-provisioning/cli.js +71 -0
  82. package/lib/channels/microsoft-provisioning/constants.js +75 -0
  83. package/lib/channels/microsoft-provisioning/errors.js +117 -0
  84. package/lib/channels/microsoft-provisioning/index.js +55 -0
  85. package/lib/channels/microsoft-provisioning/install-atk.js +158 -0
  86. package/lib/channels/microsoft-provisioning/install-teams.js +115 -0
  87. package/lib/channels/microsoft-provisioning/login-portal-device.js +236 -0
  88. package/lib/channels/microsoft-provisioning/login-portal-parse.js +71 -0
  89. package/lib/channels/microsoft-provisioning/login-portal-teams.js +193 -0
  90. package/lib/channels/microsoft-provisioning/login-portal.js +230 -0
  91. package/lib/channels/microsoft-provisioning/persist.js +110 -0
  92. package/lib/channels/microsoft-provisioning/teams-bot-args.js +119 -0
  93. package/lib/channels/microsoft-provisioning/teams-bot-controller.js +123 -0
  94. package/lib/channels/microsoft-provisioning/teams-bot-parse.js +134 -0
  95. package/lib/channels/microsoft-provisioning/teams-bot-persist.js +113 -0
  96. package/lib/channels/microsoft-provisioning/teams-bot-provision.js +234 -0
  97. package/lib/channels/microsoft-provisioning/teams-bot-secrets.js +45 -0
  98. package/lib/channels/microsoft-provisioning/teams-cli.js +82 -0
  99. package/lib/channels/runtime-tool-catalog.js +5 -2
  100. package/lib/channels/slack-channel-add-portal.js +130 -0
  101. package/lib/channels/slack-channel-add-tty-auth.js +95 -0
  102. package/lib/channels/slack-channel-add.js +258 -0
  103. package/lib/channels/slack-provisioning/apps.js +181 -0
  104. package/lib/channels/slack-provisioning/auth-store.js +110 -0
  105. package/lib/channels/slack-provisioning/auth-ticket.js +185 -0
  106. package/lib/channels/slack-provisioning/auth.js +115 -0
  107. package/lib/channels/slack-provisioning/callbacks.js +41 -0
  108. package/lib/channels/slack-provisioning/cli.js +226 -0
  109. package/lib/channels/slack-provisioning/constants.js +37 -0
  110. package/lib/channels/slack-provisioning/credentials.js +169 -0
  111. package/lib/channels/slack-provisioning/curl-shim.js +132 -0
  112. package/lib/channels/slack-provisioning/developer-install.js +118 -0
  113. package/lib/channels/slack-provisioning/env-file.js +120 -0
  114. package/lib/channels/slack-provisioning/errors.js +47 -0
  115. package/lib/channels/slack-provisioning/go-ca-bundle.js +137 -0
  116. package/lib/channels/slack-provisioning/index.js +250 -0
  117. package/lib/channels/slack-provisioning/install-cli.js +323 -0
  118. package/lib/channels/slack-provisioning/manifest.js +89 -0
  119. package/lib/channels/slack-provisioning/oauth-lock.js +33 -0
  120. package/lib/channels/slack-provisioning/offer-cli.js +113 -0
  121. package/lib/channels/slack-provisioning/onboard-members.js +122 -0
  122. package/lib/channels/slack-provisioning/onboard.js +89 -0
  123. package/lib/channels/slack-provisioning/persist.js +95 -0
  124. package/lib/channels/slack-provisioning/remaining-urls.js +158 -0
  125. package/lib/channels/slack-provisioning/with-curl-on-path.js +48 -0
  126. package/lib/channels/teams-bot-channel-add.js +94 -0
  127. package/lib/channels/vendor-dataplane-url.js +249 -0
  128. package/lib/cli/setup-certification.help.js +2 -0
  129. package/lib/cli/setup-external-system-help.js +2 -0
  130. package/lib/cli/setup-external-system.js +1 -1
  131. package/lib/commands/channel-add-help.js +366 -0
  132. package/lib/commands/channel-add-setup.js +162 -80
  133. package/lib/commands/channel-configure.js +118 -0
  134. package/lib/commands/channel.js +10 -1
  135. package/lib/commands/governance-upload-external.js +6 -3
  136. package/lib/commands/lifecycle-command-action.js +2 -5
  137. package/lib/commands/lifecycle-external.js +93 -21
  138. package/lib/commands/repair-datasource-test-payload.js +4 -2
  139. package/lib/commands/repair-datasource-webhooks-sync-bridge.js +23 -2
  140. package/lib/commands/repair-datasource.js +3 -0
  141. package/lib/commands/repair-external-run.js +59 -25
  142. package/lib/commands/repair-openapi-rest-runtime.js +127 -0
  143. package/lib/commands/repair-orchestration-tag-merge.js +339 -0
  144. package/lib/commands/repair-rbac-catalog-defaults.js +96 -0
  145. package/lib/commands/repair-rbac-platform-preset.js +26 -15
  146. package/lib/commands/repair-rbac-reader-roles.js +8 -21
  147. package/lib/commands/repair-rbac.js +10 -34
  148. package/lib/commands/repair-system-permissions.js +24 -22
  149. package/lib/commands/role-assistant-test-output.js +14 -0
  150. package/lib/commands/role-assistant.js +59 -21
  151. package/lib/commands/test-e2e-external.js +148 -21
  152. package/lib/commands/upload-credential-push-log.js +2 -1
  153. package/lib/commands/upload-publish-context.js +1 -1
  154. package/lib/commands/upload-role-assistant-shell.js +124 -0
  155. package/lib/commands/upload-sidecar-followups.js +6 -3
  156. package/lib/commands/upload.js +18 -3
  157. package/lib/core/secrets-docker-env.js +4 -1
  158. package/lib/core/secrets-env-content.js +17 -3
  159. package/lib/datasource/capability/capability-manifest.js +0 -3
  160. package/lib/datasource/capability/copy-test-payload.js +3 -0
  161. package/lib/external-system/deploy-helpers.js +26 -1
  162. package/lib/external-system/deploy.js +10 -6
  163. package/lib/external-system/download-helpers.js +29 -2
  164. package/lib/external-system/download-role-assistant.js +83 -4
  165. package/lib/external-system/download.js +40 -30
  166. package/lib/external-system/sync-deploy-manifest.js +3 -2
  167. package/lib/external-system/upload-identity.js +42 -0
  168. package/lib/generator/index.js +19 -15
  169. package/lib/generator/split.js +13 -2
  170. package/lib/lifecycle/role-assistant-governance.js +146 -0
  171. package/lib/lifecycle/scenario-upload.js +181 -30
  172. package/lib/programmatic/builder-api-cors.js +143 -0
  173. package/lib/programmatic/builder-api-request.js +6 -0
  174. package/lib/programmatic/builder-api-route-dispatch.js +56 -42
  175. package/lib/programmatic/builder-api-server.js +8 -1
  176. package/lib/programmatic/capability-registry.js +54 -0
  177. package/lib/programmatic/channel-install-help-resolve.js +359 -0
  178. package/lib/programmatic/channel-install-session.js +218 -0
  179. package/lib/programmatic/help-content/channel-onboarding.md +2 -0
  180. package/lib/programmatic/help-content/cip-overview.md +3 -1
  181. package/lib/programmatic/http-raw-response.js +62 -0
  182. package/lib/programmatic/openapi-channel-install-bindings.js +179 -0
  183. package/lib/programmatic/openapi-channel-install-schemas.js +286 -0
  184. package/lib/programmatic/openapi-component-schemas.js +18 -1
  185. package/lib/programmatic/openapi-description-enricher.js +3 -1
  186. package/lib/programmatic/openapi-descriptions.js +74 -3
  187. package/lib/programmatic/openapi-envelope-examples.js +117 -0
  188. package/lib/programmatic/openapi-operation-bindings.js +4 -1
  189. package/lib/programmatic/openapi-schema-descriptions-channel.js +316 -0
  190. package/lib/programmatic/openapi-spec.js +12 -8
  191. package/lib/programmatic/platform-rbac-catalog.js +36 -18
  192. package/lib/programmatic/route-handler-map.js +51 -1
  193. package/lib/programmatic/route-handlers-context.js +2 -1
  194. package/lib/programmatic/run-auth-permissions.js +54 -0
  195. package/lib/programmatic/run-channel-catalog.js +196 -0
  196. package/lib/programmatic/run-channel-install-artifacts.js +137 -0
  197. package/lib/programmatic/run-channel-install-copilot.js +353 -0
  198. package/lib/programmatic/run-channel-install-options.js +232 -0
  199. package/lib/programmatic/run-channel-install-teams-bot.js +204 -0
  200. package/lib/programmatic/run-channel-install.js +346 -0
  201. package/lib/programmatic/run-channel-package.js +87 -7
  202. package/lib/programmatic/workspace-context.js +2 -0
  203. package/lib/role-assistant/evidence-sync.js +4 -2
  204. package/lib/role-assistant/evidence-validation-issues.js +51 -0
  205. package/lib/role-assistant/knowledge-sync.js +10 -4
  206. package/lib/role-assistant/settings.js +49 -2
  207. package/lib/role-assistant/test-cases-evaluate.js +30 -2
  208. package/lib/role-assistant/test-cases-evidence.js +175 -0
  209. package/lib/role-assistant/test-cases-search.js +229 -0
  210. package/lib/role-assistant/test-cases.js +37 -4
  211. package/lib/role-assistant/test-runner-search.js +149 -0
  212. package/lib/role-assistant/test-runner-workhub-helpers.js +40 -2
  213. package/lib/role-assistant/test-runner-workhub-soft.js +9 -3
  214. package/lib/role-assistant/test-runner-workhub.js +29 -11
  215. package/lib/role-assistant/test-runner.js +16 -1
  216. package/lib/schema/external-datasource.schema.json +112 -18
  217. package/lib/schema/external-system.schema.json +159 -2
  218. package/lib/schema/mcp-client-profile.schema.json +103 -0
  219. package/lib/utils/app-path-resolve.js +4 -0
  220. package/lib/utils/authentication-env-template.js +44 -6
  221. package/lib/utils/credential-secrets-env.js +6 -1
  222. package/lib/utils/env-copy.js +19 -7
  223. package/lib/utils/external-env-template.js +20 -2
  224. package/lib/utils/paths.js +18 -1
  225. package/lib/utils/platform-shell-package.js +69 -0
  226. package/lib/utils/port-resolver.js +50 -1
  227. package/lib/utils/rewrite-name-flag.js +20 -0
  228. package/lib/utils/role-assistant-paths.js +13 -10
  229. package/lib/utils/schema-resolver.js +11 -1
  230. package/lib/utils/secrets-helpers.js +12 -21
  231. package/lib/utils/token-manager.js +10 -5
  232. package/lib/validation/validate.js +40 -0
  233. package/package.json +1 -1
  234. package/templates/README.md +1 -1
  235. package/templates/applications/builder-api/Dockerfile +1 -1
  236. package/templates/applications/builder-api/env.template +7 -0
  237. package/templates/applications/dataplane/application.yaml +6 -5
  238. package/templates/applications/dataplane/env.template +2 -2
  239. package/templates/applications/dataplane/rbac.yaml +7 -2
  240. package/templates/applications/keycloak/Dockerfile +30 -4
  241. package/templates/applications/keycloak/application.yaml +2 -2
  242. package/templates/applications/keycloak/cimd-lenient-parse/AbstractClientIdMetadataDocumentExecutor.java +896 -0
  243. package/templates/applications/keycloak/cimd-lenient-parse/SOURCE.md +19 -0
  244. package/templates/applications/keycloak/env.template +3 -0
  245. package/templates/applications/miso-controller/application.yaml +1 -2
  246. package/templates/applications/miso-controller/env.template +2 -0
  247. package/templates/channels/README.md +5 -5
  248. package/templates/channels/chatgpt/TROUBLESHOOTING.md +51 -0
  249. package/templates/channels/chatgpt/channel.json +59 -0
  250. package/templates/channels/chatgpt/icon.svg +1 -0
  251. package/templates/channels/chatgpt/install.template.md.hbs +20 -95
  252. package/templates/channels/chatgpt/integration/README.md +1 -1
  253. package/templates/channels/chatgpt/integration/application.json +2 -2
  254. package/templates/channels/chatgpt/integration/chatgpt-system.json +49 -4
  255. package/templates/channels/chatgpt/integration/env.template +2 -4
  256. package/templates/channels/chatgpt/integration/rbac.json +13 -0
  257. package/templates/channels/claude/TROUBLESHOOTING.md +41 -0
  258. package/templates/channels/claude/channel.json +59 -0
  259. package/templates/channels/claude/icon.svg +1 -0
  260. package/templates/channels/claude/install.template.md.hbs +21 -0
  261. package/templates/channels/claude/integration/README.md +14 -0
  262. package/templates/channels/claude/integration/application.json +15 -0
  263. package/templates/channels/claude/integration/claude-system.json +59 -0
  264. package/templates/channels/claude/integration/env.template +2 -0
  265. package/templates/channels/claude/integration/rbac.json +13 -0
  266. package/templates/channels/claude/manifest.template.json.hbs +40 -0
  267. package/templates/channels/mcp-client/channel.json +72 -0
  268. package/templates/channels/mcp-client/icon.svg +1 -0
  269. package/templates/channels/mcp-client/install.template.md.hbs +24 -0
  270. package/templates/channels/mcp-client/integration/README.md +13 -0
  271. package/templates/channels/mcp-client/integration/application.json +15 -0
  272. package/templates/channels/mcp-client/integration/env.template +2 -0
  273. package/templates/channels/mcp-client/integration/mcp-client-system.json +72 -0
  274. package/templates/channels/mcp-client/integration/rbac.json +13 -0
  275. package/templates/channels/mcp-client/manifest.template.json.hbs +41 -0
  276. package/templates/channels/mcp-client/profiles/cursor.json +26 -0
  277. package/templates/channels/mcp-client/profiles/github-copilot.json +29 -0
  278. package/templates/channels/mcp-client/profiles/vscode.json +29 -0
  279. package/templates/channels/microsoft-copilot/channel.json +73 -0
  280. package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +8 -4
  281. package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +65 -5
  282. package/templates/channels/microsoft-copilot/icon.svg +1 -0
  283. package/templates/channels/microsoft-copilot/install.template.md.hbs +9 -9
  284. package/templates/channels/microsoft-copilot/integration/README.md +1 -1
  285. package/templates/channels/microsoft-copilot/integration/application.json +2 -2
  286. package/templates/channels/microsoft-copilot/integration/env.template +3 -6
  287. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +63 -4
  288. package/templates/channels/microsoft-copilot/integration/rbac.json +13 -0
  289. package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +5 -5
  290. package/templates/channels/slack/channel.json +223 -0
  291. package/templates/channels/slack/icon.svg +1 -0
  292. package/templates/channels/slack/install.template.md.hbs +36 -28
  293. package/templates/channels/slack/integration/README.md +245 -22
  294. package/templates/channels/slack/integration/application.json +44 -7
  295. package/templates/channels/slack/integration/env.template +15 -6
  296. package/templates/channels/slack/integration/openapi/openapi.json +126 -0
  297. package/templates/channels/slack/integration/rbac.json +84 -0
  298. package/templates/channels/slack/integration/slack-datasource-commands.json +154 -0
  299. package/templates/channels/slack/integration/slack-datasource-conversations.json +28 -3
  300. package/templates/channels/slack/integration/slack-datasource-events.json +154 -0
  301. package/templates/channels/slack/integration/slack-datasource-interactive.json +154 -0
  302. package/templates/channels/slack/integration/slack-datasource-messages.json +40 -2
  303. package/templates/channels/slack/integration/slack-system.json +155 -77
  304. package/templates/channels/slack/manifest.template.json.hbs +5 -2
  305. package/templates/channels/teams-bot/channel.json +161 -0
  306. package/templates/channels/teams-bot/icon.svg +1 -0
  307. package/templates/channels/teams-bot/install.template.md.hbs +12 -13
  308. package/templates/channels/teams-bot/integration/README.md +5 -4
  309. package/templates/channels/teams-bot/integration/application.json +6 -4
  310. package/templates/channels/teams-bot/integration/env.template +5 -4
  311. package/templates/channels/teams-bot/integration/openapi/openapi.json +68 -0
  312. package/templates/channels/teams-bot/integration/rbac.json +21 -0
  313. package/templates/channels/teams-bot/integration/teams-bot-datasource-activities.json +154 -0
  314. package/templates/channels/teams-bot/integration/teams-bot-system.json +128 -23
  315. package/templates/channels/web-embed/channel.json +60 -0
  316. package/templates/channels/web-embed/install.template.md.hbs +1 -1
  317. package/templates/channels/web-embed/integration/README.md +2 -2
  318. package/templates/channels/web-embed/integration/application.json +2 -2
  319. package/templates/channels/web-embed/integration/env.template +1 -1
  320. package/templates/channels/web-embed/integration/rbac.json +13 -0
  321. package/templates/channels/web-embed/integration/web-embed-system.json +50 -4
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Create or reuse Teams Entra SSO auth-config via Agents Toolkit oauth/register.
3
+ *
4
+ * @fileoverview Capture auth-config id without operators pasting the CLI flag
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const path = require('path');
10
+ const crypto = require('crypto');
11
+ const os = require('os');
12
+ const fs = require('../../internal/fs-real-sync');
13
+ const { AUTH_CONFIG_ENV_KEY, APP_ID_URI_ENV_KEY, TENANT_GUID_RE } = require('./constants');
14
+ const {
15
+ wrapToolkitError,
16
+ missingCopilotCaptureInputsError,
17
+ missingMicrosoftTenantError
18
+ } = require('./errors');
19
+ const { ensureMicrosoftSession } = require('./auth');
20
+ const { runAtk } = require('./cli');
21
+ const {
22
+ readProvisioningState,
23
+ writeProvisioningState,
24
+ isReusableAuthConfig
25
+ } = require('./persist');
26
+
27
+ /**
28
+ * @param {string} environment
29
+ * @returns {string}
30
+ */
31
+ function stableTeamsAppId(environment) {
32
+ const digest = crypto
33
+ .createHash('sha1')
34
+ .update(`aifabrix-copilot:${environment || 'dev'}`)
35
+ .digest('hex');
36
+ return `${digest.slice(0, 8)}-${digest.slice(8, 12)}-4${digest.slice(13, 16)}-a${digest.slice(17, 20)}-${digest.slice(20, 32)}`;
37
+ }
38
+
39
+ /**
40
+ * @param {string|null|undefined} value
41
+ * @returns {string|null}
42
+ */
43
+ function resolveTeamsAppId(value) {
44
+ const raw = typeof value === 'string' ? value.trim() : '';
45
+ if (!raw) {
46
+ return null;
47
+ }
48
+ const match = raw.match(TENANT_GUID_RE);
49
+ return match ? match[0] : null;
50
+ }
51
+
52
+ /**
53
+ * Packaged manifest id when known; otherwise a stable per-environment fallback.
54
+ * @param {Object} inputs
55
+ * @returns {string}
56
+ */
57
+ function teamsAppIdForRegister(inputs) {
58
+ return resolveTeamsAppId(inputs.teamsAppId) || stableTeamsAppId(inputs.environment);
59
+ }
60
+
61
+ /**
62
+ * @param {Object} params
63
+ * @returns {string}
64
+ */
65
+ function buildOauthRegisterYaml(params) {
66
+ const name = params.registrationName || 'aifabrix-runtime-mcp-sso';
67
+ const specificApp = Boolean(resolveTeamsAppId(params.teamsAppId));
68
+ return [
69
+ '# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkit/v1.9/yaml.schema.json',
70
+ 'version: v1.9',
71
+ 'provision:',
72
+ ' - uses: oauth/register',
73
+ ' with:',
74
+ ` name: ${JSON.stringify(name)}`,
75
+ ' flow: authorizationCode',
76
+ ' appId: ${{TEAMS_APP_ID}}',
77
+ ' clientId: ${{AAD_APP_CLIENT_ID}}',
78
+ ' identityProvider: MicrosoftEntra',
79
+ ' baseUrl: ${{MCP_SERVER_URL}}',
80
+ ` applicableToApps: ${specificApp ? 'SpecificApp' : 'AnyApp'}`,
81
+ ' targetAudience: HomeTenant',
82
+ ' writeToEnvironmentFile:',
83
+ ` configurationId: ${AUTH_CONFIG_ENV_KEY}`,
84
+ ` applicationIdUri: ${APP_ID_URI_ENV_KEY}`,
85
+ ''
86
+ ].join('\n');
87
+ }
88
+
89
+ /**
90
+ * @param {string} content
91
+ * @param {string} key
92
+ * @returns {string|null}
93
+ */
94
+ function readEnvValue(content, key) {
95
+ const match = String(content || '').match(new RegExp(`^${key}\\s*=\\s*(.*)$`, 'm'));
96
+ if (!match) {
97
+ return null;
98
+ }
99
+ return match[1].trim().replace(/^['"]|['"]$/g, '') || null;
100
+ }
101
+
102
+ /**
103
+ * @param {Object} inputs
104
+ * @returns {string}
105
+ */
106
+ function writeToolkitProject(inputs) {
107
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'aifabrix-atk-oauth-'));
108
+ const envDir = path.join(dir, 'env');
109
+ fs.mkdirSync(envDir, { recursive: true });
110
+ fs.writeFileSync(path.join(dir, 'm365agents.yml'), buildOauthRegisterYaml(inputs), 'utf8');
111
+ const prior = inputs.priorAuthConfigId ? `${AUTH_CONFIG_ENV_KEY}=${inputs.priorAuthConfigId}\n` : '';
112
+ const envBody =
113
+ `TEAMSFX_ENV=dev\nTEAMS_APP_ID=${teamsAppIdForRegister(inputs)}\n` +
114
+ `AAD_APP_CLIENT_ID=${inputs.clientId}\nMCP_SERVER_URL=${inputs.mcpServerUrl}\n` +
115
+ `${prior}${APP_ID_URI_ENV_KEY}=\n`;
116
+ fs.writeFileSync(path.join(envDir, '.env.dev'), envBody, 'utf8');
117
+ return dir;
118
+ }
119
+
120
+ /**
121
+ * @param {Object} params
122
+ * @returns {Object|null}
123
+ */
124
+ function resolveCaptureInputs(params) {
125
+ const clientId =
126
+ typeof params.clientId === 'string' && params.clientId.trim() ? params.clientId.trim() : null;
127
+ const mcpServerUrl =
128
+ typeof params.mcpServerUrl === 'string' && params.mcpServerUrl.trim()
129
+ ? params.mcpServerUrl.trim()
130
+ : null;
131
+ const tenantId =
132
+ typeof params.expectedTenantId === 'string' && params.expectedTenantId.trim()
133
+ ? params.expectedTenantId.trim()
134
+ : null;
135
+ if (!clientId || !mcpServerUrl) {
136
+ return null;
137
+ }
138
+ return {
139
+ clientId,
140
+ mcpServerUrl,
141
+ tenantId,
142
+ environment: params.environment || 'dev',
143
+ projectRoot: params.projectRoot || process.cwd(),
144
+ registrationName: params.registrationName,
145
+ teamsAppId: resolveTeamsAppId(params.teamsAppId)
146
+ };
147
+ }
148
+
149
+ /**
150
+ * @param {string} dir
151
+ * @returns {{ authConfigId: string|null, applicationIdUri: string|null }}
152
+ */
153
+ function readToolkitOutputs(dir) {
154
+ const envPath = path.join(dir, 'env', '.env.dev');
155
+ const content = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf8') : '';
156
+ return {
157
+ authConfigId: readEnvValue(content, AUTH_CONFIG_ENV_KEY),
158
+ applicationIdUri: readEnvValue(content, APP_ID_URI_ENV_KEY)
159
+ };
160
+ }
161
+
162
+ /**
163
+ * @param {Object} inputs
164
+ * @param {Object} session
165
+ * @param {Object} deps
166
+ * @returns {Promise<{ authConfigId: string, applicationIdUri: string|null }>}
167
+ */
168
+ async function provisionAuthConfig(inputs, session, deps) {
169
+ const dir = writeToolkitProject(inputs);
170
+ try {
171
+ await runAtk(
172
+ session.binary,
173
+ ['provision', '--env', 'dev', '--interactive', 'false'],
174
+ { cwd: dir },
175
+ deps
176
+ );
177
+ const output = readToolkitOutputs(dir);
178
+ if (!output.authConfigId) {
179
+ throw wrapToolkitError(new Error('oauth/register did not write a configuration id'));
180
+ }
181
+ return output;
182
+ } catch (error) {
183
+ if (error && error.code === 'TOOLKIT') {
184
+ throw error;
185
+ }
186
+ throw wrapToolkitError(error);
187
+ } finally {
188
+ try {
189
+ fs.rmSync(dir, { recursive: true, force: true });
190
+ } catch {
191
+ // temp workspace is best-effort
192
+ }
193
+ }
194
+ }
195
+
196
+ /**
197
+ * @param {Object} params
198
+ * @param {Object} [deps]
199
+ * @returns {Promise<{ authConfigId: string, applicationIdUri: string|null }|null>}
200
+ */
201
+ async function captureCopilotAuthConfigId(params, deps = {}) {
202
+ const inputs = resolveCaptureInputs(params);
203
+ if (!inputs) {
204
+ throw missingCopilotCaptureInputsError(params);
205
+ }
206
+ const persisted = readProvisioningState(inputs.projectRoot);
207
+ if (isReusableAuthConfig(persisted, inputs)) {
208
+ return {
209
+ authConfigId: persisted.authConfigId,
210
+ applicationIdUri: persisted.applicationIdUri || null
211
+ };
212
+ }
213
+ const session = await ensureMicrosoftSession(inputs.tenantId, deps);
214
+ if (!session) {
215
+ return null;
216
+ }
217
+ if (!session.tenantId) {
218
+ throw missingMicrosoftTenantError();
219
+ }
220
+ const created = await provisionAuthConfig(inputs, session, deps);
221
+ writeProvisioningState(inputs.projectRoot, {
222
+ environment: inputs.environment,
223
+ tenantId: inputs.tenantId || session.tenantId,
224
+ mcpServerUrl: inputs.mcpServerUrl,
225
+ teamsAppId: teamsAppIdForRegister(inputs),
226
+ authConfigId: created.authConfigId,
227
+ applicationIdUri: created.applicationIdUri
228
+ });
229
+ return created;
230
+ }
231
+
232
+ module.exports = {
233
+ stableTeamsAppId,
234
+ resolveTeamsAppId,
235
+ teamsAppIdForRegister,
236
+ buildOauthRegisterYaml,
237
+ readEnvValue,
238
+ resolveCaptureInputs,
239
+ captureCopilotAuthConfigId
240
+ };
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Microsoft 365 session + Entra tenant check via Agents Toolkit CLI.
3
+ *
4
+ * @fileoverview Interactive login when required; never persist Microsoft tokens
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { spawn } = require('child_process');
10
+ const path = require('path');
11
+ const fs = require('../../internal/fs-real-sync');
12
+ const { TENANT_GUID_RE, ATK_ACCOUNT_NAME } = require('./constants');
13
+ const { microsoftProvisioningError, wrongTenantError, missingMicrosoftTenantError } = require('./errors');
14
+ const { resolveAtkBinary, runAtk, shouldSkipLiveToolkit } = require('./cli');
15
+ const { atkWritableHome, atkInstallEnv } = require('./install-atk');
16
+
17
+ /**
18
+ * @param {string} text
19
+ * @returns {string|null}
20
+ */
21
+ function extractTenantId(text) {
22
+ if (typeof text !== 'string' || !text.trim()) {
23
+ return null;
24
+ }
25
+ const trimmed = text.trim();
26
+ try {
27
+ const parsed = JSON.parse(trimmed);
28
+ const fromJson = tenantFromUnknown(parsed);
29
+ if (fromJson) {
30
+ return fromJson;
31
+ }
32
+ } catch {
33
+ // fall through to regex / labelled text
34
+ }
35
+ const labelled = trimmed.match(/tenantId["'\s:=]+([0-9a-f-]{36})/i);
36
+ if (labelled) {
37
+ return labelled[1].toLowerCase();
38
+ }
39
+ const match = trimmed.match(TENANT_GUID_RE);
40
+ return match ? match[0].toLowerCase() : null;
41
+ }
42
+
43
+ /**
44
+ * @param {unknown} value
45
+ * @returns {string|null}
46
+ */
47
+ function tenantFromUnknown(value) {
48
+ if (!value) {
49
+ return null;
50
+ }
51
+ if (typeof value === 'string') {
52
+ return extractTenantId(value);
53
+ }
54
+ if (Array.isArray(value)) {
55
+ for (const item of value) {
56
+ const found = tenantFromUnknown(item);
57
+ if (found) {
58
+ return found;
59
+ }
60
+ }
61
+ return null;
62
+ }
63
+ if (typeof value === 'object' && typeof value.tenantId === 'string') {
64
+ return extractTenantId(value.tenantId);
65
+ }
66
+ return null;
67
+ }
68
+
69
+ /**
70
+ * @param {string} expected
71
+ * @param {string} actual
72
+ * @returns {void}
73
+ */
74
+ function assertExpectedTenant(expected, actual) {
75
+ if (!expected) {
76
+ return;
77
+ }
78
+ if (!actual) {
79
+ throw microsoftProvisioningError(
80
+ 'Could not determine the signed-in Microsoft tenant. Run: atk auth login m365',
81
+ 'TENANT'
82
+ );
83
+ }
84
+ if (String(expected).toLowerCase() !== String(actual).toLowerCase()) {
85
+ throw wrongTenantError(expected, actual);
86
+ }
87
+ }
88
+
89
+ /**
90
+ * @param {string} bin
91
+ * @param {Object} [deps]
92
+ * @returns {Promise<void>}
93
+ */
94
+ function loginM365(bin, deps = {}) {
95
+ if (typeof deps.loginImpl === 'function') {
96
+ return deps.loginImpl(bin);
97
+ }
98
+ return new Promise((resolve, reject) => {
99
+ const child = spawn(bin, ['auth', 'login', 'm365'], {
100
+ stdio: 'inherit',
101
+ env: process.env
102
+ });
103
+ child.on('error', reject);
104
+ child.on('close', (code) => {
105
+ if (code === 0) {
106
+ resolve();
107
+ return;
108
+ }
109
+ reject(new Error(`Microsoft login exited with code ${code}`));
110
+ });
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Toolkit `auth list` often prints only the account email. Device-code login
116
+ * writes tenantId.cache.appStudio — use that when the CLI omits the GUID.
117
+ * @param {Object} [deps]
118
+ * @returns {string|null}
119
+ */
120
+ function readCachedAppStudioTenantId(deps = {}) {
121
+ const filePath = path.join(
122
+ atkWritableHome(atkInstallEnv(deps.env || process.env)),
123
+ '.fx',
124
+ 'account',
125
+ `tenantId.cache.${ATK_ACCOUNT_NAME}`
126
+ );
127
+ if (!fs.existsSync(filePath)) {
128
+ return null;
129
+ }
130
+ return extractTenantId(fs.readFileSync(filePath, 'utf8'));
131
+ }
132
+
133
+ /**
134
+ * @param {{ stdout?: string, stderr?: string }} listed
135
+ * @param {Object} [deps]
136
+ * @returns {string|null}
137
+ */
138
+ function tenantIdFromListOrCache(listed, deps) {
139
+ const fromList = extractTenantId(`${listed.stdout}\n${listed.stderr}`);
140
+ return fromList || readCachedAppStudioTenantId(deps);
141
+ }
142
+
143
+ /**
144
+ * @param {string} expectedTenant
145
+ * @param {Object} [deps]
146
+ * @returns {Promise<{ binary: string, tenantId: string }|null>}
147
+ */
148
+ async function ensureMicrosoftSession(expectedTenant, deps = {}) {
149
+ if (shouldSkipLiveToolkit(deps) && !deps.atkBinary && !deps.execFile) {
150
+ return null;
151
+ }
152
+ const binary = await resolveAtkBinary(deps);
153
+ if (!binary) {
154
+ return null;
155
+ }
156
+ let listed = await runAtk(binary, ['auth', 'list'], {}, deps);
157
+ let tenantId = tenantIdFromListOrCache(listed, deps);
158
+ if (!tenantId && process.stdin.isTTY) {
159
+ await loginM365(binary, deps);
160
+ listed = await runAtk(binary, ['auth', 'list'], {}, deps);
161
+ tenantId = tenantIdFromListOrCache(listed, deps);
162
+ }
163
+ if (!tenantId) {
164
+ tenantId = extractTenantId(expectedTenant);
165
+ }
166
+ if (!tenantId) {
167
+ throw missingMicrosoftTenantError();
168
+ }
169
+ assertExpectedTenant(expectedTenant, tenantId);
170
+ return { binary, tenantId };
171
+ }
172
+
173
+ module.exports = {
174
+ extractTenantId,
175
+ assertExpectedTenant,
176
+ loginM365,
177
+ ensureMicrosoftSession,
178
+ readCachedAppStudioTenantId
179
+ };
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Spawn Microsoft 365 Agents Toolkit (`atk` / `teamsapp`) without scattering argv.
3
+ *
4
+ * @fileoverview Documented CLI only; skipped under Jest unless deps allow it
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { promisify } = require('util');
10
+ const execFileDefault = promisify(require('child_process').execFile);
11
+ const { findOrInstallAtkBinary, atkInstallEnv } = require('./install-atk');
12
+
13
+ /**
14
+ * @returns {boolean}
15
+ */
16
+ function isJestWorker() {
17
+ return Boolean(process.env.JEST_WORKER_ID);
18
+ }
19
+
20
+ /**
21
+ * @param {Object} [deps]
22
+ * @returns {boolean}
23
+ */
24
+ function shouldSkipLiveToolkit(deps = {}) {
25
+ if (deps.allowInTests === true) {
26
+ return false;
27
+ }
28
+ return isJestWorker();
29
+ }
30
+
31
+ /**
32
+ * @param {Object} [deps]
33
+ * @returns {Promise<string|null>}
34
+ */
35
+ async function resolveAtkBinary(deps = {}) {
36
+ if (typeof deps.atkBinary === 'string' && deps.atkBinary.trim()) {
37
+ return deps.atkBinary.trim();
38
+ }
39
+ if (shouldSkipLiveToolkit(deps)) {
40
+ return null;
41
+ }
42
+ return findOrInstallAtkBinary(deps);
43
+ }
44
+
45
+ /**
46
+ * @param {string} bin
47
+ * @param {string[]} args
48
+ * @param {Object} [opts]
49
+ * @param {Object} [deps]
50
+ * @returns {Promise<{ stdout: string, stderr: string }>}
51
+ */
52
+ async function runAtk(bin, args, opts = {}, deps = {}) {
53
+ const execFileImpl = deps.execFile || execFileDefault;
54
+ const result = await execFileImpl(bin, args, {
55
+ cwd: opts.cwd,
56
+ env: atkInstallEnv(opts.env || deps.env || process.env),
57
+ timeout: opts.timeout || 180000,
58
+ maxBuffer: 2 * 1024 * 1024
59
+ });
60
+ return {
61
+ stdout: result && result.stdout ? String(result.stdout) : '',
62
+ stderr: result && result.stderr ? String(result.stderr) : ''
63
+ };
64
+ }
65
+
66
+ module.exports = {
67
+ isJestWorker,
68
+ shouldSkipLiveToolkit,
69
+ resolveAtkBinary,
70
+ runAtk
71
+ };
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Microsoft provisioning constants (Agents Toolkit + Agent 365 preview).
3
+ *
4
+ * @fileoverview Shared keys and filenames — no Microsoft tokens
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const STATE_KIND = 'microsoft-copilot-entra-sso';
10
+ const STATE_FILE = 'provisioning-state.json';
11
+ const AUTH_CONFIG_ENV_KEY = 'AIFABRIX_SSO_AUTH_ID';
12
+ const APP_ID_URI_ENV_KEY = 'AIFABRIX_SSO_APP_ID_URI';
13
+ const ATK_BINARIES = ['atk', 'teamsapp'];
14
+ const ATK_NPM_PACKAGE = '@microsoft/m365agentstoolkit-cli';
15
+ /** Teams Toolkit CLI public client — same id `atk auth login m365` uses. */
16
+ const ATK_M365_CLIENT_ID = '7ea7c24c-b1f6-4a20-9d11-9ae12e9e7ac0';
17
+ const ATK_APP_STUDIO_SCOPE = 'https://dev.teams.microsoft.com/AppDefinitions.ReadWrite';
18
+ const ATK_DEVICE_LOGIN_URL = 'https://microsoft.com/devicelogin';
19
+ const ATK_ACCOUNT_NAME = 'appStudio';
20
+ const TEAMS_BINARIES = ['teams'];
21
+ const TEAMS_BOT_STATE_KIND = 'microsoft-teams-bot';
22
+ const TEAMS_BOT_STATE_FILE = 'provisioning-state.json';
23
+ const TEAMS_CLI_PACKAGE = '@microsoft/teams.cli';
24
+ const TEAMS_OPEN_URL = 'https://teams.microsoft.com';
25
+ const TEAMS_ADMIN_APPS_URL = 'https://admin.teams.microsoft.com/policies/manage-apps';
26
+ const KV_TEAMS_BOT_APP_ID = 'teams-bot/botAppId';
27
+ const KV_TEAMS_BOT_APP_SECRET = 'teams-bot/botAppSecret';
28
+ const TEAMS_POLICY_REMAINING =
29
+ 'Approve custom app upload / org publish if tenant policy requires it';
30
+ const TEAMS_CLI_MISSING_REMAINING = [
31
+ `Install Teams Developer CLI (${TEAMS_CLI_PACKAGE}) and run teams login`,
32
+ 'Re-run aifabrix channel add teams-bot'
33
+ ];
34
+ const TENANT_GUID_RE =
35
+ /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
36
+ const SECRET_KEY_RE = /(access|refresh)?token|clientsecret|password|secret/i;
37
+
38
+ const AGENT365_CHECKPOINT = Object.freeze({
39
+ preview: true,
40
+ byoMcpRegisterCli: true,
41
+ declarativeAgentsSupported: false,
42
+ republishSupported: false,
43
+ adminApprovalRequired: true,
44
+ copilotStudioApiAttach: false,
45
+ reason:
46
+ 'Agent 365 BYO MCP is preview. Declarative Agents are not a supported BYO client. ' +
47
+ 'Republish of a registered remote MCP is not supported. Admin approval remains. ' +
48
+ 'Copilot Studio attach is pick-from-registry UI, not an API.'
49
+ });
50
+
51
+ module.exports = {
52
+ STATE_KIND,
53
+ STATE_FILE,
54
+ AUTH_CONFIG_ENV_KEY,
55
+ APP_ID_URI_ENV_KEY,
56
+ ATK_BINARIES,
57
+ ATK_NPM_PACKAGE,
58
+ ATK_M365_CLIENT_ID,
59
+ ATK_APP_STUDIO_SCOPE,
60
+ ATK_DEVICE_LOGIN_URL,
61
+ ATK_ACCOUNT_NAME,
62
+ TEAMS_BINARIES,
63
+ TEAMS_BOT_STATE_KIND,
64
+ TEAMS_BOT_STATE_FILE,
65
+ TEAMS_CLI_PACKAGE,
66
+ TEAMS_OPEN_URL,
67
+ TEAMS_ADMIN_APPS_URL,
68
+ KV_TEAMS_BOT_APP_ID,
69
+ KV_TEAMS_BOT_APP_SECRET,
70
+ TEAMS_POLICY_REMAINING,
71
+ TEAMS_CLI_MISSING_REMAINING,
72
+ TENANT_GUID_RE,
73
+ SECRET_KEY_RE,
74
+ AGENT365_CHECKPOINT
75
+ };
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Normalize Microsoft provisioning failures for Copilot / Teams Bot.
3
+ *
4
+ * @fileoverview User-facing errors without toolkit internals or tokens
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ /**
10
+ * @param {string} message
11
+ * @param {string} [code]
12
+ * @returns {Error}
13
+ */
14
+ function microsoftProvisioningError(message, code) {
15
+ const error = new Error(message);
16
+ error.code = code || 'MICROSOFT_PROVISIONING';
17
+ return error;
18
+ }
19
+
20
+ /**
21
+ * @param {string} expectedTenant
22
+ * @param {string} actualTenant
23
+ * @returns {Error}
24
+ */
25
+ function wrongTenantError(expectedTenant, actualTenant) {
26
+ return microsoftProvisioningError(
27
+ `Signed-in Microsoft tenant "${actualTenant}" does not match the Entra tenant ` +
28
+ `"${expectedTenant}" configured for this environment.`,
29
+ 'WRONG_TENANT'
30
+ );
31
+ }
32
+
33
+ /**
34
+ * @param {unknown} error
35
+ * @returns {Error}
36
+ */
37
+ function wrapToolkitError(error) {
38
+ const raw = error && error.message ? String(error.message) : String(error);
39
+ const compact = raw.replace(/\s+/g, ' ').trim().slice(0, 400);
40
+ return microsoftProvisioningError(
41
+ `Microsoft 365 Agents Toolkit could not create or read the Entra SSO auth-config. ${compact}`,
42
+ 'TOOLKIT'
43
+ );
44
+ }
45
+
46
+ /**
47
+ * @param {string} [text]
48
+ * @returns {string}
49
+ */
50
+ function redactTeamsSecrets(text) {
51
+ return String(text || '')
52
+ .replace(/CLIENT_SECRET=\S+/gi, 'CLIENT_SECRET=***')
53
+ .replace(/clientSecret["'\s:=]+[^\s]+/gi, 'clientSecret=***');
54
+ }
55
+
56
+ /**
57
+ * @param {unknown} error
58
+ * @returns {Error}
59
+ */
60
+ function wrapTeamsCliError(error) {
61
+ const raw = error && error.message ? String(error.message) : String(error);
62
+ const compact = redactTeamsSecrets(raw.replace(/\s+/g, ' ').trim()).slice(0, 400);
63
+ return microsoftProvisioningError(
64
+ `Teams Developer CLI could not provision the Azure-managed bot. ${compact}`,
65
+ 'TEAMS_CLI'
66
+ );
67
+ }
68
+
69
+ /**
70
+ * @param {string} expectedEnvironment
71
+ * @param {string} actualEnvironment
72
+ * @returns {Error}
73
+ */
74
+ function wrongEnvironmentRegistrationError(expectedEnvironment, actualEnvironment) {
75
+ return microsoftProvisioningError(
76
+ `Microsoft registration belongs to environment "${actualEnvironment}", not "${expectedEnvironment}".`,
77
+ 'WRONG_ENVIRONMENT'
78
+ );
79
+ }
80
+
81
+ /**
82
+ * @param {Object} [params]
83
+ * @returns {Error}
84
+ */
85
+ function missingMicrosoftTenantError() {
86
+ return microsoftProvisioningError(
87
+ 'Could not determine the signed-in Microsoft tenant after login. Re-run channel add in a terminal.',
88
+ 'TENANT'
89
+ );
90
+ }
91
+
92
+ /**
93
+ * @param {Object} [params]
94
+ * @returns {Error}
95
+ */
96
+ function missingCopilotCaptureInputsError(params = {}) {
97
+ const clientId = typeof params.clientId === 'string' && params.clientId.trim();
98
+ const error = microsoftProvisioningError(
99
+ clientId
100
+ ? 'Microsoft Copilot setup cannot create Entra SSO until the public MCP URL is available.'
101
+ : 'Microsoft Copilot setup cannot create Entra SSO until this environment has an Entra application id.',
102
+ 'CAPTURE_INPUTS'
103
+ );
104
+ error.statusCode = 400;
105
+ return error;
106
+ }
107
+
108
+ module.exports = {
109
+ microsoftProvisioningError,
110
+ wrongTenantError,
111
+ wrapToolkitError,
112
+ wrapTeamsCliError,
113
+ redactTeamsSecrets,
114
+ wrongEnvironmentRegistrationError,
115
+ missingCopilotCaptureInputsError,
116
+ missingMicrosoftTenantError
117
+ };