@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,253 @@
|
|
|
1
|
+
# Portal Templates Reference
|
|
2
|
+
|
|
3
|
+
This document describes how to choose the framework and template for a Digital Experience portal.
|
|
4
|
+
|
|
5
|
+
## Framework: always Experience Builder (Aura or LWR), never Visualforce
|
|
6
|
+
|
|
7
|
+
Experience Cloud sites come in two families:
|
|
8
|
+
|
|
9
|
+
- **Experience Builder sites** — built on **Aura** or **LWR** (Lightning Web Runtime). These have the drag-and-drop **Builder**, modern components, branding, and responsive layouts. This is what you want in almost all cases.
|
|
10
|
+
- **Salesforce Tabs + Visualforce sites** (a.k.a. the legacy "VF Template") — a standard-nav + Visualforce site with **no Experience Builder**. This is legacy. Do **not** create these for new portals.
|
|
11
|
+
|
|
12
|
+
**How to tell them apart:** the Metadata API `Network.enableSiteAsContainer` field is `true` for an Experience Builder site and `false` for a Salesforce Tabs + Visualforce site. In Setup → Digital Experiences → All Sites, the **Framework** column shows `Aura`, `LWR`, or `Visualforce`, and only Builder-based sites show a **Builder** workspace link.
|
|
13
|
+
|
|
14
|
+
> The bug this reference exists to prevent: creating a portal with `templateName: "VF Template"` (Salesforce Tabs + Visualforce). It produces a Visualforce-framework site with no Builder. Use the self-service site API with `siteType: AURA`, or a `communities` API Experience Builder `templateName`.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Recommended path for employee service / ITSM / help desk portals
|
|
19
|
+
|
|
20
|
+
**Preferred (richest employee experience): the `Agentforce Employee Center` Aura template via the communities API.** This is a purpose-built employee-service portal — IT and HR ticket management, a self-service catalog, a knowledge base, enablement programs, and (optionally) an embedded **Agentforce** conversational assistant. Prefer it over the plainer `Employee Portal` / `Customer Service` templates whenever the org's live template list (`GET /connect/communities/templates`) includes `Agentforce Employee Center`.
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
mcp__headless-360__dispatch(
|
|
24
|
+
method: "POST",
|
|
25
|
+
url: "/services/data/v67.0/connect/communities",
|
|
26
|
+
body: { "name": "<portal name>", "urlPathPrefix": "<alphanumeric>", "templateName": "Agentforce Employee Center" }
|
|
27
|
+
)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The communities API takes only `{name, description, templateName, templateParams, urlPathPrefix}` — pass `Agentforce Employee Center` verbatim as `templateName`. This path needs **no** MIAW Embedded Service Deployment.
|
|
31
|
+
|
|
32
|
+
> **Two layers.** `POST /connect/communities` with `templateName: "Agentforce Employee Center"` provisions the **site** (pages, ticketing, catalog, knowledge). The **conversational assistant** is a *separate* Agentforce agent — the site alone does not create one. To add it, create the internal employee agent from its shipped template (see "Agentforce assistant" below); this skill provisions the site and points the user to that step. It does **not** activate an agent automatically.
|
|
33
|
+
|
|
34
|
+
### Alternative paths (when Agentforce Employee Center is not desired or not present)
|
|
35
|
+
|
|
36
|
+
- **MIAW at creation time + a guest ESD exists →** `POST /connect/self-service/site` with `siteType: "AURA"`. This deploys an Aura Experience Builder site and wires **MIAW** in at creation time via Embedded Service Deployment (ESD) config IDs. Key inputs: `siteName` (required); `guestEmbeddedServiceConfigId` (required) — guest MIAW ESD; `embeddedServiceConfigId` (optional) — authenticated MIAW ESD; `siteType` — `AURA` (default) or `LWR`; plus `enableForGuest`, `contentDocumentId` (logo), `brandColors` (optional).
|
|
37
|
+
- **A plainer employee portal, no Agentforce, no MIAW →** communities API with `Employee Portal` (if present), else `Customer Service` or `Help Center`. Needs no ESD.
|
|
38
|
+
|
|
39
|
+
> Note: an internal "ITSM Employee Service" seed template exists as an org/feature template for the ITSM product (associated with CMDB and the `ItSrvcDscvrMgrPsl` permission set license). That is **not** a `templateName` value for `POST /connect/communities` — do not pass it as `templateName`.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Agentforce assistant for the Employee Center (optional, separate step)
|
|
44
|
+
|
|
45
|
+
The `Agentforce Employee Center` site can host an **Agentforce** conversational assistant, but the site-create call does not build one. The agent is created from a template that ships with the org:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
mcp__headless-360__dispatch(
|
|
49
|
+
method: "PATCH",
|
|
50
|
+
url: "/services/data/v67.0/headless/invoke/einstein/genai-agentbuilder/create-copilot-from-template",
|
|
51
|
+
body: {
|
|
52
|
+
"templateNameOrId": "EmployeeCopilot__AgentforceEmployeeAgent",
|
|
53
|
+
"copilotContext": { "name": "<agent label>", "company": "<company name>", "newAgentUser": true }
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- `templateNameOrId` — `EmployeeCopilot__AgentforceEmployeeAgent` is the shipped **internal employee** agent template (the service-agent equivalent is `SvcCopilotTmpl__EinsteinServiceAgent`).
|
|
59
|
+
- `copilotContext.company` is **required** — omitting it returns `500 CONTROLLER_ERROR "Company is Mandatory in Agents"`. `companyName` is a distinct, non-substitute field.
|
|
60
|
+
- The agent is created **`Inactive`** with a v1 version; it must be activated and connected to the site's channel afterward. `newAgentUser: true` auto-provisions a runtime user.
|
|
61
|
+
- The Experience Builder AI-portal editor lists attachable agents via `GET /services/data/v67.0/headless/invoke/platform/communities/unified-aiportal-setup/get-service-agent-templates`.
|
|
62
|
+
|
|
63
|
+
> Agentforce setup (agent creation, activation, channel wiring, permissions) is broad and largely out of scope for this portal-create skill. This skill provisions the **site** and, when the user wants the conversational assistant, points them to the agent template above rather than fully configuring Agentforce.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Community Templates (`POST /connect/communities`)
|
|
68
|
+
|
|
69
|
+
The communities API accepts an Experience Builder **display name** as `templateName`. Accepted strings can vary by org edition/version — **always validate against the live list** via headless-360:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
mcp__headless-360__dispatch_readonly(method: "GET", url: "/services/data/v67.0/connect/communities/templates")
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Use a returned `templateName` verbatim. The most common Experience Builder templates:
|
|
76
|
+
|
|
77
|
+
### Agentforce Employee Center (preferred for employee service)
|
|
78
|
+
**Template name:** `Agentforce Employee Center` · **Framework:** Aura · **Publisher:** Salesforce
|
|
79
|
+
|
|
80
|
+
The richest employee-service template: **IT and HR ticket management**, a **self-service catalog**, a **knowledge base**, **enablement programs**, and an optional embedded **Agentforce** conversational assistant. This is the modern successor to the plainer `Employee Portal` / `Customer Service` experiences for internal help desks. Not Visualforce (`siteAsContainerEnabled = true`).
|
|
81
|
+
|
|
82
|
+
**Use when:** Building an employee service / IT help desk / HR service portal and the org's live template list (`GET /connect/communities/templates`) includes `Agentforce Employee Center`. Prefer it over `Employee Portal` and `Customer Service` for this use case.
|
|
83
|
+
|
|
84
|
+
**Note:** The `POST /connect/communities` call provisions the site only. The Agentforce conversational assistant is a **separate** step — create it from the `EmployeeCopilot__AgentforceEmployeeAgent` template (see "Agentforce assistant for the Employee Center" above). Do not assume the site-create call activates an agent.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### Employee Portal
|
|
89
|
+
**Template name:** `Employee Portal` · **Framework:** Aura
|
|
90
|
+
|
|
91
|
+
Purpose-built Aura Experience Builder template for **employee service / internal self-service** portals (IT help desk, HR service, ITSM). A plainer alternative to `Agentforce Employee Center` — use it when the richer Agentforce template is not present or not wanted. Not Visualforce (`siteAsContainerEnabled = true`).
|
|
92
|
+
|
|
93
|
+
**Use when:** Building an employee-facing service/self-service portal via the communities API without a pre-existing MIAW Embedded Service Deployment (the self-service site API requires a guest ESD; this template does not), and `Agentforce Employee Center` is unavailable or undesired.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### Customer Service (formerly "Napili")
|
|
98
|
+
**Template name:** `Customer Service` · **Framework:** Aura · internal developerName: `Service Community Template`
|
|
99
|
+
|
|
100
|
+
The main Aura self-service template: Knowledge articles, case deflection, case management, community/Q&A. Mobile-responsive.
|
|
101
|
+
|
|
102
|
+
**Use when:** Building a self-service support community for customers or employees.
|
|
103
|
+
|
|
104
|
+
> Do not pass the legacy brand name `Napili` or a snake_case guess like `customer_service`. The current API display value is `Customer Service`.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### Help Center
|
|
109
|
+
**Template name:** `Help Center` · **Framework:** Aura · internal developerName: `Help Center Template`
|
|
110
|
+
|
|
111
|
+
Public / self-service knowledge + case deflection help center. More focused on knowledge and deflection than the fuller Customer Service community.
|
|
112
|
+
|
|
113
|
+
**Use when:** Building a knowledge-first help center or an IT help desk self-service experience.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
### Customer Account Portal
|
|
118
|
+
**Template name:** `Customer Account Portal` · **Framework:** Aura · internal developerName: `CPT Community Template`
|
|
119
|
+
|
|
120
|
+
Authenticated account self-service — view/pay invoices, manage account, access records.
|
|
121
|
+
|
|
122
|
+
**Use when:** Building an authenticated portal for customers to manage their account.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### Partner Central
|
|
127
|
+
**Template name:** `Partner Central` · **Framework:** Aura · internal developerName: `PRM Community Template`
|
|
128
|
+
|
|
129
|
+
Partner Relationship Management — channel sales, deal registration, lead distribution, partner account management.
|
|
130
|
+
|
|
131
|
+
**Use when:** Building a partner portal via the communities API (as opposed to the dedicated PRM API).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### Build Your Own
|
|
136
|
+
**Template name:** `Build Your Own` · **Framework:** Aura · internal developerName: `Starter Template`
|
|
137
|
+
|
|
138
|
+
Blank Aura starting point — full control over pages and components.
|
|
139
|
+
|
|
140
|
+
**Use when:** You want a custom Aura site without pre-built self-service pages.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### Build Your Own (LWR)
|
|
145
|
+
**Template name:** `Build Your Own (LWR)` · **Framework:** LWR · internal developerName: `talon-template-byo`
|
|
146
|
+
|
|
147
|
+
Blank modern Lightning Web Runtime site — fast, headless-friendly.
|
|
148
|
+
|
|
149
|
+
**Use when:** You want the most modern, performant framework and are comfortable building from a blank canvas.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### Microsite (LWR)
|
|
154
|
+
**Template name:** `Microsite (LWR)` · **Framework:** LWR · internal developerName: `microsite-template-marketing`
|
|
155
|
+
|
|
156
|
+
Lightweight LWR marketing microsite.
|
|
157
|
+
|
|
158
|
+
**Use when:** Building a small, fast marketing site.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### Legacy: Salesforce Tabs + Visualforce ("VF Template") — DO NOT USE
|
|
163
|
+
**Template name:** `Salesforce Tabs + Visualforce`
|
|
164
|
+
|
|
165
|
+
A standard-nav + Visualforce site with **no Experience Builder**. This is the source of the "created as Visualforce" bug. Not an Experience Builder site (`enableSiteAsContainer = false`). Avoid for all new portals.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## PRM Templates (`POST /connect/prm/setup/sites`)
|
|
170
|
+
|
|
171
|
+
PRM templates are org-specific and vary by:
|
|
172
|
+
- PRM package version installed
|
|
173
|
+
- Org configuration
|
|
174
|
+
- Industry-specific templates
|
|
175
|
+
- Custom templates added by admins
|
|
176
|
+
|
|
177
|
+
### How to Find Available PRM Templates
|
|
178
|
+
|
|
179
|
+
1. **Via headless-360:** the Aura PRM templates (`Partner Central`, `Partner Central (Enhanced)`) also appear in `mcp__headless-360__dispatch_readonly(method: "GET", url: "/services/data/v67.0/connect/communities/templates")`. Dedicated PRM-only templates are org-specific.
|
|
180
|
+
2. **Via Setup UI:** Setup → Digital Experiences → Settings → Partner Templates. Note the exact names (case-sensitive).
|
|
181
|
+
3. **Common names:** `Partner Central`, `Channel Management`, plus custom templates (varies by org).
|
|
182
|
+
|
|
183
|
+
**Important:** Template names are case-sensitive and must match exactly. If unsure, check the Setup UI or ask the user.
|
|
184
|
+
|
|
185
|
+
Alternatively, if the org does not have PRM enabled, build a partner portal via the communities API with the `Partner Central` template.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## MIAW (Messaging for In-App and Web)
|
|
190
|
+
|
|
191
|
+
- The **self-service site API** wires MIAW in at creation time via `guestEmbeddedServiceConfigId` / `embeddedServiceConfigId`. This is the recommended path when the portal needs messaging.
|
|
192
|
+
- For **general communities** (`POST /connect/communities`), MIAW is **not** part of the create call. Configure it separately — create a Messaging Channel + Embedded Service Deployment (Setup → Embedded Service Deployments), then add the Embedded Service (Messaging) component to the site's pages in Experience Builder.
|
|
193
|
+
- Embedded Service Deployments must **pre-exist**; this skill does not create them.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Template Parameters (`templateParams`)
|
|
198
|
+
|
|
199
|
+
The `templateParams` object on the communities API accepts template-specific configuration. Parameters vary by template and are not well-documented.
|
|
200
|
+
|
|
201
|
+
**Best practice:** For standard Experience Builder templates (`Customer Service`, `Help Center`, `Partner Central`), omit `templateParams` unless you need specific customization — the defaults work well. To discover parameters, create a test site via the UI and inspect the resulting Network/ExperienceBundle metadata.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Template Selection Guide
|
|
206
|
+
|
|
207
|
+
All rows dispatch through `mcp__headless-360__dispatch` / `dispatch_readonly`.
|
|
208
|
+
|
|
209
|
+
| Requirement | API | Framework | Template / `siteType` |
|
|
210
|
+
|-------------|-----|-----------|-----------------------|
|
|
211
|
+
| Employee service / ITSM / HR / help desk (richest; Agentforce-ready) | `communities` | Aura | `Agentforce Employee Center` |
|
|
212
|
+
| Employee service / ITSM / help desk (with MIAW, guest ESD exists) | `self-service/site` | Aura | `siteType: AURA` |
|
|
213
|
+
| Employee service / ITSM / help desk (plainer, no Agentforce / no MIAW) | `communities` | Aura | `Employee Portal` (fallback `Customer Service`) |
|
|
214
|
+
| Customer support / self-service community | `communities` | Aura | `Customer Service` |
|
|
215
|
+
| Knowledge base / case deflection | `communities` | Aura | `Help Center` |
|
|
216
|
+
| Authenticated account self-service | `communities` | Aura | `Customer Account Portal` |
|
|
217
|
+
| Partner portal (with PRM) | `prm/setup/sites` | Aura | Org-specific PRM template |
|
|
218
|
+
| Partner portal / channel (no PRM) | `communities` | Aura | `Partner Central` |
|
|
219
|
+
| Custom Aura site | `communities` | Aura | `Build Your Own` |
|
|
220
|
+
| Modern blank / headless-friendly site | `communities` | LWR | `Build Your Own (LWR)` |
|
|
221
|
+
| Marketing microsite | `communities` | LWR | `Microsite (LWR)` |
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Template Customization Post-Creation
|
|
226
|
+
|
|
227
|
+
After portal creation, customize via:
|
|
228
|
+
|
|
229
|
+
1. **Experience Builder** — visual page builder. Setup → Digital Experiences → [Your Site] → **Builder**. Drag-and-drop components, layouts, styling.
|
|
230
|
+
2. **Branding Editor** — colors, fonts, logo. Builder → Settings → Theme/Branding.
|
|
231
|
+
3. **Pages** — create or override pages in Builder.
|
|
232
|
+
4. **Custom components** — develop LWC (or Aura) components, deploy, and add them via Builder.
|
|
233
|
+
|
|
234
|
+
**Note:** Initial framework/template selection sets the foundation, but extensive customization is possible post-creation.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Version Compatibility
|
|
239
|
+
|
|
240
|
+
### API Version Notes
|
|
241
|
+
- All calls go through `mcp__headless-360__dispatch` / `dispatch_readonly`, which do **not** resolve the API version — pass the full `/services/data/vXX.0` prefix in every `url` (e.g. `url: "/services/data/v67.0/connect/communities"`).
|
|
242
|
+
- **v67.0 (Summer '26)** is the current/latest API version verified against a live test org at time of writing.
|
|
243
|
+
- `POST /connect/self-service/site` is available in recent versions (min-version 262).
|
|
244
|
+
- `GET /connect/communities/templates` is available v46.0+.
|
|
245
|
+
- `POST /connect/communities` is available v48.0+.
|
|
246
|
+
|
|
247
|
+
### Framework guidance
|
|
248
|
+
- **Aura Experience Builder templates** (Customer Service, Help Center, Customer Account Portal, Partner Central, Build Your Own) — current best practice for most portals.
|
|
249
|
+
- **LWR templates** (Build Your Own (LWR), Microsite (LWR)) — the most modern framework; prefer for greenfield custom or headless-friendly sites.
|
|
250
|
+
- **Salesforce Tabs + Visualforce** ("VF Template") — legacy; **do not use** for new portals.
|
|
251
|
+
- **Deprecated templates** (e.g. Kokua, Koa) — avoid.
|
|
252
|
+
|
|
253
|
+
**Best practice:** For employee service / ITSM / HR / help-desk portals, prefer the **`Agentforce Employee Center`** Aura template via the communities API — it ships the fullest employee experience (ticketing, catalog, knowledge, Agentforce-ready). Fall back to the self-service site API with `siteType: AURA` when the portal needs MIAW wired in at creation time and a guest ESD exists, or to the `Employee Portal` template (then `Customer Service`) when a plainer, non-Agentforce site is wanted. Use `Customer Service` (or `Help Center`) for customer self-service communities. Always validate exact `templateName` strings via `mcp__headless-360__dispatch_readonly(method: "GET", url: "/services/data/v67.0/connect/communities/templates")` in the target org — template availability varies by edition/version. The Agentforce conversational assistant is a separate step (`EmployeeCopilot__AgentforceEmployeeAgent`).
|
|
@@ -37,7 +37,7 @@ Always check for an existing feature before building something from scratch. The
|
|
|
37
37
|
|
|
38
38
|
2. **Search available features** — use `npx @salesforce/ui-bundle-features list` with `--search <query>` to filter by keyword. Use `--verbose` for full descriptions.
|
|
39
39
|
|
|
40
|
-
3. **Describe a feature
|
|
40
|
+
3. **Describe a feature — MANDATORY before wiring.** Run `npx @salesforce/ui-bundle-features describe <feature>` and read the feature's README via `npm view <package> readme` (using the `Package:` name from that output) before wiring it. The README is the contract: it tells you how the feature is meant to be wired — including any drop-in entry component and the file each integration example belongs in. Cross-check against the copied-in source under `describe`'s `Copy Operations` destination — that source (and its JSDoc) is the version-matched truth for what's actually installed. Do not wire from assumptions about file names or component APIs. Skipping this is the most common reason a feature installs successfully but never actually runs.
|
|
41
41
|
|
|
42
42
|
4. **Install** — use `npx @salesforce/ui-bundle-features install <feature> --ui-bundle-dir <name>`. Key options:
|
|
43
43
|
- `--dry-run` to preview changes
|
|
@@ -94,6 +94,10 @@ Features may include example files under an `__examples__/` directory (plural) s
|
|
|
94
94
|
|
|
95
95
|
If either check fails, **do NOT delete `__examples__/`** — the integration is incomplete. Fix the integration first, then re-run the verification.
|
|
96
96
|
|
|
97
|
+
### Post-install: Mount the OOTB component, don't hand-roll a parallel one
|
|
98
|
+
|
|
99
|
+
When a feature ships an integration point, the UI **must** use it rather than a parallel hand-rolled version. For features that ship an entry component, mount it — e.g. for search, mount the feature's `<Search>` on the search-results page; do **not** author a bespoke results page that queries data directly (a custom `SearchResults.tsx` against seed data or a raw GraphQL call bypasses the installed, tested feature, so the deployed sObject/CMS search never runs). The only exception is when the user **explicitly** opts out and asks for a custom one — confirm that intent, don't infer it.
|
|
100
|
+
|
|
97
101
|
### Hint Placeholders
|
|
98
102
|
|
|
99
103
|
Some copy paths use `<descriptive-name>` placeholders (e.g., `<desired-page-with-search-input>`) that the CLI does not resolve. After installation, rename or relocate these files to the intended target, or integrate their patterns into an existing file. This is separate from the `__examples__/` convention above — a single copy path can use either mechanism.
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
6. **No inline styles** — Tailwind utility classes and design tokens only.
|
|
11
11
|
7. **Catch-all last** — `path: '*'` (NotFound) must always remain the last child in the layout route.
|
|
12
12
|
8. **Never modify `appLayout.tsx`** when adding a page — layout changes are a separate concern.
|
|
13
|
+
9. **Search-results pages render the installed search feature** — when a search feature is installed (via `experience-ui-bundle-features-generate`), mount its shipped `<Search>` at the results route. Do **not** query data directly (a custom `SearchResults.tsx` against seed data or a raw GraphQL call) — that bypasses the installed feature so the deployed sObject/CMS search never runs. A custom results UI is fine *only if it's built on the feature's `useSearch` hook*, or when the user explicitly opted out of OOTB search (confirm, don't infer). See the feature's README: get the `Package:` name from `npx @salesforce/ui-bundle-features describe <feature>`, then run `npm view <package> readme`.
|
|
13
14
|
|
|
14
15
|
### Step 1 — Create the page file
|
|
15
16
|
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: platform-datamask-run
|
|
3
|
+
description: "Data Mask end-to-end operation on a sandbox: configure a masking policy over PII, run the masking job, poll it to completion, report masked-record results, and abort an in-progress run. Use when the user needs to run, monitor, or cancel a Salesforce Data Mask job, mask PII/sandbox data, or work with DataMaskPolicy / DataMaskPolicyJobRun. TRIGGER when: user runs a data mask job, masks sandbox PII, polls masking status, reports masked records, or aborts a running mask. DO NOT TRIGGER when: writing anonymization Apex by hand (use platform-apex-generate), generating test data (use platform-data-manage), or deploying unrelated metadata (use platform-metadata-deploy)."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0"
|
|
6
|
+
domains: ["Platform"]
|
|
7
|
+
minApiVersion: "67.0"
|
|
8
|
+
relatedSkills:
|
|
9
|
+
- "platform-apex-generate"
|
|
10
|
+
- "platform-data-manage"
|
|
11
|
+
- "platform-metadata-deploy"
|
|
12
|
+
cliTools:
|
|
13
|
+
- tool: ["python3"]
|
|
14
|
+
semver: ">=3.10.0"
|
|
15
|
+
- tool: ["sf"]
|
|
16
|
+
semver: ">=2.0.0"
|
|
17
|
+
accessCheck:
|
|
18
|
+
- type: userPerm
|
|
19
|
+
value: PermissionsManageDataMaskPolicies
|
|
20
|
+
- type: userPerm
|
|
21
|
+
value: PermissionsAccessDataMaskAndSeed
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# platform-datamask-run: Salesforce Data Mask End-to-End Operation
|
|
25
|
+
|
|
26
|
+
Use this skill to **operate** the Salesforce Data Mask feature on a **sandbox**: configure a
|
|
27
|
+
masking policy over PII fields, start a masking job, poll it to a terminal state, report which
|
|
28
|
+
records were masked, and abort a run that is still in progress.
|
|
29
|
+
|
|
30
|
+
Data Mask is **sandbox-only** — the run/abort REST endpoints return `403` on production (a runtime
|
|
31
|
+
sandbox guard). Confirm the target org is a sandbox before starting.
|
|
32
|
+
|
|
33
|
+
## When This Skill Owns the Task
|
|
34
|
+
|
|
35
|
+
- Running a Data Mask job against a configured policy
|
|
36
|
+
- Polling masking-job status to completion
|
|
37
|
+
- Reporting masked-record counts / per-object results
|
|
38
|
+
- Aborting (canceling) an in-progress masking run
|
|
39
|
+
- Creating or identifying the policy the job runs against
|
|
40
|
+
|
|
41
|
+
Delegate elsewhere when the user is:
|
|
42
|
+
- hand-writing anonymization Apex → `platform-apex-generate`
|
|
43
|
+
- seeding or generating test data → `platform-data-manage`
|
|
44
|
+
- deploying unrelated metadata → `platform-metadata-deploy`
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## The One Thing to Get Right First: the API surface map
|
|
49
|
+
|
|
50
|
+
The single biggest failure mode is assuming Data Mask entities are ordinary data-API objects.
|
|
51
|
+
**They are not, and the surface differs per entity.** Memorize this table before running anything —
|
|
52
|
+
guessing here is what turns a 3-second job into a 30-minute dead end.
|
|
53
|
+
|
|
54
|
+
| Entity | What it is | How you reach it |
|
|
55
|
+
|--------|-----------|------------------|
|
|
56
|
+
| `DataMaskPolicy` | The masking policy shell (config) | **Tooling API** or **Metadata API** (thin shell: `<label>`/`<description>`/`<runOnRefresh>` only) — NOT standard SOQL/`sobject describe` |
|
|
57
|
+
| `DataMaskPolicyObject` | An object targeted by a policy (holds the optional row filter) | **Tooling API only** — query AND insert; row-subset "sample" runs set `FilterEnabled`+`WhereCriteria` here (no `sampleSize` on the policy) |
|
|
58
|
+
| `DataMaskPolicyField` | A field + its masking treatment | **Tooling API only** — query AND insert; treatment cols are `MaskingCategory` + `MaskValue` |
|
|
59
|
+
| `DataMaskPolicyJobRun` | The **job** (one masking run) | **Standard SOQL** — `sf data query` works |
|
|
60
|
+
| `DataMaskPolicyJobRunDtl` | Per-object **job detail** (child, FK `DataMaskPolicyJobRunId`) | **Standard SOQL** |
|
|
61
|
+
| Start a run | — | **REST run API** `POST /services/data/v67.0/platform/data-resilience/data-mask/policies/{policyId}/run` |
|
|
62
|
+
| Abort a run | — | **REST run API** `POST /services/data/v67.0/platform/data-resilience/data-mask/jobs/{jobRunId}/abort` |
|
|
63
|
+
|
|
64
|
+
Concretely:
|
|
65
|
+
- `sf sobject describe --sobject DataMaskPolicy` → **`NOT_FOUND`** (don't retry it against standard API)
|
|
66
|
+
- `SELECT ... FROM DataMaskPolicy` via `sf data query` → **`INVALID_TYPE`**
|
|
67
|
+
- Query the **policy** via Tooling: `sf data query --use-tooling-api --query "SELECT Id, MasterLabel FROM DataMaskPolicy"`
|
|
68
|
+
- Query the **job / job-detail** via standard API: `sf data query --query "SELECT Id, Status FROM DataMaskPolicyJobRun"`
|
|
69
|
+
|
|
70
|
+
Full command reference: `references/api-surface.md`.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Pick the workflow that matches the request
|
|
75
|
+
|
|
76
|
+
This skill has **two distinct workflows**. Select ONE up front from what the user asked for, then
|
|
77
|
+
run **every** step of that workflow — neither has optional steps:
|
|
78
|
+
|
|
79
|
+
| The user wants to… | Run | Ends when |
|
|
80
|
+
|--------------------|-----|-----------|
|
|
81
|
+
| Configure/edit a policy and **mask** records; report how many were masked | **Workflow A — Mask & report** (below) | The masked count is reported from the detail rows |
|
|
82
|
+
| **Cancel / abort** a masking run | **Workflow B — Cancel a run** (further below) | The job's status is confirmed `canceled` |
|
|
83
|
+
|
|
84
|
+
Choose by the verb in the request. "Create/edit a policy and run it", "mask the PII", "how many
|
|
85
|
+
records were masked" → **Workflow A only**. "Abort", "cancel", "stop the run" → **Workflow B**. A
|
|
86
|
+
mask-and-report request does **not** include an abort: do not start a second job to "demonstrate"
|
|
87
|
+
cancelling — an unrequested run wastes a full ~5–10 min job (see the pool floor in A4) and is the top
|
|
88
|
+
cause of this task running out of turn before it finishes the masked count it *was* asked for.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Workflow A — Mask & report
|
|
93
|
+
|
|
94
|
+
### A1. Confirm sandbox + capture org context
|
|
95
|
+
Verify the org is a sandbox and grab the instance URL + a session token for the run-API calls:
|
|
96
|
+
```bash
|
|
97
|
+
sf org display --target-org <alias> --json
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### A2. Identify or create the policy
|
|
101
|
+
Prefer reusing an existing policy (fastest, no deploy):
|
|
102
|
+
```bash
|
|
103
|
+
sf data query --use-tooling-api --target-org <alias> \
|
|
104
|
+
--query "SELECT Id, DeveloperName, MasterLabel FROM DataMaskPolicy"
|
|
105
|
+
```
|
|
106
|
+
If none targets the Contact PII you need, author one with the **two-step** recipe (the
|
|
107
|
+
`DataMaskPolicy` Metadata shape is a thin shell; membership is Tooling-inserted):
|
|
108
|
+
1. **Metadata-deploy the thin shell** in **mdapi format** (`--metadata-dir` + `package.xml`; a
|
|
109
|
+
source-format `--source-dir` deploy fails "Could not infer a metadata type"). The shell carries
|
|
110
|
+
only `<label>`, `<description>`, `<runOnRefresh>`. This creates the policy *with an active
|
|
111
|
+
revision*, which A2 requires.
|
|
112
|
+
2. **Tooling-insert** the `DataMaskPolicyObject` (one per object) then its `DataMaskPolicyField`
|
|
113
|
+
rows. Each field row's treatment is `MaskingCategory` (`library`) + `MaskValue` (a snake_case
|
|
114
|
+
token like `first_name`, `email`, `phone`). There is **no `MaskingRuleType` column**.
|
|
115
|
+
|
|
116
|
+
> Insert order matters: a Tooling-created parent (no active revision) makes the child insert fail
|
|
117
|
+
> `INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY`. Metadata-deploy the shell first.
|
|
118
|
+
|
|
119
|
+
See `references/policy-authoring.md` for the full recipe and the `MaskValue` token table. Choose a
|
|
120
|
+
`MaskValue` appropriate to each field; do **not** blanket-replace.
|
|
121
|
+
|
|
122
|
+
### A3. Start the masking run (REST run API)
|
|
123
|
+
```bash
|
|
124
|
+
printf '{}' > ./empty-body.json
|
|
125
|
+
sf api request rest \
|
|
126
|
+
"/services/data/v67.0/platform/data-resilience/data-mask/policies/{policyId}/run" \
|
|
127
|
+
--method POST --body @./empty-body.json --target-org <alias>
|
|
128
|
+
```
|
|
129
|
+
The endpoint needs an **empty JSON body** (`{}`) — `sf api request rest` requires `--body` on a POST
|
|
130
|
+
even when the API takes no payload. **Pass the file with an `@` prefix** (`--body @./empty-body.json`);
|
|
131
|
+
without it the literal path is sent as the body and the API returns `JSON_PARSER_ERROR`. A `200` returns `jobRunId`, `policyId`, `status` (the run-API
|
|
132
|
+
status is UPPERCASE, e.g. `RUNNING`) and `message: "Job started successfully"`. A `409`/`CONFLICT`
|
|
133
|
+
means a run is already in progress for that policy.
|
|
134
|
+
|
|
135
|
+
> **Write `report.md` NOW, before you poll — do not wait until the end.** The masking job takes
|
|
136
|
+
> several minutes (see below), and the single most common way this task scores zero is the turn
|
|
137
|
+
> ending during the poll with **no output file written at all**. The instant you have the `jobRunId`,
|
|
138
|
+
> write `report.md` with everything known so far (policy Id/label, the run command, the `jobRunId`,
|
|
139
|
+
> status `RUNNING`, and a "polling for completion…" placeholder for the masked count). Then **update
|
|
140
|
+
> that same file** once the job finishes. A report that exists and says "still running" beats no file;
|
|
141
|
+
> a fabricated count is worse than either — only fill the count from the detail rows (A5).
|
|
142
|
+
|
|
143
|
+
### A4. Poll to a terminal state (standard SOQL)
|
|
144
|
+
Poll `DataMaskPolicyJobRun.Status` until it reaches a **terminal** value. Do **not** report a
|
|
145
|
+
mid-run status as final.
|
|
146
|
+
- Mid-run (pre-work): `pending`, `scheduled` — the job is queued but **not yet abortable**
|
|
147
|
+
- Mid-run (working): `running` — this is the **only** state in which abort succeeds
|
|
148
|
+
- Terminal: `completed`, `completed_with_errors`, `failed`
|
|
149
|
+
- Abort target: `canceled` (single "l")
|
|
150
|
+
|
|
151
|
+
**`pending` is not `running`.** Abort on a `pending`/`scheduled` job returns `409 CONFLICT`
|
|
152
|
+
("Job is not in a running state ... status=PENDING"). You must poll until the status is literally
|
|
153
|
+
`running` before you can abort — see Workflow B.
|
|
154
|
+
|
|
155
|
+
**Jobs are slow — expect several minutes, and poll with the bundled script.** Data Mask runs on a
|
|
156
|
+
backend pool/scheduler with a **~5–10 minute floor**: even a tiny (20-row) job usually does **not**
|
|
157
|
+
reach a terminal state or emit detail rows for several minutes after the run starts. This is fixed
|
|
158
|
+
overhead, **not** proportional to row count. Plan the run around it — the single biggest failure mode
|
|
159
|
+
is treating the job as instant, polling on a tight interval, and either timing out or writing a
|
|
160
|
+
"still pending" report.
|
|
161
|
+
|
|
162
|
+
Run `scripts/poll-job.sh` as a **single command** — do **not** hand-roll a SOQL poll loop:
|
|
163
|
+
```bash
|
|
164
|
+
bash scripts/poll-job.sh <alias> <jobRunId> # defaults: cap 600s (10 min), 20s interval
|
|
165
|
+
```
|
|
166
|
+
It sleeps on a low-frequency interval, short-circuits the instant a ground-truth detail row appears,
|
|
167
|
+
prints the terminal signal (`completed`/`failed`/`canceled`) on stdout, and exits `0` (or `1` on
|
|
168
|
+
timeout). **Call it once and read its result — do not wrap it in your own retry loop**, and do not
|
|
169
|
+
poll on a sub-10s interval (it just burns tool calls against a job that cannot finish sooner).
|
|
170
|
+
|
|
171
|
+
**Ground truth is the detail rows, not the parent status.** The parent `DataMaskPolicyJobRun.Status`
|
|
172
|
+
can **lag** — it may read `pending`/`running` for a while after masking actually finished. Once a
|
|
173
|
+
`total_records_masked` (or `completed`) `DataMaskPolicyJobRunDtl` row exists, the masking is done.
|
|
174
|
+
`poll-job.sh` already encodes all of this — the bounded interval and timeout, the short-circuit on
|
|
175
|
+
the ground-truth detail row, and the terminal-signal exit code — so you do **not** re-implement any
|
|
176
|
+
of it inline. Run the poller once, read its exit signal, then update `report.md` (the stub you wrote
|
|
177
|
+
before polling) with the terminal status and the masked count from A5.
|
|
178
|
+
|
|
179
|
+
### A5. Report results from the job DETAIL object
|
|
180
|
+
The parent job carries an overall status; **per-object masked counts live on the child**
|
|
181
|
+
`DataMaskPolicyJobRunDtl` (linked by `DataMaskPolicyJobRunId`). Report a concrete count, not a
|
|
182
|
+
fabricated one:
|
|
183
|
+
```bash
|
|
184
|
+
sf data query --target-org <alias> \
|
|
185
|
+
--query "SELECT Id, DataMaskPolicyJobRunId, Status FROM DataMaskPolicyJobRunDtl WHERE DataMaskPolicyJobRunId = '<jobRunId>'"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Report only what the rows literally show — do not overstate granularity.** The detail rows are
|
|
189
|
+
**object-level** status_update entries (`loaded`, `completed`, `total_records_masked` for the object,
|
|
190
|
+
e.g. Contact). They are **not** per-field rows. So state per-object success as an observed fact
|
|
191
|
+
("Contact: 27/27 records masked, 0 error rows"), but frame field-level success as an **inference**,
|
|
192
|
+
not a direct observation — say "no field-level error rows were returned, so no field is reported as
|
|
193
|
+
failed", **not** "all 5 fields succeeded" (the data does not carry a per-field success row to back
|
|
194
|
+
that claim). Overstating an inference as an observation is the most common factuality miss here.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Workflow B — Cancel a run
|
|
199
|
+
|
|
200
|
+
Use this workflow when the request is to **abort/cancel** a masking run. It targets the run that is
|
|
201
|
+
**currently in progress** — aborting is an on-demand action against a live job; nobody starts a job
|
|
202
|
+
just to cancel it. Steps B1–B4 are all required.
|
|
203
|
+
|
|
204
|
+
### B1. Confirm sandbox + identify the run to cancel
|
|
205
|
+
Confirm the org is a sandbox (`sf org display`) and get the `jobRunId` of the run to abort — the one
|
|
206
|
+
the user is asking to cancel. **Capture its `DataMaskPolicyId` too** — you need it to start a
|
|
207
|
+
replacement run if the abort window is missed (B2 exit 3 / exit 1). If they just started it, use that
|
|
208
|
+
id; otherwise query for the active run:
|
|
209
|
+
```bash
|
|
210
|
+
sf data query --target-org <alias> \
|
|
211
|
+
--query "SELECT Id, Status, DataMaskPolicyId FROM DataMaskPolicyJobRun ORDER BY CreatedDate DESC LIMIT 5"
|
|
212
|
+
```
|
|
213
|
+
Note the `DataMaskPolicyId` (`8dm` prefix) of the run you pick — that is the `<policyId>` A3 needs.
|
|
214
|
+
|
|
215
|
+
### B2. Wait for the job to be `running` (the only abortable state)
|
|
216
|
+
You can only abort while `DataMaskPolicyJobRun.Status` is `running`. A `pending`/`scheduled` job
|
|
217
|
+
`409`s; a terminal one is already done. Poll for the `running` window with the bundled poller in its
|
|
218
|
+
**`running` mode** — it exits the instant the status reads `running` (unlike the default mode, which
|
|
219
|
+
waits for a terminal state), so it will not block past the abortable window:
|
|
220
|
+
```bash
|
|
221
|
+
POLL_MODE=running bash scripts/poll-job.sh <alias> <jobRunId> 900 15
|
|
222
|
+
```
|
|
223
|
+
The cap is **900s (15 min)**, above the ~5–10 min scheduling floor so a slow-to-start job still gets
|
|
224
|
+
caught. Handle every exit:
|
|
225
|
+
- **Exit `0`** (prints `running`) → go straight to B3.
|
|
226
|
+
- **Exit `3`** → the job raced to a terminal state before `running` was caught; the abort window is
|
|
227
|
+
gone. Start a fresh run against the policy you captured in B1 (A3 with that `<policyId>`), then
|
|
228
|
+
return here and poll the **new** `jobRunId`.
|
|
229
|
+
- **Exit `1`** (timeout — the cap expired) → re-query the job's status:
|
|
230
|
+
```bash
|
|
231
|
+
sf data query --target-org <alias> \
|
|
232
|
+
--query "SELECT Id, Status FROM DataMaskPolicyJobRun WHERE Id = '<jobRunId>'"
|
|
233
|
+
```
|
|
234
|
+
If it is still non-terminal (`pending`/`scheduled`/`running`), re-run the poller **once** more (same
|
|
235
|
+
command) to continue waiting. If it is `running`, go to B3. If it is terminal, treat it like exit 3
|
|
236
|
+
— start a fresh run (A3 with the B1 `<policyId>`) and poll the new job.
|
|
237
|
+
|
|
238
|
+
Because of the ~5–10 min pool floor the `running` window is usually minutes wide, so there is time to
|
|
239
|
+
catch it; do not poll with no delay.
|
|
240
|
+
|
|
241
|
+
> **If no run is currently in progress** (the job already completed, or you must reproduce a
|
|
242
|
+
> run→cancel flow end to end), start one first with A3, then return here — poll it to `running` and
|
|
243
|
+
> abort **that** live job. Never substitute an older, already-terminal job to "show" a cancel; the
|
|
244
|
+
> abort must target the run that is actually live.
|
|
245
|
+
|
|
246
|
+
### B3. Abort via the run API
|
|
247
|
+
Abort via the run API — **not** by DML/delete on the job record:
|
|
248
|
+
```bash
|
|
249
|
+
sf api request rest \
|
|
250
|
+
"/services/data/v67.0/platform/data-resilience/data-mask/jobs/{jobRunId}/abort" \
|
|
251
|
+
--method POST --body @./empty-body.json --target-org <alias>
|
|
252
|
+
```
|
|
253
|
+
Empty JSON body (`{}`) via the `@`-prefixed file, as above. A `200` returns `status: "CANCELED"`
|
|
254
|
+
(uppercase, from the run API) and `message: "Job abort requested"`. A `409` means the job was not in
|
|
255
|
+
a `running` state (usually still `pending`/`scheduled`) — return to B2 and resume polling.
|
|
256
|
+
|
|
257
|
+
### B4. Confirm and report the cancellation
|
|
258
|
+
Cancellation is asynchronous. **Re-query** `DataMaskPolicyJobRun` and confirm `Status = canceled`
|
|
259
|
+
(lowercase, from SOQL) before reporting the abort succeeded. Verify:
|
|
260
|
+
- [ ] Confirmed the abort targeted the live job while its queried status was `running`.
|
|
261
|
+
- [ ] Re-queried `DataMaskPolicyJobRun` after the abort and saw `Status = canceled`.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## High-Signal Rules
|
|
266
|
+
|
|
267
|
+
| Rule | Rationale |
|
|
268
|
+
|------|-----------|
|
|
269
|
+
| Run each `sf` command **bare** — never add a pipe or redirect of any kind (`\|`, `\| python3`, `\| grep`, `2>&1`, `2>/dev/null`, `> file`) | `sf ... --json` already prints clean JSON on stdout; read it directly. A redirect/pipe trips an unbypassable shell-safety guard that silently stalls the whole run to timeout. Never post-process with `python3`/`grep`/`jq`, and never suppress stderr — even if a command prints a warning, the `--json` payload on stdout is still valid; just parse it as-is |
|
|
270
|
+
| Never use standard SOQL / `sobject describe` on `DataMaskPolicy*` config objects | They return `INVALID_TYPE` / `NOT_FOUND` — use Tooling API or MDAPI |
|
|
271
|
+
| Read masked counts from `DataMaskPolicyJobRunDtl`, never invent them | The child detail is the source of truth for per-object results |
|
|
272
|
+
| Only `completed` / `completed_with_errors` / `failed` are terminal | Reporting `running`/`scheduled` as final is wrong |
|
|
273
|
+
| Abort only via the run-API abort endpoint | DML/delete on the job record is not a real abort and corrupts state |
|
|
274
|
+
| Always re-query status after abort and confirm `canceled` | An abort call returning 200 is not proof the job stopped |
|
|
275
|
+
| Data Mask runs on sandboxes only | Run/abort endpoints `403` on production |
|
|
276
|
+
| Use API version `v67.0` or later, and no `/connect/` segment | The run/abort endpoints are `/services/data/v67.0/platform/data-resilience/data-mask/...` — a `connect` segment or a pre-v67 version returns `NOT_FOUND` |
|
|
277
|
+
| Poll via `scripts/poll-job.sh` (one call), never a hand-rolled SOQL loop | The script caps attempts and short-circuits on the ground-truth detail row; a manual loop against the lagging parent status is the #1 cause of a run timing out with no report |
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Gotchas
|
|
282
|
+
|
|
283
|
+
| Issue | Resolution |
|
|
284
|
+
|-------|------------|
|
|
285
|
+
| `sf sobject describe DataMaskPolicy` → `NOT_FOUND` | It's a Tooling/MDAPI entity — query with `--use-tooling-api`, don't retry standard API |
|
|
286
|
+
| `SELECT ... FROM DataMaskPolicy` → `INVALID_TYPE` | Same cause — use Tooling API for the policy; standard API only for `DataMaskPolicyJobRun`/`Dtl` |
|
|
287
|
+
| Run start returns `409` | A run is already in progress for that policy — poll the existing one or wait for it to finish |
|
|
288
|
+
| Abort returns `409` "status=PENDING" | The job is still `pending`/`scheduled`, not yet `running` — keep polling and abort only once it reads `running`; don't give up on the abort |
|
|
289
|
+
| Small job finishes before you can abort it | The `running` window is seconds on a small sandbox — start a fresh run and poll tightly; never substitute a previously-aborted job to fake the flow |
|
|
290
|
+
| Abort returns `200` but SOQL status still `running` | Cancellation is async — keep polling the SOQL status until `canceled`; don't report success early |
|
|
291
|
+
| Run API says `CANCELED` but SOQL says `running` | Case + surface differ: the run API is UPPERCASE, SOQL picklist is lowercase. Trust the SOQL value for terminal state |
|
|
292
|
+
| Job "finished" instantly | Re-check: `scheduled` is not terminal. Poll until a terminal value actually appears |
|
|
293
|
+
| Run/abort endpoint `NOT_FOUND` | The path must be `/services/data/v67.0/platform/data-resilience/data-mask/...` — no `/connect/` segment, and version `v67.0`+ (Core 262). See `references/api-surface.md` |
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Output Format
|
|
298
|
+
|
|
299
|
+
Report the sections for **the workflow you ran** — do not add sections for the other one. **Keep it
|
|
300
|
+
tight — show each command once, at the step it belongs to; do not append a second "full command log"
|
|
301
|
+
that repeats calls already shown.** Prefer a compact table over prose; a reader should reach the key
|
|
302
|
+
result in the first screenful.
|
|
303
|
+
|
|
304
|
+
**Workflow A (mask & report):**
|
|
305
|
+
1. **Policy used** (Id + label, and whether reused or created)
|
|
306
|
+
2. **Run** — job Id, final terminal status, masked-record count (from the detail object). Collapse
|
|
307
|
+
the poll loop to one line (e.g. "polled 5×, `running`→`completed`"); do not print a row per poll.
|
|
308
|
+
3. **Per-object results** — from `DataMaskPolicyJobRunDtl`. Report the object-level counts the rows
|
|
309
|
+
actually carry; if there are no field-level error rows, say so as an inference ("no field-level
|
|
310
|
+
errors reported"), not as a claimed per-field success. See A5 for the exact phrasing.
|
|
311
|
+
4. **Commands run** — already shown inline above; here just list any not yet shown. Do **not**
|
|
312
|
+
re-paste the full sequence a second time.
|
|
313
|
+
|
|
314
|
+
**Workflow B (cancel a run):**
|
|
315
|
+
1. **Job cancelled** — the job Id, that it was `running` when aborted, that the abort was issued via
|
|
316
|
+
the run-API abort endpoint, and the re-queried `canceled` status.
|
|
317
|
+
2. **Commands run** — as above, no re-pasting.
|
|
318
|
+
|
|
319
|
+
**Accuracy notes that keep factuality high:**
|
|
320
|
+
- The run/abort REST response returns a **15-character** `jobRunId` (e.g. `1aGXK0000000uob`); SOQL
|
|
321
|
+
returns the **18-character** form of the same record (e.g. `1aGXK0000000uob2AA`). They are the
|
|
322
|
+
**same job** — when both appear, note that rather than presenting them as two IDs.
|
|
323
|
+
- Do not assert a masked count, a per-field outcome, or a terminal status you did not actually query.
|
|
324
|
+
Every number in the report must trace to a query result shown in the command log.
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Cross-Skill Integration
|
|
329
|
+
|
|
330
|
+
| Need | Delegate to | Reason |
|
|
331
|
+
|------|-------------|--------|
|
|
332
|
+
| Seed realistic PII records to mask | [platform-data-manage](../platform-data-manage/SKILL.md) | Test-data creation |
|
|
333
|
+
| Author custom anonymization Apex | [platform-apex-generate](../platform-apex-generate/SKILL.md) | Apex authoring |
|
|
334
|
+
| Deploy the policy metadata to the org | [platform-metadata-deploy](../platform-metadata-deploy/SKILL.md) | Metadata deployment |
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Reference File Index
|
|
339
|
+
|
|
340
|
+
| File | When to read |
|
|
341
|
+
|------|-------------|
|
|
342
|
+
| `references/api-surface.md` | Exact per-entity API surface, all CLI commands, run/abort REST endpoints, and status picklist values |
|
|
343
|
+
| `references/policy-authoring.md` | Two-step authoring recipe (MDAPI thin shell → Tooling object/field inserts) and the `MaskingCategory`/`MaskValue` treatment table |
|
|
344
|
+
| `references/run-and-abort.md` | The run → poll → report → re-run → abort sequence in full, with sample responses |
|
|
345
|
+
| `scripts/poll-job.sh` | Bounded poller: waits for a terminal status (default) or, with `POLL_MODE=running`, for the abortable `running` window |
|