Access policy reference
Reference for Retool access policy rules, statuses, error codes, audit events, and API endpoints.
Reference for the components of an access policy, the errors enforcement produces, and the API and audit surfaces that expose them. For the semantics of enforcement, including how grants combine and why a query returns what it does, refer to Data access enforcement. For an introduction to the model, refer to Access policies.
Policy structure
A policy belongs to an organization and applies to one or more resources.
| Field | Description |
|---|---|
| Name | Display name. Defaults to Untitled policy. |
| Description | Optional explanation, visible to users with Own access to the resource. |
| Status | Draft, Active, or Inactive. Refer to Statuses. |
| Access level | Full access or Granular access. |
| Assignment | The permission groups the policy applies to, and the groups excluded from it. |
| Environments | The resource environments the policy covers. At least one is required. |
| Rules | The table, column, and row grants that make up granular access. |
Access levels
| Access level | Behavior |
|---|---|
| Full access | Grants unrestricted access to the resource. Rules are not evaluated. |
| Granular access | Grants only what the policy's rules allow. Anything not granted is blocked. |
Full access is not equivalent to granting read and write access to every table. It bypasses rule evaluation, which means it also bypasses restrictions that apply only to granular grants, including the block on GUI mode queries.
If any policy covering a user grants Full access to a resource, that user reaches all of its data regardless of other policies.
Full access to a resource compared to full access to a table
Two grants use similar wording and behave differently.
| Grant | Where you set it | Scope |
|---|---|---|
| Unrestricted access to this resource, shown as Full access once set | The policy's access level. | The whole resource, including statements that do not reference a specific table. |
| Allow read + write access to | A rule on a selected table. | The selected table only. |
Selecting every table in a granular rule is not equivalent to Full access. Granular rules are always evaluated against the tables they name, so a statement that references no table is blocked no matter how many tables the rules cover.
Data definition statements
Statements that change database structure, such as CREATE, ALTER, DROP, and RENAME, succeed only under Full access.
Under granular access, they return unsupported_query_construct, because enforcement cannot evaluate these statement types against a policy's rules. The reason identifies the statement type, in the form 'RenameStmt' statements are not supported by data security policy enforcement.
Rules
Each rule targets one table.
| Field | Description |
|---|---|
| Table | The table the rule grants. |
| Actions | read, write, or both. |
| Columns | The columns granted. Refer to Column grants. A rule listing no columns grants nothing. |
| Row filters | The filters narrowing which rows the rule grants. Each filter is one condition: a column, an operator, and a value. No filter grants every row. |
Actions
| Action | Grants |
|---|---|
| Allow read access to | Reading the granted data. |
| Allow write access to | Inserting, updating, and deleting the granted data. |
| Allow read + write access to | Both. |
Write grants do not validate the values a user writes. Refer to Row filters do not validate writes.
Column grants
Under Column access, choose the action, then name the columns it applies to. The column field offers two shortcuts above the table's individual columns.
| Option | Grants | SELECT * |
|---|---|---|
| All present + future columns | Every column on the table, including columns added to it later. | Allowed. |
| All present columns | Each column the table has now, selected individually. Columns added later are not covered. | Blocked. |
| A named column | That column only. | Blocked. |
Columns allowed indicates how many columns the rule currently grants. A rule that lists no columns grants nothing, so every rule needs at least one column or one of the shortcuts. Refer to Grants and their results for why a wildcard is blocked under a fixed column list.
Row filter operators
A filter value is formatted according to the column's type, as a string, number, or boolean. Columns that are neither numeric nor boolean are compared as strings.
| Operator | Matches rows where the column |
|---|---|
| Equal to | Equals the value. |
| Not equal to | Does not equal the value. |
| Less than | Is less than the value. |
| Greater than | Is greater than the value. |
| Contains | Contains the value. |
| RegEx text match | Matches the value as a regular expression. |
| LIKE | Matches the value as a SQL LIKE pattern. |
| Is null | Holds no value. |
| Is not null | Holds any value. |
Is null and Is not null compare the column alone and take no value. The rest each take one.
Multiple filters combine with AND, requiring every filter to match, or OR, requiring at least one. The choice applies to every filter in the rule, and filters cannot be nested. A column can appear in more than one filter, which is how a bounded range is expressed. Refer to Filter on a range.
Supported embedded expressions
Row filter values support the following {{ }} embedded expressions.
| Embedded expression | Resolves to |
|---|---|
{{ current_user.id }} | The user's Retool ID. |
{{ current_user.email }} | The user's email address. |
{{ current_user.sid }} | The user's session identifier. |
{{ current_user.firstName }} | The user's first name. |
{{ current_user.lastName }} | The user's last name. |
{{ current_user.externalIdentifier }} | The user's external identifier. |
{{ current_user.metadata.<attribute> }} | The named user attribute. |
{{ environment.variables.<NAME> }} | The named environment variable. |
{{ secrets.<name> }} | The named secret. |
An embedded expression must resolve to a single value. {{ current_user.groups }} is a list and cannot be used. Values from retoolContext are controlled by whoever runs the query and cannot be used.
If an embedded expression cannot be evaluated for the user running a query, the query is blocked.
Statuses
| Status | Meaning |
|---|---|
| Draft | Edited but not yet saved. Has no effect. |
| Active | In effect for the assigned groups and environments. |
| Inactive | Saved, but not in effect. |
A policy you are editing keeps its existing status until you save. An Active policy you are part way through editing stays tagged Active, and Retool keeps enforcing the last saved version of it until you save your changes on the Access Enforcement tab.
Deactivating a policy removes the access it granted. Policies persist when data access enforcement is turned off for the resource.
Which groups a policy covers
A policy's assignment has two lists, one that gives groups the policy's grants and one that removes groups from it.
| Relation | Effect |
|---|---|
| Apply to | Members of these groups receive the policy's grants. |
| Except | Members of these groups are not subject to this policy, even if they also belong to a group in Apply to. |
Grants from multiple policies are additive. For any single column, a user reaches a row if any policy granting that column permits it, and a row is returned only if every column the query references permits it.
Where enforcement applies
| Surface | Behavior on an enforced resource |
|---|---|
| Apps, query library, raw SQL | Enforced. |
| Agents and AI query generation | Enforced as the user who invoked them. |
| Schema browser | Filtered to granted tables and columns. |
| GUI mode queries | Blocked for granular grants, allowed under Full access. |
| Workflow runs with no user to attribute them to, including those triggered by a schedule, a webhook, a query, an email, or another agent | Each query on the resource is blocked. |
| Workflow runs started manually or from an app | Blocked, unless the organization attributes them to the user who started them. |
| Public and embedded apps | Blocked, because no signed-in user can be resolved. |
| Queries with no resolvable user | Blocked. |
| Catalog and introspection schemas | Always blocked, not configurable. |
| Queries Retool cannot parse | Blocked. |
| Data definition statements | Blocked under granular access, allowed under Full access. |
Error codes
Blocked queries return HTTP 403 with a structured payload identifying access policies as the source. Queries Retool cannot parse at all return HTTP 400.
| Reason code | Meaning |
|---|---|
insufficient_data_access_grants | No policy grants the requested table, column, or action. |
catalog_access | The query references a database catalog or introspection schema. |
public_app_unsupported | The query originates from a public or embedded app. |
gui_mode_unsupported | The query uses GUI mode on a resource with granular grants. |
headless_workflow_run | The query comes from a workflow run with no invoking user. |
unsupported_query_construct | The query parsed, but uses constructs enforcement cannot evaluate. |
policy_evaluation_failed | A filter value could not be resolved, or evaluation failed. |
Messages name the table or column involved so a builder can act on them. They never reveal the contents of a row filter.
Audit events
| Event | Recorded when |
|---|---|
DATA_SECURITY_POLICY_CREATED | A policy is created. |
DATA_SECURITY_POLICY_UPDATED | A policy is edited, activated, or deactivated. |
DATA_SECURITY_POLICY_DELETED | A policy is deleted. |
DATA_SECURITY_POLICY_QUERY_BLOCKED | A query is blocked by a policy. |
Query run events additionally record whether a policy narrowed the query or left it unchanged, and which policies applied.
Audit entries record policy identifiers and names. Refer to Audit trail logged events.
API endpoints
Access policies are read-only through the Retool API. Create and modify policies in the UI.
| Method | Endpoint | Returns |
|---|---|---|
GET | /data_security_policies | All policies in the organization. |
GET | /data_security_policies/{policyId} | A single policy. |
GET | /data_security_policies/{policyId}/users | The users a policy applies to. |
GET | /resource_configurations/{configurationId}/users | The users affected by policies on a resource configuration. |
These endpoints require the Data Security Read scope on the access token. Refer to Configure Retool API authentication.