@aifabrix/builder 2.53.0 → 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 +119 -16
  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,186 @@
1
+ /**
2
+ * MCP client continuation for channel add: profile, preflight, Integration Client, mcp.json.
3
+ *
4
+ * @fileoverview Keep add-channel.js free of MCP client continuation logic
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { runChatGptPreflight } = require('./chatgpt-preflight');
10
+ const {
11
+ printValidating,
12
+ printRuntimeDeployed,
13
+ printRuntimeUnavailable,
14
+ printOAuthConnected,
15
+ printOAuthNotConnected,
16
+ printRemainingSteps,
17
+ printFixThenRerun
18
+ } = require('./channel-add-tty');
19
+ const { requireMcpClientProfile } = require('./mcp-client/profiles');
20
+ const { ensureMcpClientIntegrationClient } = require('./mcp-client/ensure-client');
21
+ const { resolveMcpConfigPath } = require('./mcp-client/paths');
22
+ const { mergeMcpClientConfig } = require('./mcp-client/config-merge');
23
+
24
+ const REMAINING_STEP = 'Reload the editor.';
25
+
26
+ /**
27
+ * @param {string} message
28
+ * @returns {string}
29
+ */
30
+ function mcpClientPreflightMessage(message) {
31
+ return String(message || '').replace(/^ChatGPT preflight:\s*/i, 'MCP client preflight: ');
32
+ }
33
+
34
+ /**
35
+ * @param {Object} params
36
+ * @returns {string}
37
+ */
38
+ function mcpClientResumeCommand(params) {
39
+ const profile = params.mcpClientProfile;
40
+ const profileKey = (profile && profile.key) || '<profile>';
41
+ const name =
42
+ (params.options && params.options.name) ||
43
+ (params.runtimeValues && (params.runtimeValues.baseName || params.runtimeValues.appName)) ||
44
+ '';
45
+ const quoted = name ? `"${name}"` : '"<name>"';
46
+ return `aifabrix channel add mcp-client --target ${profileKey} --name ${quoted}`;
47
+ }
48
+
49
+ /**
50
+ * Fail closed when --target / --profile is missing or unknown.
51
+ * @param {string} channelTarget
52
+ * @param {Object} options
53
+ * @returns {Object|null}
54
+ */
55
+ function maybeAssertMcpClientProfile(channelTarget, options = {}) {
56
+ if (channelTarget !== 'mcp-client') {
57
+ return null;
58
+ }
59
+ if (options.apiKey || options.auth === 'apiKey' || options.authMode === 'apiKey') {
60
+ const error = new Error('MCP client does not support API keys. Use OAuth.');
61
+ error.boundary = 'oauth';
62
+ throw error;
63
+ }
64
+ return requireMcpClientProfile(options);
65
+ }
66
+
67
+ /**
68
+ * @param {Object} params
69
+ * @param {Error} error
70
+ * @returns {void}
71
+ */
72
+ function printMcpClientPreflightFailure(params, error) {
73
+ const message = mcpClientPreflightMessage(error && error.message);
74
+ if (/pkce|authorization.server|protected resource/i.test(message)) {
75
+ printRuntimeDeployed();
76
+ printOAuthNotConnected();
77
+ printFixThenRerun('Fix OAuth discovery', mcpClientResumeCommand(params));
78
+ return;
79
+ }
80
+ printRuntimeUnavailable();
81
+ printFixThenRerun('Fix the Runtime connection', mcpClientResumeCommand(params));
82
+ }
83
+
84
+ /**
85
+ * @param {Object} params
86
+ * @returns {Promise<Object|null>}
87
+ */
88
+ async function maybeAssertMcpClientPreflight(params) {
89
+ if (params.channelTarget !== 'mcp-client') {
90
+ return null;
91
+ }
92
+ const profile = params.mcpClientProfile || requireMcpClientProfile(params.options || {});
93
+ params.mcpClientProfile = profile;
94
+ printValidating(profile.displayName);
95
+ try {
96
+ params.preflight = await runChatGptPreflight(params);
97
+ printRuntimeDeployed();
98
+ if (!(params.preflight && params.preflight.skipped)) {
99
+ printOAuthConnected();
100
+ }
101
+ return params.preflight;
102
+ } catch (error) {
103
+ if (error && error.message) {
104
+ error.message = mcpClientPreflightMessage(error.message);
105
+ }
106
+ printMcpClientPreflightFailure(params, error);
107
+ throw error;
108
+ }
109
+ }
110
+
111
+ /**
112
+ * @param {Object} profile
113
+ * @param {Object} runtimeValues
114
+ * @param {string|undefined} clientSecret
115
+ * @returns {Object}
116
+ */
117
+ function mcpServerEntry(profile, runtimeValues, clientSecret) {
118
+ const auth = { CLIENT_ID: profile.oauth.keycloakClientId };
119
+ if (clientSecret) {
120
+ auth.CLIENT_SECRET = clientSecret;
121
+ }
122
+ return {
123
+ url: runtimeValues && runtimeValues.mcpUrl,
124
+ auth
125
+ };
126
+ }
127
+
128
+ /**
129
+ * @param {Object} params
130
+ * @returns {Promise<Object>}
131
+ */
132
+ async function runMcpClientChannelAddContinuation(params) {
133
+ const profile = params.mcpClientProfile || requireMcpClientProfile(params.options || {});
134
+ const ensured = await ensureMcpClientIntegrationClient({
135
+ ctx: params.ctx,
136
+ profile,
137
+ deps: params.deps
138
+ });
139
+ const filePath = resolveMcpConfigPath(profile, params.pathDeps);
140
+ const merged = mergeMcpClientConfig({
141
+ profile,
142
+ filePath,
143
+ entry: mcpServerEntry(profile, params.runtimeValues, ensured.clientSecret),
144
+ deps: params.fsDeps
145
+ });
146
+ printRemainingSteps('', [profile.reload.remainingStep || REMAINING_STEP]);
147
+ return {
148
+ profileKey: profile.key,
149
+ configPath: merged.filePath,
150
+ created: ensured.created,
151
+ added: ensured.added,
152
+ recovered: merged.recovered
153
+ };
154
+ }
155
+
156
+ /**
157
+ * @param {Object} params
158
+ * @returns {Promise<Object|null>}
159
+ */
160
+ async function maybeRunMcpClientContinuation(params) {
161
+ if (params.channelTarget !== 'mcp-client') {
162
+ return null;
163
+ }
164
+ return runMcpClientChannelAddContinuation(params);
165
+ }
166
+
167
+ /**
168
+ * Dry-run TTY: no Integration Client create and no mcp.json write.
169
+ * @param {Object} params
170
+ * @returns {void}
171
+ */
172
+ function printMcpClientDryRunTty(params) {
173
+ const profile = params.mcpClientProfile || requireMcpClientProfile(params.options || {});
174
+ printValidating(profile.displayName);
175
+ printRuntimeDeployed();
176
+ printRemainingSteps('', [profile.reload.remainingStep || REMAINING_STEP]);
177
+ }
178
+
179
+ module.exports = {
180
+ maybeAssertMcpClientProfile,
181
+ maybeAssertMcpClientPreflight,
182
+ maybeRunMcpClientContinuation,
183
+ runMcpClientChannelAddContinuation,
184
+ printMcpClientDryRunTty,
185
+ mcpServerEntry
186
+ };
@@ -8,7 +8,9 @@
8
8
 
