A restriction rule is a condition attached to an entity's sharing policy that either grants a group of users extra access to the records it matches, or narrows the records a group can see. Rules are the fine-tuning layer of record-level security: the policy sets the baseline (owner, default access, hierarchy, shares), and rules add or take away slices of records on top of it. You build them under Setup → Access Control → Policies, on the policy of the entity you want to scope.
Overview
Every rule belongs to one entity's policy and has three parts:
- The rule itself — its type (Access Grant or Access Filter), its effect, the audience it applies to (internal staff, external portal and partner users, or both) and the one operation it takes part in.
- Expressions — one or more formulas that pick the records the rule is about, for example
Region == "West". - Targets — the users the rule is for: a role, team, business unit, profile, all internal or all external users, or "whoever is reading". A target can also be an Except that leaves a group out.
An Access Grant rule adds records: users it targets can read (or update, or delete) every record its expressions match, on top of what the baseline already gives them. An Access Filter rule takes records away: users it applies to see only the records its expressions match, whatever the baseline gave them.
When to use it
- Each region, branch or business unit should see only its own records, while the entity's default is Private.
- A group should be able to edit records it does not own — for example, a back-office team that corrects every West order.
- Field staff should see only the visits, plans or tasks assigned to them or to the people below them.
- Portal users should see only the records that belong to their own contact or account.
- One group (head office, auditors) should be exempt from a filter everyone else gets.
If the goal is "managers see their reports' records", you do not need a rule: keep Grant access using hierarchy on in the policy. If one person needs one record, a share is simpler — see record security.
How xMatix handles it
Grants add, filters narrow
When a user reads a list, xMatix first works out their baseline: ownership, the policy's default access for their audience, the hierarchy and shares. It then adds every enabled Access Grant rule that targets them for the operation being performed, and finally keeps only the records that match every enabled Access Filter rule that applies to them. There is no deny effect; a filter is the only way to take records away.
Grant rules matter only when the baseline does not already reach every record. With a Read Only default, a Grant Read rule changes nothing, because the user already reads everything; a Grant Write rule still widens editing.
How a rule's parts combine
- Several expressions on one rule must all match — they are combined with AND. To say "West OR North", write both in one formula.
- Several grant rules add up — a record is reached if any one of them matches.
- Several filter rules all apply — a record stays visible only if it matches every one.
- Only expressions marked Valid take part. An expression marked Invalid or Not Validated is skipped. A grant rule with no valid expression grants nothing; a filter rule with no valid expression filters nothing.
Who a rule is for
A rule first has to match the user's audience: Internal rules apply to staff, External rules to portal and partner users, All to both. Then its targets decide:
- an Except target that matches the user switches the rule off for that user, even if an Applies to target also matches;
- otherwise at least one Applies to target must match;
- a grant rule with no Applies to target applies to nobody, while a filter rule with none applies to everyone in its audience.
Holders of View All on the entity skip the whole record filter when reading, filters included. Modify All does the same for update and delete. That is why an administrator often sees records a filter hides from everyone else.
Rules that already ship
A few entities ship with Access Filter rules. Visits and visit plans are filtered to the field resource they are assigned to (users who are not linked to a resource are not filtered). Employee, payslip, tax-declaration, monthly TDS projection and TDS certificate records are filtered to the reader's own employee resource. Their formulas are good models for your own — open them from the entity's policy to read them.
Prerequisites
- The
setup.security.managecapability, which opens the Access control area of Setup. - An active policy on the entity. Many entities, including every entity you create, have no policy; an entity without one, or with an inactive one, ignores rules entirely. Create one first (record security).
- Profile access to the entity for every affected user. Rules decide which records show; they never let a user use an entity their profiles do not grant (security profiles).
- Roles, teams and business units in place when your targets name them (roles, teams and business units).
- A test user who holds only the profile you are scoping. Your own account probably has View All, so it cannot show you what scoped users see.
Procedure
Step 1 — Open the entity's policy
Go to Setup → Access Control → Policies and find the row whose Entity column names your entity. Each entity has at most one policy, so edit the existing one rather than creating a second. Open the policy's name. The header shows Entity, Ownership, Internal Access, External Access, Status, Hierarchy Access, Manual Share and Team Access, and below it the Rules table (Name, Type, Effect, Audience, Priority, Enabled, Description, Modified). Write down the current values so you can roll back.
If the entity has no row, select New policy and create one first.
- 1
Internal Access is the baseline you tighten to Private in Step 2; External Access is set independently.
- 2
Hierarchy Access on lets managers read records owned by users in descendant roles.
- 3
Manual Share and Team Access decide whether shares are honoured at all.
- 4
Edit Policy opens the ownership, default-access and switch fields.
- 5
New Rule creates a grant or filter rule under this policy.
- 6
Each rule row shows Type, Effect, Audience, Priority and Enabled; open the name for its Expressions and Targets tabs.
Step 2 — Set the baseline the rules will build on
Grant rules only make sense on top of a narrow baseline. Select Edit Policy and check Internal default access (and External default access for portal users):
- To give each group only its slice through grant rules, set the default to Private.
- To keep the default broad and narrow it with filter rules, leave it at Read Only and go on to an Access Filter rule in Step 3.
Leave Grant access using hierarchy on only if managers should inherit their reports' records. Changing a default from Read Only to Private hides records for everyone at once, so do it in a quiet window and test straight away (Step 6).
Step 3 — Create the rule, disabled
On the policy page select New Rule. In the New Security Rule dialog:
- 1
Name the population and the beneficiary so the Rules table reads like a policy.
- 2
Access Grant gives records back; Access Filter narrows what the default exposes. Greyed types are reserved.
- 3
Grant Read is the effect a rule can actually deliver today — targets accept only the Read grant mask.
- 4
Applies To Operations is locked by the effect; Applies To Audience picks All, Internal or External users.
- 5
Priority orders evaluation; lower numbers run first.
- 6
Enabled is on by default — turn it off while authoring; Stop Processing On Match short-circuits later rules.
- Name — say what the rule does and for whom, for example
West records → West business unit. The name cannot be changed later. - Rule Type — Access Grant to add records, Access Filter to narrow them.
- Effect — for a grant: Grant Read (see), or Grant Write (change). For a filter: Filter Visible Records.
- Applies To Audience — All, Internal or External.
- Applies To Operations — Grant Read is fixed to Read (1). Grant Write offers Update (4) or Delete (8) — one per rule. A filter can be set to Read, Update or Delete.
- Priority and Description — optional; Priority is shown in the table but does not change the result.
- Enabled — on by default. Untick it so the rule cannot affect anyone while you build it.
Select Create. The rule appears in the Rules table as disabled. Open its name to reach the rule's page, which has an Expressions tab and a Targets tab (titled Applies To for a filter).
Step 4 — Write the condition
On the Expressions tab select Add Expression. In the New Rule Expression dialog:
- Name — a short label, for example
West region. - Expression Mode — Formula (the only mode you can pick).
- Return Type — Boolean. An Access Filter also offers Record Filter, which behaves the same way.
- Formulae — the condition, using the record's fields by name, for example
Region == "West". See Formula reference for the user and owner conditions you can use.
Select Create. xMatix checks the formula when it is saved and fills in the table's Validation column (Valid or Invalid), Validation Message and Validated. An invalid formula is still saved, but it takes no part in the rule — always confirm Valid before going on. To change a formula, use Edit Expression on its row.
Step 5 — Choose who the rule is for
On the Targets tab (or Applies To for a filter) select Add Target:
- Name — a short label.
- Mode — Applies to to include a group, Except to leave one out.
- Target Type — Current User, Owner, Team, Role, Business Unit, All Internal, All External or Profile. Team, Role, Business Unit and Profile then ask you to pick the specific one. Current User and Owner both mean "whoever is reading": the rule's formula does all the selecting. A filter and an Except target can use only Team, Role, Business Unit, All Internal, All External and Profile.
- Grant Mask (grant rules only) — Read (1), the only value offered. It does not limit a Grant Write rule; the rule's effect and operation decide what is granted.
Select Create. For "each business unit sees its own records", choose Business Unit and pick the unit. Users belong to a business unit through their active roles, so a user with no role in that unit is not covered.
Step 6 — Test, then enable
Sign in as the test user (allow up to two minutes for policy changes to reach signed-in users). With the rule still disabled, confirm the baseline you expect. Then, as administrator, open the rule, select Edit Rule, tick Enabled and save. Test again with at least three checks: a record the rule should reach, a record it should not, and — for a Grant Write rule — a save. Repeat with a user from a group the rule should not affect.
Step 7 — Exempt a group from a filter
To keep a filter from applying to, say, a head-office role, open the filter rule, go to Applies To, select Add Target, set Mode to Except, Target Type to Role and pick the role. Users holding that role now see the records as if the filter did not exist. The same works on grant rules, to keep one group out of a grant.
Step 8 — Change, switch off or remove a rule
- Change a rule's settings — on the policy page use Edit Rule on the rule's row (or Edit Rule on the rule's own page). Name cannot be changed.
- Switch a rule off — Edit Rule → untick Enabled. This is the first thing to do when a rule misbehaves: its effect stops while the policy and other rules stay as they are.
- Remove a rule, expression or target — use Delete on its row and confirm.
- Switch the whole policy off — Edit Policy → Active off. This is the emergency lever: every rule stops, and the entity falls back to Private with hierarchy, sharing and team access all off, so only owners and View All holders can read its records.
Formula reference
A rule formula is a condition on one record of the policy's entity. It can use:
| You can use | How | Example |
|---|---|---|
| The record's fields | By field name. Prefixing the entity name is allowed and ignored. | Region == "West" |
| A related record's fields | Through the lookup, with a dot. | VisitPlan.AssignedToResourceId != null |
| Comparisons and logic | ==, !=, <, >, <=, >=, AND, OR, NOT and brackets. | Status == "Open" AND Amount > 100000 |
| Who is reading | User.Id, User.Email, User.UserName, User.DisplayName, User.ContactId, User.IsExternal. | OwnerId == User.Id |
| The reader's resource | User.ResourceId (their own resource), User.HasResource (true when they are linked to one), User.ResourceIds (their resource plus the resources of everyone below them in the role tree). | ResourceId != null && User.ResourceIds.Contains(ResourceId.Value) |
| The reader and their team | User.HierarchyUserIds — the reader plus every user holding a role below theirs, whatever the policy's hierarchy switch says. | User.HierarchyUserIds.Contains(OwnerId.Value) |
| Accounts the reader can see | User.VisibleAccountIds — the accounts the reader may read under Account's own record security. Not allowed in a rule on Account itself. | User.VisibleAccountIds.Contains(AccountId.Value) |
| The record's owner | Owner.InRole("Role name"), Owner.InRoleAndSubordinates("Role name"), Owner.InTeam("Team name") — use the role or team Name from Setup → Access Control. | Owner.InRoleAndSubordinates("Regional Head") |
| The current time | Env.UtcNow (UTC). | ExpiryDate > Env.UtcNow |
The symbol forms &&, || and ! work too, and are what the shipped rules use.
Things a formula cannot do:
- It cannot name the reader's business unit, role, team or profile directly —
User.BusinessUnitIdsand similar are refused as unsupported. Scope by group with the rule's targets instead, and use the formula to pick the records. "Each unit sees its own records" is therefore one rule per unit. User.ResourceIds,User.HierarchyUserIdsand the owner conditions are empty when they resolve to nobody — a reader with no resource, or a role or team with no members — so the condition matches no record. Guard filters with!User.HasResource || …when back-office users who have no resource should stay unfiltered, as the shipped visit filters do.- A condition over a related list (such as
Members.Any(…)) works only on standard entities, not on entities you create.
Fields
The rule dialog (New Security Rule / Edit Security Rule):
| Field | What it means | Notes |
|---|---|---|
| Name | The rule's name. | Required. Cannot be changed after creation. |
| Rule Type | Access Grant adds records; Access Filter narrows them. | Ownership Resolution and Principal Expansion are listed but cannot be selected. |
| Effect | Grant Read, Grant Write or Grant Share for a grant; Filter Visible Records for a filter. | Grant Share has no effect, because nothing in xMatix asks for share access. Resolve Owner cannot be selected. |
| Applies To Audience | All, Internal or External. | Specific Principal Type cannot be selected. |
| Applies To Operations | The one operation the rule takes part in. | Grant Read: Read (1). Grant Write: Update (4) or Delete (8). Filter: Read, Update or Delete. |
| Priority | A number, default 100. | Displayed only; every applicable rule is used regardless of priority. |
| Description | Free text shown in the Rules table. | Optional. |
| Enabled | Whether the rule takes part. | On by default for a new rule. |
| Stop Processing On Match | Shown but cannot be changed. | Has no effect. |
The expression dialog (New Rule Expression / Edit Rule Expression):
| Field | What it means | Notes |
|---|---|---|
| Name | The expression's label. | Required. Cannot be changed after creation. |
| Expression Mode | How the condition is written. | Only Formula can be chosen. |
| Return Type | What the formula produces. | Boolean for grants; Boolean or Record Filter for filters. |
| Formulae | The condition. | Required. See Formula reference. |
| Validation, Validation Message, Validated | Filled in by xMatix on save (table columns, not dialog fields). | Valid, Invalid, Not Validated or Pending. Only Valid expressions are used. |
The target dialog (Add Target / Edit Target):
| Field | What it means | Notes |
|---|---|---|
| Name | The target's label. | Required. Cannot be changed after creation. |
| Mode | Applies to includes the group; Except excludes it. | A matching Except wins over any Applies to. |
| Target Type | Which kind of principal. | Current User, Owner, Team, Role, Business Unit, All Internal, All External, Profile. Custom Principal cannot be selected. |
| Team / Role / Business Unit / Profile | The specific principal, for those types. | Shown in the table as Static Target Id. |
| Grant Mask | Read (1). | Grant rules only; the only value accepted. |
Business rules
- Effect must fit the rule type. Access Grant takes Grant Read, Grant Write or Grant Share; Access Filter takes Filter Visible Records. An expression on a mismatched rule is marked Invalid with "Effect … is not valid for rule type …".
- Owner conditions must name a real role or team. On save, a name that does not exist marks the expression Invalid with "Unknown owner principal — … Use the role / team Name (or id) from Setup → Access Control." Names are matched ignoring case.
- Expressions on one rule combine with AND; grant rules combine with OR; filter rules combine with AND.
- Invalid expressions are skipped silently for lists and record pages. Reports are stricter: if a rule that applies to the reader cannot be translated for the report engine, reports on that entity are refused for that reader rather than shown unfiltered.
- Grant rules are skipped when the default already allows the operation. A Grant Read rule does nothing on a Read Only entity.
- Business units come from roles. A Business Unit target covers users whose active roles belong to that unit.
- Team targets always count, whatever the policy's Allow team access switch says; that switch only governs team shares.
- Changes reach signed-in users within about two minutes, because security settings are cached.
Example
A distributor keeps orders Private for staff and wants each region's order desk to see that region's orders, with the national team seeing everything.
- In Setup → Access Control → Policies the administrator opens the order entity's policy. Its Ownership is User Owned and Internal Access is Private.
- They select New Rule: Name
West orders → West desk, Access Grant, Grant Read, Audience Internal, Enabled off. Create. - On the rule's Expressions tab they add
Region == "West". The Validation column shows Valid. - On Targets they add Applies to · Business Unit · West.
- They repeat Steps 2–4 for
North orders → North desk. - They sign in as a West desk user who owns no orders: the list is empty. They enable both rules, wait two minutes and sign in again: the user now sees every West order and no North ones. A North user sees only North orders. The national team's profile has View All, so they continue to see everything.
- A month later the West desk also needs to correct order details. The administrator adds a third rule,
West orders editable by West desk, with Grant Write, Update (4), the same expression and target, and confirms the desk's profile grants Update on orders.
Training
Practice exercise
In a sandbox, pick an entity whose policy is Private for staff (or create a policy with Internal default access = Private for a custom entity). Create two records with a text field set to A and B, owned by an administrator. Give a test user a profile that reads the entity, without View All.
- Sign in as the test user: you see neither record.
- Add a disabled Access Grant / Grant Read rule with the expression
<YourField> == "A"and an Applies to target of Role = the test user's role. Confirm the expression is Valid. - Enable the rule and wait two minutes. Expected result: the test user sees record A only.
- Add an Except target for the same role. Expected result: the test user sees nothing again.
Quick reference
- Grants add records; filters narrow them; there is no deny.
- A rule needs an active policy on the entity — no policy, no rules.
- Build rules disabled, check Valid, then enable.
- Expressions on one rule are ANDed; put "or" inside one formula.
- A grant with no Applies to target grants nothing; a filter with none applies to everyone.
- Except beats Applies to.
- One operation per rule: Grant Write for Update and for Delete are separate rules.
- Formulas cannot name the reader's business unit — use targets for groups.
- View All skips filters for reading; test with a scoped account.
- Allow two minutes for changes to take effect.
Permissions
| Task | What you need |
|---|---|
| Open Setup → Access Control → Policies; create, edit, enable, disable and delete rules, expressions and targets | The setup.security.manage capability. Without it the Access control area is not shown in Setup. |
| Be affected by a rule at all | Profile access to the entity. Rules never widen entity-level access. |
| Bypass every rule when reading | View All on the entity in one of the user's profiles. |
| Bypass every rule when updating or deleting | Modify All on the entity. |
Configuration
| What | Where | What changing it affects |
|---|---|---|
| The entity's baseline (ownership, default access, switches, Active) | Setup → Access Control → Policies → Edit Policy | What every user reaches before rules; an inactive policy ignores all its rules. |
| Rules, expressions and targets | Policy page → New Rule, then the rule's page | Extra or narrower access for selected users. |
| Roles and the role tree | Setup → Access Control → Roles | Who a Role or Business Unit target covers, and what User.HierarchyUserIds, User.ResourceIds and Owner.InRoleAndSubordinates contain. |
| Teams and members | Setup → Access Control → Teams | Who a Team target and Owner.InTeam cover. |
| Business units | Setup → Access Control → Business units | Who a Business Unit target covers (through roles). |
| Profiles, View All and Modify All | Setup → Access Control → Profiles | Who a Profile target covers, and who bypasses rules. |
| Automatic profile and team assignment | Setup → Access Control → Security assignment | Which users end up in the groups your targets name. |
Common problems
The rule grants nothing
Check, in order: the policy is Active; the rule is Enabled; every expression shows Valid; the rule's audience matches the user; the rule has an Applies to target that matches the user and no Except target that does; the user's profile grants the entity; and the default is not already Read Only (which makes Grant Read rules redundant). Then wait two minutes and reload.
The expression is marked Invalid with "Formula contains unsupported runtime context references."
The formula uses a User. or Env. name xMatix does not provide to rules — commonly User.BusinessUnitIds, User.RoleIds or User.Teams. Use one of the tokens in the Formula reference, and scope by group with a target instead.
The expression is marked Invalid with "Unknown owner principal"
An Owner.InRole, Owner.InRoleAndSubordinates or Owner.InTeam condition names a role or team that does not exist. Copy the exact Name from Setup → Access Control → Roles or Teams, in double quotes.
The expression is marked Invalid with "Owner tokens take one double-quoted role or team name"
The owner condition is malformed — a missing quote, no brackets or two arguments. Write it as Owner.InRole("Name").
Users see more than the filter should allow
Another path is open: the user has View All; an Except target matches them; the filter's audience does not include them; or its expression is not Valid, so it filters nothing.
Back-office users lost every record after a resource filter
A filter that uses User.ResourceIds matches nothing for a user with no linked resource. Add !User.HasResource || at the start of the formula, or add an Except target for the back-office role.
Reports on the entity are refused for some users
A rule that applies to them cannot be translated for the report engine, so reports fail closed. Simplify the rule's formula, or check its Validation Message.
Common questions
Can a rule say "the current user's business unit"?
No. A formula cannot read the reader's business unit, role, team or profile. Write one rule per unit instead: the formula picks that unit's records (for example Region == "West") and a Business Unit target picks its people. Each rule can then be tested and switched off on its own. If records carry an owner, Owner.InRoleAndSubordinates("…") can select records by who owns them rather than by a field.
Do rules apply to administrators?
Not to users with View All (for reading) or Modify All (for update and delete) on the entity — those profile settings bypass record security, filters included. Keep them for genuine administrators and auditors, and test rules with an account that lacks them.
Can a rule let a group edit records they do not own?
Yes. Create an Access Grant rule with Grant Write and Update (4), and a second one with Delete (8) if they should also delete. Unless the default already lets them read the records, add a Grant Read rule with the same expression and target, or they will not see what they may edit. Their profiles must still grant Update (and Delete) on the entity.
Can a rule apply only to portal users?
Yes. Set Applies To Audience to External, or use an All External target. User.ContactId holds the portal user's contact, so a formula such as ContactId == User.ContactId limits them to their own records. Internal and external default access are set separately on the policy.
Why is my rule's priority ignored?
Priority is displayed but not used: every applicable grant is added and every applicable filter applied, whatever the order. Stop Processing On Match is likewise fixed and has no effect.
