permission-sets-vs-profiles

Use when designing or auditing Salesforce access control — deciding between Profiles, Permission Sets, and Permission Set Groups. Triggers: 'user can't see field', 'too many profiles', 'permission model', 'least privilege', 'profile migration'. NOT for sharing rules or record-level access — use security/fls-crud for that.

Best use case

permission-sets-vs-profiles is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Use when designing or auditing Salesforce access control — deciding between Profiles, Permission Sets, and Permission Set Groups. Triggers: 'user can't see field', 'too many profiles', 'permission model', 'least privilege', 'profile migration'. NOT for sharing rules or record-level access — use security/fls-crud for that.

Teams using permission-sets-vs-profiles should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/permission-sets-vs-profiles/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/admin/permission-sets-vs-profiles/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/permission-sets-vs-profiles/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How permission-sets-vs-profiles Compares

Feature / Agentpermission-sets-vs-profilesStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Use when designing or auditing Salesforce access control — deciding between Profiles, Permission Sets, and Permission Set Groups. Triggers: 'user can't see field', 'too many profiles', 'permission model', 'least privilege', 'profile migration'. NOT for sharing rules or record-level access — use security/fls-crud for that.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

You are a Salesforce Admin expert in access control architecture. Your goal is to design a permission model that follows least-privilege, scales as the org grows, and aligns with Salesforce's direction of travel toward profile retirement. Use this skill when there are too many profiles and the user wants to know how to simplify—typically by moving to permission sets and permission set groups.

## Before Starting

Check for `salesforce-context.md` in the project root. If present, read it first — particularly org edition, sharing model, and whether managed packages are involved.
Only ask for information not already covered there.

Gather if not available:
- How many custom profiles exist today?
- Is this a greenfield design or migrating an existing org?
- Are managed packages in use? (They often force specific profile assignments)
- Is Person Accounts enabled? (Affects profile assignment complexity)

## How This Skill Works

### Mode 1: Build from Scratch

Greenfield org or new feature requiring access design.

1. Map user personas (roles, not job titles) → what objects, fields, record types they need
2. Design a "Minimum Access" base profile for all users
3. Create Permission Sets for additive access grants per feature/object/action
4. Group overlapping Permission Sets into Permission Set Groups per persona
5. Validate: every user should be assignable via base profile + 1-3 PSGs

### Mode 2: Review Existing

Profile-heavy legacy org. Goal: reduce profiles, move to Permission Set Groups.

1. Run audit SOQL (see references/examples.md) — count profiles, perm set assignments, user distribution
2. Identify profile clusters: profiles that differ by only 1-3 permissions are merge candidates
3. Extract additive permissions from profiles into Permission Sets
4. Identify the lowest-common-denominator profile and make it the base
5. Test: assign base profile + relevant PSG to a test user, verify access matches original profile
6. Migrate user-by-user or in batches, verify, decommission old profiles

### Mode 3: Troubleshoot

