Users and Permissions
Profile, permission-set group, and role access model
Assignment Model
The repo uses Salesforce profiles plus functional permission-set groups. Profiles identify the broad Salesforce user type, but feature access should live in permission sets and permission-set groups.
| User type | Baseline assignment |
|---|---|
| Internal staff | Sales User profile plus functional groups. |
| Managers | Sales User profile plus matching manager groups. |
| Administrators | System Administrator profile plus every non-guest permission-set group. |
| 3PL integrations | API profile plus ThreePL_Integration. |
Do not fix normal access bugs by adding broad admin groups. Add or repair the smallest permission set that owns the missing object, field, Apex class, tab, or custom permission, then include that permission set in the correct group.
Permission-Set Groups
Functional groups in source include:
| Area | Groups |
|---|---|
| Sales | Sales_User_Group, Sales_Manager, Sales_Admin |
| Customer service | Customer_Service_User |
| Finance | Finance_User, Finance_Manager, Finance_Admin |
| Operations | Operations_User, Operations_Manager, Operations_Admin |
| Purchasing | Purchasing_User, Purchasing_Manager, Purchasing_Admin |
| Warehouse | Warehouse_User, Warehouse_Manager, Warehouse_Admin |
| Commissions | Commission_User, Commission_Manager_Group, Commission_Admin |
| 3PL | ThreePL_Operations, ThreePL_Integration, ThreePL_Runtime_Integration |
| Public payment sites | Payments_Public_Checkout_Site_Guest_Access, Payments_Webhook_Site_Guest_Access |
Human access is group-first:
- User groups are the baseline worker groups.
- Manager groups layer on top of user groups.
- Admin groups layer on top of manager and user groups.
- Specialty groups are opt-in bundles for a cross-functional surface.
- Guest groups are only for Salesforce site guest users.
- Integration groups are only for API or runtime users unless a setup runbook explicitly says otherwise.
The group hierarchy is intentionally monotonic. If a manager or admin group is missing access held by the user tier, update the group composition and scripts/permissions/group-policy.config.json.
Assignment Models
The machine-readable source of truth is scripts/permissions/group-policy.config.json.
| User model | Required access |
|---|---|
| System administrators | System Administrator profile plus every non-guest group, including user, manager, admin, specialty, and integration groups. |
| Sales representatives | Sales User profile plus Sales_User_Group as the baseline. Add manager/admin or cross-functional groups only when the job function requires them. |
| Internal Task users | Task_Activity_Context_Access through their assigned internal group, so Quick Text presets, Item Group lookup search, and Discussed Item context work consistently. |
Task_Activity_Context_Access is intentionally in all internal UI-facing groups. If users cannot see task note presets, Item Group lookup search, or Discussed Item context, check this permission set first.
npm run permissions:policy checks that configured assignment models still match source metadata. npm run permissions:org:audit -- --target-org vesper checks live org assignment drift, including System Administrator users missing required groups and Sales User profile users missing the sales baseline.
Source Files
| File or folder | Purpose |
|---|---|
features-*/main/default/permissionsets | Permission-set XML for object CRUD, FLS, Apex class access, tab access, custom permissions, and user permissions. |
features-core/main/default/permissionsetgroups | Permission-set-group XML for human, guest, and integration bundles. |
scripts/permissions/group-policy.config.json | Role catalog, group tiers, monotonic chains, System Administrator full-access model, Sales User baseline model, and Task access coverage model. |
scripts/permissions/permission-audit.config.json | Audit ignore list for intentional metadata exceptions. |
scripts/permissions/coverage-planner.mjs | Coverage-layer routing rules used by the gap planner and generator. |
destructiveChanges/destructiveChanges.xml | Retired permission sets or groups that should be removed from orgs. |
Coverage layers exist so broad object, field, or Apex coverage can be regenerated consistently without hand-editing every role group. Current generated layers include Core_CRM_Coverage_Layer, CRM_Coverage_Layer, and Orders_Coverage_Layer.
Admin Checks
Before adding a user to a group, confirm the job function and the least access that lets the user work. Do not use admin groups to fix normal sales or operations access issues.
Run local access checks before changing metadata:
npm run permissions:roles:report
npm run permissions:roles:report -- --group Sales_User_Group --json
npm run permissions:roles:report -- --group Sales_Admin --json
npm run permissions:who-can -- --object Sales_Order__c --access read
npm run permissions:who-can -- --field Sales_Order__c.Status__c --access edit
npm run permissions:matrix:crud -- --scope groups --object Sales_Order__cCommon troubleshooting commands:
npm run permissions:audit -- --class QuoteApprovalController
npm run permissions:audit -- --class SalesOrderSyncService
npm run permissions:audit -- --field Activity.Product_Group__c
npm run permissions:org:audit -- --target-org vesper --user zan@exoclub.com
npm run permissions:org:audit -- --target-org vesper --group Sales_User_GroupFor Lightning errors like No apex action available for SomeController.someMethod, check class coverage first. The fix belongs in the permission set that owns the feature, not as a one-off direct user assignment.
Production Drift
Use the org audit when validating a live QA or production org against source:
npm run permissions:org:audit -- --target-org vesperThe broad sandbox repair script is intentionally aggressive:
node scripts/permissions/apply-sales-baseline-org.mjs --target-org vesper --admin-username raf@exoclub.com.vesperIt resets active standard users to the configured baseline: the named admin gets every local permission-set group, and other active standard users get the Sales User profile plus Sales_User_Group. Use it only when intentionally normalizing a sandbox or migration org, then rerun the org audit.
Change Workflow
When adding or fixing access:
- Identify the missing surface: object, field, Apex class, tab, custom permission, or group assignment.
- Update the smallest owning permission set. For shared generated coverage, update planner specs and run
npm run permissions:coverage:generate. - Add the permission set to the correct permission-set group if the access should reach a role.
- Update
scripts/permissions/group-policy.config.jsonif the group structure, tier chain, or assignment model changed. - Run
npm run permissions:audit,npm run permissions:policy, and any targetedpermissions:org:auditcheck for the target org. - Deploy metadata and verify with the affected user or profile.
Do not add access to deprecated package pages, Apex, or flows unless the historical surface is still intentionally supported. If retired metadata is removed, update destructiveChanges/destructiveChanges.xml and run npm run architecture:retirement:audit.
Last updated on