@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.
- package/bin/aifabrix.js +2 -2
- package/lib/api/assistants.api.js +8 -5
- package/lib/api/channel-identity.api.js +41 -0
- package/lib/api/evidence-authoring.api.js +5 -1
- package/lib/api/evidence.api.js +2 -0
- package/lib/api/types/evidence.types.js +2 -0
- package/lib/api/work-search.api.js +136 -0
- package/lib/channels/add-channel.js +163 -126
- package/lib/channels/approval-guides/chatgpt.js +14 -18
- package/lib/channels/approval-guides/claude.js +29 -0
- package/lib/channels/approval-guides/index.js +88 -22
- package/lib/channels/approval-guides/mcp-client.js +27 -0
- package/lib/channels/approval-guides/microsoft-copilot.js +52 -3
- package/lib/channels/approval-guides/slack.js +10 -10
- package/lib/channels/approval-guides/teams-bot.js +8 -12
- package/lib/channels/channel-add-continuations.js +91 -0
- package/lib/channels/channel-add-ensure.js +124 -27
- package/lib/channels/channel-add-existing.js +160 -28
- package/lib/channels/channel-add-failure.js +60 -0
- package/lib/channels/channel-add-remaining.js +486 -0
- package/lib/channels/channel-add-tty.js +190 -0
- package/lib/channels/channel-add-wizard-config.js +138 -0
- package/lib/channels/channel-add-wizard.js +250 -0
- package/lib/channels/channel-artifact-generator.js +27 -13
- package/lib/channels/channel-cardinality.js +83 -0
- package/lib/channels/channel-catalog-icon.js +45 -0
- package/lib/channels/channel-cli-instructions.js +75 -0
- package/lib/channels/channel-configuration-map.js +213 -0
- package/lib/channels/channel-credential.js +11 -14
- package/lib/channels/channel-definition-project.js +101 -0
- package/lib/channels/channel-definition-registry.js +154 -0
- package/lib/channels/channel-description.js +59 -2
- package/lib/channels/channel-discovery.js +16 -2
- package/lib/channels/channel-external-system.js +86 -9
- package/lib/channels/channel-install-envelope-actions.js +88 -0
- package/lib/channels/channel-install-envelope-microsoft.js +155 -0
- package/lib/channels/channel-install-envelope.js +356 -0
- package/lib/channels/channel-install-help-md.js +172 -0
- package/lib/channels/channel-install-http-payload.js +62 -0
- package/lib/channels/channel-install-inventory.js +115 -0
- package/lib/channels/channel-install-profiles.js +90 -0
- package/lib/channels/channel-instance-collision.js +118 -0
- package/lib/channels/channel-instance-key.js +100 -0
- package/lib/channels/channel-instance-materialize.js +240 -0
- package/lib/channels/channel-integration-generator.js +16 -9
- package/lib/channels/channel-integration-template.js +101 -22
- package/lib/channels/channel-inventory-fetch.js +79 -0
- package/lib/channels/channel-oauth-preflight.js +104 -0
- package/lib/channels/channel-package-version.js +76 -0
- package/lib/channels/channel-predefined-client.js +154 -0
- package/lib/channels/channel-probe.js +7 -2
- package/lib/channels/channel-runtime-resolver.js +180 -72
- package/lib/channels/channel-status-display.js +86 -16
- package/lib/channels/channel-targets.js +106 -92
- package/lib/channels/chatgpt-callback.js +318 -0
- package/lib/channels/chatgpt-channel-add.js +229 -0
- package/lib/channels/chatgpt-preflight.js +396 -0
- package/lib/channels/chatgpt-runtime-contract.js +17 -0
- package/lib/channels/chatgpt-setup-values.js +124 -0
- package/lib/channels/claude-callback.js +67 -0
- package/lib/channels/claude-channel-add.js +254 -0
- package/lib/channels/claude-runtime-contract.js +40 -0
- package/lib/channels/claude-runtime.js +58 -0
- package/lib/channels/claude-setup-values.js +89 -0
- package/lib/channels/mcp-client/config-merge.js +148 -0
- package/lib/channels/mcp-client/ensure-client.js +231 -0
- package/lib/channels/mcp-client/paths.js +53 -0
- package/lib/channels/mcp-client/profiles.js +122 -0
- package/lib/channels/mcp-client/redirect-uris.js +99 -0
- package/lib/channels/mcp-client/runtime.js +59 -0
- package/lib/channels/mcp-client-channel-add.js +186 -0
- package/lib/channels/microsoft-copilot-channel-add.js +117 -7
- package/lib/channels/microsoft-copilot-entra-identifier-uris.js +187 -0
- package/lib/channels/microsoft-copilot-entra-sso-form.js +106 -18
- package/lib/channels/microsoft-copilot-entra-sso.js +31 -2
- package/lib/channels/microsoft-copilot-package-prior.js +107 -0
- package/lib/channels/microsoft-copilot-package.js +29 -28
- package/lib/channels/microsoft-provisioning/a365.js +80 -0
- package/lib/channels/microsoft-provisioning/auth-config.js +240 -0
- package/lib/channels/microsoft-provisioning/auth.js +179 -0
- package/lib/channels/microsoft-provisioning/cli.js +71 -0
- package/lib/channels/microsoft-provisioning/constants.js +75 -0
- package/lib/channels/microsoft-provisioning/errors.js +117 -0
- package/lib/channels/microsoft-provisioning/index.js +55 -0
- package/lib/channels/microsoft-provisioning/install-atk.js +158 -0
- package/lib/channels/microsoft-provisioning/install-teams.js +115 -0
- package/lib/channels/microsoft-provisioning/login-portal-device.js +236 -0
- package/lib/channels/microsoft-provisioning/login-portal-parse.js +71 -0
- package/lib/channels/microsoft-provisioning/login-portal-teams.js +193 -0
- package/lib/channels/microsoft-provisioning/login-portal.js +230 -0
- package/lib/channels/microsoft-provisioning/persist.js +110 -0
- package/lib/channels/microsoft-provisioning/teams-bot-args.js +119 -0
- package/lib/channels/microsoft-provisioning/teams-bot-controller.js +123 -0
- package/lib/channels/microsoft-provisioning/teams-bot-parse.js +134 -0
- package/lib/channels/microsoft-provisioning/teams-bot-persist.js +113 -0
- package/lib/channels/microsoft-provisioning/teams-bot-provision.js +234 -0
- package/lib/channels/microsoft-provisioning/teams-bot-secrets.js +45 -0
- package/lib/channels/microsoft-provisioning/teams-cli.js +82 -0
- package/lib/channels/runtime-tool-catalog.js +5 -2
- package/lib/channels/slack-channel-add-portal.js +130 -0
- package/lib/channels/slack-channel-add-tty-auth.js +95 -0
- package/lib/channels/slack-channel-add.js +258 -0
- package/lib/channels/slack-provisioning/apps.js +181 -0
- package/lib/channels/slack-provisioning/auth-store.js +110 -0
- package/lib/channels/slack-provisioning/auth-ticket.js +185 -0
- package/lib/channels/slack-provisioning/auth.js +115 -0
- package/lib/channels/slack-provisioning/callbacks.js +41 -0
- package/lib/channels/slack-provisioning/cli.js +226 -0
- package/lib/channels/slack-provisioning/constants.js +37 -0
- package/lib/channels/slack-provisioning/credentials.js +169 -0
- package/lib/channels/slack-provisioning/curl-shim.js +132 -0
- package/lib/channels/slack-provisioning/developer-install.js +118 -0
- package/lib/channels/slack-provisioning/env-file.js +120 -0
- package/lib/channels/slack-provisioning/errors.js +47 -0
- package/lib/channels/slack-provisioning/go-ca-bundle.js +137 -0
- package/lib/channels/slack-provisioning/index.js +250 -0
- package/lib/channels/slack-provisioning/install-cli.js +323 -0
- package/lib/channels/slack-provisioning/manifest.js +89 -0
- package/lib/channels/slack-provisioning/oauth-lock.js +33 -0
- package/lib/channels/slack-provisioning/offer-cli.js +113 -0
- package/lib/channels/slack-provisioning/onboard-members.js +122 -0
- package/lib/channels/slack-provisioning/onboard.js +89 -0
- package/lib/channels/slack-provisioning/persist.js +95 -0
- package/lib/channels/slack-provisioning/remaining-urls.js +158 -0
- package/lib/channels/slack-provisioning/with-curl-on-path.js +48 -0
- package/lib/channels/teams-bot-channel-add.js +94 -0
- package/lib/channels/vendor-dataplane-url.js +249 -0
- package/lib/cli/setup-certification.help.js +2 -0
- package/lib/cli/setup-external-system-help.js +2 -0
- package/lib/cli/setup-external-system.js +1 -1
- package/lib/commands/channel-add-help.js +366 -0
- package/lib/commands/channel-add-setup.js +162 -80
- package/lib/commands/channel-configure.js +118 -0
- package/lib/commands/channel.js +10 -1
- package/lib/commands/governance-upload-external.js +6 -3
- package/lib/commands/lifecycle-command-action.js +2 -5
- package/lib/commands/lifecycle-external.js +93 -21
- package/lib/commands/repair-datasource-test-payload.js +4 -2
- package/lib/commands/repair-datasource-webhooks-sync-bridge.js +23 -2
- package/lib/commands/repair-datasource.js +3 -0
- package/lib/commands/repair-external-run.js +59 -25
- package/lib/commands/repair-openapi-rest-runtime.js +127 -0
- package/lib/commands/repair-orchestration-tag-merge.js +339 -0
- package/lib/commands/repair-rbac-catalog-defaults.js +96 -0
- package/lib/commands/repair-rbac-platform-preset.js +26 -15
- package/lib/commands/repair-rbac-reader-roles.js +8 -21
- package/lib/commands/repair-rbac.js +10 -34
- package/lib/commands/repair-system-permissions.js +24 -22
- package/lib/commands/role-assistant-test-output.js +14 -0
- package/lib/commands/role-assistant.js +59 -21
- package/lib/commands/test-e2e-external.js +148 -21
- package/lib/commands/upload-credential-push-log.js +2 -1
- package/lib/commands/upload-publish-context.js +1 -1
- package/lib/commands/upload-role-assistant-shell.js +124 -0
- package/lib/commands/upload-sidecar-followups.js +6 -3
- package/lib/commands/upload.js +18 -3
- package/lib/core/secrets-docker-env.js +4 -1
- package/lib/core/secrets-env-content.js +17 -3
- package/lib/datasource/capability/capability-manifest.js +0 -3
- package/lib/datasource/capability/copy-test-payload.js +3 -0
- package/lib/external-system/deploy-helpers.js +26 -1
- package/lib/external-system/deploy.js +10 -6
- package/lib/external-system/download-helpers.js +29 -2
- package/lib/external-system/download-role-assistant.js +83 -4
- package/lib/external-system/download.js +40 -30
- package/lib/external-system/sync-deploy-manifest.js +3 -2
- package/lib/external-system/upload-identity.js +42 -0
- package/lib/generator/index.js +19 -15
- package/lib/generator/split.js +13 -2
- package/lib/lifecycle/role-assistant-governance.js +146 -0
- package/lib/lifecycle/scenario-upload.js +181 -30
- package/lib/programmatic/builder-api-cors.js +143 -0
- package/lib/programmatic/builder-api-request.js +6 -0
- package/lib/programmatic/builder-api-route-dispatch.js +56 -42
- package/lib/programmatic/builder-api-server.js +8 -1
- package/lib/programmatic/capability-registry.js +54 -0
- package/lib/programmatic/channel-install-help-resolve.js +359 -0
- package/lib/programmatic/channel-install-session.js +218 -0
- package/lib/programmatic/help-content/channel-onboarding.md +2 -0
- package/lib/programmatic/help-content/cip-overview.md +3 -1
- package/lib/programmatic/http-raw-response.js +62 -0
- package/lib/programmatic/openapi-channel-install-bindings.js +179 -0
- package/lib/programmatic/openapi-channel-install-schemas.js +286 -0
- package/lib/programmatic/openapi-component-schemas.js +18 -1
- package/lib/programmatic/openapi-description-enricher.js +3 -1
- package/lib/programmatic/openapi-descriptions.js +74 -3
- package/lib/programmatic/openapi-envelope-examples.js +117 -0
- package/lib/programmatic/openapi-operation-bindings.js +4 -1
- package/lib/programmatic/openapi-schema-descriptions-channel.js +316 -0
- package/lib/programmatic/openapi-spec.js +12 -8
- package/lib/programmatic/platform-rbac-catalog.js +36 -18
- package/lib/programmatic/route-handler-map.js +51 -1
- package/lib/programmatic/route-handlers-context.js +2 -1
- package/lib/programmatic/run-auth-permissions.js +54 -0
- package/lib/programmatic/run-channel-catalog.js +196 -0
- package/lib/programmatic/run-channel-install-artifacts.js +137 -0
- package/lib/programmatic/run-channel-install-copilot.js +353 -0
- package/lib/programmatic/run-channel-install-options.js +232 -0
- package/lib/programmatic/run-channel-install-teams-bot.js +204 -0
- package/lib/programmatic/run-channel-install.js +346 -0
- package/lib/programmatic/run-channel-package.js +87 -7
- package/lib/programmatic/workspace-context.js +2 -0
- package/lib/role-assistant/evidence-sync.js +4 -2
- package/lib/role-assistant/evidence-validation-issues.js +51 -0
- package/lib/role-assistant/knowledge-sync.js +10 -4
- package/lib/role-assistant/settings.js +49 -2
- package/lib/role-assistant/test-cases-evaluate.js +30 -2
- package/lib/role-assistant/test-cases-evidence.js +175 -0
- package/lib/role-assistant/test-cases-search.js +229 -0
- package/lib/role-assistant/test-cases.js +37 -4
- package/lib/role-assistant/test-runner-search.js +149 -0
- package/lib/role-assistant/test-runner-workhub-helpers.js +40 -2
- package/lib/role-assistant/test-runner-workhub-soft.js +9 -3
- package/lib/role-assistant/test-runner-workhub.js +29 -11
- package/lib/role-assistant/test-runner.js +16 -1
- package/lib/schema/external-datasource.schema.json +119 -16
- package/lib/schema/external-system.schema.json +159 -2
- package/lib/schema/mcp-client-profile.schema.json +103 -0
- package/lib/utils/app-path-resolve.js +4 -0
- package/lib/utils/authentication-env-template.js +44 -6
- package/lib/utils/credential-secrets-env.js +6 -1
- package/lib/utils/env-copy.js +19 -7
- package/lib/utils/external-env-template.js +20 -2
- package/lib/utils/paths.js +18 -1
- package/lib/utils/platform-shell-package.js +69 -0
- package/lib/utils/port-resolver.js +50 -1
- package/lib/utils/rewrite-name-flag.js +20 -0
- package/lib/utils/role-assistant-paths.js +13 -10
- package/lib/utils/schema-resolver.js +11 -1
- package/lib/utils/secrets-helpers.js +12 -21
- package/lib/utils/token-manager.js +10 -5
- package/lib/validation/validate.js +40 -0
- package/package.json +1 -1
- package/templates/README.md +1 -1
- package/templates/applications/builder-api/Dockerfile +1 -1
- package/templates/applications/builder-api/env.template +7 -0
- package/templates/applications/dataplane/application.yaml +6 -5
- package/templates/applications/dataplane/env.template +2 -2
- package/templates/applications/dataplane/rbac.yaml +7 -2
- package/templates/applications/keycloak/Dockerfile +30 -4
- package/templates/applications/keycloak/application.yaml +2 -2
- package/templates/applications/keycloak/cimd-lenient-parse/AbstractClientIdMetadataDocumentExecutor.java +896 -0
- package/templates/applications/keycloak/cimd-lenient-parse/SOURCE.md +19 -0
- package/templates/applications/keycloak/env.template +3 -0
- package/templates/applications/miso-controller/application.yaml +1 -2
- package/templates/applications/miso-controller/env.template +2 -0
- package/templates/channels/README.md +5 -5
- package/templates/channels/chatgpt/TROUBLESHOOTING.md +51 -0
- package/templates/channels/chatgpt/channel.json +59 -0
- package/templates/channels/chatgpt/icon.svg +1 -0
- package/templates/channels/chatgpt/install.template.md.hbs +20 -95
- package/templates/channels/chatgpt/integration/README.md +1 -1
- package/templates/channels/chatgpt/integration/application.json +2 -2
- package/templates/channels/chatgpt/integration/chatgpt-system.json +49 -4
- package/templates/channels/chatgpt/integration/env.template +2 -4
- package/templates/channels/chatgpt/integration/rbac.json +13 -0
- package/templates/channels/claude/TROUBLESHOOTING.md +41 -0
- package/templates/channels/claude/channel.json +59 -0
- package/templates/channels/claude/icon.svg +1 -0
- package/templates/channels/claude/install.template.md.hbs +21 -0
- package/templates/channels/claude/integration/README.md +14 -0
- package/templates/channels/claude/integration/application.json +15 -0
- package/templates/channels/claude/integration/claude-system.json +59 -0
- package/templates/channels/claude/integration/env.template +2 -0
- package/templates/channels/claude/integration/rbac.json +13 -0
- package/templates/channels/claude/manifest.template.json.hbs +40 -0
- package/templates/channels/mcp-client/channel.json +72 -0
- package/templates/channels/mcp-client/icon.svg +1 -0
- package/templates/channels/mcp-client/install.template.md.hbs +24 -0
- package/templates/channels/mcp-client/integration/README.md +13 -0
- package/templates/channels/mcp-client/integration/application.json +15 -0
- package/templates/channels/mcp-client/integration/env.template +2 -0
- package/templates/channels/mcp-client/integration/mcp-client-system.json +72 -0
- package/templates/channels/mcp-client/integration/rbac.json +13 -0
- package/templates/channels/mcp-client/manifest.template.json.hbs +41 -0
- package/templates/channels/mcp-client/profiles/cursor.json +26 -0
- package/templates/channels/mcp-client/profiles/github-copilot.json +29 -0
- package/templates/channels/mcp-client/profiles/vscode.json +29 -0
- package/templates/channels/microsoft-copilot/channel.json +73 -0
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +8 -4
- package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +65 -5
- package/templates/channels/microsoft-copilot/icon.svg +1 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +9 -9
- package/templates/channels/microsoft-copilot/integration/README.md +1 -1
- package/templates/channels/microsoft-copilot/integration/application.json +2 -2
- package/templates/channels/microsoft-copilot/integration/env.template +3 -6
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +63 -4
- package/templates/channels/microsoft-copilot/integration/rbac.json +13 -0
- package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +5 -5
- package/templates/channels/slack/channel.json +223 -0
- package/templates/channels/slack/icon.svg +1 -0
- package/templates/channels/slack/install.template.md.hbs +36 -28
- package/templates/channels/slack/integration/README.md +245 -22
- package/templates/channels/slack/integration/application.json +44 -7
- package/templates/channels/slack/integration/env.template +15 -6
- package/templates/channels/slack/integration/openapi/openapi.json +126 -0
- package/templates/channels/slack/integration/rbac.json +84 -0
- package/templates/channels/slack/integration/slack-datasource-commands.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-conversations.json +28 -3
- package/templates/channels/slack/integration/slack-datasource-events.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-interactive.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-messages.json +40 -2
- package/templates/channels/slack/integration/slack-system.json +155 -77
- package/templates/channels/slack/manifest.template.json.hbs +5 -2
- package/templates/channels/teams-bot/channel.json +161 -0
- package/templates/channels/teams-bot/icon.svg +1 -0
- package/templates/channels/teams-bot/install.template.md.hbs +12 -13
- package/templates/channels/teams-bot/integration/README.md +5 -4
- package/templates/channels/teams-bot/integration/application.json +6 -4
- package/templates/channels/teams-bot/integration/env.template +5 -4
- package/templates/channels/teams-bot/integration/openapi/openapi.json +68 -0
- package/templates/channels/teams-bot/integration/rbac.json +21 -0
- package/templates/channels/teams-bot/integration/teams-bot-datasource-activities.json +154 -0
- package/templates/channels/teams-bot/integration/teams-bot-system.json +128 -23
- package/templates/channels/web-embed/channel.json +60 -0
- package/templates/channels/web-embed/install.template.md.hbs +1 -1
- package/templates/channels/web-embed/integration/README.md +2 -2
- package/templates/channels/web-embed/integration/application.json +2 -2
- package/templates/channels/web-embed/integration/env.template +1 -1
- package/templates/channels/web-embed/integration/rbac.json +13 -0
- 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 {
|
|
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:
|
|
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
|
-
|
|
101
|
-
|
|
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
|
-
|
|
104
|
-
|
|
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 =
|
|
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
|
+
};
|