User reports wrong access (can't see something, can see too much).

1. **Missing access**: Check FLS first (Profile + Perm Sets), then Object CRUD, then Sharing/Visibility
2. **Too much access**: Identify which perm set is granting the access — don't remove from profile unless you've checked all perm set assignments
3. **Unexpected field visible**: Check if any perm set grants the field — perm set FLS can be MORE permissive than profile FLS

Debugging order: Field-Level Security → Object CRUD → Record Visibility → Sharing Rules

## Decision Matrix

| Scenario | Use |
|----------|-----|
| System-level settings (login hours, IP restrictions, password policy) | Profile — these don't exist in Perm Sets |
| Object and Field access for a feature | Permission Set |
| Access bundle for a user persona (e.g. "Sales Rep") | Permission Set Group |
| Temporarily elevated access | Permission Set (assign/revoke without profile change) |
| AppExchange package access | Profile (packages often require it) + Perm Set for additional access |
| New feature rollout to subset of users | Permission Set — don't create a new profile |
| "Admin-lite" users who need more than standard but less than SysAdmin | Permission Set Group |

**Salesforce roadmap callout:** Salesforce has announced Profile UI simplification (Spring '26+) and is moving toward a perm-set-first model. New orgs should design perm-set-first. Profile retirement for user-facing permissions is in progress — build for it now.

## Permission Architecture Pattern

```
Every user =
  Base Profile (Minimum Access — login, password policy, session settings)
  + Permission Set Group (persona-level feature bundle)
  [+ ad-hoc Permission Sets for temporary/individual access]
```

**Minimum Access Profile:** Standard platform license profile stripped to the minimum. No object access. No field access. Just login settings. All access granted via Permission Sets.

## Naming Conventions

| Artifact | Pattern | Example |
|----------|---------|---------|
| Permission Set | `[Object]_[Access Level]_[Context]` | `Account_Edit_SalesRep`, `Case_Read_PortalUser` |
| Permission Set Group | `[Persona]_[Feature Set]` | `SalesRep_Core`, `CaseManager_Full` |
| Base Profile | `[License Type]_MinimumAccess` | `SalesforceUser_MinimumAccess` |


## Recommended Workflow

Step-by-step instructions for an AI agent or practitioner activating this skill:

1. Gather context — confirm the org edition, relevant objects, and current configuration state
2. Review official sources — check the references in this skill's well-architected.md before making changes
3. Implement or advise — apply the patterns from Core Concepts and Common Patterns sections above
4. Validate — run the skill's checker script and verify against the Review Checklist below
5. Document — record any deviations from standard patterns and update the template if needed

---

## Salesforce-Specific Gotchas

- **FLS is additive, not restrictive**: A Permission Set can grant MORE field access than a Profile, and it wins. The "most restrictive wins" rule applies within the same layer (two profiles can't stack), but a Perm Set always adds to Profile access. A user with Profile FLS=Read + Perm Set FLS=Edit has Edit. This surprises people who expect Profiles to cap access.
- **Login hours and IP restrictions are Profile-only**: These system-level controls don't exist in Permission Sets. You cannot fully retire Profiles — keep a base profile with these settings. Don't move users to "No Profile" or Minimum Access profiles without confirming these settings are acceptable.
- **Cloned profiles carry all the original's tech debt**: A profile cloned from System Administrator 3 years ago probably has explicit denies, weird FLS, and long-forgotten AppExchange grants. Audit before using clones as a base — they're not clean slates.
- **Permission Set Group propagation delay**: Changes to a PSG take up to 10 minutes to propagate to assigned users. If a user reports access not working immediately after an assignment, wait and retest before escalating.
- **Managed packages and profiles**: Some AppExchange packages require their managed profile to be assigned. You can layer Permission Sets on top, but you cannot always replace the package profile. Document this as an exception.

## Proactive Triggers

Surface these WITHOUT being asked:
- **User reports "can't see" a field** → Check FLS before checking sharing. 80% of "missing field" issues are FLS, not sharing. If the field is FLS-hidden on both Profile and all assigned Perm Sets, it won't appear even with full record access.
- **More than 10 custom profiles detected** → Flag as an Operational Excellence issue. This is a profile sprawl signal. Begin audit: which profiles differ by fewer than 5 permissions? Those are merge candidates.
- **Profile used as a security boundary between user groups** → Flag as architectural risk. Profiles are not a sharing boundary — the sharing model controls record visibility. A user with a "restricted" profile can still see records they have sharing access to.
- **`ViewAllData` or `ModifyAllData` on any non-admin permission set** → Flag as Critical immediately. No justification is acceptable for community/portal users. Internal users require documented approval.
- **Permission Set Group not used where 3+ Perm Sets overlap for the same persona** → Flag. If users of the same type always get the same 3 Perm Sets, that's a PSG waiting to be created. Managing individual Perm Set assignments at scale is an administrative burden and an audit nightmare.
- **Perm Set with 50+ object permissions checked** → Flag. This is likely a copy of a legacy profile being ported into a Perm Set. It defeats the purpose of granular permission management.

## Output Artifacts

| When you ask for...              | You get...                                                          |
|----------------------------------|---------------------------------------------------------------------|
| Access design for new feature    | Perm Set + PSG design with naming + persona mapping table           |
| Profile audit                    | Merge candidates, redundant profiles, migration priority order      |
| Troubleshoot missing access      | Step-by-step debug path: FLS → CRUD → Sharing → Visibility          |
| Migration plan                   | Phase plan: audit → design → test → migrate → decommission          |

## Related Skills

- **security/fls-crud**: Use when the issue is Apex-side CRUD/FLS enforcement (`WITH SECURITY_ENFORCED`, `stripInaccessible`, user mode). NOT for declarative permission architecture.
- **admin/record-types-and-page-layouts**: Use when access design and Record Type visibility must be planned together. NOT when the main problem is page UX rather than user access.
- **admin/validation-rules**: Use when a validation bypass depends on a Custom Permission granted via a Permission Set. NOT for debugging sharing, CRUD, or profile sprawl.

Related Skills

permission-set-groups-and-muting

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when designing or reviewing permission-set-group architecture, especially profile minimization, group composition, muting strategy, and migration away from profile-heavy security models. Triggers: 'permission set group', 'muting permission set', 'profiles to permission sets', 'PSG architecture', 'muted permissions'. NOT for record-sharing design or CRUD/FLS review in Apex code.

permission-set-deployment-ordering

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when deploying permission sets, permission set groups, or profiles and encountering cross-reference errors, silent permission loss, or ordering failures. Triggers: 'permission set deployment fails', 'cross-reference id error during deploy', 'permissions disappear after deployment', 'permission set group deployment error'. NOT for permission set design or architecture decisions (use permission-set-architecture), NOT for creating permission sets from scratch (use admin/permission-set-architecture).

migration-from-change-sets-to-sfdx

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when planning or executing a migration from change-set-based deployments to Salesforce DX source-driven development. Trigger keywords: 'migrate from change sets', 'move to SFDX', 'convert metadata to source format', 'sf project convert mdapi', 'source-driven development adoption'. NOT for greenfield SFDX project setup (use sf-cli-and-sfdx-essentials), unlocked package design (use unlocked-package-development), or DevOps Center pipeline creation (use devops-center-pipeline).

apex-user-and-permission-checks

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when Apex needs to check what the running user is, can see, or can do — via UserInfo, FeatureManagement, FeatureManagement.checkPermission, or FeatureManagement.checkPermissionType. Covers custom permissions, permission sets, user licenses, and profile checks. NOT for FLS/CRUD (use Security.stripInaccessible or `with user_mode`), sharing rules, or external user license logic.

apex-custom-permissions-check

8
from PranavNagrecha/AwesomeSalesforceSkills

Custom Permissions in Apex: FeatureManagement.checkPermission, $Permission global variable, permission-set gating of feature code, Custom Permission metadata. NOT for CRUD/FLS enforcement (use security-apex-crud-fls). NOT for standard Salesforce permissions (use permission-set-architecture).

picklist-and-value-sets

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when creating or managing picklist fields: choosing between Global Value Sets and object-local picklists, configuring controlling and dependent field relationships, managing picklist values, and replacing values in existing data records. NOT for formula fields that reference picklists (use formula-fields), NOT for record type picklist filtering (use record-types-and-page-layouts), NOT for picklist fields in Flow (use the appropriate flow skill).

custom-permissions

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when creating, assigning, or checking custom permissions to control feature access beyond CRUD and FLS. Trigger keywords: 'custom permission', 'FeatureManagement.checkPermission', '$Permission global variable', 'feature gate', 'named access grant', 'beta feature flag'. NOT for permission sets (use permission-set-architecture).

analytics-permission-and-sharing

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring CRM Analytics (formerly Einstein Analytics) app sharing, dataset-level permissions, row-level security predicates, sharing inheritance, or license assignment. Trigger keywords: CRM Analytics security, row-level security predicate, dataset permissions, analytics sharing inheritance, Analytics Plus license. NOT for standard Salesforce OWD/sharing rules, profile-based record access, or non-Analytics report folder sharing.

xss-and-injection-prevention

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when writing or reviewing Visualforce pages, Apex controllers, or LWC components that output user-supplied data, build dynamic queries, or construct HTTP responses. Triggers: 'XSS in Visualforce', 'SOQL injection vulnerability', 'how to encode output in Apex', 'JSENCODE Visualforce', 'open redirect prevention'. NOT for Apex CRUD/FLS enforcement (use soql-security or apex-crud-and-fls), NOT for Shield encryption (use shield-encryption-key-management), NOT for AppExchange security review process (use secure-coding-review-checklist).

visualforce-security-and-modernization

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when hardening or modernizing legacy Visualforce pages — covers the platform CSRF token model and when disabling it is a security regression, view state encryption guarantees and the 170 KB ceiling, FLS/CRUD enforcement gaps on `<apex:outputField>` and on getters that return sObjects, `<apex:includeScript>` interaction with the org Content Security Policy, hosting LWC inside a VF page via `lightning:container` / `lightning-out`, and the retire-vs-harden-vs-leave-alone decision for an inventory of legacy pages. Triggers: 'should I rewrite this Visualforce page in LWC', 'CSRF protection disabled on Visualforce page is that safe', 'community user sees a field they should not on a Visualforce page', 'view state encryption is that enough for sensitive data', 'how do I host an LWC inside a Visualforce page', 'apex:dynamicComponent and apex:actionFunction safe to keep'. NOT for greenfield Visualforce architecture (use apex/visualforce-fundamentals — controller types, view state pattern selection, PDF rendering); NOT for Visualforce email template authoring (use apex/visualforce-email-templates if/when that skill is authored); NOT for general Apex security review across triggers and async (use apex/soql-security and security/secure-coding-review-checklist).

transaction-security-policies

8
from PranavNagrecha/AwesomeSalesforceSkills

Transaction Security policy creation and configuration: condition builder, enhanced policies, enforcement actions (block, MFA, notification, end session), real-time monitoring mode, and policy troubleshooting. NOT for Event Monitoring log analysis or Shield Event Monitoring setup (use event-monitoring). NOT for Apex testing or debug-log analysis.

sso-saml-troubleshooting

8
from PranavNagrecha/AwesomeSalesforceSkills

Diagnosing broken SAML SSO into Salesforce — IdP-initiated vs SP-initiated flows, signing-certificate validity / expiry, NameID format mismatches, RelayState handling, audience / entityId / issuer mismatches, clock skew, the SAML Assertion Validator in Setup, the Login History debug log, and the My Domain prerequisite for SSO. Covers the standard diagnostic loop: read the SAML response, identify which check failed, fix at the IdP or SP. NOT for OAuth / OpenID Connect SSO (see security/oauth-openid-troubleshooting), NOT for setting up SSO from scratch (see security/sso-saml-setup).