> For the complete documentation index, see [llms.txt](https://docs.avonnicomponents.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.avonnicomponents.com/flow/help/permissions-and-data-access.md).

# Permissions & Data Access

## How Avonni Components Handle Security

Avonni components run within your Salesforce org and adhere to the same security model as any native Salesforce feature. When a component queries data, Salesforce enforces your org's field-level security (FLS), object permissions (CRUD), and sharing rules.

This page covers how that works in practice, what the "Strip Inaccessible Fields" setting does, how record actions behave, and how to troubleshoot common permission-related issues.

***

## Object and Field Permissions

Before a component can display data, Salesforce checks whether the running user has access to the object and fields being queried.

### Object-level access

If a user doesn't have Read permission on an object, any query that references that object will fail entirely. This includes relationship fields — if your Data Table queries Accounts and includes `Account.Owner.Manager.Name`, the user needs Read access to the User object for that relationship to resolve.

When a query references a related object the user can't access, the query fails at parse time. Salesforce doesn't return partial results — the entire query throws an error.

### Field-level access

If a user has access to the object but not to a specific field, the behavior depends on how the component is configured:

* **Without "Strip Inaccessible Fields":** The query runs but Salesforce may throw a security exception if FLS isn't enforced in the Apex code.
* **With "Strip Inaccessible Fields" enabled:** The query runs, and fields the user can't access are silently removed from the results. The component displays what the user is allowed to see.

***

## What "Strip Inaccessible Fields" Actually Does

The "Strip Inaccessible Fields" toggle (available on components with data sources) runs `Security.stripInaccessible()` **after** the query returns results. It removes fields from the result set that the user doesn't have FLS access to.

### What it handles

* Fields the user can't read are removed from query results
* The component renders without those fields (columns appear empty or are hidden)
* No error is thrown — the component works, just with fewer fields visible

### What it doesn't handle

* **Object-level access failures.** If the user can't access the object at all, the query fails before `stripInaccessible` ever runs. The toggle has no effect.
* **Relationship object access.** If a query includes a lookup to an object the user can't read (e.g., querying Contacts with `Account.ParentId` where the user can't read Accounts), the SOQL fails at parse time. Strip Inaccessible Fields only processes results — if there are no results, there's nothing to strip.
* **Aggregate or formula fields** that reference inaccessible fields behind the scenes.

In short: **Strip Inaccessible Fields is a post-query safety net, not a pre-query filter.** It can't fix a query that couldn't run in the first place.

***

## Record Actions Run as the Running User

Everything above is about reading data. The actions that write data are enforced the same way. Delete Selected Record(s), Duplicate Selected Record(s) and Update Records all run as the user who triggers them, so object permissions, field permissions and sharing apply to that user.

One difference is worth knowing, because it catches people out. Components that read data offer a **Query System Mode** setting, which lets that query ignore the running user's access. **The record actions have no equivalent setting.** They always run in the user's context, whatever Query System Mode is set to on the same component.

Deleting is where this shows up most, because Salesforce is stricter about delete than about read or edit. To delete a record, a user needs Delete on the object, plus record-level access from one of:

* owning the record
* sitting above the owner in the role hierarchy, with Grant Access Using Hierarchies enabled on the object
* having Modify All on that object

Sharing that grants Read/Write does **not** grant delete. A user can open a record, edit it, and still not be allowed to delete it.

### Delete fails with "insufficient access rights on object id"

The usual shape: one user creates a record, a different user triggers the delete action on it, and the delete fails with that message. The person who created the record can delete it without any problem.

That is the rule above rather than a component fault. Three ways to resolve it, from the narrowest to the most involved:

1. **Put the deleting users above the record owners in the role hierarchy**, and enable Grant Access Using Hierarchies on the object. This works when the people deleting sit above the people creating, and it changes nothing for anyone else.
2. **Grant Modify All on that one object** through a permission set. It is narrower than Modify All Data because it covers a single object, but it still bypasses sharing for every record of that object, so check that this is acceptable before using it.
3. **Move the delete into a flow.** Replace the row action with [Open Flow Dialog](/flow/component-builder/interactions-panel/open-flow-dialog.md), pass `{{Record.Id}}` into a flow input variable, and let the flow call a subflow running in system context to perform the delete. Add [Refresh All Queries](/flow/component-builder/interactions-panel/refresh-all-queries.md) to the dialog's finish interactions so the component reloads afterwards. The elevated rights then sit in the flow instead of on your users.

