Platform Policy Rule Generate
Use this skill when authoring PolicyRuleDefinition and PolicyRuleDefinitionSet metadata XML for Salesforce Data Cloud governance policies, or when editing *.policyRuleDefinition / *.policyRuleDefinitionSet files. Covers the category decision tree, full schema for all policy variants (ACCESS, GOVERNANCE, RECORD, TRANSFORM), UI-compatibility rules for the Data Governance Policy Builder, output hygiene for user-facing agent responses, and validation guardrails. Do NOT use this skill for UserAccessPolicy, AccessPolicy, SharingRules, PermissionSet, or any other access-control metadata type — those have their own types and live outside the PolicyRuleDefinition schema.
- Skill ID
- forcedotcom/sf-skills/platform-policy-rule-generate
- Publisher
- forcedotcom
- Repository
- sf-skills
- Installs
- 0
- Files
- 9
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
forcedotcom/sf-skills/platform-policy-rule-generateInstalls these files- SKILL.md
- references/deploy-errors.md
- references/policy-schema-full.md
- references/templates-access.md
- references/templates-advanced.md
- references/templates-record.md
- references/templates-transform.md
- references/templates.md
- references/ui-compatibility.md
What this skill tells the agent
Authoring Policy Rule Definitions
Gating: requires the EnforceOMatic and PolicyRuleMDAPI org permissions. Min API version: 64.0 (66.0 for conditions using PolicyJsonExpression).
This skill covers the on-disk metadata XML format for authoring policies. Use it whenever a task asks to write a *.policyRuleDefinition or *.policyRuleDefinitionSet file, or ship a metadata package containing them. The runtime side (RuleProvider, hooks) is out of scope.
Eval coverage: This skill is exercised by the team's ADK eval framework, not bytests/evals/under the skill directory. Five datasets covering the ACCESS / GOVERNANCE / RECORD / TRANSFORM variants live inpackages/adk-eval/eval/domains/platform-policy-rule-generate/datasets/.
1. Package Layout
A deployable package always contains:
<fixture>/
package.xml
policyRuleDefinitionSets/<setName>.policyRuleDefinitionSet
policyRuleDefinitions/<ruleName>.policyRuleDefinitionpackage.xml template (use <version>[ftest]</version> for ftests, 64.0 or higher for real orgs):
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>Rule0</members>
<name>PolicyRuleDefinition</name>
</types>
<types>
<members>Set1</members>
<name>PolicyRuleDefinitionSet</name>
</types>
<version>64.0</version>
</Package>2. PolicyRuleDefinitionSet Schema
<PolicyRuleDefinitionSet xmlns="http://soap.sforce.com/2006/04/metadata">
<label>Set1</label>
<description>Optional free text</description>
<replicated>false</replicated> <!-- MinAppVersion 260 -->
<builderCompatible>true</builderCompatible> <!-- MinAppVersion 262, author-settable -->
<!-- builderValidated: server-managed — do not set in authored XML -->
</PolicyRuleDefinitionSet>| Element | Req | Notes |
|---|---|---|
<label> | yes | Master label. File basename (devName) is the MDAPI identifier, not the label. |
<description> | no | Free text. |
<replicated> | no | true triggers placeholder transformation across companion orgs. Omit for null/false. |
<builderCompatible> | no | true = rules audited per §7 checklist. false = API-only. Omit = unaudited. Informational only — no deploy/runtime effect. |
<builderValidated> | no | Server-managed. Never set in authored XML. Server overwrites on validation. |
3. PolicyRuleDefinition — Core Fields
| Element | Req | Notes |
|---|---|---|
<label> | yes | MasterLabel. |
<category> | yes | See §4. Drives resourceScopeType and whether policyRuleResourceDomains/resourceTransform are required. Does NOT constrain `effect` outside of TRANSFORM. |
<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. |
<action> | yes (≥1) | Read, TupleRead, Create, etc. Multiple elements OR-combine. |
<policyRuleDefinitionSetName> | yes | Developer name of parent set. |
<principalScopeType> | yes | Always ANY. |
<resourceScopeType> | yes | ANY, FIELD, RECORD, DATASPACE, or SPAN. Must match category (§4). |
<principalAuthenticationLevel> | no | INTERNAL, AUTHENTICATED, UNIDENTIFIED, IDENTIFIED. |
<ruleConsumer> | no | ALL, DATACLOUD, MULESOFT, TABLEAU, CORE. |
<policyRuleResourceDomains> | no | Required for RECORD (RLS) and FIELD-scope TRANSFORM rules only. Forbidden on ACCESS/GOVERNANCE. |
<resourceTransform> | no | Required (and only valid) when category=TRANSFORM. |
<whenPolicyRuleDefinitionClauseConjunction> | no | WHEN conditions. |
<unlessPolicyRuleDefinitionClauseConjunction> | no | UNLESS conditions. Not UI-editable — prefer WHEN + negated operator. |
4. Category Decision Tree
Category names a domain (where in the platform's enforcement layers the rule applies). Effect names the action (allow / deny / transform). They are independent except for TRANSFORM.
The only Category × Effect rule the platform validates:
effect=Transform⇔category=TRANSFORM_POLICY_RULE_DEFINITION(bidirectional; mismatched throwsINVALIDFORCATEGORY).- All other categories (
ACCESS,GOVERNANCE,RECORD,IDENTIFIED_RECORD) accept eitherPermitorForbid.
Note on the platform's auto-fill default: When<category>is omitted from authored XML, the server fills it in fromeffect:Permit→ACCESS,Forbid→GOVERNANCE,Transform→TRANSFORM. This is a default-fill, not a validation. If you author an explicit category that contradicts this default, it is accepted and persisted as-is.
Picking the category
What kind of policy?
│
├── OLS/FLS allow/deny on tagged or classified resources
│ category = ACCESS_POLICY_RULE_DEFINITION (allow/deny attestation in the access plane)
│ | GOVERNANCE_POLICY_RULE_DEFINITION (governance-audited)
│ effect = Permit | Forbid (chosen independently from category)
│ resourceScopeType = ANY | FIELD | DATASPACE
│ NO <policyRuleResourceDomains>
│ condition: resourcePath=TAG|CLASSIFICATION CONTAINS_ANY <ref>
│ For "objects AND all their fields" → action=TupleRead + OR-of-ENTITYTYPE clause (§7)
│ Note: "Block access to Foo object" → tag Foo with <yourTag>, write rule on tag
│ Do NOT use <resourceDomain>Foo</resourceDomain> — forbidden for ACCESS/GOVERNANCE
│
├── Row-level filter on a DMO/DLO
│ category = RECORD_POLICY_RULE_DEFINITION
│ effect = Permit | Forbid
│ resourceScopeType = RECORD
│ <policyRuleResourceDomains> = the DMO/DLO API name ← entity targeting allowed here
│
├── Identified-Guest record access
│ NOT authorable via MDAPI — SESSION_CONSUMER_ID is not in RuleContextPathType
│ Must be implemented as a runtime RuleProvider.
│
└── Field masking
category = TRANSFORM_POLICY_RULE_DEFINITION ← required by RuleBuilder validator
effect = Transform ← required by RuleBuilder validator
resourceScopeType = FIELD (structured) or SPAN (unstructured)
<policyRuleResourceDomains> = the DMO whose field is masked
<resourceTransform> required (e.g. NULL_RESOURCE_TRANSFORM, LAST_N_CHARS_RESOURCE_TRANSFORM)ACCESS vs GOVERNANCE — how to choose
Both legally accept Permit and Forbid. Pick by which enforcement layer should record/audit the rule and what the prompt literally asks for:
| Use case | Pick | Reason |
|---|---|---|
| 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. |
| 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. |
| 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) |
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.
Scope × category compatibility — any combination outside this matrix throws INVALIDFORCATEGORY:
ACCESS | GOVERNANCE | TRANSFORM | RECORD | |
|---|---|---|---|---|
ANY | Yes | Yes | No | No |
DATASPACE | Yes | Yes | No | No |
More from forcedotcom
Use this skill in a project
Open any RiverX project, search the Skills panel for forcedotcom/sf-skills/platform-policy-rule-generate, and install it in one click.
