@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,204 @@
1
+ /**
2
+ * Teams Bot portal install: Microsoft login when Azure-managed provision is skipped.
3
+ *
4
+ * @fileoverview Refresh/continue must start sign-in, not reprint Ready
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { toChannelInstallEnvelope } = require('../channels/channel-install-envelope');
10
+ const {
11
+ startPortalMicrosoftLogin,
12
+ isLoopbackAuthorizeUrl
13
+ } = require('../channels/microsoft-provisioning');
14
+ const { resolveChannelRuntimeValues } = require('../channels/channel-runtime-resolver');
15
+ const { vendorFacingUrlsFromCtx } = require('../channels/vendor-dataplane-url');
16
+ const { persistHelpPayload, remainingCtxFromResult, envelopeFromInstall } = require('./run-channel-install-copilot');
17
+ const { httpError } = require('./channel-install-session');
18
+
19
+ /**
20
+ * @param {string} definitionKey
21
+ * @param {Object|null} result
22
+ * @returns {boolean}
23
+ */
24
+ function teamsBotInstallStillWaiting(definitionKey, result) {
25
+ if (definitionKey !== 'teams-bot') {
26
+ return false;
27
+ }
28
+ const bot = result && result.teamsBotProvision;
29
+ if (bot && bot.connected === true) {
30
+ return false;
31
+ }
32
+ return Boolean(bot && bot.skipped === true);
33
+ }
34
+
35
+ /**
36
+ * @param {import('./workspace-context').WorkspaceContext} ctx
37
+ * @param {Object} addOptions
38
+ * @param {string} definitionKey
39
+ * @returns {Object}
40
+ */
41
+ function teamsBotWaitingRuntimeValues(ctx, addOptions, definitionKey) {
42
+ const vendor = vendorFacingUrlsFromCtx(ctx);
43
+ return resolveChannelRuntimeValues({
44
+ dataplaneBaseUrl: vendor.dataplaneBaseUrl,
45
+ controllerUrl: vendor.controllerUrl,
46
+ channelTarget: definitionKey,
47
+ appName: addOptions.name,
48
+ instanceSystemKey: addOptions.systemKey || ctx.instanceSystemKey || ctx.systemKey,
49
+ environment: ctx.environment,
50
+ appDescription: typeof addOptions.description === 'string' ? addOptions.description : ''
51
+ });
52
+ }
53
+
54
+ /**
55
+ * @param {Object} runtimeValues
56
+ * @param {Object|null} login
57
+ * @returns {Object}
58
+ */
59
+ function applyPortalMicrosoftLogin(runtimeValues, login) {
60
+ const loginUrl = login && login.loginUrl ? String(login.loginUrl).trim() : '';
61
+ if (loginUrl && !isLoopbackAuthorizeUrl(loginUrl)) {
62
+ runtimeValues.microsoftLoginUrl = loginUrl;
63
+ }
64
+ if (login && login.userCode) {
65
+ runtimeValues.microsoftLoginUserCode = login.userCode;
66
+ }
67
+ return runtimeValues;
68
+ }
69
+
70
+ /**
71
+ * @param {Object|null} login
72
+ * @returns {Error}
73
+ */
74
+ function teamsBotWaitingWithoutSignInError() {
75
+ return httpError(
76
+ 'Could not start Microsoft sign-in. Use Get a new code, complete sign-in, then click Continue.',
77
+ 409
78
+ );
79
+ }
80
+
81
+ /**
82
+ * @param {Object} addOptions
83
+ * @param {Object} runtimeValues
84
+ * @returns {Object}
85
+ */
86
+ function skippedTeamsBotResult(addOptions, runtimeValues, provision) {
87
+ const remaining = provision && Array.isArray(provision.remaining) ? provision.remaining : [];
88
+ return {
89
+ runtimeValues: { ...runtimeValues, appName: runtimeValues.appName || addOptions.name },
90
+ teamsBotProvision: {
91
+ skipped: true,
92
+ connected: false,
93
+ ...(remaining.length > 0 ? { remaining } : {})
94
+ }
95
+ };
96
+ }
97
+
98
+ /**
99
+ * @param {import('./workspace-context').WorkspaceContext} ctx
100
+ * @param {Object} addOptions
101
+ * @param {string} definitionKey
102
+ * @param {Object} runtimeValues
103
+ * @param {Object|null} login
104
+ * @returns {Object}
105
+ */
106
+ function persistWaitingTeamsBotEnvelope(ctx, addOptions, definitionKey, runtimeValues, login, provision) {
107
+ applyPortalMicrosoftLogin(runtimeValues, login);
108
+ const loginUrl =
109
+ typeof runtimeValues.microsoftLoginUrl === 'string' ? runtimeValues.microsoftLoginUrl.trim() : '';
110
+ if (!loginUrl && !(login && (login.authenticated === true || login.waiting === true))) {
111
+ throw teamsBotWaitingWithoutSignInError();
112
+ }
113
+ const result = skippedTeamsBotResult(addOptions, runtimeValues, provision);
114
+ const envelope = toChannelInstallEnvelope({
115
+ channelTarget: definitionKey,
116
+ displayName: addOptions.name,
117
+ ctx: remainingCtxFromResult(ctx, result, addOptions),
118
+ runtimeValues: result.runtimeValues,
119
+ verdicts: {
120
+ runtime: { ok: true, label: 'Deployed' },
121
+ oauth: { ok: false, label: 'Not connected' },
122
+ vendorSession: { ok: false, label: 'Sign in required' }
123
+ }
124
+ });
125
+ return persistHelpPayload(ctx, addOptions, envelope, definitionKey, result);
126
+ }
127
+
128
+ /**
129
+ * @param {import('./workspace-context').WorkspaceContext} ctx
130
+ * @param {Object} addOptions
131
+ * @param {string} definitionKey
132
+ * @param {Object} deps
133
+ * @param {Object|null} login
134
+ * @returns {Promise<Object|null>}
135
+ */
136
+ async function retryTeamsBotIfAuthenticated(ctx, addOptions, definitionKey, deps, login) {
137
+ if (!login || login.authenticated !== true || addOptions.teamsBotProvisionRetry === true) {
138
+ return null;
139
+ }
140
+ if (typeof deps.executeAddChannel !== 'function') {
141
+ return null;
142
+ }
143
+ const result = await deps.executeAddChannel(
144
+ ctx,
145
+ { ...addOptions, teamsBotProvisionRetry: true },
146
+ deps,
147
+ definitionKey
148
+ );
149
+ if (!teamsBotInstallStillWaiting(definitionKey, result)) {
150
+ const envelope = envelopeFromInstall(ctx, addOptions, result, definitionKey);
151
+ return persistHelpPayload(ctx, addOptions, envelope, definitionKey, result);
152
+ }
153
+ const runtimeValues = teamsBotWaitingRuntimeValues(ctx, addOptions, definitionKey);
154
+ return persistWaitingTeamsBotEnvelope(
155
+ ctx,
156
+ addOptions,
157
+ definitionKey,
158
+ runtimeValues,
159
+ login,
160
+ result.teamsBotProvision
161
+ );
162
+ }
163
+
164
+ /**
165
+ * @param {import('./workspace-context').WorkspaceContext} ctx
166
+ * @param {Object} addOptions
167
+ * @param {string} definitionKey
168
+ * @param {Object} [deps]
169
+ * @returns {Promise<Object>}
170
+ */
171
+ async function persistWaitingTeamsBotInstall(ctx, addOptions, definitionKey, deps = {}) {
172
+ const runtimeValues = teamsBotWaitingRuntimeValues(ctx, addOptions, definitionKey);
173
+ let login = { waiting: true };
174
+ try {
175
+ login = await startPortalMicrosoftLogin({
176
+ installationKey: addOptions.systemKey || ctx.instanceSystemKey || ctx.systemKey,
177
+ expectedTenantId: runtimeValues.entraTenantId,
178
+ retryLogin: addOptions.retryLogin === true,
179
+ loginCli: 'teams',
180
+ deps: (deps && deps.microsoftProvisioningDeps) || {}
181
+ });
182
+ } catch (err) {
183
+ if (err && (err.statusCode || err.code === 'WRONG_TENANT' || err.code === 'TOOLKIT')) {
184
+ throw err;
185
+ }
186
+ throw httpError((err && err.message) || 'Could not start Microsoft sign-in.', 409);
187
+ }
188
+ const captured = await retryTeamsBotIfAuthenticated(
189
+ ctx,
190
+ addOptions,
191
+ definitionKey,
192
+ deps,
193
+ login
194
+ );
195
+ if (captured) {
196
+ return captured;
197
+ }
198
+ return persistWaitingTeamsBotEnvelope(ctx, addOptions, definitionKey, runtimeValues, login);
199
+ }
200
+
201
+ module.exports = {
202
+ teamsBotInstallStillWaiting,
203
+ persistWaitingTeamsBotInstall
204
+ };
@@ -0,0 +1,346 @@
1
+ /**
2
+ * Builder-api generic channel install (help markdown + machine envelope).
3
+ *
4
+ * @fileoverview Wraps add-channel; default HTTP is helpMarkdown + phase + userActions
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { runAddChannel } = require('../channels/add-channel');
12
+ const registry = require('../channels/channel-definition-registry');
13
+ const { assertChannelInstanceAvailable, adoptExistingInstanceAsContinue } = require('../channels/channel-instance-collision');
14
+ const { assertChannelCardinality } = require('../channels/channel-cardinality');
15
+ const { assertIntegrationClientPermissions } = require('../channels/channel-oauth-preflight');
16
+ const {
17
+ formatChannelCliInstructions,
18
+ isCliProvisioningMode
19
+ } = require('../channels/channel-cli-instructions');
20
+ const { runWithWorkspaceContext } = require('./workspace-context');
21
+ const { createHttpRawResult } = require('./http-raw-response');
22
+ const {
23
+ requireChannelInstallSession,
24
+ httpError
25
+ } = require('./channel-install-session');
26
+ const {
27
+ resolveChannelInstallHelp,
28
+ resolveInstallDefinitionKey
29
+ } = require('./channel-install-help-resolve');
30
+ const {
31
+ assertChannelInstallTarget,
32
+ toChannelAddOptionsFromBody,
33
+ isRetryLoginFlag
34
+ } = require('./run-channel-install-options');
35
+ const { listChannelTargets } = require('./run-channel-catalog');
36
+ const {
37
+ peekPortalMicrosoftLogin,
38
+ awaitPortalMicrosoftLogin
39
+ } = require('../channels/microsoft-provisioning');
40
+ const {
41
+ isCopilotEntraWaitingError,
42
+ copilotInstallStillWaiting,
43
+ persistWaitingCopilotInstall,
44
+ envelopeFromInstall,
45
+ persistHelpPayload
46
+ } = require('./run-channel-install-copilot');
47
+ const {
48
+ persistWaitingTeamsBotInstall,
49
+ teamsBotInstallStillWaiting
50
+ } = require('./run-channel-install-teams-bot');
51
+
52
+ const DEFAULT_DEPS = { runAddChannel };
53
+
54
+ /**
55
+ * @param {import('./workspace-context').WorkspaceContext} ctx
56
+ * @returns {Object}
57
+ */
58
+ function authContextFromWorkspace(ctx) {
59
+ return {
60
+ controllerUrl: ctx.controllerUrl,
61
+ environment: ctx.environment,
62
+ dataplaneUrl: ctx.dataplaneUrl,
63
+ authConfig: { type: 'bearer', token: ctx.bearerToken, preserveBearer: true }
64
+ };
65
+ }
66
+
67
+ /**
68
+ * @param {import('./workspace-context').WorkspaceContext} ctx
69
+ * @param {Object} addOptions
70
+ * @param {Object} [deps]
71
+ * @returns {Promise<Object>}
72
+ */
73
+ function rethrowAsChannelInstallHttpError(err) {
74
+ if (err && err.statusCode) {
75
+ throw err;
76
+ }
77
+ const status = Number(err && err.status);
78
+ if (status >= 400 && status < 600) {
79
+ throw httpError(err.message, status);
80
+ }
81
+ const message = err && err.message ? String(err.message) : '';
82
+ if (/validation failed|does not match expected system key/i.test(message)) {
83
+ throw httpError(message, 400);
84
+ }
85
+ if (/oauth-plugin-vault-reference-id|OAuthPluginVault/i.test(message)) {
86
+ throw httpError(
87
+ 'Copilot app package is not ready until Teams Entra SSO registration is stored on this install.',
88
+ 409
89
+ );
90
+ }
91
+ throw err;
92
+ }
93
+
94
+ /**
95
+ * @param {import('./workspace-context').WorkspaceContext} ctx
96
+ * @param {Object} addOptions
97
+ * @param {Object} [deps]
98
+ * @param {string} definitionKey
99
+ * @returns {Promise<Object>}
100
+ */
101
+ async function executeAddChannel(ctx, addOptions, deps = DEFAULT_DEPS, definitionKey) {
102
+ const runAdd = deps.runAddChannel || runAddChannel;
103
+ const options = {
104
+ ...addOptions,
105
+ quiet: true,
106
+ projectRoot: ctx.getUserRoot(),
107
+ authContext: authContextFromWorkspace(ctx)
108
+ };
109
+ const channelTarget = definitionKey || ctx.systemKey;
110
+ try {
111
+ return await runWithWorkspaceContext(ctx, () => runAdd(channelTarget, options));
112
+ } catch (err) {
113
+ if (err && err.boundary === 'permissions') {
114
+ throw httpError(err.message, 403);
115
+ }
116
+ rethrowAsChannelInstallHttpError(err);
117
+ }
118
+ }
119
+
120
+ /**
121
+ * @param {import('./workspace-context').WorkspaceContext} ctx
122
+ * @param {Object} body
123
+ * @param {Object} [deps]
124
+ * @returns {Promise<Object>}
125
+ */
126
+ async function runChannelInstall(ctx, body, deps = DEFAULT_DEPS) {
127
+ const definitionKey = resolveInstallDefinitionKey(ctx);
128
+ if (definitionKey !== ctx.systemKey && !ctx.instanceSystemKey) {
129
+ ctx.instanceSystemKey = ctx.systemKey;
130
+ }
131
+ assertChannelInstallTarget(definitionKey, body || {});
132
+ const definition = registry.getChannelDefinition(definitionKey);
133
+ if (definition && isCliProvisioningMode(definition)) {
134
+ const name = (body && body.name) || 'Finance';
135
+ throw httpError(formatChannelCliInstructions(definition, { name }), 409);
136
+ }
137
+ const addOptions = toChannelAddOptionsFromBody(body || {}, definition);
138
+ if (addOptions.systemKey) {
139
+ ctx.instanceSystemKey = addOptions.systemKey;
140
+ }
141
+ await assertIntegrationClientPermissions(ctx, definitionKey, deps);
142
+ await adoptExistingInstanceAsContinue(ctx, addOptions, body, deps);
143
+ await assertChannelCardinality(ctx, definitionKey, {
144
+ continueInstall: addOptions.continueInstall === true,
145
+ force: body && body.force === true,
146
+ deps
147
+ });
148
+ await assertChannelInstanceAvailable(ctx, addOptions.systemKey, {
149
+ getExternalSystem: deps.getExternalSystem,
150
+ continueInstall: addOptions.continueInstall === true,
151
+ force: body && body.force === true
152
+ });
153
+ return addChannelOrCopilotWaiting(ctx, addOptions, deps, definitionKey);
154
+ }
155
+
156
+ /**
157
+ * @param {import('./workspace-context').WorkspaceContext} ctx
158
+ * @param {Object} addOptions
159
+ * @param {Object} deps
160
+ * @param {string} definitionKey
161
+ * @returns {Promise<Object>}
162
+ */
163
+ function persistCopilotWaiting(ctx, addOptions, definitionKey, deps) {
164
+ return persistWaitingCopilotInstall(ctx, addOptions, definitionKey, {
165
+ ...deps,
166
+ executeAddChannel
167
+ });
168
+ }
169
+
170
+ /**
171
+ * @param {import('./workspace-context').WorkspaceContext} ctx
172
+ * @param {Object} addOptions
173
+ * @param {Object} deps
174
+ * @param {string} definitionKey
175
+ * @returns {Promise<Object>}
176
+ */
177
+ async function addChannelOrCopilotWaiting(ctx, addOptions, deps, definitionKey) {
178
+ if (definitionKey === 'microsoft-copilot' && addOptions.retryLogin === true) {
179
+ return persistCopilotWaiting(ctx, addOptions, definitionKey, deps);
180
+ }
181
+ if (definitionKey === 'teams-bot' && addOptions.retryLogin === true) {
182
+ return persistWaitingTeamsBotInstall(ctx, addOptions, definitionKey, {
183
+ ...deps,
184
+ executeAddChannel
185
+ });
186
+ }
187
+ try {
188
+ const result = await executeAddChannel(ctx, addOptions, deps, definitionKey);
189
+ if (copilotInstallStillWaiting(definitionKey, result)) {
190
+ return persistCopilotWaiting(ctx, addOptions, definitionKey, deps);
191
+ }
192
+ if (teamsBotInstallStillWaiting(definitionKey, result)) {
193
+ return persistWaitingTeamsBotInstall(ctx, addOptions, definitionKey, {
194
+ ...deps,
195
+ executeAddChannel
196
+ });
197
+ }
198
+ const envelope = envelopeFromInstall(ctx, addOptions, result, definitionKey);
199
+ return persistHelpPayload(ctx, addOptions, envelope, definitionKey, result);
200
+ } catch (err) {
201
+ if (definitionKey === 'microsoft-copilot' && isCopilotEntraWaitingError(err)) {
202
+ return persistCopilotWaiting(ctx, addOptions, definitionKey, deps);
203
+ }
204
+ throw err;
205
+ }
206
+ }
207
+
208
+ /**
209
+ * @param {import('./workspace-context').WorkspaceContext} ctx
210
+ * @param {Object} [query]
211
+ * @returns {Object}
212
+ */
213
+ function getChannelInstall(ctx, query = {}) {
214
+ return resolveChannelInstallHelp(ctx, query);
215
+ }
216
+
217
+ /**
218
+ * @param {import('./workspace-context').WorkspaceContext} ctx
219
+ * @returns {Object}
220
+ */
221
+ function getChannelInstallHelp(ctx) {
222
+ const payload = resolveChannelInstallHelp(ctx);
223
+ return createHttpRawResult({
224
+ contentType: 'text/markdown; charset=utf-8',
225
+ body: payload.helpMarkdown,
226
+ fileName: 'help.md'
227
+ });
228
+ }
229
+
230
+ /**
231
+ * @param {import('./workspace-context').WorkspaceContext} ctx
232
+ * @param {Object} [deps]
233
+ * @returns {Promise<Object>}
234
+ */
235
+ function continueInstallArgs(bodyOrDeps, deps) {
236
+ if (bodyOrDeps && typeof bodyOrDeps.runAddChannel === 'function') {
237
+ return { body: {}, deps: bodyOrDeps };
238
+ }
239
+ return { body: bodyOrDeps || {}, deps: deps || DEFAULT_DEPS };
240
+ }
241
+
242
+ /**
243
+ * @param {Object} session
244
+ * @param {Object} body
245
+ * @returns {string}
246
+ */
247
+ function continueVaultReferenceId(session, body) {
248
+ const fromBody =
249
+ typeof body.oauthPluginVaultReferenceId === 'string' ? body.oauthPluginVaultReferenceId.trim() : '';
250
+ if (fromBody) {
251
+ return fromBody;
252
+ }
253
+ return typeof session.oauthPluginVaultReferenceId === 'string'
254
+ ? session.oauthPluginVaultReferenceId.trim()
255
+ : '';
256
+ }
257
+
258
+ /**
259
+ * Slash prefix is chosen on first POST; continue must not fall back to `af`.
260
+ * @param {Object} session
261
+ * @param {Object} body
262
+ * @returns {Object}
263
+ */
264
+ function continueCommandPrefix(session, body) {
265
+ const fromBody =
266
+ typeof body.commandPrefix === 'string' ? body.commandPrefix.trim() : '';
267
+ const configuration = body.configuration && typeof body.configuration === 'object'
268
+ ? body.configuration
269
+ : {};
270
+ const fromConfig =
271
+ typeof configuration.commandPrefix === 'string' ? configuration.commandPrefix.trim() : '';
272
+ const fromSession =
273
+ typeof session.commandPrefix === 'string' ? session.commandPrefix.trim() : '';
274
+ const commandPrefix = fromBody || fromConfig || fromSession;
275
+ return commandPrefix ? { commandPrefix } : {};
276
+ }
277
+
278
+ /**
279
+ * Device-code wait is Copilot and Teams Bot. Slack continue must not sit on that timer.
280
+ * @param {Object} session
281
+ * @param {boolean} retryLogin
282
+ * @param {import('./workspace-context').WorkspaceContext} ctx
283
+ * @returns {boolean}
284
+ */
285
+ function shouldAwaitPortalMicrosoftLogin(session, retryLogin, ctx) {
286
+ if (retryLogin || !session.installationKey) {
287
+ return false;
288
+ }
289
+ const definitionKey = session.definitionKey || resolveInstallDefinitionKey(ctx);
290
+ return definitionKey === 'microsoft-copilot' || definitionKey === 'teams-bot';
291
+ }
292
+
293
+ async function prepareCopilotContinueLogin(session, retryLogin, ctx) {
294
+ if (!shouldAwaitPortalMicrosoftLogin(session, retryLogin, ctx)) {
295
+ return;
296
+ }
297
+ const peeked = peekPortalMicrosoftLogin(session.installationKey);
298
+ if (peeked && peeked.authenticated === true) {
299
+ await awaitPortalMicrosoftLogin(session.installationKey, 15000);
300
+ return;
301
+ }
302
+ if (peeked && peeked.loginUrl) {
303
+ throw httpError(
304
+ 'Finish Microsoft sign-in in the browser, then click Continue.',
305
+ 409
306
+ );
307
+ }
308
+ }
309
+
310
+ /**
311
+ * @param {import('./workspace-context').WorkspaceContext} ctx
312
+ * @param {Object} [body]
313
+ * @param {Object} [deps]
314
+ * @returns {Promise<Object>}
315
+ */
316
+ async function continueChannelInstall(ctx, bodyOrDeps = {}, deps = DEFAULT_DEPS) {
317
+ const parsed = continueInstallArgs(bodyOrDeps, deps);
318
+ const session = requireChannelInstallSession(ctx);
319
+ const retryLogin = isRetryLoginFlag(parsed.body.retryLogin);
320
+ await prepareCopilotContinueLogin(session, retryLogin, ctx);
321
+ const token = typeof parsed.body.token === 'string' ? parsed.body.token.trim() : '';
322
+ const vaultId = continueVaultReferenceId(session, parsed.body);
323
+ return runChannelInstall(ctx, {
324
+ name: session.name,
325
+ profile: session.profile || undefined,
326
+ allowExperimental: session.allowExperimental === true,
327
+ continueInstall: true,
328
+ ...(session.installationKey ? { systemKey: session.installationKey } : {}),
329
+ ...continueCommandPrefix(session, parsed.body),
330
+ ...(retryLogin ? { retryLogin: true } : {}),
331
+ ...(!retryLogin && token ? { token } : {}),
332
+ ...(!retryLogin && session.slackAuthTicket ? { slackAuthTicket: session.slackAuthTicket } : {}),
333
+ ...(vaultId ? { oauthPluginVaultReferenceId: vaultId } : {})
334
+ }, parsed.deps);
335
+ }
336
+
337
+ module.exports = {
338
+ listChannelTargets,
339
+ runChannelInstall,
340
+ getChannelInstall,
341
+ getChannelInstallHelp,
342
+ continueChannelInstall,
343
+ shouldAwaitPortalMicrosoftLogin,
344
+ toChannelAddOptionsFromBody,
345
+ envelopeFromInstall
346
+ };