{% hint style="info" %}
Despite its name, **Delete Selected Record(s) used as a row action deletes only the row it was triggered from**, not the current selection. So replacing a row action with the flow approach above is a like-for-like swap.
{% endhint %}

***

## Visibility Rules and Custom Permissions

Avonni components support visibility rules based on custom permissions. A component becomes visible or hidden based on whether the running user has a specific custom permission assigned.

### How it works

1. The component checks if the running user has the custom permission
2. Based on the result, the component is shown or hidden
3. This check runs every time the page or screen loads

### Common issue: visibility rules not evaluating correctly

If a visibility rule based on a custom permission doesn't work as expected — for example, all users see the same result regardless of whether they have the permission — the root cause is usually how Salesforce handles the permission check.

**Troubleshooting steps:**

1. **Confirm the custom permission exists** in Setup > Custom Permissions
2. **Confirm it's assigned** to the right permission set, and that permission set is assigned to the right users
3. **Test with a non-admin user.** System administrators bypass many permission checks. Always test visibility rules with a standard user profile.
4. **Check your Avonni package version.** Earlier versions had an issue where the underlying query used `USER_MODE` for Setup entities, which prevented standard users from reading custom permission metadata. This was fixed — make sure you're on the latest version.

***

## Troubleshooting

### "My Component Shows No Data"

When a component appears but shows no records, work through these checks in order:

#### 1. Is it a permission issue?

Open the browser console (F12) and look for error messages. Common ones:

* `Insufficient privileges` or `No access to entity` — The user can't read the object being queried
* `Field is not accessible` — FLS is blocking a specific field
* No error at all, just empty results — Could be sharing rules limiting the record set

#### 2. Does it work for an admin?

Log in as an admin and load the same page/screen. If the admin sees data but the user doesn't, it's almost certainly a permission or sharing issue.

#### 3. Check sharing rules

Even if a user has object and field access, sharing rules control *which records* they can see. If the user's role doesn't grant access to the records in the query, results will be empty.

#### 4. Check the "Strip Inaccessible Fields" toggle

If this toggle is off and the user lacks FLS on a queried field, the component may throw an error instead of showing partial data. Try enabling it to see if the component loads with reduced fields.

#### 5. Check relationship fields

If your query includes lookup fields to other objects (e.g., `Contact.Account.Name`), verify the user has Read access to each object in the chain. A single broken link in the relationship chain will cause the entire query to fail.

### "A User Can See a Record but Can't Delete It"

This is expected Salesforce behavior rather than a component issue. Read and Read/Write access let a user see and edit a record; deleting additionally requires ownership, a role above the owner, or Modify All on the object. Turning on Query System Mode does not change it, because that setting applies to the query and not to the actions. See [Record Actions Run as the Running User](#record-actions-run-as-the-running-user) above for the three ways to handle it.

### Custom Permission Visibility Not Working

| Symptom                                                   | Likely cause                                              | Fix                                                       |
| --------------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------- |
| All users see the component (even without the permission) | Permission check returning `undefined` instead of `false` | Update to latest package version                          |
| No users see the component (even with the permission)     | Custom permission not assigned via permission set         | Assign the permission set to the users                    |
| Works for admins, not for standard users                  | Admin profile bypasses permission checks                  | Test with standard user; assign permission set explicitly |
| Intermittent — sometimes works, sometimes doesn't         | Browser caching or session issues                         | Test in incognito; clear cache                            |

### Deployment & Permission Sets

When deploying Avonni components between environments (sandbox to production), remember:

* **Avonni permission sets** must be assigned separately in each environment. Deploying a page layout doesn't carry over permission set assignments.
* **Custom permissions** used in visibility rules must exist in the target environment. If they don't, the visibility rule will silently fail (the component may always hide or always show).
* **Package licenses** must be assigned to users in each environment. A deployed component won't render if the user doesn't have the Avonni package license in that org.

See also: [Installation & Licenses Management](/flow/getting-started/installation-and-licenses-management.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.avonnicomponents.com/flow/help/permissions-and-data-access.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