9
9
  'use strict';
10
10
 
11
- const { resolveChannelAuthContext } = require('./channel-auth-context');
11
+ const {
12
+ resolveChannelAuthContext
13
+ } = require('./channel-auth-context');
12
14
  const {
13
15
  normalizeBaseChannelName,
14
16
  resolveChannelDisplayName
@@ -19,7 +21,17 @@ const { loadChannelPackageContext } = require('./channel-discovery');
19
21
  const { getInboundMicrosoftEntraIdProvider } = require('../api/token-providers.api');
20
22
  const { getKeycloakEntraIdentityProvider } = require('../api/keycloak.api');
21
23
  const { resolveChannelRuntimeValues } = require('./channel-runtime-resolver');
24
+ const { vendorFacingUrlsFromCtx } = require('./vendor-dataplane-url');
22
25
  const { assertOauthPluginVaultReferenceId } = require('./microsoft-copilot-entra-sso');
26
+ const {
27
+ getCopilotPackageSourceDir,
28
+ readPriorOauthPluginVaultReferenceId
29
+ } = require('./microsoft-copilot-package-prior');
30
+ const { captureCopilotAuthConfigId } = require('./microsoft-provisioning');
31
+ const { ensureCopilotInstallClient } = require('./channel-predefined-client');
32
+ const { ensureCopilotEntraIdentifierUris } = require('./microsoft-copilot-entra-identifier-uris');
33
+ const { formatSuccessLine, formatWarningLine } = require('../utils/cli-layout-chalk');
34
+ const logger = require('../utils/logger');
23
35
 
24
36
  /**
25
37
  * @param {Object} options
@@ -32,8 +44,25 @@ function hasOauthPluginVaultReference(options) {
32
44
  );
33
45
  }
34
46
 
47
+ /**
48
+ * Reuse prior package vault reference when the CLI flag is omitted.
49
+ * @param {Object} options
50
+ * @returns {void}
51
+ */
52
+ function applyPriorOauthPluginVaultReference(options) {
53
+ if (hasOauthPluginVaultReference(options)) {
54
+ return;
55
+ }
56
+ const projectRoot = options.projectRoot || process.cwd();
57
+ const prior = readPriorOauthPluginVaultReferenceId(getCopilotPackageSourceDir(projectRoot));
58
+ if (prior) {
59
+ options.oauthPluginVaultReferenceId = prior;
60
+ }
61
+ }
62
+
35
63
  /**
36
64
  * Load Trust source + Keycloak Entra IdP for Copilot packaging (null on miss/error).
65
+ * Read-only — audience/scopes are seeded by Miso installer baseline.
37
66
  * @param {Object} ctx
38
67
  * @returns {Promise<{ entraProvider: Object|null, entraIdentityProvider: Object|null }>}
39
68
  */
@@ -77,8 +106,10 @@ async function resolveCopilotFormContextForError(params) {
77
106
  packageContext = null;
78
107
  }
79
108
  const { entraProvider, entraIdentityProvider } = await loadMicrosoftCopilotEntraContext(ctx);
109
+ const vendor = vendorFacingUrlsFromCtx(ctx);
80
110
  return resolveChannelRuntimeValues({
81
- dataplaneBaseUrl: ctx.dataplaneUrl,
111
+ dataplaneBaseUrl: vendor.dataplaneBaseUrl,
112
+ controllerUrl: vendor.controllerUrl,
82
113
  channelTarget: 'microsoft-copilot',
83
114
  appName: name,
84
115
  baseName,
@@ -91,17 +122,92 @@ async function resolveCopilotFormContextForError(params) {
91
122
  });
92
123
  }
93
124
 
125
+ /**
126
+ * Capture Teams Entra SSO auth-config via Agents Toolkit when the flag is omitted.
127
+ * @param {Object} params
128
+ * @returns {Promise<void>}
129
+ */
130
+ async function tryCaptureOauthPluginVaultReference(params) {
131
+ const { options, formContext, ctx } = params;
132
+ if (options.dryRun === true) {
133
+ return;
134
+ }
135
+ const captured = await captureCopilotAuthConfigId({
136
+ clientId: formContext && formContext.entraSsoClientId,
137
+ mcpServerUrl: (formContext && (formContext.mcpUrl || formContext.entraSsoBaseUrl)) || null,
138
+ expectedTenantId: formContext && formContext.entraTenantId,
139
+ environment: (ctx && ctx.environment) || (formContext && formContext.environment),
140
+ projectRoot: options.projectRoot,
141
+ teamsAppId: formContext && formContext.packageAppId
142
+ });
143
+ if (captured && captured.authConfigId) {
144
+ options.oauthPluginVaultReferenceId = captured.authConfigId;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * @param {Object} options
150
+ * @param {{ status?: string, reason?: string }|null} result
151
+ * @returns {void}
152
+ */
153
+ function logIdentifierUriEnsureResult(options, result) {
154
+ if (!result || options.quiet === true) {
155
+ return;
156
+ }
157
+ if (result.status === 'updated') {
158
+ logger.log(formatSuccessLine('Added Teams Entra SSO identifier URI on the Microsoft Entra app'));
159
+ return;
160
+ }
161
+ if (result.status !== 'skipped' || !result.reason || result.reason === 'tests') {
162
+ return;
163
+ }
164
+ if (result.reason === 'missing-inputs' || result.reason === 'dry-run') {
165
+ return;
166
+ }
167
+ logger.log(
168
+ formatWarningLine(
169
+ `Entra identifier URIs were not updated automatically (${result.reason}). Use the az command in INSTALL.md.`
170
+ )
171
+ );
172
+ }
173
+
174
+ /**
175
+ * After vault capture, merge api://auth-{authConfigId}/{clientId} onto the Entra app.
176
+ * @param {Object} params
177
+ * @returns {Promise<void>}
178
+ */
179
+ async function tryEnsureCopilotEntraIdentifierUris(params) {
180
+ const { options } = params;
181
+ if (options.dryRun === true || !hasOauthPluginVaultReference(options)) {
182
+ return;
183
+ }
184
+ const formContext = params.formContext || (await resolveCopilotFormContextForError(params));
185
+ const result = await ensureCopilotEntraIdentifierUris({
186
+ clientId: formContext && formContext.entraSsoClientId,
187
+ oauthPluginVaultReferenceId: options.oauthPluginVaultReferenceId,
188
+ dryRun: options.dryRun === true
189
+ });
190
+ logIdentifierUriEnsureResult(options, result);
191
+ }
192
+
94
193
  /**
95
194
  * @param {Object} params
96
195
  * @throws {Error}
97
196
  */
98
197
  async function assertMicrosoftCopilotOauthReference(params) {
99
198
  const { options } = params;
100
- if (hasOauthPluginVaultReference(options)) {
101
- return;
199
+ const vaultFromFlag = hasOauthPluginVaultReference(options);
200
+ let formContext = params.formContext || null;
201
+ if (!vaultFromFlag) {
202
+ formContext = formContext || (await resolveCopilotFormContextForError(params));
203
+ await tryCaptureOauthPluginVaultReference({ ...params, formContext });
204
+ }
205
+ if (!hasOauthPluginVaultReference(options)) {
206
+ formContext = formContext || (await resolveCopilotFormContextForError(params));
207
+ assertOauthPluginVaultReferenceId({ ...options, formContext });
102
208
  }
103
- const formContext = await resolveCopilotFormContextForError(params);
104
- assertOauthPluginVaultReferenceId({ ...options, formContext });
209
+ await ensureCopilotInstallClient(params);
210
+ await tryEnsureCopilotEntraIdentifierUris({ ...params, formContext });
105
211
  }
106
212
 
107
213
  /**
@@ -113,7 +219,10 @@ async function assertMicrosoftCopilotOauthReferenceBeforeForce(options) {
113
219
  if (hasOauthPluginVaultReference(options)) {
114
220
  return;
115
221
  }
116
- const ctx = await resolveChannelAuthContext('microsoft-copilot', { silent: options.quiet });
222
+ const ctx =
223
+ options.authContext && typeof options.authContext === 'object'
224
+ ? options.authContext
225
+ : await resolveChannelAuthContext('microsoft-copilot', { silent: options.quiet });
117
226
  const baseName = normalizeBaseChannelName(options.name);
118
227
  const name = resolveChannelDisplayName(baseName, ctx.environment);
119
228
  const rawDescription =
@@ -131,6 +240,7 @@ async function assertMicrosoftCopilotOauthReferenceBeforeForce(options) {
131
240
 
132
241
  module.exports = {
133
242
  hasOauthPluginVaultReference,
243
+ applyPriorOauthPluginVaultReference,
134
244
  loadMicrosoftCopilotEntraContext,
135
245
  resolveCopilotFormContextForError,
136
246
  assertMicrosoftCopilotOauthReference,
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Merge Teams Entra SSO identifier URIs onto the Microsoft Entra app.
3
+ *
4
+ * @fileoverview Keep api://{clientId} and add api://auth-{authConfigId}/{clientId}
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { promisify } = require('util');
10
+ const execFileDefault = promisify(require('child_process').execFile);
11
+ const {
12
+ parseOauthPluginVaultAuthConfigId,
13
+ buildTeamsWebApplicationInfoResource
14
+ } = require('./microsoft-copilot-entra-sso-form');
15
+
16
+ /**
17
+ * @param {Object} [deps]
18
+ * @returns {boolean}
19
+ */
20
+ function shouldSkipLiveAz(deps = {}) {
21
+ if (deps.allowInTests === true) {
22
+ return false;
23
+ }
24
+ return Boolean(process.env.JEST_WORKER_ID);
25
+ }
26
+
27
+ /**
28
+ * @param {unknown} value
29
+ * @returns {string}
30
+ */
31
+ function trimNonEmptyString(value) {
32
+ return typeof value === 'string' ? value.trim() : '';
33
+ }
34
+
35
+ /**
36
+ * @param {string|null|undefined} clientId
37
+ * @param {string|null|undefined} oauthPluginVaultReferenceId
38
+ * @returns {string[]|null}
39
+ */
40
+ function requiredCopilotIdentifierUris(clientId, oauthPluginVaultReferenceId) {
41
+ const appId = trimNonEmptyString(clientId);
42
+ const authConfigId = parseOauthPluginVaultAuthConfigId(oauthPluginVaultReferenceId);
43
+ const teamsUri = buildTeamsWebApplicationInfoResource(authConfigId, appId);
44
+ if (!appId || !teamsUri) {
45
+ return null;
46
+ }
47
+ return [`api://${appId}`, teamsUri];
48
+ }
49
+
50
+ /**
51
+ * Preserve existing URIs and append any missing required URIs.
52
+ * @param {unknown} existing
53
+ * @param {string[]} required
54
+ * @returns {string[]}
55
+ */
56
+ function mergeIdentifierUris(existing, required) {
57
+ const out = [];
58
+ const seen = new Set();
59
+ const add = (uri) => {
60
+ const normalized = trimNonEmptyString(uri);
61
+ if (!normalized || seen.has(normalized)) {
62
+ return;
63
+ }
64
+ seen.add(normalized);
65
+ out.push(normalized);
66
+ };
67
+ if (Array.isArray(existing)) {
68
+ existing.forEach(add);
69
+ }
70
+ (required || []).forEach(add);
71
+ return out;
72
+ }
73
+
74
+ /**
75
+ * @param {unknown} existing
76
+ * @param {string[]} required
77
+ * @returns {boolean}
78
+ */
79
+ function identifierUrisAlreadyPresent(existing, required) {
80
+ const set = new Set(
81
+ Array.isArray(existing) ? existing.map((uri) => trimNonEmptyString(uri)).filter(Boolean) : []
82
+ );
83
+ return (required || []).every((uri) => set.has(uri));
84
+ }
85
+
86
+ /**
87
+ * @param {string} stdout
88
+ * @returns {string[]}
89
+ */
90
+ function parseIdentifierUriJson(stdout) {
91
+ try {
92
+ const parsed = JSON.parse(String(stdout || '[]'));
93
+ if (!Array.isArray(parsed)) {
94
+ return [];
95
+ }
96
+ return parsed.map((uri) => trimNonEmptyString(uri)).filter(Boolean);
97
+ } catch {
98
+ return [];
99
+ }
100
+ }
101
+
102
+ /**
103
+ * @param {string[]} args
104
+ * @param {Object} deps
105
+ * @returns {Promise<{ stdout: string, stderr: string }>}
106
+ */
107
+ async function runAz(args, deps) {
108
+ const execFileImpl = deps.execFile || execFileDefault;
109
+ const result = await execFileImpl('az', args, {
110
+ timeout: deps.timeout || 60000,
111
+ maxBuffer: 2 * 1024 * 1024
112
+ });
113
+ return {
114
+ stdout: result && result.stdout ? String(result.stdout) : '',
115
+ stderr: result && result.stderr ? String(result.stderr) : ''
116
+ };
117
+ }
118
+
119
+ /**
120
+ * @param {Error} error
121
+ * @returns {string}
122
+ */
123
+ function azFailureReason(error) {
124
+ const code = error && error.code;
125
+ if (code === 'ENOENT') {
126
+ return 'Azure CLI is not available';
127
+ }
128
+ const message = error && error.message ? String(error.message).split('\n')[0] : '';
129
+ return message ? `Azure CLI: ${message.slice(0, 180)}` : 'Azure CLI update failed';
130
+ }
131
+
132
+ /**
133
+ * @param {Object} params
134
+ * @param {Object} [deps]
135
+ * @returns {Promise<{ status: string, reason?: string, identifierUris?: string[] }>}
136
+ */
137
+ async function applyIdentifierUriMerge(params, deps) {
138
+ const shown = await runAz(
139
+ ['ad', 'app', 'show', '--id', params.clientId, '--query', 'identifierUris', '-o', 'json'],
140
+ deps
141
+ );
142
+ const current = parseIdentifierUriJson(shown.stdout);
143
+ if (identifierUrisAlreadyPresent(current, params.required)) {
144
+ return { status: 'unchanged', identifierUris: current };
145
+ }
146
+ const next = mergeIdentifierUris(current, params.required);
147
+ await runAz(['ad', 'app', 'update', '--id', params.clientId, '--identifier-uris', ...next], deps);
148
+ return { status: 'updated', identifierUris: next };
149
+ }
150
+
151
+ /**
152
+ * Add the Teams auth-config URI without removing existing identifier URIs.
153
+ * Non-blocking: missing Azure CLI or Graph permission returns skipped.
154
+ * @param {Object} params
155
+ * @param {Object} [deps]
156
+ * @returns {Promise<{ status: string, reason?: string, identifierUris?: string[] }>}
157
+ */
158
+ async function ensureCopilotEntraIdentifierUris(params = {}, deps = {}) {
159
+ if (params.dryRun === true) {
160
+ return { status: 'skipped', reason: 'dry-run' };
161
+ }
162
+ if (shouldSkipLiveAz(deps)) {
163
+ return { status: 'skipped', reason: 'tests' };
164
+ }
165
+ const required = requiredCopilotIdentifierUris(
166
+ params.clientId,
167
+ params.oauthPluginVaultReferenceId
168
+ );
169
+ const clientId = trimNonEmptyString(params.clientId);
170
+ if (!required || !clientId) {
171
+ return { status: 'skipped', reason: 'missing-inputs' };
172
+ }
173
+ try {
174
+ return await applyIdentifierUriMerge({ clientId, required }, deps);
175
+ } catch (error) {
176
+ return { status: 'skipped', reason: azFailureReason(error) };
177
+ }
178
+ }
179
+
180
+ module.exports = {
181
+ shouldSkipLiveAz,
182
+ requiredCopilotIdentifierUris,
183
+ mergeIdentifierUris,
184
+ identifierUrisAlreadyPresent,
185
+ parseIdentifierUriJson,
186
+ ensureCopilotEntraIdentifierUris
187
+ };