@salesforce/afv-skills 1.66.0 → 1.68.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/README.md +55 -5
- package/package.json +2 -4
- package/skills/agentforce-offline-experimentation-run/SKILL.md +26 -49
- package/skills/agentforce-offline-experimentation-run/scripts/bt_compare.py +81 -0
- package/skills/agentforce-offline-experimentation-run/scripts/bt_fetch.py +358 -0
- package/skills/agentforce-offline-experimentation-run/scripts/bt_patch_agent.py +110 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/__init__.py +34 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/agentpatch.py +483 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/agentsrc.py +565 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/cache.py +95 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/compare.py +617 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/fetch.py +1012 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/judge.py +148 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/messages.py +92 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/patch.py +327 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/redact.py +40 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/results.py +288 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/scoring.py +340 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/sfap.py +238 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/splits.py +136 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/stdm.py +98 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/tokens.py +173 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/units.py +199 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/versions.py +194 -0
- package/skills/agentforce-offline-experimentation-run/scripts/build_report.py +366 -378
- package/skills/agentforce-offline-experimentation-run/scripts/resolve-token.sh +14 -4
- package/skills/agentforce-offline-experimentation-run/scripts/sfap_replay.py +472 -796
- package/skills/commerce-react-storefront-create/SKILL.md +350 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +2 -2
- package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +28 -16
- package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +18 -1
- package/skills/dx-lifecycle-center/SKILL.md +5 -2
- package/skills/dx-lifecycle-center/assets/widgets/connect-connected/connect-connected.json +65 -0
- package/skills/dx-lifecycle-center/assets/widgets/connect-connected/schema.json +32 -0
- package/skills/dx-lifecycle-center/assets/widgets/connect-sign-in/connect-sign-in.json +57 -0
- package/skills/dx-lifecycle-center/assets/widgets/connect-sign-in/schema.json +21 -0
- package/skills/dx-lifecycle-center/examples/workflows.md +20 -6
- package/skills/dx-lifecycle-center/references/connect-org.md +21 -2
- package/skills/dx-lifecycle-center/references/deploy.md +2 -2
- package/skills/dx-lifecycle-center/references/list-orgs.md +1 -1
- package/skills/dx-lifecycle-center/scripts/card-policy.jq +71 -0
- package/skills/dx-lifecycle-center/scripts/fill-widget.jq +29 -0
- package/skills/dx-lifecycle-center/scripts/widget.sh +28 -0
- package/skills/dx-org-devhub-configure/SKILL.md +85 -84
- package/skills/dx-org-devhub-configure/examples/status-output.md +25 -2
- package/skills/dx-org-devhub-configure/scripts/devhub.sh +265 -140
- package/skills/dx-org-devhub-configure/scripts/test-devhub.sh +100 -15
- package/skills/dx-packaging-move-to-2gp-migrate/SKILL.md +89 -0
- package/skills/dx-packaging-move-to-2gp-migrate/references/api-operations.md +164 -0
- package/skills/dx-scratch-def-configure/SKILL.md +163 -0
- package/skills/dx-scratch-def-configure/examples/confirm-card.md +53 -0
- package/skills/dx-scratch-def-configure/examples/report-recipes.md +100 -0
- package/skills/dx-scratch-def-configure/references/features.json +3270 -0
- package/skills/dx-scratch-def-configure/references/project-scratch-def.schema.json +1841 -0
- package/skills/dx-scratch-def-configure/references/settings-map.json +682 -0
- package/skills/dx-scratch-def-configure/scripts/lib_scratch_def.py +1306 -0
- package/skills/dx-scratch-def-configure/scripts/requirements.txt +3 -0
- package/skills/dx-scratch-def-configure/scripts/scrape_config_values.py +848 -0
- package/skills/education-cloud-domain-configure/SKILL.md +22 -24
- package/skills/education-cloud-domain-configure/references/dependent-features.md +9 -0
- package/skills/education-cloud-domain-configure/references/domain-features.md +15 -0
- package/skills/education-cloud-domain-configure/references/gotchas-extended.md +8 -0
- package/skills/education-cloud-domain-configure/references/setup-widgets.md +123 -0
- package/skills/education-cloud-multi-campus-configure/SKILL.md +1 -1
- package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +1 -1
- package/skills/experience-design-validate/SKILL.md +1 -1
- package/skills/experience-search-coordinate/SKILL.md +19 -13
- package/skills/experience-search-coordinate/references/content-route.md +79 -1
- package/skills/experience-search-coordinate/references/media-route.md +30 -4
- package/skills/experience-ui-bundle-features-generate/SKILL.md +1 -1
- package/skills/experience-ui-bundle-mfa-configure/SKILL.md +1 -1
- package/skills/field-service-data-capture-migrate/SKILL.md +1 -1
- package/skills/platform-apex-generate/SKILL.md +14 -11
- package/skills/platform-apex-test-generate/SKILL.md +2 -1
- package/skills/platform-datamask-run/SKILL.md +52 -71
- package/skills/platform-datamask-run/references/api-surface.md +10 -4
- package/skills/platform-datamask-run/references/policy-authoring.md +56 -7
- package/skills/platform-datamask-run/references/run-and-abort.md +17 -10
- package/skills/platform-datamask-run/scripts/poll-job.sh +15 -25
- package/skills/platform-dataspace-access-configure/SKILL.md +19 -1
- package/skills/platform-metadata-deploy/README.md +1 -1
- package/skills/platform-metadata-deploy/SKILL.md +114 -15
- package/skills/platform-metadata-deploy/references/agent-deployment-guide.md +3 -4
- package/skills/platform-metadata-deploy/references/orchestration.md +2 -3
- package/skills/platform-metadata-discovery-get/SKILL.md +185 -0
- package/skills/platform-metadata-discovery-get/references/api-map.md +25 -0
- package/skills/platform-metadata-discovery-get/references/h360-routes.md +30 -0
- package/skills/platform-metadata-discovery-get/references/scoped-soql.md +52 -0
- package/skills/platform-metadata-grounding-get/SKILL.md +170 -0
- package/skills/platform-policy-rule-generate/SKILL.md +84 -232
- package/skills/platform-policy-rule-generate/references/condition-model.md +47 -0
- package/skills/platform-policy-rule-generate/references/condition-templates.md +89 -0
- package/skills/platform-policy-rule-generate/references/conjunction-compiler.md +25 -0
- package/skills/platform-policy-rule-generate/references/conjunction-expression.md +22 -0
- package/skills/platform-policy-rule-generate/references/consumer-all.md +9 -0
- package/skills/platform-policy-rule-generate/references/consumer-datacloud-ui.md +91 -0
- package/skills/platform-policy-rule-generate/references/deploy-errors.md +24 -36
- package/skills/platform-policy-rule-generate/references/examples/ExistsJoinRLS/package.xml +12 -0
- package/skills/platform-policy-rule-generate/references/examples/ExistsJoinRLS/policyRuleDefinitionSets/ExistsJoinRLS.policyRuleDefinitionSet +6 -0
- package/skills/platform-policy-rule-generate/references/examples/ExistsJoinRLS/policyRuleDefinitions/ExistsJoinRLS_Rule_1.policyRuleDefinition +91 -0
- package/skills/platform-policy-rule-generate/references/examples/FieldReadDeny/package.xml +12 -0
- package/skills/platform-policy-rule-generate/references/examples/FieldReadDeny/policyRuleDefinitionSets/FieldReadDeny.policyRuleDefinitionSet +6 -0
- package/skills/platform-policy-rule-generate/references/examples/FieldReadDeny/policyRuleDefinitions/FieldReadDeny_Rule_1.policyRuleDefinition +72 -0
- package/skills/platform-policy-rule-generate/references/examples/LastCharactersFieldMasking/package.xml +12 -0
- package/skills/platform-policy-rule-generate/references/examples/LastCharactersFieldMasking/policyRuleDefinitionSets/LastCharactersFieldMasking.policyRuleDefinitionSet +6 -0
- package/skills/platform-policy-rule-generate/references/examples/LastCharactersFieldMasking/policyRuleDefinitions/LastCharactersFieldMasking_Rule_1.policyRuleDefinition +77 -0
- package/skills/platform-policy-rule-generate/references/examples/PrincipalFieldMatchRLS/package.xml +12 -0
- package/skills/platform-policy-rule-generate/references/examples/PrincipalFieldMatchRLS/policyRuleDefinitionSets/PrincipalFieldMatchRLS.policyRuleDefinitionSet +6 -0
- package/skills/platform-policy-rule-generate/references/examples/PrincipalFieldMatchRLS/policyRuleDefinitions/PrincipalFieldMatchRLS_Rule_1.policyRuleDefinition +77 -0
- package/skills/platform-policy-rule-generate/references/examples/TaggedObjectAccess/package.xml +12 -0
- package/skills/platform-policy-rule-generate/references/examples/TaggedObjectAccess/policyRuleDefinitionSets/TaggedObjectAccess.policyRuleDefinitionSet +4 -0
- package/skills/platform-policy-rule-generate/references/examples/TaggedObjectAccess/policyRuleDefinitions/TaggedObjectAccess_Rule_1.policyRuleDefinition +65 -0
- package/skills/platform-policy-rule-generate/references/headless-transport.md +87 -0
- package/skills/platform-policy-rule-generate/references/policy-schema-full.md +17 -10
- package/skills/platform-policy-rule-generate/references/policy-shapes.md +74 -0
- package/skills/platform-policy-rule-generate/references/principal-expression.md +31 -0
- package/skills/platform-policy-rule-generate/references/reference-resolution.md +51 -0
- package/skills/platform-policy-rule-generate/references/resource-expression.md +48 -0
- package/skills/platform-policy-rule-generate/references/runtime-context.md +9 -0
- package/skills/platform-policy-rule-generate/references/templates-access.md +11 -9
- package/skills/platform-policy-rule-generate/references/templates-advanced.md +4 -2
- package/skills/platform-policy-rule-generate/references/templates-record.md +37 -22
- package/skills/platform-policy-rule-generate/references/templates-transform.md +10 -8
- package/skills/platform-policy-rule-generate/references/templates.md +2 -2
- package/skills/platform-policy-rule-generate/references/ui-compatibility.md +35 -17
- package/skills/platform-report-generate/SKILL.md +9 -4
- package/skills/platform-report-generate/references/chart-types.md +26 -2
- package/skills/platform-report-generate/references/column-names.md +43 -0
- package/skills/platform-report-generate/references/errors-and-troubleshooting.md +1 -1
- package/skills/platform-report-generate/references/verification-checklist.md +10 -2
- package/skills/platform-value-set-generate/SKILL.md +19 -19
- package/skills/platform-widget-generate/SKILL.md +25 -51
- package/skills/platform-widget-generate/examples/formulas.json +19 -2
- package/skills/platform-widget-generate/examples/localized-labels.json +57 -0
- package/skills/platform-widget-generate/references/widget-actions.md +29 -0
- package/skills/platform-widget-generate/references/widget-bundle-validation.md +1 -0
- package/skills/platform-widget-generate/references/widget-formulas.md +24 -7
- package/skills/platform-widget-generate/references/widget-gotchas.md +10 -0
- package/skills/platform-widget-generate/references/widget-labels.md +78 -0
- package/skills/platform-widget-generate/references/widget-styling.md +12 -0
- package/skills/sales-call-scoring-configure/SKILL.md +17 -10
- package/skills/sales-call-scoring-configure/scripts/enable-call-scoring.sh +55 -33
- package/skills/service-digital-engagement-channel-configure/SKILL.md +11 -7
- package/skills/service-digital-engagement-channel-configure/assets/messaging_channel_template.xml +33 -0
- package/skills/service-digital-engagement-channel-configure/references/channel_settings.md +123 -16
- package/skills/service-digital-engagement-deployment-configure/SKILL.md +37 -100
- package/skills/service-digital-engagement-deployment-configure/assets/esd_web_update_template.xml +83 -8
- package/skills/service-digital-engagement-deployment-configure/examples/esd_web_prechat_fields.xml +74 -0
- package/skills/service-digital-engagement-deployment-configure/references/connect_api_creation.md +13 -3
- package/skills/service-digital-engagement-deployment-configure/references/deployment_settings.md +13 -78
- package/skills/service-digital-engagement-deployment-configure/references/onboarding_contract.md +5 -6
- package/skills/service-digital-engagement-deployment-configure/references/prechat_forms.md +245 -0
- package/skills/service-itsm-agentic-setup-incident-management/SKILL.md +164 -120
- package/skills/service-itsm-agentic-setup-incident-management/examples/output-templates.md +61 -37
- package/skills/service-itsm-agentic-setup-incident-management/references/audit-tracking.md +42 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/broadcast-communications.md +23 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/email-to-incident.md +23 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/incident-dashboards.md +25 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/incident-persona-psg.md +30 -146
- package/skills/service-itsm-agentic-setup-incident-management/references/incident-preferences.md +32 -136
- package/skills/service-itsm-agentic-setup-incident-management/references/major-incident-management.md +32 -155
- package/skills/service-itsm-agentic-setup-incident-management/references/manage-incidents-with-ai.md +45 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/priority-matrix.md +32 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/service-mgmt-privilege.md +30 -140
- package/skills/service-itsm-agentic-setup-incident-management/references/sla-milestones.md +110 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: platform-metadata-grounding-get
|
|
3
|
+
description: "Find metadata that already exists in a Salesforce org by meaning, when you do not know its exact API name. Use to find objects, fields, flows, Apex classes, picklist values, permission sets, validation rules, record types, and sharing rules by what they store or do. Use before creating metadata to check whether something similar already exists, and before writing Apex, LWC, SOQL, or Flow logic to confirm the real names. Use to read how a field, object, or validation rule is configured, and which profiles and permission sets can read or edit a field. Works through the Metadata Grounding MCP (search_metadata, query_metadata, describe_metadata) or the Salesforce MCP operations searchMetadata, queryMetadata, and describeMetadata. Needs Salesforce Catalog in the org. DO NOT TRIGGER for choosing between grounding, SOQL, and the CLI (use platform-metadata-discovery-get), retrieving source (platform-metadata-retrieve), or Data Cloud DLO and DMO schema (data360-code-extension-generate)."
|
|
4
|
+
metadata:
|
|
5
|
+
relatedSkills:
|
|
6
|
+
- data360-code-extension-generate
|
|
7
|
+
- platform-metadata-discovery-get
|
|
8
|
+
- platform-metadata-retrieve
|
|
9
|
+
version: "2.2"
|
|
10
|
+
accessCheck: "CDP.orgHasUnifiedCatalogProvisioned"
|
|
11
|
+
domains:
|
|
12
|
+
- "Platform"
|
|
13
|
+
mcpTools:
|
|
14
|
+
metadata-grounding:
|
|
15
|
+
tools:
|
|
16
|
+
- "search_metadata"
|
|
17
|
+
- "query_metadata"
|
|
18
|
+
- "describe_metadata"
|
|
19
|
+
semver: ">=1.0.0"
|
|
20
|
+
headless-360:
|
|
21
|
+
tools:
|
|
22
|
+
- "describe"
|
|
23
|
+
- "dispatch"
|
|
24
|
+
- "dispatch_readonly"
|
|
25
|
+
semver: ">=1.0.0"
|
|
26
|
+
cliTools:
|
|
27
|
+
- tool:
|
|
28
|
+
- "sf"
|
|
29
|
+
semver: ">=2.0.0"
|
|
30
|
+
id: "platform-metadata-grounding-get"
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
# Salesforce Metadata Grounding
|
|
34
|
+
|
|
35
|
+
Metadata grounding searches the org's Salesforce Catalog, an index of the org's metadata with names, labels, descriptions, and configuration properties. It finds metadata by meaning, so "customer rewards status" can find a field labeled Loyalty Tier. It has three read-only operations: search, query, and describe.
|
|
36
|
+
|
|
37
|
+
Results are ranked and capped. They are never a complete list, and grounding never returns source.
|
|
38
|
+
|
|
39
|
+
## When Not to Use Grounding
|
|
40
|
+
|
|
41
|
+
- Questions about standard Salesforce features or product behavior that do not depend on this org.
|
|
42
|
+
- A name you already know. Check it with scoped SOQL, which is exact and real time.
|
|
43
|
+
- A complete list, a count, or proof that something does not exist. Use scoped SOQL or `sf org list metadata`.
|
|
44
|
+
- Source to edit or deploy. Retrieve it with `platform-metadata-retrieve`.
|
|
45
|
+
- Where something is used, or what breaks if it changes. Grounding has no reference data.
|
|
46
|
+
- Metadata already returned in this conversation that has not changed since.
|
|
47
|
+
|
|
48
|
+
`platform-metadata-discovery-get` picks the right tool for each of these.
|
|
49
|
+
|
|
50
|
+
## Pick the Server
|
|
51
|
+
|
|
52
|
+
Two servers reach the same catalog and return the same results. Use one server per request, never both for the same lookup.
|
|
53
|
+
|
|
54
|
+
The Salesforce MCP is shown in Setup today as the Headless360 (H360) MCP Server. On that server, `searchMetadata`, `queryMetadata`, and `describeMetadata` are operation ids that you pass to `describe` and `dispatch`. They are not tool names. The tools `search_metadata`, `query_metadata`, and `describe_metadata` exist only on the Metadata Grounding MCP.
|
|
55
|
+
|
|
56
|
+
| Order | Server | How to call |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| 1 | Metadata Grounding MCP | Call `search_metadata`, `query_metadata`, or `describe_metadata` with the inputs below. |
|
|
59
|
+
| 2 | Salesforce MCP, when the Metadata Grounding MCP is not connected or keeps failing | Call `describe` on the operation id `searchMetadata`, `queryMetadata`, or `describeMetadata`. Do not use `discover`, and do not describe the grounding recipe, which is too large to read. Then call the path `describe` returns with the same inputs. Use `dispatch_readonly` for `searchMetadata` and pass the inputs as query parameters. Use `dispatch` for `queryMetadata` and `describeMetadata`, which are POST calls but only read, and pass the inputs as the JSON body. Do not use other metadata search operations. |
|
|
60
|
+
| Neither connected | | Grounding is not available. Use the name and label fallback in `platform-metadata-discovery-get`. |
|
|
61
|
+
|
|
62
|
+
## When a Call Fails
|
|
63
|
+
|
|
64
|
+
| What happens | What to do |
|
|
65
|
+
|---|---|
|
|
66
|
+
| The error says Salesforce Catalog is not enabled, or the user lacks the Customize Application permission | Stop using grounding on both servers for the rest of the session. Use the fallback and tell the user why, once. |
|
|
67
|
+
| Any other error or a timeout | Retry once. If it fails again, use the next server for this request. After failures on two requests, use the next server for the rest of the session. |
|
|
68
|
+
| The tool or server is not present | Start with the next server. |
|
|
69
|
+
|
|
70
|
+
A missing tool, an access error, or a 404 is not proof that the metadata does not exist.
|
|
71
|
+
|
|
72
|
+
## Response Shapes
|
|
73
|
+
|
|
74
|
+
| Call | Metadata Grounding MCP | Salesforce MCP |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| Search | `{results, totalCount}` | Same payload in the response body |
|
|
77
|
+
| Describe and query | Wrapped as `{defaultExc: "<json string>", responseCode}`. Parse the `defaultExc` string to read `types`, `typeDetails`, or `records`. | Payload in the response body, not wrapped |
|
|
78
|
+
| Error | An array of `{errorCode, message}` | Same array in the response body |
|
|
79
|
+
|
|
80
|
+
Handle both shapes. If the response has a `defaultExc` string, parse it. Otherwise read the payload directly.
|
|
81
|
+
|
|
82
|
+
## Catalog Type Names
|
|
83
|
+
|
|
84
|
+
Type names are case-sensitive, and some differ from Metadata API names.
|
|
85
|
+
|
|
86
|
+
| Metadata API name | Catalog type |
|
|
87
|
+
|---|---|
|
|
88
|
+
| CustomObject | `SObject` (subtypes `CustomObject`, `StandardData`) |
|
|
89
|
+
| CustomField | `SObjectField` (subtypes `CustomField`, `StandardField`, `CustomPersonAccountField`) |
|
|
90
|
+
| GlobalValueSet, StandardValueSet | `PicklistValueSet` (subtypes `Global`, `Standard`, `Local`) |
|
|
91
|
+
| FlexiPage | `Flexipage` |
|
|
92
|
+
| CustomTab | `Tab` |
|
|
93
|
+
| CustomApplication | `TabSet` |
|
|
94
|
+
| QuickAction | `QuickActionDefinition` |
|
|
95
|
+
| Queue | `Group` with subtype `Queue` |
|
|
96
|
+
| Role | `UserRole` |
|
|
97
|
+
|
|
98
|
+
Most other types use the Metadata API name, for example `ApexClass`, `ApexTrigger`, `Flow`, `PermissionSet`, `PermissionSetGroup`, `Profile`, `ValidationRule`, `RecordType`, `SharingRule`, `FieldPermissions`, `PicklistValue`, and `CustomPermission`.
|
|
99
|
+
|
|
100
|
+
Call describe with no `requests` only when a type you need is in neither list, and read only the type names. The full response is about 29K characters. Call describe with a `metadataType` only when you need that type's properties.
|
|
101
|
+
|
|
102
|
+
## Search
|
|
103
|
+
|
|
104
|
+
Inputs:
|
|
105
|
+
- `query`: required plain-language phrase. An empty query returns `ILLEGAL_QUERY_PARAMETER_VALUE`.
|
|
106
|
+
- `metadataType`: optional catalog type name.
|
|
107
|
+
- `metadataSubType`: optional single value. It requires `metadataType`.
|
|
108
|
+
- `parentIdentifier`: optional, to search inside one object or permission container.
|
|
109
|
+
- `limit`: 1 to 100, default 50. Use 10 to 20.
|
|
110
|
+
|
|
111
|
+
How to search well:
|
|
112
|
+
1. **Filter by type when you can.** For broad questions, run a few searches on likely types, such as `SObject`, `SObjectField`, and `Flow`, instead of one unfiltered search.
|
|
113
|
+
2. **Search inside an object** by passing its returned identifier as `parentIdentifier`. First search `SObject` for the exact object API name, or reuse a field result's `parentIdentifier`, then copy the identifier unchanged. Never pass the raw object API name. This finds fields related to a topic. It is not a full field list.
|
|
114
|
+
3. **Try one more phrasing** with synonyms or likely labels before you report "no match found in the org catalog."
|
|
115
|
+
4. **Trust the service's exposure policy.** Do not infer visibility or support from API-name suffixes. Keep results relevant to the user's requested domain; intentionally exposed Data Cloud metadata must remain available when it is relevant.
|
|
116
|
+
5. **Stop at search** when names, labels, and descriptions answer the question. Do not query after a search that returned nothing.
|
|
117
|
+
|
|
118
|
+
## Query
|
|
119
|
+
|
|
120
|
+
Query returns full records with type-specific `properties`, such as a field's data type, required flag, length, formula, default, help text, and picklist value set.
|
|
121
|
+
|
|
122
|
+
Send exactly one of:
|
|
123
|
+
- `metadataIdentifiers`: 1 to 50 identifiers, to read the records themselves.
|
|
124
|
+
- `parentIdentifiers`: 1 to 10 identifiers, to read their child records.
|
|
125
|
+
|
|
126
|
+
Use `parentIdentifiers` for picklist values: search `PicklistValueSet` for the field, then pass the value set's identifier. Do not pass an object. That returns every field on it, which is very large (about 77KB for Contact). For a full field list, use scoped SOQL on `EntityParticle`.
|
|
127
|
+
|
|
128
|
+
Identifiers have three parts separated by `::`: the 18-character org id, the name, and the type. Use only identifiers the tools returned. Never build, shorten, or edit one.
|
|
129
|
+
|
|
130
|
+
## Common Patterns
|
|
131
|
+
|
|
132
|
+
**Is there a field for this already?** Search `SObjectField` with the user's words and the object's `parentIdentifier`. Show the best matches with API name, label, and description.
|
|
133
|
+
|
|
134
|
+
**How is this field configured?** Search for the field, then query its identifier and read `properties`.
|
|
135
|
+
|
|
136
|
+
**What values does this picklist have?** Search `PicklistValueSet` for the field, then query the value set with `parentIdentifiers`.
|
|
137
|
+
|
|
138
|
+
**Who can read or edit this field?** Search `FieldPermissions` with the field's API name, such as `Contact.Loyalty_Tier__c`. Each result's parent is a profile or permission set. Query the results to read the read and edit flags. Results stop at 100, so for a complete list use scoped SOQL on `FieldPermissions`.
|
|
139
|
+
|
|
140
|
+
**What does this validation rule enforce?** Search `ValidationRule`, then query it for the formula, error message, and active flag.
|
|
141
|
+
|
|
142
|
+
## Limits
|
|
143
|
+
|
|
144
|
+
- **Flows:** the header only, meaning process type, trigger type, trigger object, and active status. No elements or logic. Trigger object is not a filter, so searching cannot list every flow on an object.
|
|
145
|
+
- **Apex:** signatures only, no method bodies. Managed classes return an empty stub.
|
|
146
|
+
- **Pages and actions:** `Flexipage` and `QuickActionDefinition` records are not children of their object. Searching with the object as `parentIdentifier` does not find them. Search by meaning instead.
|
|
147
|
+
- **Not in the catalog:** page layouts, reports, custom metadata types, and custom settings.
|
|
148
|
+
- **Freshness:** the catalog can take several minutes to reflect deploys and other changes. For anything changed in this session, trust the deploy results and confirm with SOQL, which is real time.
|
|
149
|
+
|
|
150
|
+
## Grounding Discipline
|
|
151
|
+
|
|
152
|
+
- Cite the API names, labels, and properties the tools returned. Say which statements are observed and which are inferred.
|
|
153
|
+
- Say "no match found in the org catalog." Never say the metadata does not exist.
|
|
154
|
+
- Never treat results as a complete list.
|
|
155
|
+
- Never write or deploy files built from query output. It returns properties, not source.
|
|
156
|
+
- Every identifier starts with the org id. If you also use the CLI or another tool, confirm both point to the same org before you combine results.
|
|
157
|
+
|
|
158
|
+
<!-- skill-validate: ignore-start -->
|
|
159
|
+
<!-- codey:operations start -->
|
|
160
|
+
## Operations Reference
|
|
161
|
+
|
|
162
|
+
Operations this skill uses — routing and dependency reference.
|
|
163
|
+
|
|
164
|
+
| Operation | Purpose | Status | Call | Depends on |
|
|
165
|
+
|-----------|---------|--------|------|------------|
|
|
166
|
+
| `describe-metadata` | read | — | `POST /metadata-grounding/schema` | — |
|
|
167
|
+
| `search-metadata` | read | — | `GET /metadata-grounding/search` | — |
|
|
168
|
+
| `query-metadata` | read | — | `POST /metadata-grounding/query` | — |
|
|
169
|
+
<!-- codey:operations end -->
|
|
170
|
+
<!-- skill-validate: ignore-end -->
|
|
@@ -1,273 +1,125 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-policy-rule-generate
|
|
3
|
-
description: "
|
|
3
|
+
description: "THE skill for creating a Data Cloud / Data Governance access policy — authors and deploys a PolicyRuleDefinitionSet + PolicyRuleDefinition pair (CRUD) covering OLS, FLS, RLS, masking/transform, and tag/classification-based access for the DATACLOUD or ALL consumer. TRIGGER when the user wants to create/write/author a Data Cloud or Data Governance policy, access policy, or policy rule, or to grant access to a Data Cloud object THROUGH A POLICY — a Data Cloud policy-create request routes here, not to the tag/classification surface. Resolves every reference via Data 360 MCP. SCOPE: Data Cloud policies only (not Security Center, DSAR, or User Access Policies). DO NOT TRIGGER to create tags/classifications, or to grant object/dataspace access via a PERMISSION SET / RBAC grant (use platform-dataspace-access-configure). For a vague object-access ask, surface both skills and ASK the permission-set way vs the policy way; if unsure the object is Data Cloud, ask which first."
|
|
4
4
|
metadata:
|
|
5
|
-
|
|
5
|
+
relatedSkills:
|
|
6
|
+
- "platform-dataspace-access-configure"
|
|
7
|
+
version: "2.0"
|
|
6
8
|
domains: ["Platform", "Data 360"]
|
|
7
|
-
minApiVersion: "
|
|
9
|
+
minApiVersion: "66.0"
|
|
8
10
|
cliTools:
|
|
9
11
|
- tool: ["jq"]
|
|
10
12
|
semver: ">=1.6.0"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
mcpTools:
|
|
14
|
+
data360:
|
|
15
|
+
tools: ["execute", "payload_examples", "search"]
|
|
16
|
+
semver: ">=1.0.0"
|
|
17
|
+
headless-360:
|
|
18
|
+
tools: ["discover", "describe", "dispatch", "dispatch_readonly"]
|
|
19
|
+
semver: ">=1.0.0"
|
|
13
20
|
---
|
|
14
21
|
|
|
15
|
-
#
|
|
22
|
+
# Generate Policy Rule Metadata
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
**Min API version:** 64.0 (66.0 for conditions using `PolicyJsonExpression`).
|
|
24
|
+
This skill generates H360 policy metadata for the explicit `DATACLOUD` or `ALL` consumer. OLS, FLS, RLS, and Transform are shared policy shapes; `DATACLOUD` additionally requires the Data Governance Policy Builder contract. `ALL` uses the general metadata/runtime contract and does not inherit DG UI restrictions.
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
## When to use this skill (routing)
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
> **Eval coverage:** This skill is exercised by the team's ADK eval framework, not by `tests/evals/` under the skill directory. Five datasets covering the ACCESS / GOVERNANCE / RECORD / TRANSFORM variants live in `packages/adk-eval/eval/domains/platform-policy-rule-generate/datasets/`.
|
|
25
|
-
|
|
26
|
-
## 1. Package Layout
|
|
27
|
-
|
|
28
|
-
A deployable package always contains:
|
|
29
|
-
|
|
30
|
-
```text
|
|
31
|
-
<fixture>/
|
|
32
|
-
package.xml
|
|
33
|
-
policyRuleDefinitionSets/<setName>.policyRuleDefinitionSet
|
|
34
|
-
policyRuleDefinitions/<ruleName>.policyRuleDefinition
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
`package.xml` template (use `<version>[ftest]</version>` for ftests, `64.0` or higher for real orgs):
|
|
38
|
-
|
|
39
|
-
```xml
|
|
40
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
41
|
-
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
42
|
-
<types>
|
|
43
|
-
<members>Rule0</members>
|
|
44
|
-
<name>PolicyRuleDefinition</name>
|
|
45
|
-
</types>
|
|
46
|
-
<types>
|
|
47
|
-
<members>Set1</members>
|
|
48
|
-
<name>PolicyRuleDefinitionSet</name>
|
|
49
|
-
</types>
|
|
50
|
-
<version>64.0</version>
|
|
51
|
-
</Package>
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## 2. PolicyRuleDefinitionSet Schema
|
|
57
|
-
|
|
58
|
-
```xml
|
|
59
|
-
<PolicyRuleDefinitionSet xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
60
|
-
<label>Set1</label>
|
|
61
|
-
<description>Optional free text</description>
|
|
62
|
-
<replicated>false</replicated> <!-- MinAppVersion 260 -->
|
|
63
|
-
<builderCompatible>true</builderCompatible> <!-- MinAppVersion 262, author-settable -->
|
|
64
|
-
<!-- builderValidated: server-managed — do not set in authored XML -->
|
|
65
|
-
</PolicyRuleDefinitionSet>
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
| Element | Req | Notes |
|
|
69
|
-
|---------|-----|-------|
|
|
70
|
-
| `<label>` | yes | Master label. File basename (devName) is the MDAPI identifier, not the label. |
|
|
71
|
-
| `<description>` | no | Free text. |
|
|
72
|
-
| `<replicated>` | no | `true` triggers placeholder transformation across companion orgs. Omit for null/false. |
|
|
73
|
-
| `<builderCompatible>` | no | `true` = rules audited per §7 checklist. `false` = API-only. Omit = unaudited. Informational only — no deploy/runtime effect. |
|
|
74
|
-
| `<builderValidated>` | no | **Server-managed. Never set in authored XML.** Server overwrites on validation. |
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## 3. PolicyRuleDefinition — Core Fields
|
|
79
|
-
|
|
80
|
-
| Element | Req | Notes |
|
|
81
|
-
|---------|-----|-------|
|
|
82
|
-
| `<label>` | yes | MasterLabel. |
|
|
83
|
-
| `<category>` | yes | See §4. Drives `resourceScopeType` and whether `policyRuleResourceDomains`/`resourceTransform` are required. **Does NOT constrain `effect` outside of TRANSFORM.** |
|
|
84
|
-
| `<effect>` | yes | `Permit`, `Forbid`, or `Transform`. The only category-coupling enforced by core: `effect=Transform ↔ category=TRANSFORM_POLICY_RULE_DEFINITION` (bidirectional). All other categories accept Permit and Forbid freely. |
|
|
85
|
-
| `<action>` | yes (≥1) | `Read`, `TupleRead`, `Create`, etc. Multiple elements OR-combine. |
|
|
86
|
-
| `<policyRuleDefinitionSetName>` | yes | Developer name of parent set. |
|
|
87
|
-
| `<principalScopeType>` | yes | Always `ANY`. |
|
|
88
|
-
| `<resourceScopeType>` | yes | `ANY`, `FIELD`, `RECORD`, `DATASPACE`, or `SPAN`. Must match category (§4). |
|
|
89
|
-
| `<principalAuthenticationLevel>` | no | `INTERNAL`, `AUTHENTICATED`, `UNIDENTIFIED`, `IDENTIFIED`. |
|
|
90
|
-
| `<ruleConsumer>` | no | `ALL`, `DATACLOUD`, `MULESOFT`, `TABLEAU`, `CORE`. |
|
|
91
|
-
| `<policyRuleResourceDomains>` | no | Required for RECORD (RLS) and FIELD-scope TRANSFORM rules only. Forbidden on ACCESS/GOVERNANCE. |
|
|
92
|
-
| `<resourceTransform>` | no | Required (and only valid) when `category=TRANSFORM`. |
|
|
93
|
-
| `<whenPolicyRuleDefinitionClauseConjunction>` | no | WHEN conditions. |
|
|
94
|
-
| `<unlessPolicyRuleDefinitionClauseConjunction>` | no | UNLESS conditions. Not UI-editable — prefer WHEN + negated operator. |
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
## 4. Category Decision Tree
|
|
28
|
+
This is the single entry point for **creating a Data Cloud / Data Governance access policy** (a `PolicyRuleDefinitionSet` + `PolicyRuleDefinition` pair). Any request to *create / write / author a policy, an access policy, a data governance policy, a Data Cloud policy, or a policy rule* (OLS / FLS / RLS / masking / tag- or classification-based object access) **whose target is Data Cloud** routes here — **do not** hand a Data Cloud policy-create request to the Data Governance tag/classification surface; that surface owns tags and classifications, not policy authoring.
|
|
99
29
|
|
|
100
|
-
**
|
|
30
|
+
**Scope today: Data Cloud policies only.** This skill covers Data Cloud / Data Governance access policies. It does **not** yet cover core administrative policies, CMDB policies, or other non-Data-Cloud policy types (those are a planned future extension), and it is **not** the route for Security Center security policies, DSAR policies, or User Access Policies — leave those to their own core surfaces. If a policy-create request does not name Data Cloud and it is unclear whether the target object is a Data Cloud object, **ask which object first** (or whether it is Data Cloud) before routing here; core access-control surfaces (e.g. `scoped-access`) surfacing for a non-Data-Cloud request is legitimate.
|
|
101
31
|
|
|
102
|
-
|
|
32
|
+
Two adjacent skills, and how this one relates:
|
|
103
33
|
|
|
104
|
-
-
|
|
105
|
-
-
|
|
34
|
+
- **Data Governance tags / classifications** (create a tag, create/assign a classification, list governance tags): that is a *different* surface (`data360` Data Governance). This skill only *consumes* already-existing tags/classifications as policy references — it does not create them.
|
|
35
|
+
- **`platform-dataspace-access-configure`** — the **permission-set / RBAC** way to grant object or dataspace access (PermissionSet `dataspaceScopes` + the Object Access Grants Connect API). Data-space access grants go there.
|
|
106
36
|
|
|
107
|
-
|
|
37
|
+
**Object access can be granted two ways — infer from context, ask only when vague.** For a Data Cloud / Data Governance object-access request, read the framing before acting:
|
|
108
38
|
|
|
109
|
-
|
|
39
|
+
- The user is **driving from a permission set** (mentions a permission set, RBAC, or an object grant on a permset) → this is an **object access grant** → route to `platform-dataspace-access-configure`, no need to ask.
|
|
40
|
+
- The user **frames it as a policy** (says policy, access policy, policy rule, OLS/FLS/RLS, tag/classification-based) → **create the policy here**, no need to ask.
|
|
41
|
+
- The request is **genuinely vague** — "grant object access to X" with no mechanism and no clue → **ASK** whether they want the **permission-set way** (`platform-dataspace-access-configure`) or the **access-policy way** (this skill). If it is also unclear whether the object is Data Cloud, ask which object first.
|
|
110
42
|
|
|
111
|
-
|
|
112
|
-
What kind of policy?
|
|
113
|
-
│
|
|
114
|
-
├── OLS/FLS allow/deny on tagged or classified resources
|
|
115
|
-
│ category = ACCESS_POLICY_RULE_DEFINITION (allow/deny attestation in the access plane)
|
|
116
|
-
│ | GOVERNANCE_POLICY_RULE_DEFINITION (governance-audited)
|
|
117
|
-
│ effect = Permit | Forbid (chosen independently from category)
|
|
118
|
-
│ resourceScopeType = ANY | FIELD | DATASPACE
|
|
119
|
-
│ NO <policyRuleResourceDomains>
|
|
120
|
-
│ condition: resourcePath=TAG|CLASSIFICATION CONTAINS_ANY <ref>
|
|
121
|
-
│ For "objects AND all their fields" → action=TupleRead + OR-of-ENTITYTYPE clause (§7)
|
|
122
|
-
│ Note: "Block access to Foo object" → tag Foo with <yourTag>, write rule on tag
|
|
123
|
-
│ Do NOT use <resourceDomain>Foo</resourceDomain> — forbidden for ACCESS/GOVERNANCE
|
|
124
|
-
│
|
|
125
|
-
├── Row-level filter on a DMO/DLO
|
|
126
|
-
│ category = RECORD_POLICY_RULE_DEFINITION
|
|
127
|
-
│ effect = Permit | Forbid
|
|
128
|
-
│ resourceScopeType = RECORD
|
|
129
|
-
│ <policyRuleResourceDomains> = the DMO/DLO API name ← entity targeting allowed here
|
|
130
|
-
│
|
|
131
|
-
├── Identified-Guest record access
|
|
132
|
-
│ NOT authorable via MDAPI — SESSION_CONSUMER_ID is not in RuleContextPathType
|
|
133
|
-
│ Must be implemented as a runtime RuleProvider.
|
|
134
|
-
│
|
|
135
|
-
└── Field masking
|
|
136
|
-
category = TRANSFORM_POLICY_RULE_DEFINITION ← required by RuleBuilder validator
|
|
137
|
-
effect = Transform ← required by RuleBuilder validator
|
|
138
|
-
resourceScopeType = FIELD (structured) or SPAN (unstructured)
|
|
139
|
-
<policyRuleResourceDomains> = the DMO whose field is masked
|
|
140
|
-
<resourceTransform> required (e.g. NULL_RESOURCE_TRANSFORM, LAST_N_CHARS_RESOURCE_TRANSFORM)
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### ACCESS vs GOVERNANCE — how to choose
|
|
144
|
-
|
|
145
|
-
Both legally accept Permit and Forbid. Pick by *which enforcement layer should record/audit the rule* and **what the prompt literally asks for**:
|
|
146
|
-
|
|
147
|
-
| Use case | Pick | Reason |
|
|
148
|
-
|---|---|---|
|
|
149
|
-
| The prompt names "ACCESS policy rule" / "access rule" / "OLS/FLS" explicitly | `ACCESS_POLICY_RULE_DEFINITION` | Matches the prompt's vocabulary; sits in the data-access enforcement layer. |
|
|
150
|
-
| The prompt names "governance" / "audit" / "policy framework" / data-residency or compliance language | `GOVERNANCE_POLICY_RULE_DEFINITION` | Matches the prompt's vocabulary; rules surface in governance reporting. |
|
|
151
|
-
| Prompt is ambiguous and only describes allow/deny semantics | Default to `ACCESS` for Permit, `GOVERNANCE` for Forbid (mirrors the platform's auto-fill default; safe and deployable, but **not required**) |
|
|
152
|
-
|
|
153
|
-
> **Important — honor the explicit category in the prompt.** If the prompt says "ACCESS policy rule that denies …" or "GOVERNANCE policy rule that permits …", emit exactly that category. Do not silently swap to the auto-fill default just because effect is Forbid (or Permit). The platform accepts both. The agent must not override the user's stated intent.
|
|
154
|
-
|
|
155
|
-
**Scope × category compatibility** — any combination outside this matrix throws `INVALIDFORCATEGORY`:
|
|
156
|
-
|
|
157
|
-
| | `ACCESS` | `GOVERNANCE` | `TRANSFORM` | `RECORD` |
|
|
158
|
-
|------------|:--------:|:------------:|:-----------:|:--------:|
|
|
159
|
-
| `ANY` | Yes | Yes | No | No |
|
|
160
|
-
| `DATASPACE`| Yes | Yes | No | No |
|
|
161
|
-
| `FIELD` | Yes | Yes | Yes | No |
|
|
162
|
-
| `RECORD` | No | No | No | Yes |
|
|
163
|
-
| `SPAN` | No | No | Yes | No |
|
|
164
|
-
|
|
165
|
-
---
|
|
166
|
-
|
|
167
|
-
## 5. Condition Patterns (Quick Reference)
|
|
168
|
-
|
|
169
|
-
Every `<conditions>` block needs **all four**: `<clause>`, `<operator>`, one path element, and the value.
|
|
43
|
+
"Access to a **data space**" is the permission-set path — route it to `platform-dataspace-access-configure`.
|
|
170
44
|
|
|
171
|
-
|
|
172
|
-
|------|-------------|----------|-------|
|
|
173
|
-
| Resource has tag | `<resourcePath>TAG</resourcePath>` | `CONTAINS_ANY` | `<valueReferenceType>CUSTOM_TAG` \| `STANDARD_TAG</valueReferenceType>` |
|
|
174
|
-
| Resource has classification | `<resourcePath>CLASSIFICATION</resourcePath>` | `CONTAINS_ANY` | `CUSTOM_CLASSIFICATION` \| `STANDARD_CLASSIFICATION` |
|
|
175
|
-
| Principal has permission | `<principalPath>ASSIGNED_PERMISSIONS_PATH</principalPath>` | `CONTAINS_ANY` \| `CONTAINS_NONE` | `<valueReferenceType>CUSTOM_PERMISSION</valueReferenceType>` |
|
|
176
|
-
| Session in dataspace | `<contextPath>SESSION_DATASPACE</contextPath>` | `CONTAINS_ANY` | `<valueReferenceType>DATASPACE</valueReferenceType>` |
|
|
177
|
-
| Record field = user attribute | `<resourcePath>RECORDFIELD</resourcePath>` + `<valueDomain>Schema:field</valueDomain>` | `EQUALS` | `<valuePrincipalPath>USER_ID` \| `ORGANIZATION_ID` \| `USER_ROLE_ID</valuePrincipalPath>` |
|
|
178
|
-
| Entity type check | `<resourcePath>ENTITYTYPE</resourcePath>` | `IS` | `<valueString>{"t":"Text","v":"FIELD"}</valueString>` |
|
|
45
|
+
H360 policy **create / read / update** run over the headless-360 MCP `/headless/metadata` MD-CRUD path via `dispatch`: `discover`/`describe` the operation, then `dispatch` a POST create / PUT update of the generated XML and `dispatch_readonly` GET it back to verify. See `references/headless-transport.md` for the exact request/response shapes. There is **no `sf`/MDAPI fallback** — if the headless-360 MCP session is unavailable, or the type/op is not yet on the MD-CRUD allowlist (`400 UNSUPPORTED_OPERATION`), or the org lacks feature provisioning (`400 FIELD_INTEGRITY_EXCEPTION`), surface that gap to the operator rather than routing around it. This skill covers **create, read, update, and delete (CRUD)**. **Delete does NOT run over `/headless/metadata`** — Core has no real metadata delete (a metadata DELETE 405s, and the interim delete is a no-op 200 that removes nothing), so a policy is deleted over the Data 360 MCP **Data Governance Access Policy** surface (`d360_data_governance_access_policy_delete`), which removes the Access Policy and every embedded rule by developer name. See the "Deleting a Policy" section below. Use the Data 360 MCP tools to resolve exact org references before writing XML — `search`/`payload_examples`/`execute` against read-only lookup operations (tag, classification, dataspace, and every resource object: custom/derived DMO via `d360_dmo_list`/`d360_dmo_get`, standard DMO via `d360_data_model_objects_list`/`d360_data_model_object_get`, DLO via `d360_dlo_list`/`d360_dlo_get`, calculated insight object via `d360_ci_list`/`d360_ci_get`). Only when no Data 360 MCP session is reachable, resolve a custom `__dlm` DMO's fields by a read-only headless-360 `dispatch_readonly` sObject describe as a last resort (it can miss `__dlm` objects — see `references/reference-resolution.md`). Author **creates and updates only** over `/headless/metadata` MD-CRUD — never via a Data 360 MCP `_create`/`_update` operation; the Data 360 MCP mutation surface is used only for **delete** (`access_policy_delete`, whole-policy) and, to remove a single rule while keeping the policy, `access_policy_rule_replace`. All tag/classification/dataspace/DMO/DLO/CIO lookups stay read-only. Never resolve a reference through an `sf` CLI command.
|
|
179
46
|
|
|
180
|
-
|
|
47
|
+
## Deterministic Workflow
|
|
181
48
|
|
|
182
|
-
|
|
183
|
-
|
|
49
|
+
1. Require `consumer`: accept only `DATACLOUD` or `ALL`; do not infer or default it.
|
|
50
|
+
2. Select the operating mode. Use normal author mode unless the request explicitly says to recreate a named retrieved evidence package exactly. In explicit evidence-recreation mode, the named API 69.0 example is authoritative: preserve its condition order, exact conjunctions, persisted `SCALAR_ATTRIBUTE`/`SOQLTARGETLISTEXPR` operands, and evidence values, while omitting `builderCompatible` and `builderValidated`. Exact recreation takes precedence over normal authoring rewrites and target-org re-resolution. It proves only evidence fidelity, not current-org authorability, runtime enforcement, or Policy Builder validation.
|
|
51
|
+
3. Identify the policy set developer name and rule developer name.
|
|
52
|
+
4. Choose the shared policy shape, category, effect, action, and resource scope **deterministically from the request signal** — do not ask the user "is this OLS/RLS/FLS?" when the signal is clear (read of a specific named object → RLS; hide a field → FLS; mask a field value → Transform; tag/classification tenant-wide → OLS). See `references/policy-shapes.md#selecting-the-shape-deterministic--do-not-ask-the-user`. Every renderable rule MUST carry **at least one resource condition** (principal conditions are optional; a zero-conditions or principal-only rule is not deployable/renderable) — if the shape has no valid resource condition (e.g. object-wide read with no row filter), obtain a resource condition or route object-wide read to the permission-set path (`platform-dataspace-access-configure`) rather than authoring an unrenderable rule.
|
|
53
|
+
5. In normal author mode, resolve every tag, classification, custom permission, DMO/DLO, field, resource domain, join field, and principal field in the target org through MCP — never through an `sf` CLI command. Resolve tags, classifications, dataspaces, and every resource object's schema and fields through the Data 360 MCP read-only lookup operations from `references/reference-resolution.md#data-360-mcp-lookup-operations`. Resource objects are not only DMOs — resolve custom/derived DMOs (the `__dlm` suffix that most `resourceDomains` entries target) via `d360_dmo_list`/`d360_dmo_get` (family `DataModelObject`), standard/canonical DMOs via `d360_data_model_objects_list`/`d360_data_model_object_get` (family `DataModelObjectCatalog`), raw ingested DLOs via `d360_dlo_list`/`d360_dlo_get`, and calculated insight objects (CIOs) via `d360_ci_list`/`d360_ci_get`. `d360_dmo_get` returns the DMO with all field definitions; pass `includeFields:"true"` to `d360_dmo_list`. Only when no Data 360 MCP session is reachable, resolve a custom `__dlm` DMO's field API names with a read-only headless-360 `dispatch_readonly` sObject describe as a last resort — it can miss `__dlm` objects that are absent from the sObjects surface, so prefer `d360_dmo_get` whenever Data 360 MCP is available. For custom permissions and ID-valued principal comparisons (e.g. `ProfileId`), for which no Data 360 MCP lookup exists, resolve read-only through `dispatch_readonly` (a SOQL `/query` or metadata read). The MCP path addresses the org implicitly and `/headless/metadata` resolves the API version server-side, so no `ORG_ID`/`ORG_API_VERSION` resolution is needed; evidence-recreation fixtures retain the `{API_VERSION}` placeholder for the eval harness. User-provided values may be developer names, fully qualified names, labels, or partial descriptions: resolve each to the exact target-org developer/API name before generating XML. A Data 360 MCP lookup result's `id` is not the value to persist unless the field itself is ID-valued (e.g. `ProfileId`). For STANDARD_TAG/STANDARD_CLASSIFICATION `<valueReference>` values, construct the dotted path per `references/reference-resolution.md#constructing-valuereference-for-standard_tag--standard_classification` — it is not a single-field copy from the lookup record. For other `<valueDomain>`/`<select>` values, take the resolved developer/API name from the same record. When a label or description matches a reference, retain the resolved developer/API name in the metadata and do not emit the label unless the schema explicitly requires a label. Never invent reference names, infer a developer name from a label, or reuse evidence-package values.
|
|
54
|
+
6. Construct the shared policy model from `references/condition-model.md`; reject `PLACEHOLDER` because it is internal-only.
|
|
55
|
+
7. In normal author mode, if `consumer=DATACLOUD`, apply `references/consumer-datacloud-ui.md`: build a typed custom-conjunction plan for the API/UI projection, serialize it as nested MDAPI `conjunctionExpression` `AND`/`OR` groups, enforce one action and one resource domain, reject plural principal attributes, and validate directional scalar/RLS capabilities. If `consumer=ALL`, apply only `references/consumer-all.md` and base validation; make no UI-renderability claim. In evidence-recreation mode, preserve the named example's exact conjunction instead of recompiling it.
|
|
56
|
+
8. Number conditions only after grouping is complete, validate complete conjunction coverage, then render XML. For evidence recreation, retain the evidence condition order and validate its existing numbering without rewriting it.
|
|
57
|
+
9. Author the set XML and the definition XML as two components, omitting `builderCompatible` and `builderValidated`. The MD-CRUD path takes each component's XML directly as `xmlRep` (see step 10) — no `package.xml`/manifest or `ORG_API_VERSION` interpolation is required. Eval fixtures retain the `{API_VERSION}` placeholder for the harness.
|
|
58
|
+
10. **Preview and confirm before writing.** The deterministic routing means no mid-flow clarifying questions; the single human checkpoint is here. Show the operator the resolved shape, target object/references, and the concrete rule (conditions + effect) and get an explicit go-ahead before the create/update dispatch. Then verify via the transport: flatten the generated `.policyRuleDefinitionSet`/`.policyRuleDefinition` XML to a single-line string (a defensive default — a properly-escaped multi-line `xmlRep` also persists, but single-line sidesteps any client that mangles newlines), `dispatch` a POST create (PUT for an update) to `/headless/metadata` for the set and then the rule, and `dispatch_readonly` GET each back to confirm a 2xx response. See `references/headless-transport.md` for the exact request/response shapes, the `xmlRep` newline guidance, and the transient-retry note. **UI-renderable-contract check:** the set read-back must carry server-added `<builderCompatible>false</builderCompatible>` and `<builderValidated>false</builderValidated>` even though neither was authored — `false` is EXPECTED for a hand-authored create ("not yet builder-validated," not "not renderable") and is the concrete signal the policy was accepted as a DG-builder-class object. Both flags remain server-managed; never author either one.
|
|
184
59
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
## 6. Validation Guardrails
|
|
188
|
-
|
|
189
|
-
1. Every `<conditions>` needs an `<operator>`. Missing operator → reject.
|
|
190
|
-
2. Every `<conditions>` needs at least one path element (`<resourcePath>`, `<principalPath>`, `<contextPath>`, or `<valueDomain>`).
|
|
191
|
-
3. `<contextPath>` is exclusively `SESSION_DATASPACE`. Never put a resource path value there.
|
|
192
|
-
4. Scope × category must be in the §4 matrix. Common offenders: ACCESS/GOVERNANCE + RECORD scope; RECORD + ANY/FIELD scope; TRANSFORM + ANY/RECORD scope. (Effect is independent of category except for TRANSFORM — see §4.)
|
|
193
|
-
5. `<resourceTransform>` and `effect=Transform` are coupled. Transform effect needs a resourceTransform. Permit/Forbid must not have one.
|
|
194
|
-
6. `<policyRuleResourceDomains>` is **required** for RECORD (RLS) and FIELD-scope TRANSFORM; **forbidden** on ACCESS/GOVERNANCE.
|
|
195
|
-
7. `<conjunctionExpression>` indices must match actual `<conditions>` count. Off-by-one → reject.
|
|
196
|
-
8. `<clause>` inside `<conditions>` must match the wrapper (`WHEN` inside `<when…>`, `UNLESS` inside `<unless…>`).
|
|
197
|
-
9. JSON literals in `<valueString>` must escape `"` to `"`. Wrong escaping silently corrupts the literal.
|
|
198
|
-
10. Reference targets (`<valueReference>`, `<resourceDomain>`) must exist in the target org at deploy time.
|
|
199
|
-
11. `SCALAR_ATTRIBUTE` / `PLURAL_ATTRIBUTE` are not in `RulePrincipalPathType` — not in MDAPI contract. Use a runtime RuleProvider for those shapes.
|
|
200
|
-
12. `IDENTIFIED_RECORD` is not authorable via MDAPI — `SESSION_CONSUMER_ID` not in `RuleContextPathType`.
|
|
201
|
-
13. Standard tag/classification dev names are fully-qualified dotted paths (e.g. `DataGovernanceTags.ExternalData.Visibility.Public`). Retrieve an existing rule to get the exact string before authoring.
|
|
202
|
-
14. Min API versions: `PolicyRuleDefinition` = 64.0; `PolicyJsonExpression` conditions = 66.0; `<replicated>` = 260+; `<builderCompatible>` / `<builderValidated>` = 262+.
|
|
203
|
-
|
|
204
|
-
> **Note on `<conjunctionExpression>` shape:** A bare top-level index (e.g. `<conjunctionExpression>1</conjunctionExpression>`) deploys cleanly — the server-side parser accepts bare tokens at the top level. It is **not** a deploy-time validation error. It does, however, crash the Data Governance Policy Builder UI on load — see §7.
|
|
205
|
-
|
|
206
|
-
---
|
|
60
|
+
## Deleting a Policy
|
|
207
61
|
|
|
208
|
-
|
|
62
|
+
Delete a policy over the Data 360 MCP **Data Governance Access Policy** surface, **not** `/headless/metadata` — Core has no real metadata delete (a metadata DELETE 405s or no-ops), so it never belongs on that transport. A `PolicyRuleDefinitionSet` authored by this skill surfaces there as an **Access Policy** addressable by its developer name. Because hand-authored sets land `builderCompatible: false`, an `access_policy_list` needs `includeIncompatible: true` to show them, but `access_policy_get` and `access_policy_delete` work by name regardless of builder-compatibility.
|
|
209
63
|
|
|
210
|
-
|
|
64
|
+
`d360_data_governance_access_policy_delete` takes a single `name` (the set's developer name) and is a **whole-policy delete**: one call removes the Access Policy **and every embedded rule** (its `PolicyRuleDefinition` members). There is therefore **no leaf-before-parent ordering** and **no discrete single-rule delete** — to drop one rule while keeping the policy, re-author the surviving rule set via `d360_data_governance_access_policy_rule_replace` instead. Confirm the delete by reading the policy back with `d360_data_governance_access_policy_get` by name: a not-found result (or the policy being absent from an `includeIncompatible` list) is the success signal. There is **no `sf` CLI fallback**.
|
|
211
65
|
|
|
212
|
-
|
|
66
|
+
## Validated Policy Shapes
|
|
213
67
|
|
|
214
|
-
|
|
215
|
-
- **Bare top-level condition index** in `<conjunctionExpression>` (e.g. `1`, or `(AND (OR 1 2) 3)`) → crash on builder load in `buildCriteria`. Deploy is unaffected, but the policy is uneditable in the UI. Always wrap: `(AND 1)` for a single condition; `(AND (OR 1 2) (AND 3))` instead of `(AND (OR 1 2) 3)`.
|
|
216
|
-
- `category = ACCESS_POLICY_RULE_DEFINITION` + `effect = Forbid` → the **Data Governance Policy Builder UI** (not MDAPI) collapses it to GOVERNANCE on save; round-trip via the builder will rewrite the category. MDAPI deploy is unaffected — the original ACCESS+Forbid combination is valid and deploys without modification. If your goal is UI round-trippability, prefer GOVERNANCE for Forbid; if the source of truth is MDAPI, ACCESS+Forbid is fine.
|
|
217
|
-
- Any `<unlessPolicyRuleDefinitionClauseConjunction>` block → silently dropped on first UI save.
|
|
218
|
-
- More than one `<action>` → only the first is kept.
|
|
219
|
-
- `ruleConsumer` ≠ `DATACLOUD` → UI hardcodes DATACLOUD on save.
|
|
220
|
-
- Top-level `(OR 1 2)` conjunction → triggers `// ERROR: Unsupported rule!` path, rule silently dropped.
|
|
68
|
+
For an object-level security policy with tags/classifications and principal conditions, begin with `references/examples/TaggedObjectAccess/`. Select the conjunction contract from the explicit consumer: `DATACLOUD` requires the UI custom-conjunction form; `ALL` uses the general form.
|
|
221
69
|
|
|
222
|
-
|
|
70
|
+
The real example has:
|
|
223
71
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
72
|
+
- One `PolicyRuleDefinitionSet`: `TaggedObjectAccess`.
|
|
73
|
+
- One `PolicyRuleDefinition`: `TaggedObjectAccess_Rule_1`.
|
|
74
|
+
- `GOVERNANCE_POLICY_RULE_DEFINITION`.
|
|
75
|
+
- `Permit` and `TupleRead`.
|
|
76
|
+
- `ANY` resource scope.
|
|
77
|
+
- Two entity-type conditions, one principal-permission condition, one principal-expression condition, and two tag conditions.
|
|
78
|
+
- A grouped conjunction expression: `(AND (OR 1 2) (AND 3 4) (AND 5 6))`.
|
|
229
79
|
|
|
230
|
-
For the
|
|
80
|
+
For the validated field-level security deny shape, use `references/examples/FieldReadDeny/`: `GOVERNANCE_POLICY_RULE_DEFINITION`, `Forbid`, `Read`, and one entity-type discriminator whose right operand is `FIELD`. This example validates the deny shape; it does not establish that every other FLS shape is invalid.
|
|
231
81
|
|
|
232
|
-
|
|
82
|
+
For the validated field-masking shape, use `references/examples/LastCharactersFieldMasking/`: `TRANSFORM_POLICY_RULE_DEFINITION`, `Transform`, `Read`, `FIELD` scope, an explicit `resourceTransform`, and one entity-type discriminator whose right operand is `FIELD`. The retrieved `LAST_N_CHARS_RESOURCE_TRANSFORM` uses a top-level `resourceExpression` of type `ARGLIST`; do not generalize its argument shape to other transforms.
|
|
233
83
|
|
|
234
|
-
|
|
84
|
+
For the validated row-level security shapes, use `references/examples/PrincipalFieldMatchRLS/` for direct record-field comparisons and `references/examples/ExistsJoinRLS/` for an `EXISTS` join block. Both use `RECORD_POLICY_RULE_DEFINITION`, `Permit`, `Read`, `RECORD` scope, and an exact target DMO in `policyRuleResourceDomains`. Resolve every DMO and field in the target org before authoring.
|
|
235
85
|
|
|
236
|
-
|
|
237
|
-
2. **Pick category first** (§4). Category fixes effect, resourceScopeType, and whether policyRuleResourceDomains/resourceTransform are required.
|
|
238
|
-
3. **Lay out the bare rule**: top-level fields only, no conditions. Match the category template in [`references/templates.md`](references/templates.md).
|
|
239
|
-
4. **Add conditions one at a time**, each with all four anchors: `<clause>`, `<operator>`, one path element, and the value.
|
|
240
|
-
5. **Update `<conjunctionExpression>`** — 1-indexed prefix notation. Bare top-level index (e.g. `1`) deploys but breaks the UI; wrap as `(AND 1)` if UI editability matters (§7).
|
|
241
|
-
6. **Run the UI-compatibility check** (§7 / [`references/ui-compatibility.md`](references/ui-compatibility.md)). If any item trips, attempt the "unless" rewrite first; if not possible, get explicit operator confirmation before continuing.
|
|
242
|
-
7. **Update `package.xml`** — list each `<members>` for both types.
|
|
243
|
-
8. **Set `<builderCompatible>`** on the set to `true` if §7 checklist passes; `false` if intentionally API-only.
|
|
244
|
-
9. **Sanity-check against §6 (guardrails)** before considering done.
|
|
245
|
-
10. **Validate with dry-run** before any non-dry deploy to a persistent org. Surface errors using the error reference in [`references/deploy-errors.md`](references/deploy-errors.md).
|
|
86
|
+
Dataspace-scoped OLS is parked and unsupported because the UI-retrieved references did not pass MDAPI validation in the source org. Do not construct it until a separately validated real-org shape is available.
|
|
246
87
|
|
|
247
|
-
|
|
248
|
-
- **Runtime enforcement** — does the rule enforce what's intended? (action choice, condition shape)
|
|
249
|
-
- **MDAPI deploy validity** — does it deploy? (§6 guardrails, scope×category, tag dev names, org perms)
|
|
250
|
-
- **UI editability** — can the builder render and re-save it? (§7 checklist, OR-of-ENTITYTYPE requirement)
|
|
88
|
+
## Required References
|
|
251
89
|
|
|
252
|
-
|
|
90
|
+
- `references/condition-model.md`: how to construct a condition as left operand, operator, and right operand.
|
|
91
|
+
- `references/condition-templates.md`: copyable condition shapes.
|
|
92
|
+
- `references/resource-expression.md`: resource-side projections, joins, aliases, and predicates.
|
|
93
|
+
- `references/policy-shapes.md`: deterministic OLS, FLS, and masking top-level fields.
|
|
94
|
+
- `references/principal-expression.md`: principal-side `SOQLTARGETLISTEXPR` expressions.
|
|
95
|
+
- `references/conjunction-expression.md`: one-indexed boolean grouping.
|
|
96
|
+
- `references/reference-resolution.md`: exact target-org reference resolution.
|
|
97
|
+
- `references/headless-transport.md`: the `dispatch`/`dispatch_readonly` `/headless/metadata` request/response shapes (the sole transport; no CLI fallback).
|
|
98
|
+
- `references/consumer-datacloud-ui.md`: Data Governance UI grouping, cardinality, scalar attributes, and RLS field capabilities.
|
|
99
|
+
- `references/consumer-all.md`: general `ALL` consumer contract.
|
|
100
|
+
- `references/runtime-context.md`: `MIN_API_VERSION`, `ORG_API_VERSION`, and evidence-version handling.
|
|
101
|
+
- `references/conjunction-compiler.md`: deterministic bucket, index, and custom-conjunction construction.
|
|
102
|
+
- `references/examples/TaggedObjectAccess/`: semantic OLS evidence package.
|
|
103
|
+
- `references/examples/FieldReadDeny/`: semantic FLS deny evidence package.
|
|
104
|
+
- `references/examples/LastCharactersFieldMasking/`: semantic field-masking evidence package.
|
|
105
|
+
- `references/examples/PrincipalFieldMatchRLS/`: semantic direct-comparison RLS evidence package.
|
|
106
|
+
- `references/examples/ExistsJoinRLS/`: semantic projection-join RLS evidence package.
|
|
253
107
|
|
|
254
|
-
|
|
108
|
+
The semantic examples are derived from retrieved server output and retain source-org-specific values. Whether a given example also retains the server-managed compatibility flags depends on when it was captured, not on a contract — `TaggedObjectAccess`'s set, for instance, carries only `<label>` and no compatibility flags, while the other four examples do carry them. They prove persisted metadata shapes, not Policy Builder open/save compatibility or a public MDAPI enum contract. Treat them as evidence, not directly deployable templates. Do not copy persisted compatibility fields, IDs, references, or undocumented enum values into authored packages; resolve every org-specific value again, change component identities and requested policy values, and validate the result in the target org.
|
|
255
109
|
|
|
256
|
-
|
|
110
|
+
## Package Contract
|
|
257
111
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
112
|
+
```text
|
|
113
|
+
<policy>/
|
|
114
|
+
package.xml
|
|
115
|
+
policyRuleDefinitionSets/<setName>.policyRuleDefinitionSet
|
|
116
|
+
policyRuleDefinitions/<ruleName>.policyRuleDefinition
|
|
117
|
+
```
|
|
262
118
|
|
|
263
|
-
|
|
119
|
+
The rule must contain `<policyRuleDefinitionSetName>` equal to the set filename without its extension. The package must list both metadata types.
|
|
264
120
|
|
|
265
|
-
|
|
121
|
+
Both the set and the rule take a human-readable `<label>`. The set's `<label>` conventionally matches its developer name (`TaggedObjectAccess`'s set uses `<label>TaggedObjectAccess</label>`); the rule's `<label>` conventionally identifies its position within the set (`TaggedObjectAccess_Rule_1` uses `<label>Rule 1</label>`). This is a plain descriptive label, distinct from the reference-resolution rule against emitting a *resolved-reference* label (see `references/reference-resolution.md`): never substitute a tag/classification/permission's display label for its resolved developer/API name, but the set's and rule's own `<label>` are always fine to author.
|
|
266
122
|
|
|
267
|
-
|
|
123
|
+
The MD-CRUD path sends each component's XML as `xmlRep` and resolves the API version server-side, so no `package.xml`/manifest `<version>` and no `ORG_API_VERSION` interpolation are required. The `package.xml` shown above and the `<version>{API_VERSION}</version>` placeholder are retained only for the eval fixtures and as the logical component set. Historical evidence versions are provenance only. Never modify the caller's `sfdx-project.json` to set an operation-specific version.
|
|
268
124
|
|
|
269
|
-
|
|
270
|
-
|--------|------|
|
|
271
|
-
| Full path enums, operators, value sets, JSON expressions (PROJECTION / ARGLIST / SOQLTARGETLISTEXPR) | [`references/policy-schema-full.md`](references/policy-schema-full.md) |
|
|
272
|
-
| Copy-paste templates — index at [`references/templates.md`](references/templates.md); per-variant: [`templates-access.md`](references/templates-access.md), [`templates-record.md`](references/templates-record.md), [`templates-transform.md`](references/templates-transform.md), [`templates-advanced.md`](references/templates-advanced.md) |
|
|
273
|
-
| Full UI-compatibility checklist, round-trip rules, operator/path support matrix | [`references/ui-compatibility.md`](references/ui-compatibility.md) |
|
|
125
|
+
Do not author `builderCompatible` or `builderValidated`. Both appear in persisted metadata, and neither is part of the generated package contract until a separately defined Policy Builder validation workflow exists.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Condition Model
|
|
2
|
+
|
|
3
|
+
Each `<conditions>` element is a comparison:
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
condition = left operand + operator + right operand
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The XML does not contain literal `<left>` or `<right>` elements. The operand type determines which elements represent each side.
|
|
10
|
+
|
|
11
|
+
| Logical part | XML representation |
|
|
12
|
+
|---|---|
|
|
13
|
+
| Resource left operand | `resourcePath`, optionally `resourceExpression` |
|
|
14
|
+
| Principal left operand | `principalPath`, optionally `principalExpression` |
|
|
15
|
+
| Context left operand | `contextPath` |
|
|
16
|
+
| Comparison | `operator` |
|
|
17
|
+
| Right reference or literal | `policyRuleValueSet` |
|
|
18
|
+
| Right record/domain value | `valueDomain` |
|
|
19
|
+
| Right principal-derived value | `valuePrincipalPath` |
|
|
20
|
+
| Clause polarity | `clause` inside the matching WHEN/UNLESS wrapper |
|
|
21
|
+
|
|
22
|
+
Every condition must be constructed in this order:
|
|
23
|
+
|
|
24
|
+
1. Select the wrapper: `whenPolicyRuleDefinitionClauseConjunction` or `unlessPolicyRuleDefinitionClauseConjunction`.
|
|
25
|
+
2. Set `<clause>` to `WHEN` or `UNLESS` to match the wrapper.
|
|
26
|
+
3. Select the left path. Most conditions use one of `resourcePath`, `principalPath`, or `contextPath`; a record-field-to-principal comparison uses both `resourcePath=RECORDFIELD` and a principal expression.
|
|
27
|
+
4. Add a `resourceExpression` or `principalExpression` if the selected left operand requires an expression.
|
|
28
|
+
5. Select the operator valid for that operand.
|
|
29
|
+
6. Add the right-side representation required by the shape. Most conditions use one of `policyRuleValueSet`, `valueDomain`, or `valuePrincipalPath`; a record-field-to-principal comparison uses `valueDomain` and `valuePrincipalPath` together.
|
|
30
|
+
|
|
31
|
+
Example: principal has a permission.
|
|
32
|
+
|
|
33
|
+
```xml
|
|
34
|
+
<conditions>
|
|
35
|
+
<clause>WHEN</clause>
|
|
36
|
+
<operator>CONTAINS_ANY</operator>
|
|
37
|
+
<policyRuleValueSet>
|
|
38
|
+
<valueReference>cust_perm1</valueReference>
|
|
39
|
+
<valueReferenceType>CUSTOM_PERMISSION</valueReferenceType>
|
|
40
|
+
</policyRuleValueSet>
|
|
41
|
+
<principalPath>ASSIGNED_PERMISSIONS_PATH</principalPath>
|
|
42
|
+
</conditions>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This means: left operand `principal.assignedPermissions`, operator `CONTAINS_ANY`, right operand custom permission `cust_perm1`.
|
|
46
|
+
|
|
47
|
+
For FLS and masking, condition 1 must be `resourcePath=ENTITYTYPE`, `operator=IS`, and `valueText=FIELD`. OLS instead begins with two entity-type conditions for `OBJECT` and `FIELD`, grouped with `OR`.
|