@salesforce/afv-skills 1.40.0 → 1.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/automation-flow-generate/SKILL.md +32 -43
- package/skills/experience-portal-create/SKILL.md +497 -0
- package/skills/experience-portal-create/assets/report-template.md +30 -0
- package/skills/experience-portal-create/references/mcp-invocation.md +288 -0
- package/skills/experience-portal-create/references/post-creation-activate-publish.md +165 -0
- package/skills/experience-portal-create/references/templates.md +253 -0
- package/skills/experience-ui-bundle-features-generate/SKILL.md +5 -1
- package/skills/experience-ui-bundle-frontend-generate/SKILL.md +2 -0
- package/skills/experience-ui-bundle-frontend-generate/references/page.md +1 -0
- package/skills/platform-datamask-run/SKILL.md +345 -0
- package/skills/platform-datamask-run/references/api-surface.md +130 -0
- package/skills/platform-datamask-run/references/policy-authoring.md +185 -0
- package/skills/platform-datamask-run/references/run-and-abort.md +116 -0
- package/skills/platform-datamask-run/scripts/poll-job.sh +115 -0
- package/skills/platform-dataspace-access-configure/SKILL.md +51 -3
- package/skills/platform-dataspace-access-configure/scripts/inspect-dataspace-scopes.sh +56 -0
- package/skills/platform-lightning-type-widget-coordinate/references/build-plan-format.md +1 -0
- package/skills/platform-sandbox-configure/SKILL.md +17 -2
- package/skills/platform-trial-org-create/SKILL.md +175 -0
- package/skills/platform-trial-org-create/examples/create_request.json +9 -0
- package/skills/platform-trial-org-create/examples/error_response.json +41 -0
- package/skills/platform-trial-org-create/examples/success_response.json +27 -0
- package/skills/platform-trial-org-create/references/error_codes.md +42 -0
- package/skills/platform-trial-org-create/references/signup_request_fields.md +69 -0
- package/skills/platform-trial-org-create/scripts/create_signup_request.sh +175 -0
- package/skills/platform-trial-org-create/scripts/get_signup_request.sh +155 -0
- package/skills/platform-widget-generate/SKILL.md +47 -6
- package/skills/platform-widget-generate/examples/conditional.json +3 -3
- package/skills/platform-widget-generate/examples/list-with-foreach.json +2 -2
- package/skills/platform-widget-generate/examples/single-object.json +2 -2
- package/skills/platform-widget-generate/references/widget-bundle-layout.md +1 -1
- package/skills/service-agentforce-channel-configure/SKILL.md +271 -0
- package/skills/service-agentforce-channel-configure/references/agent-wiring.md +97 -0
- package/skills/service-agentforce-channel-configure/references/channel-branch-email.md +145 -0
- package/skills/service-agentforce-channel-configure/references/channel-branch-voice.md +69 -0
- package/skills/service-agentforce-channel-configure/references/channel-types.md +61 -0
- package/skills/service-agentforce-channel-configure/references/live-traffic-gate.md +86 -0
- package/skills/service-agentforce-channel-configure/references/queue-resolution.md +135 -0
- package/skills/service-agentforce-channel-configure/references/routing-flow.md +384 -0
- package/skills/service-catalog-template-deploy/SKILL.md +310 -0
- package/skills/service-catalog-template-deploy/references/cli-invocation.md +258 -0
- package/skills/service-catalog-template-deploy/scripts/activate-verify.mjs +164 -0
- package/skills/service-catalog-template-deploy/scripts/build-deploy-payload.mjs +94 -0
- package/skills/service-catalog-template-deploy/scripts/resolve-template.mjs +331 -0
- package/skills/service-catalog-template-search/SKILL.md +212 -0
- package/skills/service-catalog-template-search/references/cli-invocation.md +128 -0
- package/skills/service-catalog-template-search/scripts/classify-catalog.mjs +205 -0
- package/skills/service-concierge-portal-generate/SKILL.md +126 -0
- package/skills/service-concierge-portal-generate/references/portal-deploy-runbook.md +1428 -0
- package/skills/service-digital-engagement-channel-configure/SKILL.md +46 -6
- package/skills/service-digital-engagement-channel-configure/assets/messaging_channel_template.xml +2 -1
- package/skills/service-digital-engagement-channel-configure/examples/asa_agent_channel.xml +4 -1
- package/skills/service-helpagent-coordinate/README.md +8 -2
- package/skills/service-helpagent-coordinate/SKILL.md +126 -130
- package/skills/service-helpagent-coordinate/assets/help-agent-spec.md +70 -53
- package/skills/service-helpagent-coordinate/references/agent-script.md +571 -457
- package/skills/service-helpagent-coordinate/references/channel-voice.md +38 -9
- package/skills/service-helpagent-coordinate/references/channel-web-chat.md +173 -49
- package/skills/service-helpagent-coordinate/references/output-report-format.md +126 -0
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +153 -0
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/examples/output-templates.md +79 -0
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/scripts/verify-child-verdict.mjs +35 -0
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/SKILL.md +271 -0
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/references/cli-invocation.md +265 -0
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/scripts/classify-enable-plan.mjs +220 -0
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/scripts/classify-final-report.mjs +102 -0
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/scripts/record-enable-result.mjs +73 -0
- package/skills/service-itsm-agentic-setup-agentforce-studio-validate/SKILL.md +206 -0
- package/skills/service-itsm-agentic-setup-agentforce-studio-validate/references/cli-invocation.md +194 -0
- package/skills/service-itsm-agentic-setup-agentforce-studio-validate/scripts/classify-readiness.mjs +223 -0
- package/skills/service-itsm-agentic-setup-cmdb-configure/SKILL.md +45 -7
- package/skills/service-itsm-agentic-setup-cmdb-configure/references/mcp-invocation.md +45 -5
- package/skills/service-itsm-agentic-setup-configure/SKILL.md +116 -0
- package/skills/service-itsm-agentic-setup-configure/examples/output-templates.md +64 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/SKILL.md +158 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/references/cli-invocation.md +361 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/references/error-taxonomy.md +44 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/references/reactivation.md +66 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/references/report-format.md +66 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/references/specialized-templates.md +148 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/references/workflow-detail.md +169 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/build-create-body.mjs +116 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/classify-agent-existence.mjs +185 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/classify-preflight.mjs +168 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/create-scratch-dir.mjs +58 -0
- package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/render-report.mjs +197 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/SKILL.md +186 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/action-availability.md +51 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/cli-invocation.md +345 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/error-taxonomy.md +44 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/reactivation.md +63 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/report-format.md +44 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/workflow-detail.md +149 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/build-create-body.mjs +110 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/classify-action-availability.mjs +201 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/classify-activate-result.mjs +135 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/classify-agent-existence.mjs +194 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/classify-preflight.mjs +158 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/create-scratch-dir.mjs +58 -0
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/render-report.mjs +191 -0
- package/skills/service-itsm-agentic-setup-incident-management/SKILL.md +133 -0
- package/skills/service-itsm-agentic-setup-incident-management/examples/output-templates.md +71 -0
- package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +308 -0
- package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone.json +23 -0
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +193 -0
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +57 -0
- package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +394 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/SKILL.md +266 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/references/cli-invocation.md +106 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/references/helper-contracts.md +142 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/references/permset-topology.md +82 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/scripts/classify-action-surface.mjs +137 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/scripts/classify-assignment-state.mjs +99 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/scripts/classify-permset-availability.mjs +120 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/scripts/resolve-target-user.mjs +86 -0
- package/skills/service-itsm-agentic-setup-uel-user-create/SKILL.md +284 -0
- package/skills/service-itsm-agentic-setup-uel-user-create/references/mcp-invocation.md +302 -0
- package/skills/service-itsm-channels-coordinate/SKILL.md +472 -0
- package/skills/service-itsm-incident-mgmt-configure/SKILL.md +212 -0
- package/skills/service-itsm-incident-mgmt-configure/references/mcp-invocation.md +225 -0
- package/skills/service-itsm-incident-priority-configure/SKILL.md +53 -12
- package/skills/service-itsm-swarming-configure/SKILL.md +212 -0
- package/skills/service-itsm-teams-configure/SKILL.md +395 -0
- package/skills/service-itsm-teams-configure/references/azure-credential-population.md +213 -0
- package/skills/service-itsm-teams-configure/references/gotchas.md +23 -0
- package/skills/service-itsm-teams-coordinate/SKILL.md +175 -0
- package/skills/service-itsm-teams-coordinate/examples/output-templates.md +85 -0
- package/skills/service-itsm-teams-debug/SKILL.md +144 -0
- package/skills/service-itsm-teams-debug/references/configuration-checklists.md +277 -0
- package/skills/service-itsm-teams-debug/references/report-generation.md +95 -0
- package/skills/service-itsm-teams-employee-agent-configure/SKILL.md +139 -0
- package/skills/service-itsm-teams-employee-agent-configure/assets/Teams_AgentForce.EmbeddedServiceConfig-meta.xml +43 -0
- package/skills/service-itsm-teams-employee-agent-configure/references/teams-embedded-employee-agent.md +480 -0
- package/skills/service-itsm-teams-itdesk-configure/SKILL.md +232 -0
- package/skills/service-itsm-teams-itservice-configure/SKILL.md +391 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: service-itsm-teams-configure
|
|
3
|
+
description: "Enable Microsoft Teams for Employee Service (ITSM) in Salesforce — the Salesforce Go feature service-cloud-itsm-teams-integration gating Teams-based IT Desk and IT Service collaboration. Use this for: 'enable Teams for employee service', 'turn on ITSM Teams integration', 'enable Microsoft Teams for IT Service', 'set up Salesforce IT Desk Teams app', 'enable ITSMTeamsEnabled', 'why can't I enable the Teams org preference', or any request to enable/verify this Salesforce Go feature. DO NOT TRIGGER for configuring the TeamsNotifications notification-channel preference or for enabling the Swarming feature itself (service-itsm-swarming-configure)."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0"
|
|
6
|
+
domains: ["Service"]
|
|
7
|
+
minApiVersion: "67.0"
|
|
8
|
+
relatedSkills:
|
|
9
|
+
- "experience-portal-create"
|
|
10
|
+
- "service-itsm-channels-coordinate"
|
|
11
|
+
- "service-itsm-swarming-configure"
|
|
12
|
+
- "service-itsm-teams-employee-agent-configure"
|
|
13
|
+
- "service-itsm-teams-itdesk-configure"
|
|
14
|
+
- "service-itsm-teams-itservice-configure"
|
|
15
|
+
mcpTools:
|
|
16
|
+
headless-360:
|
|
17
|
+
tools: ["describe", "discover", "dispatch", "dispatch_readonly"]
|
|
18
|
+
semver: ">=1.0.0"
|
|
19
|
+
cliTools:
|
|
20
|
+
- tool: ["sf"]
|
|
21
|
+
semver: ">=2.0.0"
|
|
22
|
+
accessCheck:
|
|
23
|
+
- type: "orgPerm"
|
|
24
|
+
value: "MSTeamsSetupAutomationAccess"
|
|
25
|
+
allowed-tools: |
|
|
26
|
+
Read AskUserQuestion Bash
|
|
27
|
+
mcp__headless-360__discover
|
|
28
|
+
mcp__headless-360__describe
|
|
29
|
+
mcp__headless-360__dispatch
|
|
30
|
+
mcp__headless-360__dispatch_readonly
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
# Enable Microsoft Teams for Employee Service (ITSM)
|
|
34
|
+
|
|
35
|
+
Enable the Salesforce Go feature **"Microsoft Teams for Employee Service"**
|
|
36
|
+
(`service-cloud-itsm-teams-integration`) — the feature that lets IT Desk and IT Service
|
|
37
|
+
agents track tickets, request catalog items, and get Agentforce assistance from inside
|
|
38
|
+
Microsoft Teams. Every operation dispatches through **headless-360**.
|
|
39
|
+
|
|
40
|
+
> **Execute one step at a time.** These steps make real, state-changing API calls. Run a single
|
|
41
|
+
> operation, show its result, confirm it succeeded, then proceed — do not batch multiple setup
|
|
42
|
+
> calls into one parallel block.
|
|
43
|
+
|
|
44
|
+
## Scope
|
|
45
|
+
|
|
46
|
+
- **In scope**: Enabling the `service-cloud-itsm-teams-integration` Go feature via its
|
|
47
|
+
feature-enablement Connect API; verifying feature and `ITSMTeamsEnabled` preference state
|
|
48
|
+
afterward; explaining why the direct org-preference PATCH route fails and why this route
|
|
49
|
+
works instead; disabling the feature if requested; giving the user step-by-step instructions
|
|
50
|
+
for the Azure/Entra app registration (Step 4a) since no Salesforce API can perform that part;
|
|
51
|
+
once the user provides the resulting Client ID/Tenant ID (in chat) and the Client Secret (via the
|
|
52
|
+
`TEAMS_ENTRA_CLIENT_SECRET` env var / secret file, never in chat), writing them
|
|
53
|
+
directly into the `MSTeamsSetupClientCredentialsEC` Named Credential via API — this
|
|
54
|
+
Salesforce-side write is always automated by this skill, never deferred back to the user;
|
|
55
|
+
registering the Experience Cloud site as the Teams "preferred site" extension via
|
|
56
|
+
`/connect/service-itsm-teams/graph-api/extensions` once that credential exists.
|
|
57
|
+
- **Out of scope**: Notification-channel preferences (`Notifications`, `TeamsNotifications`) —
|
|
58
|
+
a separate concern from this feature. Enabling the `service-cloud-swarming` Go feature itself —
|
|
59
|
+
delegate to `service-itsm-swarming-configure`. The IT Desk/fulfiller checklist group (Turn on
|
|
60
|
+
IT Desk, Install IT Desk app, Manage User Access, Set Teams as Collaboration Tool for
|
|
61
|
+
Swarming) — delegate to `service-itsm-teams-itdesk-configure`. The IT Service/employee
|
|
62
|
+
checklist group (Turn on IT Service, Install IT Service app, Manage User Access, Select a
|
|
63
|
+
Digital Experience Site) — delegate to `service-itsm-teams-itservice-configure`. Portal/site
|
|
64
|
+
creation — use `experience-portal-create`. The actual Azure-side actions (clicking through the
|
|
65
|
+
Azure portal, generating the client secret, granting Microsoft admin consent) must be
|
|
66
|
+
performed by the user in the Microsoft admin center — no Salesforce API reaches Azure/Entra —
|
|
67
|
+
but this skill still provides the exact instructions for those steps (see Gotchas and Step 4a)
|
|
68
|
+
rather than treating them as someone else's problem.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## The problem this skill solves
|
|
73
|
+
|
|
74
|
+
`ITSMTeamsEnabled` is the Salesforce Go page toggle preference gating Microsoft Teams ITSM integration. Its
|
|
75
|
+
UDD definition (`ServiceItsmTeams.settings.xml`) declares `orgAccess="always"` but has **no
|
|
76
|
+
`editAccess` attribute** — unlike working preferences such as `Notifications`/`TeamsNotifications`,
|
|
77
|
+
which explicitly set `editAccess="always"`. As a result, the direct Setup preferences Connect
|
|
78
|
+
API route is blocked:
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
GET /services/data/vXX.0/setup/org/preferences/ITSMTeamsEnabled
|
|
82
|
+
PATCH /services/data/vXX.0/setup/org/preferences/ITSMTeamsEnabled body: {"desiredState": true}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Both return `401`:
|
|
86
|
+
```json
|
|
87
|
+
{"error_code":"API_ERROR","status_code":401,"body":"[{\"errorCode\":\"INSUFFICIENT_ACCESS\",\"message\":\"Cannot read data!\"}]"}
|
|
88
|
+
```
|
|
89
|
+
(`"Cannot update preference value!"` on the PATCH). This is a real, code-level access gate
|
|
90
|
+
(`StandardMetadataChecker` in `setup-connect-impl` relays an Aura `NoAccessException` — "bit(s)
|
|
91
|
+
do not have READ/WRITE access" — for this preference specifically), **not** a version-prefix or
|
|
92
|
+
routing mistake. Do not retry this route with different API versions or bodies.
|
|
93
|
+
|
|
94
|
+
**The verified working path is different: enable the Go *feature*, not the preference
|
|
95
|
+
directly.** The Salesforce Go feature-enablement Connect API sits behind a different access
|
|
96
|
+
check and, on enable, flips `ITSMTeamsEnabled` (and related feature state) as a side effect.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Workflow
|
|
101
|
+
|
|
102
|
+
### Step 1 — Check current feature status
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
mcp__headless-360__dispatch(
|
|
106
|
+
method: "POST",
|
|
107
|
+
url: "/services/data/v67.0/connect/setup/discovery/features/status",
|
|
108
|
+
body: { "featureApiNames": ["service-cloud-itsm-teams-integration"] }
|
|
109
|
+
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Response shape:
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"items": [
|
|
116
|
+
{
|
|
117
|
+
"apiName": "service-cloud-itsm-teams-integration",
|
|
118
|
+
"status": "ENABLED", // or "NOT_ENABLED" / "DISABLED"
|
|
119
|
+
"blockedByApexLock": false,
|
|
120
|
+
"dependencyStatuses": [],
|
|
121
|
+
"enableBlockedReasons": [],
|
|
122
|
+
"disableBlockedReasons": []
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
If `status` is already `"ENABLED"`, skip to Step 3 (verification) — do not re-enable.
|
|
129
|
+
If `enableBlockedReasons` is non-empty, surface those reasons to the user (typically a missing
|
|
130
|
+
license/add-on) before attempting Step 2.
|
|
131
|
+
|
|
132
|
+
### Step 2 — Enable the feature
|
|
133
|
+
|
|
134
|
+
```text
|
|
135
|
+
mcp__headless-360__dispatch(
|
|
136
|
+
method: "POST",
|
|
137
|
+
url: "/services/data/v67.0/connect/setup/discovery/feature/service-cloud-itsm-teams-integration/enable",
|
|
138
|
+
body: {}
|
|
139
|
+
)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Known gotcha (verified):** this call can return `500 INTERNAL_ERROR` even when the feature
|
|
143
|
+
successfully ends up `ENABLED`. Do not treat a `500` here as a hard failure — always re-run
|
|
144
|
+
Step 1 (`features/status`) and Step 3 (`ITSMTeamsEnabled` read) afterward to check actual state
|
|
145
|
+
before reporting failure to the user. If status still shows `NOT_ENABLED` after retrying once,
|
|
146
|
+
then report the failure with the raw error.
|
|
147
|
+
|
|
148
|
+
### Step 3 — Verify `ITSMTeamsEnabled` flipped
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
mcp__headless-360__dispatch_readonly(
|
|
152
|
+
method: "GET",
|
|
153
|
+
url: "/services/data/v67.0/setup/org/preferences/ITSMTeamsEnabled"
|
|
154
|
+
)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Expect `200 {"isPreferenceEnabled": true}`. This confirms the underlying preference — otherwise
|
|
158
|
+
inaccessible via direct PATCH — is now enabled as a side effect of the feature enable.
|
|
159
|
+
|
|
160
|
+
### Step 4 — Report *interim* status (setup is NOT complete yet)
|
|
161
|
+
|
|
162
|
+
Report feature status and whether `ITSMTeamsEnabled` reads `true` — but **frame this as progress,
|
|
163
|
+
not completion.** Enabling the Go feature is only the first half. The integration is **not
|
|
164
|
+
functional** until the Microsoft Entra app is registered, its credentials are written into the
|
|
165
|
+
Named Credential + Auth Provider, and admin consent is granted (Step 4a). Do **not** call this an
|
|
166
|
+
"optional manual tail," do **not** mark Teams "Done"/"configured"/"complete," and do **not** hand
|
|
167
|
+
back to any coordinator as done. State plainly: *"The Salesforce feature is enabled; Teams
|
|
168
|
+
integration is not yet complete — the required Microsoft Entra app registration comes next."* Then
|
|
169
|
+
proceed directly into Step 4a. See the **Completion contract** below for what "complete" requires.
|
|
170
|
+
|
|
171
|
+
### Step 4a — Follow the Go page's own order: Create Entra app → Configure Named Credentials → Grant consent
|
|
172
|
+
|
|
173
|
+
The Salesforce Go feature page (Setup → Salesforce Go → this feature,
|
|
174
|
+
`.../lightning/setup/page/feature/service-cloud-itsm-teams-integration/home?topic=SalesforceGo`)
|
|
175
|
+
renders a **"Complete the Required Steps" → "Integrate Salesforce with Teams"** checklist with
|
|
176
|
+
exactly three items, in this order — verified from a live screenshot of the page. Follow this
|
|
177
|
+
order; do not skip ahead to Named Credentials before the Entra app exists, and do not treat
|
|
178
|
+
"Grant Azure Administrator Consent" as optional:
|
|
179
|
+
|
|
180
|
+
1. **Create Microsoft Entra ID App** ("Set Up Microsoft Entra ID App" button — opens
|
|
181
|
+
portal.azure.com). There is no Salesforce API for this sub-step; give the user these exact
|
|
182
|
+
clicks and wait for them to provide the resulting values:
|
|
183
|
+
- **portal.azure.com** → **Microsoft Entra ID** → **App registrations** → **New registration**.
|
|
184
|
+
Name it something identifiable (e.g. `Salesforce ITSM Teams Integration`); single-tenant is
|
|
185
|
+
fine unless the user's org spans multiple tenants; no redirect URI is needed for the
|
|
186
|
+
client-credentials flow used here.
|
|
187
|
+
- From the app's **Overview** page, note the **Application (client) ID** and **Directory
|
|
188
|
+
(tenant) ID**.
|
|
189
|
+
- **Certificates & secrets** → **New client secret** → copy the secret **value** immediately
|
|
190
|
+
(unrecoverable after leaving the page).
|
|
191
|
+
- **API permissions** → **Add a permission** → **Microsoft Graph** → **Application
|
|
192
|
+
permissions** → add the Graph permissions this integration needs (at minimum
|
|
193
|
+
`ChannelMessage.Send`, `Team.ReadBasic.All`, `Channel.ReadBasic.All`,
|
|
194
|
+
`TeamworkAppSettings.ReadWrite.All` — confirm against the org's current Teams for Employee
|
|
195
|
+
Service documentation, since required scopes can change between releases).
|
|
196
|
+
- Provide the credentials **without exposing the secret in chat**: the **Client ID** and
|
|
197
|
+
**Tenant ID** are non-secret identifiers and may be given in the conversation, but the
|
|
198
|
+
**Client Secret is a confidential credential — NEVER ask for it in chat and never accept it
|
|
199
|
+
there.** The user places the secret in the `TEAMS_ENTRA_CLIENT_SECRET` environment variable
|
|
200
|
+
(or a gitignored secret file whose path they give you); you read it from that source at write
|
|
201
|
+
time and never print, echo, or log its value.
|
|
202
|
+
2. **Configure Setup Named Credentials** ("Go to Setup" button on the Go page — the manual
|
|
203
|
+
equivalent of what this skill automates). **Once you have the Client ID / Tenant ID and the
|
|
204
|
+
secret is available in the env var / file, do not tell the user to enter anything into Setup —
|
|
205
|
+
call the Named Credential APIs directly**, per "Populating `MSTeamsSetupClientCredentialsEC`
|
|
206
|
+
given a user-supplied client ID/secret" under Step 5 below. **This same set of values must ALSO be written into the
|
|
207
|
+
`microsoft_auth_provider` Auth Provider** (the inbound-SSO side, distinct from the outbound-Graph
|
|
208
|
+
Named Credential) — the org provisions this Auth Provider empty. Do this automatically too; see
|
|
209
|
+
"Populating the `microsoft_auth_provider` Auth Provider" under Step 5. Both artifacts share the
|
|
210
|
+
same Client ID / Tenant ID / Client Secret and must be populated together — populating only the
|
|
211
|
+
Named Credential leaves portal SSO login broken.
|
|
212
|
+
3. **Grant Azure Administrator Consent** ("Grant Consent" button on the Go page). Clicking it
|
|
213
|
+
opens a modal with a one-time consent link to a **fixed Salesforce-owned Entra app**
|
|
214
|
+
(`client_id=cd6bd63f-41ef-47cc-9465-86e986179a29`, tenant segment `organizations` — not the
|
|
215
|
+
user's own tenant ID, and not the app created in step 1) requesting the
|
|
216
|
+
`Organization.ReadWrite.All` delegated scope:
|
|
217
|
+
```text
|
|
218
|
+
https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=cd6bd63f-41ef-47cc-9465-86e986179a29&response_type=code&redirect_uri=https://salesforce.com&response_mode=query&scope=Organization.ReadWrite.All
|
|
219
|
+
```
|
|
220
|
+
This link is static — it does not need to be fetched per-org or per-user, and headless-360 has
|
|
221
|
+
no operation that generates or dispatches it (it's rendered by an internal Aura controller with
|
|
222
|
+
no public Connect API mirror). **Paste this exact link and tell the user to click it, signed in
|
|
223
|
+
as a Microsoft tenant admin, to grant consent** — this action authenticates as the Microsoft
|
|
224
|
+
admin and cannot be performed by this skill via API.
|
|
225
|
+
|
|
226
|
+
Everything the user does above (steps 1's Azure clicks and step 3's consent click) is their
|
|
227
|
+
manual responsibility because no Salesforce API reaches Azure/Entra. Everything Salesforce-side —
|
|
228
|
+
writing the supplied credential (secret read from the env var / secret file, never from chat) into
|
|
229
|
+
the Named Credential in step 2 — is this skill's job to automate; that division of labor is the
|
|
230
|
+
entire point of this skill.
|
|
231
|
+
|
|
232
|
+
### Step 4b — Delegate to the IT Desk / IT Service child skills
|
|
233
|
+
|
|
234
|
+
Before touching the "Set Up Salesforce IT Desk" / "Set Up Salesforce IT Service" checklist
|
|
235
|
+
groups, ask the user which they want — these are two independent halves of the feature
|
|
236
|
+
(fulfiller side vs. employee side) and a user may only need one:
|
|
237
|
+
|
|
238
|
+
- **Salesforce IT Desk** — for IT agents/fulfillers to swarm on and resolve tickets from Teams.
|
|
239
|
+
Invoke `service-itsm-teams-itdesk-configure`.
|
|
240
|
+
- **Salesforce IT Service** — for employees to create and manage their own tickets from Teams.
|
|
241
|
+
Invoke `service-itsm-teams-itservice-configure`.
|
|
242
|
+
- **Both** — invoke both child skills.
|
|
243
|
+
|
|
244
|
+
Each child skill handles its own 3-4 item checklist group (Turn on `<app>` → Install `<app>`
|
|
245
|
+
App on Teams → Manage User Access → optional 4th item) end-to-end — do not duplicate that logic
|
|
246
|
+
here.
|
|
247
|
+
|
|
248
|
+
### Step 4c — Delegate the embedded Agentforce agent (Teams "Ask AI Agent")
|
|
249
|
+
|
|
250
|
+
If the user wants the embedded Agentforce agent to **reply** inside the Teams custom client
|
|
251
|
+
("Salesforce Employee Assist" → "Ask AI Agent") — i.e. build the `Teams_AgentForce` MIAW
|
|
252
|
+
deployment, its Web channel (**User Verification ON + a `JWKS_URL` Key Set**), the routing flow to the
|
|
253
|
+
IT Service Employee Agent, and the **Agent Access permission set** for the portal user — **invoke
|
|
254
|
+
`service-itsm-teams-employee-agent-configure`.** That is a distinct, large capability with its own
|
|
255
|
+
object model; do not attempt it inline here. It requires the employee portal site
|
|
256
|
+
(`experience-portal-create`) to exist first.
|
|
257
|
+
|
|
258
|
+
### Step 5 — Register the preferred site (Teams extension), once the Azure credential exists
|
|
259
|
+
|
|
260
|
+
Once the org has an external credential named `MSTeamsSetupClientCredentialsEC` (see Step 4a and
|
|
261
|
+
"Populating..." below), register the Experience Cloud site that should back the Teams integration:
|
|
262
|
+
|
|
263
|
+
```text
|
|
264
|
+
mcp__headless-360__dispatch(
|
|
265
|
+
method: "POST",
|
|
266
|
+
url: "/services/data/v67.0/connect/service-itsm-teams/graph-api/extensions",
|
|
267
|
+
body: { "siteUrlPathPrefixes": ["<site urlPathPrefix from GET /connect/communities>"] }
|
|
268
|
+
)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Update later with:
|
|
272
|
+
```text
|
|
273
|
+
mcp__headless-360__dispatch(
|
|
274
|
+
method: "PATCH",
|
|
275
|
+
url: "/services/data/v67.0/connect/service-itsm-teams/graph-api/extensions/{extensionId}",
|
|
276
|
+
body: { "siteUrlPathPrefixes": ["<updated prefix list>"] }
|
|
277
|
+
)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
If this returns `400 UNKNOWN_EXCEPTION "...external credential \"MSTeamsSetupClientCredentialsEC\"
|
|
281
|
+
might not exist"`, the Azure/Entra step (Gotchas) has not been completed yet — this is not a bug
|
|
282
|
+
in the call itself.
|
|
283
|
+
|
|
284
|
+
If instead it returns `AccessDenied` (or `400 UNKNOWN_EXCEPTION "Exception while creating Teams
|
|
285
|
+
extension: Unable to fetch tenant ID"`) **even after** the external credential shows
|
|
286
|
+
`authenticationStatus: "Configured"`, the cause is almost always the **Azure app's Graph
|
|
287
|
+
permissions being of type _Delegated_ rather than _Application_** (client-credentials token flow
|
|
288
|
+
cannot use delegated-only permissions). This is a **fixable Azure/Entra misconfiguration, not a
|
|
289
|
+
hard license wall** — verified live this session: the same call went from `AccessDenied` to
|
|
290
|
+
`201 Success` (`com_sf_itsm_teams_config`) after two changes on the Azure side, with no license
|
|
291
|
+
change:
|
|
292
|
+
|
|
293
|
+
1. In the Azure app registration → **API permissions**, ensure the Microsoft Graph permissions are
|
|
294
|
+
the **Application** type (not Delegated), then click **"Grant admin consent"** for the tenant.
|
|
295
|
+
2. **Repopulate the credential** (see "Populating..." below) — re-provisioning or any feature
|
|
296
|
+
re-enable can leave the EC/Auth Provider empty; a freshly-populated `MSTeamsSetupClientCredentialsEC`
|
|
297
|
+
showing `authenticationStatus: "Configured"` is required at the moment of the retry.
|
|
298
|
+
|
|
299
|
+
Retry Step 5 after both. Only treat this as a genuine org-license blocker (the `MsTeamsAppApiFamily`
|
|
300
|
+
gotcha below) if the call **still** fails once Application-type Graph permissions + admin consent
|
|
301
|
+
are confirmed and the credential is freshly `Configured`.
|
|
302
|
+
|
|
303
|
+
Once you have the Azure Client ID and Tenant ID (given in chat) and the Client Secret (read from the
|
|
304
|
+
`TEAMS_ENTRA_CLIENT_SECRET` env var / secret file — never requested in chat; Step 4a), do the
|
|
305
|
+
Salesforce-side writes yourself — do not tell the user to enter values in Setup. The full verified
|
|
306
|
+
recipe (populating `MSTeamsSetupClientCredentialsEC`, populating the `microsoft_auth_provider` Auth
|
|
307
|
+
Provider for inbound SSO via the Metadata API, matching the portal user's `Username` to the Microsoft
|
|
308
|
+
UPN so `MsTeamsItsmSSOHandler` resolves them, and granting the portal user `ApiEnabled` for the Teams
|
|
309
|
+
Connect APIs) — with exact API bodies, the AuthProvider MDAPI template, the Web-vs-SPA callback
|
|
310
|
+
constraint, and their gotchas — is in:
|
|
311
|
+
|
|
312
|
+
**→ `references/azure-credential-population.md`**
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Completion contract — do NOT report Teams setup "complete" until all of these hold
|
|
317
|
+
|
|
318
|
+
The Go-feature enable (Steps 1–3) is necessary but **not sufficient**. The single most common
|
|
319
|
+
failure mode is declaring Teams "configured/done/complete" after Step 3 while the Microsoft Entra
|
|
320
|
+
app is still unregistered — which leaves in-Teams sign-in and the outbound Graph integration
|
|
321
|
+
**broken**. Treat the Entra app registration as a **blocking prerequisite of completion**, never an
|
|
322
|
+
optional tail. Report **complete only when every item below is verified** (not merely instructed):
|
|
323
|
+
|
|
324
|
+
1. **Feature enabled** — `service-cloud-itsm-teams-integration` reads `ENABLED` and
|
|
325
|
+
`ITSMTeamsEnabled` reads `true` (Steps 1–3).
|
|
326
|
+
2. **Microsoft Entra app registered** — the user has completed Step 4a's Azure clicks and provided
|
|
327
|
+
the Client ID and Tenant ID (in chat) with the Client Secret placed in the
|
|
328
|
+
`TEAMS_ENTRA_CLIENT_SECRET` env var / secret file (never pasted in chat). Until they do, **stop
|
|
329
|
+
and wait** — this is a hard gate; you cannot proceed past it, and you must not report completion
|
|
330
|
+
around it.
|
|
331
|
+
3. **Credentials populated (Salesforce-side, automated by this skill)** — `MSTeamsSetupClientCredentialsEC`
|
|
332
|
+
reads `authenticationStatus: "Configured"` **and** the `microsoft_auth_provider` Auth Provider is
|
|
333
|
+
populated with the same values (see `references/azure-credential-population.md`). Populating only
|
|
334
|
+
one leaves either outbound Graph or inbound SSO broken.
|
|
335
|
+
4. **Admin consent granted** — the user has clicked the static consent link in Step 4a item 3,
|
|
336
|
+
signed in as a Microsoft tenant admin.
|
|
337
|
+
5. **Preferred site registered** — the Teams extension call in Step 5 returns success (or the user
|
|
338
|
+
has explicitly deferred the employee-site half).
|
|
339
|
+
|
|
340
|
+
If any of 2–4 is pending, the correct status is **"Blocked on Microsoft-admin action — Teams
|
|
341
|
+
integration incomplete,"** with the exact next step called out. A partial state is **not** a
|
|
342
|
+
success; do not soften it, and do not let a coordinator mark this feature `Done`.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Disabling (if requested)
|
|
347
|
+
|
|
348
|
+
```text
|
|
349
|
+
mcp__headless-360__dispatch(
|
|
350
|
+
method: "POST",
|
|
351
|
+
url: "/services/data/v67.0/connect/setup/discovery/feature/service-cloud-itsm-teams-integration/disable",
|
|
352
|
+
body: {}
|
|
353
|
+
)
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Re-run Step 1/Step 3 afterward to confirm. Disabling `ITSMTeamsEnabled`'s underlying
|
|
357
|
+
provisioning (SSO handler, named/external credentials, PKCE OAuth client) may not be fully
|
|
358
|
+
reversed by this call alone — verify with the user whether they also need those artifacts
|
|
359
|
+
removed and treat that as a separate, manual Setup exercise.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Related, separately-enabled preferences
|
|
364
|
+
|
|
365
|
+
Two sibling org preferences drive the "Fulfiller Hub" and "Employee Hub" halves of this feature
|
|
366
|
+
and, unlike `ITSMTeamsEnabled`, **are** directly writable via the standard Setup preferences
|
|
367
|
+
Connect API — `GET/PATCH /services/data/v67.0/setup/org/preferences/OrgHasITSMFulfillerTeams`
|
|
368
|
+
("Enable Salesforce IT Desk") and `.../OrgHasEmployeeServiceTeams` ("Enable Salesforce IT
|
|
369
|
+
Service"). Both take `{"desiredState": true}` and return `{"isPreferenceEnabled": true}`. They are
|
|
370
|
+
independent bits — enabling them does **not** unblock `ITSMTeamsEnabled`; enable them alongside,
|
|
371
|
+
not instead of, the Step 2 feature-enable call if the user wants both Hubs.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Gotchas
|
|
376
|
+
|
|
377
|
+
The verified, load-bearing pitfalls (direct-PATCH 401, empty Auth Provider, Azure Web-vs-SPA
|
|
378
|
+
redirect, Username=UPN handler, portal API-Enabled, static consent link, `MsTeamsAppApiFamily`
|
|
379
|
+
403 hard gate, version-prefix requirement, and more) are catalogued in
|
|
380
|
+
[`references/gotchas.md`](references/gotchas.md). Read it before reporting a step as failed or
|
|
381
|
+
retrying an enablement guess.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Related Skills
|
|
386
|
+
|
|
387
|
+
| Skill | When to use instead |
|
|
388
|
+
|-------|---------------------|
|
|
389
|
+
| `service-itsm-teams-itdesk-configure` | The "Set Up Salesforce IT Desk" checklist group (fulfiller side) — this skill delegates to it (see Step 4b) |
|
|
390
|
+
| `service-itsm-teams-itservice-configure` | The "Set Up Salesforce IT Service" checklist group (employee side) — this skill delegates to it (see Step 4b) |
|
|
391
|
+
| `service-itsm-teams-employee-agent-configure` | Making the embedded Agentforce agent reply in the Teams "Ask AI Agent" custom client (`Teams_AgentForce` MIAW deployment) — this skill delegates to it (see Step 4c) |
|
|
392
|
+
| `service-itsm-swarming-configure` | Enabling the `service-cloud-swarming` Go feature for "Set Teams as Collaboration Tool for Swarming" — invoked by `service-itsm-teams-itdesk-configure`, not by this skill directly |
|
|
393
|
+
| Notification-channel preferences | Enabling the `Notifications`/`TeamsNotifications` preferences is a distinct concern from this feature (no dedicated child skill exists yet) |
|
|
394
|
+
| `experience-portal-create` | Creating the employee-service portal/site itself |
|
|
395
|
+
| `service-itsm-channels-coordinate` | Top-level menu across Teams, Slack, Swarming, Notifications, Portal |
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Populating the Azure credentials, inbound SSO, and portal-user access (Step 5 detail)
|
|
2
|
+
|
|
3
|
+
Reference for `service-itsm-teams-configure` Step 5. Once the org has an external credential named
|
|
4
|
+
`MSTeamsSetupClientCredentialsEC` and the user has supplied their Azure **Client ID** and **Tenant
|
|
5
|
+
ID** (non-secret identifiers, given in chat) and placed the **Client Secret** in the
|
|
6
|
+
`TEAMS_ENTRA_CLIENT_SECRET` environment variable or a gitignored secret file (Step 4a — **never ask
|
|
7
|
+
for the secret in chat**), these are the Salesforce-side writes that populate the outbound Graph
|
|
8
|
+
credential, the inbound-SSO Auth Provider, and the portal-user access that make the Teams IT Service
|
|
9
|
+
/ IT Desk apps actually work. Read the secret from that env var / file at write time; never print,
|
|
10
|
+
echo, or log its value, and never send the literal `$TEAMS_ENTRA_CLIENT_SECRET` token to an API —
|
|
11
|
+
always resolve it to its actual value first (see the Secret-substitution note in Step 2). Do all of
|
|
12
|
+
these yourself — the user's manual responsibility ends at the Azure admin center.
|
|
13
|
+
|
|
14
|
+
## Populating `MSTeamsSetupClientCredentialsEC` given a user-supplied client ID/secret
|
|
15
|
+
|
|
16
|
+
**Once the user supplies the Client ID and Tenant ID (in chat) and the Client Secret is available in
|
|
17
|
+
the `TEAMS_ENTRA_CLIENT_SECRET` env var / secret file (Step 4a — never in chat), write them into
|
|
18
|
+
Salesforce yourself via the calls below. Do not respond by telling the user to open Setup and enter
|
|
19
|
+
the values manually — that defeats the purpose of this skill.** The user's manual responsibility
|
|
20
|
+
ends at the Azure admin center (Step 4a); every Salesforce-side write, including this one, is this
|
|
21
|
+
skill's job.
|
|
22
|
+
|
|
23
|
+
1. Fix the `AuthProviderUrl` parameter (it ships with a literal `{tenant_id}` placeholder):
|
|
24
|
+
```text
|
|
25
|
+
mcp__headless-360__dispatch(
|
|
26
|
+
method: "PUT",
|
|
27
|
+
url: "/services/data/v67.0/named-credentials/external-credentials/MSTeamsSetupClientCredentialsEC",
|
|
28
|
+
body: { /* GET the record first, then re-PUT its full parameters[]/principals[] with
|
|
29
|
+
AuthProviderUrl set to https://login.microsoftonline.com/<tenant id>/oauth2/v2.0/token */ }
|
|
30
|
+
)
|
|
31
|
+
```
|
|
32
|
+
This endpoint is full-replace — GET the EC first and mutate, don't send a partial body.
|
|
33
|
+
2. Set the principal's client ID + secret (both required together in one call; there is no
|
|
34
|
+
partial-update path for just the client ID):
|
|
35
|
+
**Secret substitution — read this first.** `mcp__headless-360__dispatch` is a JSON API call, **not
|
|
36
|
+
a shell**: it does **not** expand `$TEAMS_ENTRA_CLIENT_SECRET`. Passing the literal string
|
|
37
|
+
`"$TEAMS_ENTRA_CLIENT_SECRET"` in the body stores that literal text as the OAuth client secret and
|
|
38
|
+
Graph authentication then fails after an apparently-successful configuration. You must resolve the
|
|
39
|
+
env var to its **actual value** and place that value into `clientSecret.value` at call time. Read it
|
|
40
|
+
with a **non-logging** read (e.g. a single `printenv TEAMS_ENTRA_CLIENT_SECRET` captured into an
|
|
41
|
+
in-memory variable, or read the secret file) — never `echo`/print it, never place the resolved
|
|
42
|
+
secret in any text you emit to the user or into a log, and never write it to disk. The `<secret
|
|
43
|
+
value read from $TEAMS_ENTRA_CLIENT_SECRET>` placeholder below denotes that resolved value, not a
|
|
44
|
+
literal to send:
|
|
45
|
+
```text
|
|
46
|
+
mcp__headless-360__dispatch(
|
|
47
|
+
method: "POST", // or PUT (update-credential) if credentials already exist for this principal
|
|
48
|
+
url: "/services/data/v67.0/named-credentials/credential",
|
|
49
|
+
body: {
|
|
50
|
+
"externalCredential": "MSTeamsSetupClientCredentialsEC",
|
|
51
|
+
"principalName": "NamedAuthPrincipal",
|
|
52
|
+
"principalType": "NamedPrincipal",
|
|
53
|
+
"authenticationProtocol": "OAuth",
|
|
54
|
+
"authenticationProtocolVariant": "ClientCredentialsClientSecretBasic",
|
|
55
|
+
// clientSecret.value MUST be the resolved secret read from the TEAMS_ENTRA_CLIENT_SECRET env
|
|
56
|
+
// var / secret file — NOT the literal "$TEAMS_ENTRA_CLIENT_SECRET" token (dispatch does not
|
|
57
|
+
// expand shell variables). Resolve in memory via a non-logging read; never echo it.
|
|
58
|
+
"credentials": { "clientId": {"value": "<client id>"}, "clientSecret": {"value": "<secret value read from $TEAMS_ENTRA_CLIENT_SECRET>"} }
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
```
|
|
62
|
+
3. Verify: `GET /services/data/v67.0/named-credentials/external-credentials/MSTeamsSetupClientCredentialsEC`
|
|
63
|
+
should show `authenticationStatus: "Configured"`.
|
|
64
|
+
4. If `MSTeamsSetupAutomationAccess` (the EC principal's access-gating permission set) is
|
|
65
|
+
unassigned for the running user, assign it via `POST /services/data/v67.0/sobjects/PermissionSetAssignment`
|
|
66
|
+
(`AssigneeId`, `PermissionSetId`) before retrying Step 5 — it auto-provisions but is not
|
|
67
|
+
auto-assigned.
|
|
68
|
+
|
|
69
|
+
## Populating the `microsoft_auth_provider` Auth Provider (inbound SSO — do NOT skip)
|
|
70
|
+
|
|
71
|
+
Enabling the Teams feature also provisions a Microsoft-type **Auth Provider** named
|
|
72
|
+
`microsoft_auth_provider` (Setup → Identity → Auth Providers), left **empty** (no Consumer Key,
|
|
73
|
+
Consumer Secret, or endpoint URLs). This is the **inbound SSO** side — it authenticates employees
|
|
74
|
+
logging into the Experience Cloud portal that the Teams IT Service app embeds. It is a *separate
|
|
75
|
+
artifact* from the outbound-Graph `MSTeamsSetupClientCredentialsEC` Named Credential, but takes the
|
|
76
|
+
**same three values** the user supplied (secret from the env var / file, never chat). Populate it automatically in the same pass — a previous run
|
|
77
|
+
of this skill forgot this step, leaving portal SSO login broken even though the Named Credential
|
|
78
|
+
was configured.
|
|
79
|
+
|
|
80
|
+
**Key constraint (verified):** `AuthProvider.ConsumerSecret` is `createable` but **NOT
|
|
81
|
+
`updateable`** on the SObject — so `sf data update` / a Connect PATCH **cannot** set the secret on
|
|
82
|
+
the already-provisioned (empty) record, and headless-360 `discover` exposes **no** Connect route
|
|
83
|
+
that writes an Auth Provider secret. The working path is the **Metadata API**: `AuthProvider` is a
|
|
84
|
+
full MDAPI type whose `<consumerSecret>` round-trips on deploy. Author a source-format file and
|
|
85
|
+
deploy it (this sets every field, including the secret, with no UI):
|
|
86
|
+
|
|
87
|
+
```xml
|
|
88
|
+
<!-- force-app/main/default/authproviders/microsoft_auth_provider.authprovider-meta.xml -->
|
|
89
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
90
|
+
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
91
|
+
<authorizeUrl>https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/authorize</authorizeUrl>
|
|
92
|
+
<consumerKey><CLIENT_ID></consumerKey>
|
|
93
|
+
<consumerSecret>${TEAMS_ENTRA_CLIENT_SECRET}</consumerSecret>
|
|
94
|
+
<defaultScopes>openid profile email offline_access https://graph.microsoft.com/.default</defaultScopes>
|
|
95
|
+
<friendlyName>microsoft_auth_provider</friendlyName>
|
|
96
|
+
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
|
|
97
|
+
<providerType>Microsoft</providerType>
|
|
98
|
+
<sendAccessTokenInHeader>true</sendAccessTokenInHeader>
|
|
99
|
+
<sendClientCredentialsInHeader>false</sendClientCredentialsInHeader>
|
|
100
|
+
<tokenUrl>https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token</tokenUrl>
|
|
101
|
+
</AuthProvider>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
sf project deploy start --source-dir force-app --target-org <org-alias>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Secret handling:** substitute `<TENANT_ID>` / `<CLIENT_ID>` (non-secret) directly, but inject the
|
|
109
|
+
`<consumerSecret>` value from `$TEAMS_ENTRA_CLIENT_SECRET` at build time (e.g. `envsubst` into a
|
|
110
|
+
gitignored temp copy under a scratch dir, deploy that, then delete it). **Never commit the populated
|
|
111
|
+
file** and never echo the secret. The secret comes from the env var / secret file — not from chat.
|
|
112
|
+
|
|
113
|
+
Notes:
|
|
114
|
+
- Use the **tenant-specific** `/…/<TENANT_ID>/oauth2/v2.0/…` endpoints, not `/common/` or
|
|
115
|
+
`/organizations/` — single-tenant Azure apps reject the generic endpoints.
|
|
116
|
+
- `--metadata-dir` (MDAPI format) proved flaky here ("named in package.xml but not found in zipped
|
|
117
|
+
directory"); the **source-format `--source-dir` deploy is the reliable route** — include a minimal
|
|
118
|
+
`sfdx-project.json` with `sourceApiVersion`.
|
|
119
|
+
- `<executionUser>` is optional for a Microsoft SSO Auth Provider (only needed when a registration
|
|
120
|
+
handler runs Apex); it may not bind on deploy and that is fine.
|
|
121
|
+
- **Verify** with `sf data query "SELECT ConsumerKey, AuthorizeUrl, TokenUrl, DefaultScopes FROM
|
|
122
|
+
AuthProvider WHERE DeveloperName = 'microsoft_auth_provider'"`. The **Consumer Secret is
|
|
123
|
+
write-only and will not read back** — a null secret in the query is expected, not a failure;
|
|
124
|
+
confirm the ConsumerKey and URLs populated.
|
|
125
|
+
- **After populating, give the user the Auth Provider's Callback URL to register in Azure.** (The
|
|
126
|
+
callback URL is not a secret.) The redirect URI the Azure app must trust is the OAuth callback endpoint on the org's My
|
|
127
|
+
Domain: `https://<my-domain>/services/authcallback/microsoft_auth_provider` (get `<my-domain>` from
|
|
128
|
+
`sf org display --json` → `instanceUrl`, or read the "OAuth-Only Initialization URL" from the Auth
|
|
129
|
+
Provider's Salesforce Configuration section in Setup). This is a **manual Azure step** — no
|
|
130
|
+
Salesforce API reaches Azure — so paste the exact URL and tell the user: **portal.azure.com → the
|
|
131
|
+
app registration → Authentication → add a platform → *Web* → add this Redirect URI → Save.**
|
|
132
|
+
- **Register the redirect URI under the "Web" platform, NOT "Single-page application" (SPA) — verified.**
|
|
133
|
+
This Auth Provider is a **confidential client**: it does a server-side token exchange using the
|
|
134
|
+
ConsumerSecret. Azure rejects secret-based token requests against a redirect URI registered as SPA,
|
|
135
|
+
so if the callback is added under the SPA platform the login *appears* to start (Salesforce even logs
|
|
136
|
+
a `LoginHistory` "Success" and mints `OauthToken` rows) but the callback round-trip fails at
|
|
137
|
+
`.../services/authcallback/microsoft_auth_provider` with **`OAUTH_APPROVAL_ERROR_GENERIC`**. Moving
|
|
138
|
+
the same redirect URI from the SPA platform to the Web platform in the Azure app fixes it. When you
|
|
139
|
+
emit the callback URL, explicitly tell the user it must go under **Web**, not SPA.
|
|
140
|
+
- Optionally also give the Single Logout URL (`https://<my-domain>/services/auth/rp/oidc/logout`) for
|
|
141
|
+
the app's Front-channel logout URL. Without the redirect URI registered on the Azure side, portal SSO
|
|
142
|
+
login fails with a redirect-mismatch error even though the Auth Provider is fully populated.
|
|
143
|
+
|
|
144
|
+
## Making a portal user resolvable to the signed-in Microsoft user (Username = MS email — verified)
|
|
145
|
+
|
|
146
|
+
Populating the Auth Provider and its callback is not enough for a person to actually log into the
|
|
147
|
+
embedded Experience Cloud portal from the Teams IT Service (Employee) or IT Desk app. When a user
|
|
148
|
+
signs in through Microsoft, a custom Apex registration handler bound to `microsoft_auth_provider` —
|
|
149
|
+
**`MsTeamsItsmSSOHandler`** (Core module `service-itsm-teams-impl`) — resolves *which* Salesforce user
|
|
150
|
+
they are. Its logic (verified against Core source):
|
|
151
|
+
|
|
152
|
+
```apex
|
|
153
|
+
global boolean canCreateUser(Auth.UserData data) { return false; } // no JIT
|
|
154
|
+
global User createUser(Id portalId, Auth.UserData data) {
|
|
155
|
+
String loginValue = data.email; // the Microsoft email/UPN claim
|
|
156
|
+
List<User> users = [SELECT Id FROM User WHERE Username = :loginValue LIMIT 2];
|
|
157
|
+
if (users.isEmpty() || users.size() > 1) return null; // 0 or >1 match → no login
|
|
158
|
+
return users[0];
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
So the **Microsoft `email`/UPN claim must exactly equal a Salesforce `User.Username`** — not
|
|
163
|
+
`User.Email`, not `FederationIdentifier`. Exactly one active user must match; zero matches or a
|
|
164
|
+
duplicate both return `null`, and the app then shows **"you don't have access to the Microsoft account
|
|
165
|
+
in Salesforce."** There is **one handler / one Microsoft Auth Provider for the whole module** — both
|
|
166
|
+
the IT Service (Employee) and IT Desk (Fulfiller) apps use it; the Employee-vs-Fulfiller split lives
|
|
167
|
+
only in notification/adaptive-card routing, never in user resolution.
|
|
168
|
+
|
|
169
|
+
**Do this automatically** (this is a Salesforce-side write — do not defer it to the user): once you
|
|
170
|
+
know the Microsoft UPN the person signs in with, ensure the intended portal user's `Username` equals
|
|
171
|
+
it. First confirm no other user already holds that Username (a duplicate breaks the match too), then
|
|
172
|
+
set it via `PATCH /services/data/v67.0/sobjects/User/<userId>` body `{"Username": "<ms-upn>"}`. In this
|
|
173
|
+
session the empPortal user's Username was renamed to the tenant UPN (e.g. `admin@<tenant>.onmicrosoft.com`)
|
|
174
|
+
and login then resolved. Note UEL "Unified Employee" users are `UserType=Standard` internal users added
|
|
175
|
+
directly as Experience Cloud `NetworkMember`s (ContactId can be null) — they are **not** external
|
|
176
|
+
CspLitePortal users; the Username-match rule is the same regardless.
|
|
177
|
+
|
|
178
|
+
## Granting the portal user API Enabled for the Teams Connect APIs (verified)
|
|
179
|
+
|
|
180
|
+
Even with SSO resolving correctly, the Teams IT Service (Employee) app calls Connect (Chatter) APIs
|
|
181
|
+
on the embedded portal — e.g.
|
|
182
|
+
`/empPortal/services/data/v66.0/connect/it-service/permissions/EmployeeApp?networkId=<networkId>`.
|
|
183
|
+
If the signed-in user lacks the **API Enabled** user permission, these calls fail with
|
|
184
|
+
**`API_DISABLED_FOR_ORG`** ("...or user type") and the browser Network tab shows **403 Forbidden** —
|
|
185
|
+
the app UI then fails to load its data even though login itself succeeded.
|
|
186
|
+
|
|
187
|
+
The managed permission sets the child skills assign (`TeamsForEmployeeUser`, `EmployeeHubEmployeeUser`)
|
|
188
|
+
do **not** grant `ApiEnabled`, and being managed-package permission sets they **cannot be edited** — a
|
|
189
|
+
Metadata API retrieve reports "cannot be found" and a direct SObject PATCH fails with "invalid record
|
|
190
|
+
id." The working fix is to **create a new *unmanaged* permission set with `ApiEnabled` only, deploy it,
|
|
191
|
+
and assign it** to the portal user. Do this yourself (Salesforce-side write):
|
|
192
|
+
|
|
193
|
+
```xml
|
|
194
|
+
<!-- force-app/main/default/permissionsets/Teams_Employee_ApiAccess.permissionset-meta.xml -->
|
|
195
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
196
|
+
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
197
|
+
<label>Teams Employee API Access</label>
|
|
198
|
+
<description>Grants API Enabled to Unified Employee users so the MS Teams IT Service/Employee app can call Connect APIs. Added during ITSM Teams setup.</description>
|
|
199
|
+
<hasActivationRequired>false</hasActivationRequired>
|
|
200
|
+
<userPermissions><enabled>true</enabled><name>ApiEnabled</name></userPermissions>
|
|
201
|
+
</PermissionSet>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
sf project deploy start --source-dir force-app --target-org <org-alias>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Then assign it: `POST /services/data/v67.0/sobjects/PermissionSetAssignment` with `AssigneeId` (the
|
|
209
|
+
portal user) and `PermissionSetId` (the new set). **Grant `ApiEnabled` only — do NOT also add
|
|
210
|
+
`ChatterInternalUser`:** the Unified Employee license permits `ApiEnabled` but forbids
|
|
211
|
+
`ChatterInternalUser`, and including it makes the whole assignment fail with "user license doesn't allow
|
|
212
|
+
the permission: ChatterInternalUser." Verify with a query on `PermissionSet` /
|
|
213
|
+
`PermissionSetAssignment` (`PermissionsApiEnabled = true`).
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Gotchas — Microsoft Teams for Employee Service (ITSM) feature enablement
|
|
2
|
+
|
|
3
|
+
Verified, load-bearing pitfalls encountered enabling the Teams ITSM feature and wiring the
|
|
4
|
+
Azure/Entra app, Named Credential, Auth Provider, and portal user. Read these before reporting a
|
|
5
|
+
step as failed or retrying an enablement guess.
|
|
6
|
+
|
|
7
|
+
| Issue | Detail |
|
|
8
|
+
|-------|--------|
|
|
9
|
+
| Direct `PATCH /setup/org/preferences/ITSMTeamsEnabled` | Always `401 INSUFFICIENT_ACCESS`. Do not retry this route — use the feature-enable API instead. |
|
|
10
|
+
| `/enable` call returns `500 INTERNAL_ERROR` | Can still succeed. Always re-check `features/status` and the preference read before concluding failure. |
|
|
11
|
+
| `OrgHasITSMFulfillerTeams` / `OrgHasEmployeeServiceTeams` do not gate `ITSMTeamsEnabled` | These are separate Hub-visibility bits; enabling them does not itself unblock the Teams Salesforce Go page toggle preference. |
|
|
12
|
+
| `microsoft_auth_provider` Auth Provider must be populated too (easy to forget) | Enabling the feature provisions an **empty** Microsoft Auth Provider (`microsoft_auth_provider`) for inbound portal SSO — separate from the `MSTeamsSetupClientCredentialsEC` Named Credential but needing the **same** Client ID/Tenant ID/Client Secret. `AuthProvider.ConsumerSecret` is **not `updateable`** (so `sf data update`/Connect PATCH can't set it) and no headless-360 route writes it — populate via **Metadata API source-format deploy** (`sf project deploy start --source-dir`, `<consumerSecret>` round-trips). See "Populating the `microsoft_auth_provider` Auth Provider" under Step 5. Skipping this leaves portal login broken even with the Named Credential configured. |
|
|
13
|
+
| Azure redirect URI must be under the **Web** platform, not SPA | The `microsoft_auth_provider` Auth Provider is a **confidential client** (server-side token exchange using the ConsumerSecret). Azure rejects secret-based token requests against a redirect URI registered as **Single-page application (SPA)**. Symptom: login *appears* to start (Salesforce logs `LoginHistory` "Success" and mints `OauthToken` rows) but the callback fails at `.../services/authcallback/microsoft_auth_provider` with **`OAUTH_APPROVAL_ERROR_GENERIC`**. Fix (verified): register the callback URI under the Azure app's **Web** platform, not SPA. When emitting the callback URL to the user, always say **Web**. See the callback-URL note under "Populating the `microsoft_auth_provider` Auth Provider." |
|
|
14
|
+
| Portal login "you don't have access to the Microsoft account in Salesforce" → Username must equal the MS email/UPN | A custom Apex registration handler **`MsTeamsItsmSSOHandler`** (Core `service-itsm-teams-impl`, bound to `microsoft_auth_provider`) resolves the signed-in Microsoft user by `SELECT Id FROM User WHERE Username = :data.email` — the **Microsoft `email`/UPN claim must exactly equal a Salesforce `User.Username`** (not `User.Email`, not `FederationIdentifier`); `canCreateUser` returns false (no JIT), and 0 or >1 matches both return null → login denied. **One handler serves BOTH the IT Service (Employee) and IT Desk (Fulfiller) apps.** Fix (verified): set the intended portal user's `Username` to the MS UPN (after confirming no duplicate) via `PATCH .../sobjects/User/<id>` `{"Username":"<ms-upn>"}`. See "Making a portal user resolvable..." under Step 5. |
|
|
15
|
+
| Portal Connect API `API_DISABLED_FOR_ORG` / 403 → user needs API Enabled | The Teams IT Service (Employee) app calls Connect APIs on the embedded portal (e.g. `/connect/it-service/permissions/EmployeeApp`); without the **API Enabled** user permission these return `API_DISABLED_FOR_ORG` (403 in the Network tab) and the app fails to load data despite a successful login. The managed permission sets (`TeamsForEmployeeUser`, `EmployeeHubEmployeeUser`) don't grant `ApiEnabled` and **can't be edited** (managed-package: MDAPI retrieve "cannot be found", SObject PATCH "invalid record id"). Fix (verified): create + deploy a new **unmanaged** permission set with `ApiEnabled` only and assign it. **Do not add `ChatterInternalUser`** — the Unified Employee license forbids it (assignment fails "user license doesn't allow the permission: ChatterInternalUser"). See "Granting the portal user API Enabled..." under Step 5. |
|
|
16
|
+
| Azure/Entra app registration + admin consent have no Salesforce API | Salesforce only exposes a consent URL via an internal Aura controller (no public REST contract) — the user must click through the Azure admin center themselves. Give them the exact steps in Step 4a rather than a vague pointer, and once they provide the Client ID/Tenant ID (in chat) with the Client Secret in the `TEAMS_ENTRA_CLIENT_SECRET` env var / secret file (**never request the secret in chat**), take over immediately and write the credential into Salesforce yourself (see "Populating `MSTeamsSetupClientCredentialsEC`..." under Step 5) — do not tell them to enter it manually in Setup. |
|
|
17
|
+
| Go page's real checklist order (verified from a live screenshot) | The "Integrate Salesforce with Teams" group on the feature's Go page has exactly 3 items, in this order: **Create Microsoft Entra ID App** → **Configure Setup Named Credentials** → **Grant Azure Administrator Consent**. This is a *separate* checklist group from "Set Up Salesforce IT Desk" / "Set Up Salesforce IT Service" (delegated to `service-itsm-teams-itdesk-configure` / `service-itsm-teams-itservice-configure`) — do not conflate the groups when reporting progress to the user. |
|
|
18
|
+
| "Grant Azure Administrator Consent" consent link is static, not per-org | Clicking "Grant Consent" on the Go page opens a modal with this exact link: `https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=cd6bd63f-41ef-47cc-9465-86e986179a29&response_type=code&redirect_uri=https://salesforce.com&response_mode=query&scope=Organization.ReadWrite.All`. The `client_id` here is Salesforce's own multi-tenant Entra app (**not** the app the user registers in step 1, and **not** related to the Client ID/Secret that go into the Named Credential) — it requests `Organization.ReadWrite.All` from whichever Microsoft tenant the signed-in admin belongs to (`organizations` tenant segment, not a specific tenant ID). headless-360 has no operation that generates this link or reads the Go page's live checklist state (searched `discover` for "grant Azure administrator consent generate consent URL" and "guided setup checklist progress Salesforce Go" — no matching SOR) — paste the link above verbatim and tell the user to click it themselves, signed in as a Microsoft tenant admin. |
|
|
19
|
+
| `preferredSite` / Teams extension registration **is** a public Connect API (verified) — corrects an earlier assumption | `POST /services/data/v67.0/connect/service-itsm-teams/graph-api/extensions` body `{"siteUrlPathPrefixes": ["<site urlPathPrefix>"]}` registers the Experience Cloud site as the Teams extension target; `PATCH .../extensions/{extensionId}` updates it. Verified live: it dispatches and reaches real logic (not a stub) — it fails with `400 UNKNOWN_EXCEPTION "We couldn't access the credential(s)... external credential \"MSTeamsSetupClientCredentialsEC\" might not exist"` until the Azure/Entra app registration is done and that named/external credential is wired up in Setup. Once the credential exists, call this to complete preferred-site selection — do not treat it as Aura-only. |
|
|
20
|
+
| `service-itsm-teams-connect-api` SOR (headless-360 `discover`) | Also exposes `get-teams-get-teams-list`, `get-teams-get-channel-list`, `post-teams-channel-message-send`, `get-teams-get-permissions`, `get-service-itsm-teams-collaboration-app-settings` (valid `targetApplication` values are `TeamsFulfillerApp` / `TeamsEmployeeApp`, not `teams`) — useful for verifying end-to-end Teams connectivity after the manual tail is complete. |
|
|
21
|
+
| `ms-teams-app-connect-api` (`/connect/ms-teams-app/tenant-config`) gates Step 5 and has **no known unlock path** | `GET`/`PUT`/`DELETE` all return `403 FUNCTIONALITY_NOT_ENABLED [MsTeamsAppApiFamily]`, even after `service-cloud-itsm-teams-integration` is enabled and `MSTeamsSetupClientCredentialsEC` is fully configured. **Verified this is the same blocker as Step 5's "Unable to fetch tenant ID" error** — `post-teams-extension`/`patch-teams-extension-update` internally depend on this tenant-config lookup. Checked and ruled out: (a) no Go feature-enablement API name unlocks it — tried `ms-teams-app`, `ms-teams-app-integration`, `microsoft-teams-app-integration`, `teams-app-connect-api`, `msteams-app-api`, `service-cloud-ms-teams-app-api`, `MsTeamsAppApiFamily` itself, all `400 NOT_FOUND "Could not find the requested feature"`; (b) no `PermissionSetLicense` among all 112 in the org grants it — only `TeamsForEmployeePsl`/`TeamsForITSrvcsPsl` relate to Teams, and neither gates this family. This appears to be a hard org/edition-level license gate with no self-service unlock via headless-360 — if a user hits this, Step 5 cannot be completed in this org; do not keep retrying enablement guesses. |
|
|
22
|
+
| A `MSTeamsSetupAutomationAccess` ("Automate Microsoft Teams Setup") permission set also auto-provisions | Was unassigned in this session — assign it to the Setup admin driving this flow if further automation steps need it. (The IT Desk/IT Service checklist permission sets — `TeamsForITSrvcsUser`, `TeamsForEmployeeUser`, `MicrosoftGraphAccess` — are documented in the child skills.) |
|
|
23
|
+
| Version prefix required | headless-360 `dispatch`/`dispatch_readonly` do not resolve API versions — always pass the full `/services/data/vXX.0/...` prefix. |
|