Exodus Salesforce Docs
Admin Guide

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 typeBaseline assignment
Internal staffSales User profile plus functional groups.
ManagersSales User profile plus matching manager groups.
AdministratorsSystem Administrator profile plus every non-guest permission-set group.
3PL integrationsAPI 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:

AreaGroups
SalesSales_User_Group, Sales_Manager, Sales_Admin
Customer serviceCustomer_Service_User
FinanceFinance_User, Finance_Manager, Finance_Admin
OperationsOperations_User, Operations_Manager, Operations_Admin
PurchasingPurchasing_User, Purchasing_Manager, Purchasing_Admin
WarehouseWarehouse_User, Warehouse_Manager, Warehouse_Admin
CommissionsCommission_User, Commission_Manager_Group, Commission_Admin
3PLThreePL_Operations, ThreePL_Integration, ThreePL_Runtime_Integration
Public payment sitesPayments_Public_Checkout_Site_Guest_Access, Payments_Webhook_Site_Guest_Access

Human access is group-first:

  1. User groups are the baseline worker groups.
  2. Manager groups layer on top of user groups.
  3. Admin groups layer on top of manager and user groups.
  4. Specialty groups are opt-in bundles for a cross-functional surface.
  5. Guest groups are only for Salesforce site guest users.
  6. 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 modelRequired access
System administratorsSystem Administrator profile plus every non-guest group, including user, manager, admin, specialty, and integration groups.
Sales representativesSales 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 usersTask_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 folderPurpose
features-*/main/default/permissionsetsPermission-set XML for object CRUD, FLS, Apex class access, tab access, custom permissions, and user permissions.
features-core/main/default/permissionsetgroupsPermission-set-group XML for human, guest, and integration bundles.
scripts/permissions/group-policy.config.jsonRole catalog, group tiers, monotonic chains, System Administrator full-access model, Sales User baseline model, and Task access coverage model.
scripts/permissions/permission-audit.config.jsonAudit ignore list for intentional metadata exceptions.
scripts/permissions/coverage-planner.mjsCoverage-layer routing rules used by the gap planner and generator.
destructiveChanges/destructiveChanges.xmlRetired 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__c

Common 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_Group

For 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 vesper

The broad sandbox repair script is intentionally aggressive:

node scripts/permissions/apply-sales-baseline-org.mjs --target-org vesper --admin-username raf@exoclub.com.vesper

It 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:

  1. Identify the missing surface: object, field, Apex class, tab, custom permission, or group assignment.
  2. Update the smallest owning permission set. For shared generated coverage, update planner specs and run npm run permissions:coverage:generate.
  3. Add the permission set to the correct permission-set group if the access should reach a role.
  4. Update scripts/permissions/group-policy.config.json if the group structure, tier chain, or assignment model changed.
  5. Run npm run permissions:audit, npm run permissions:policy, and any targeted permissions:org:audit check for the target org.
  6. 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

On this page