Why the MutingPermissionSet Metadata Type Prevents “Permission Set Sprawl”
In a persona-based security architecture built on PermissionSetGroup, you assemble reusable feature PermissionSets (for example, Order_Management_Core and Billing_Invoicing_Core). But what happens when an Auditor or Junior Support Agent persona needs 95% of Order_Management_Core, except the ability to Delete orders or edit the Discount_Percentage__c field?
Without MutingPermissionSet (mutingpermissionsets/<Name>.mutingpermissionset-meta.xml), you would have to clone and maintain duplicate Permission Sets. With MutingPermissionSet, you attach a single muting rule to the PermissionSetGroup to subtract specific permissions while keeping your core Permission Sets untouched.
The Counter-Intuitive XML Rule: <allowDelete>true</allowDelete> Means Muted!
Because MutingPermissionSet extends PermissionSet, it uses the exact same XML tags (objectPermissions, fieldPermissions, userPermissions, customPermissions, classAccesses).
Warning
Critical XML Syntax Inversion: Inside a .mutingpermissionset-meta.xml file, setting a boolean tag to true means “Mute (Disable) this permission”, and setting it to false means “Do NOT mute this permission.”
For example, to mute Delete and Modify All on Order__c while leaving Read, Create, and Edit active in the Permission Set Group, you set allowDelete and modifyAllRecords to true and set allowRead, allowCreate, and allowEdit to false!
Real-World XML Example (mutingpermissionsets/Support_Agent_Muted.mutingpermissionset-meta.xml)
<?xml version="1.0" encoding="UTF-8"?>
<MutingPermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
<description>Mutes Delete access on Orders and Edit access on Margin_Percent__c for Support Agents.</description>
<fieldPermissions>
<editable>true</editable>
<field>Order__c.Margin_Percent__c</field>
<readable>false</readable>
</fieldPermissions>
<label>Support Agent Muted</label>
<objectPermissions>
<allowCreate>false</allowCreate>
<allowDelete>true</allowDelete>
<allowEdit>false</allowEdit>
<allowRead>false</allowRead>
<modifyAllRecords>true</modifyAllRecords>
<object>Order__c</object>
<viewAllRecords>false</viewAllRecords>
</objectPermissions>
<userPermissions>
<enabled>true</enabled>
<name>ExportReport</name>
</userPermissions>
</MutingPermissionSet>Querying MutingPermissionSet via SOQL
In the Salesforce database, a MutingPermissionSet is stored in the PermissionSet table with PermissionSetGroupId != null.
1. List All Muting Permission Sets and Their Parent Permission Set Groups
SELECT Id, Name, Label, PermissionSetGroupId,
PermissionSetGroup.DeveloperName, PermissionSetGroup.Status,
LastModifiedDate
FROM PermissionSet
WHERE PermissionSetGroupId != null
ORDER BY PermissionSetGroup.DeveloperName ASC2. Inspect Muted Object Permissions Inside a MutingPermissionSet
SELECT Parent.Name, Parent.PermissionSetGroup.DeveloperName,
SobjectType, PermissionsRead, PermissionsCreate,
PermissionsEdit, PermissionsDelete, PermissionsModifyAllRecords
FROM ObjectPermissions
WHERE Parent.PermissionSetGroupId != null
ORDER BY Parent.Name, SobjectTypeSenior Architect Best Practices
- One
MutingPermissionSetPerPermissionSetGroup: EachPermissionSetGroupcan reference at most one<mutingPermissionSets>entry. Name it consistently as<PSG_DeveloperName>_Muted. - Muting Only Affects the Specific
PermissionSetGroup: If a user is assignedOrder_Coredirectly (or via a secondPermissionSetGroupthat does not muteDelete), the user still retainsDeletepermission. Muting is scoped strictly to thePermissionSetGroupthat contains theMutingPermissionSet.
Frequently asked questions
How does XML syntax in a MutingPermissionSet work if setting a permission to true mutes it?
This is the most important syntax rule of MutingPermissionSet: setting a permission flag to true inside a .mutingpermissionset-meta.xml file means that permission is MUTED (disabled) for users assigned to the parent PermissionSetGroup!
Can a MutingPermissionSet be assigned directly to a User without a PermissionSetGroup?
No. A MutingPermissionSet can only exist as a child member inside a PermissionSetGroup (referenced via the mutingPermissionSets tag) and each PermissionSetGroup can contain at most one MutingPermissionSet.
What happens if you mute Read permission on an object inside a MutingPermissionSet?
Because Salesforce enforces permission dependencies, muting allowRead on an object automatically mutes allowCreate, allowEdit, allowDelete, viewAllRecords, and modifyAllRecords for that object within the PermissionSetGroup.
How do you query MutingPermissionSet records in SOQL?
In SOQL, a MutingPermissionSet is stored in the standard PermissionSet object with Type = 'Muted' and a non-null PermissionSetGroupId pointing to its parent PermissionSetGroup.
Comments
Questions, corrections and tips are welcome. Comments are GitHub Discussions, so you sign in with GitHub.