From 4ce3d4283abb54ae6b21e9052f7d52e876be8cdf Mon Sep 17 00:00:00 2001 From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 16:05:16 +0000 Subject: [PATCH 1/2] docs: document conditional row-level access and allow_all in access policies --- docs-mintlify/docs.json | 6 + .../data-modeling/data-access-policies.mdx | 11 +- .../conditional-row-level-access.mdx | 284 ++++++++++++++++++ .../data-modeling/data-access-policies.mdx | 120 +++++++- 4 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 docs-mintlify/recipes/access-control/conditional-row-level-access.mdx diff --git a/docs-mintlify/docs.json b/docs-mintlify/docs.json index ab131e9bacec3..7348d54411761 100644 --- a/docs-mintlify/docs.json +++ b/docs-mintlify/docs.json @@ -648,6 +648,12 @@ "recipes/configuration/custom-data-model-per-tenant" ] }, + { + "group": "Access Control", + "pages": [ + "recipes/access-control/conditional-row-level-access" + ] + }, { "group": "Core Data API", "pages": [ diff --git a/docs-mintlify/docs/data-modeling/data-access-policies.mdx b/docs-mintlify/docs/data-modeling/data-access-policies.mdx index cf65f076bfa3d..9cd3816bc63f1 100644 --- a/docs-mintlify/docs/data-modeling/data-access-policies.mdx +++ b/docs-mintlify/docs/data-modeling/data-access-policies.mdx @@ -492,6 +492,14 @@ view(`orders_view`, { +### Conditional row-level filters + +You can switch which `row_level` filter applies based on the +[security context][ref-sec-ctx] — for example, to scope a group to its region +or to let admins bypass row filters with `row_level.allow_all: true`. See the +[conditional row-level access recipe][ref-recipe-conditional-row-level] for +worked examples in YAML and JavaScript. + ### Mandatory filters You can apply mandatory row-level filters to specific groups to ensure they only see data matching certain criteria: @@ -621,4 +629,5 @@ cube(`orders`, { [ref-ref-dap-role]: /reference/data-modeling/data-access-policies#role [ref-ref-dap-masking]: /reference/data-modeling/data-access-policies#member-masking [ref-ref-mask-dim]: /reference/data-modeling/dimensions#mask -[ref-core-data-apis]: /reference/core-data-apis \ No newline at end of file +[ref-core-data-apis]: /reference/core-data-apis +[ref-recipe-conditional-row-level]: /recipes/access-control/conditional-row-level-access \ No newline at end of file diff --git a/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx b/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx new file mode 100644 index 0000000000000..9bf3352bd9a31 --- /dev/null +++ b/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx @@ -0,0 +1,284 @@ +--- +title: Conditional row-level access +description: Switch row-level filters based on the security context, and let an admin policy grant unrestricted row access on top of more restrictive policies. +--- + +## Use case + +You want different row-level filters to apply to the same group depending on +who the user is. For example: + +- Users in different regional groups should see only rows for their region. +- Admins should bypass row filters entirely, even when other policies restrict +the same role. + +You can express both patterns with [`access_policy`][ref-ref-dap] by combining +[`conditions`][ref-ref-dap-conditions], [`row_level.allow_all`][ref-ref-dap-row-level], +and the [_OR_ semantics across policies][ref-dap-rls] that match the same group. + +## Data modeling + +### Region-based switching + +Define one policy per region, and gate each policy with a `conditions` entry +that checks the user's [security context][ref-sec-ctx]. Only the policy whose +condition evaluates to `true` contributes its `row_level` filter to the query — +the others are skipped. + +In the following example, users in the `analyst` group see rows for their +region: members of the `emea` group are restricted to EMEA orders, and members +of the `amer` group are restricted to AMER orders. + + + +```yaml title="YAML" +cubes: + - name: orders + # ... + + access_policy: + - group: analyst + conditions: + - if: "{ security_context.groups and 'emea' in security_context.groups }" + row_level: + filters: + - member: region + operator: equals + values: ["EMEA"] + + - group: analyst + conditions: + - if: "{ security_context.groups and 'amer' in security_context.groups }" + row_level: + filters: + - member: region + operator: equals + values: ["AMER"] +``` + +```javascript title="JavaScript" +cube(`orders`, { + // ... + + access_policy: [ + { + group: `analyst`, + conditions: [ + { if: securityContext.groups && securityContext.groups.includes(`emea`) } + ], + row_level: { + filters: [ + { + member: `region`, + operator: `equals`, + values: [`EMEA`] + } + ] + } + }, + { + group: `analyst`, + conditions: [ + { if: securityContext.groups && securityContext.groups.includes(`amer`) } + ], + row_level: { + filters: [ + { + member: `region`, + operator: `equals`, + values: [`AMER`] + } + ] + } + } + ] +}) +``` + + + +In JavaScript, you can also express the same pattern by making `row_level` +itself a function of `securityContext` and returning different filters +depending on the caller: + + + +```yaml title="YAML" +cubes: + - name: orders + # ... + + access_policy: + - group: analyst + conditions: + - if: "{ security_context.groups and ('emea' in security_context.groups or 'amer' in security_context.groups) }" + row_level: + filters: + - member: region + operator: equals + values: + - "{ 'EMEA' if 'emea' in security_context.groups else 'AMER' }" +``` + +```javascript title="JavaScript" +cube(`orders`, { + // ... + + access_policy: [ + { + group: `analyst`, + row_level: { + filters: [ + { + member: `region`, + operator: `equals`, + values: [ + securityContext.groups && securityContext.groups.includes(`emea`) + ? `EMEA` + : `AMER` + ] + } + ] + } + } + ] +}) +``` + + + +### Admin override with `allow_all` + +To let admins bypass row-level filters that apply to a role, add a second +policy for the same group that grants [`row_level.allow_all`][ref-ref-dap-row-level] +when `securityContext.is_admin` is true. Because policies that match the same +group are combined with _OR_ semantics, the admin policy unlocks every row +regardless of the more restrictive analyst policy: + + + +```yaml title="YAML" +cubes: + - name: orders + # ... + + access_policy: + # Region-restricted access for regular analysts + - group: analyst + row_level: + filters: + - member: region + operator: equals + values: ["{ security_context.region }"] + + # Admin override: full row access when the user is an admin + - group: analyst + conditions: + - if: "{ security_context.is_admin }" + row_level: + allow_all: true +``` + +```javascript title="JavaScript" +cube(`orders`, { + // ... + + access_policy: [ + { + // Region-restricted access for regular analysts + group: `analyst`, + row_level: { + filters: [ + { + member: `region`, + operator: `equals`, + values: [securityContext.region] + } + ] + } + }, + { + // Admin override: full row access when the user is an admin + group: `analyst`, + conditions: [ + { if: securityContext.is_admin } + ], + row_level: { + allow_all: true + } + } + ] +}) +``` + + + +### Composing boolean logic with `conditions` + +`conditions` accept full boolean logic, so you can switch which `row_level` +applies based on combined checks against the security context and user +attributes. In YAML, use `and`, `or`, `not`, and parentheses inside +`{ ... }`. In JavaScript, use `&&`, `||`, and `!`. Multiple `conditions` +entries on a single policy are combined with _AND_ semantics; multiple +matching policies are combined with _OR_ semantics. + +In the following example, full-time analysts who are _either_ admins _or_ +owners and are _not_ contractors get unrestricted row access; everyone else +in the `analyst` group falls back to the region-restricted policy above. + + + +```yaml title="YAML" +cubes: + - name: orders + # ... + + access_policy: + - group: analyst + conditions: + - if: "{ user_attributes.is_full_time_employee and user_attributes.tenure_years >= 2 }" + - if: "{ user_attributes.is_admin or user_attributes.is_owner }" + - if: "{ not (security_context.groups and 'contractors' in security_context.groups) }" + row_level: + allow_all: true +``` + +```javascript title="JavaScript" +cube(`orders`, { + // ... + + access_policy: [ + { + group: `analyst`, + conditions: [ + { if: userAttributes.is_full_time_employee && userAttributes.tenure_years >= 2 }, + { if: userAttributes.is_admin || userAttributes.is_owner }, + { if: !(securityContext.groups && securityContext.groups.includes(`contractors`)) } + ], + row_level: { + allow_all: true + } + } + ] +}) +``` + + + +## Result + +With these policies in place: + +- Regional analysts see only rows for the region attached to their security +context, because only the policy whose `conditions` match contributes its +`row_level` filter. +- Admins see all rows, because the admin policy's `row_level.allow_all: true` +combines with the regional policy via _OR_ semantics. +- Users without any matching policy are denied access by default. + + +[ref-ref-dap]: /reference/data-modeling/data-access-policies +[ref-ref-dap-conditions]: /reference/data-modeling/data-access-policies#conditions +[ref-ref-dap-row-level]: /reference/data-modeling/data-access-policies#row-level +[ref-dap-rls]: /docs/data-modeling/access-control/data-access-policies#row-level-access +[ref-sec-ctx]: /docs/data-modeling/access-control/context diff --git a/docs-mintlify/reference/data-modeling/data-access-policies.mdx b/docs-mintlify/reference/data-modeling/data-access-policies.mdx index 5698a33e556a5..5ab02668a91e1 100644 --- a/docs-mintlify/reference/data-modeling/data-access-policies.mdx +++ b/docs-mintlify/reference/data-modeling/data-access-policies.mdx @@ -208,6 +208,61 @@ cube(`orders`, { +#### Boolean logic in `if` expressions + +`if` expressions support full boolean logic so you can compose checks against +the [security context][ref-sec-ctx] and user attributes: + +- In YAML, expressions inside `{ ... }` use Jinja-style operators: `and`, `or`, +`not`, and parentheses for grouping. +- In JavaScript, expressions use native operators: `&&`, `||`, and `!`. +- Multiple `conditions` entries on a single policy are combined with _AND_ +semantics — every entry must evaluate to `true` for the policy to take effect. +- Multiple policies that match the same group are combined with _OR_ semantics — +if any matching policy grants access, the user gets access. + +In the following example, a single policy combines three `conditions` entries +that each use a different boolean operator: + + + +```yaml title="YAML" +cubes: + - name: orders + # ... + + access_policy: + - group: manager + conditions: + - if: "{ user_attributes.is_full_time_employee and user_attributes.tenure_years >= 2 }" + - if: "{ user_attributes.is_admin or user_attributes.is_owner }" + - if: "{ not (security_context.groups and 'contractors' in security_context.groups) }" + member_level: + includes: "*" +``` + +```javascript title="JavaScript" +cube(`orders`, { + // ... + + access_policy: [ + { + group: `manager`, + conditions: [ + { if: userAttributes.is_full_time_employee && userAttributes.tenure_years >= 2 }, + { if: userAttributes.is_admin || userAttributes.is_owner }, + { if: !(securityContext.groups && securityContext.groups.includes(`contractors`)) } + ], + member_level: { + includes: `*` + } + } + ] +}) +``` + + + ### `member_level` The optional `member_level` parameter, when present, configures [member-level @@ -452,6 +507,68 @@ REST (JSON) API][ref-rest-query-filters] queries, allowing to use the same set o You can also use `and` and `or` parameters to combine multiple filters into [boolean logical operators][ref-rest-boolean-ops]. +#### `allow_all` + +Use the `allow_all` parameter to make the row-level intent of a policy explicit +without listing any filters: + +- `allow_all: true` grants the policy access to all rows. It is equivalent to +omitting `row_level` (or omitting `filters`) and is useful when you want the +policy to clearly state that no row-level restriction applies. +- `allow_all: false` denies the policy access to all rows. Other matching +policies (if any) still apply on top — see [row-level access][ref-dap-rls]. + + + +```yaml title="YAML" +cubes: + - name: orders + # ... + + access_policy: + - group: admin + row_level: + allow_all: true + + - group: guest + row_level: + allow_all: false +``` + +```javascript title="JavaScript" +cube(`orders`, { + // ... + + access_policy: [ + { + group: `admin`, + row_level: { + allow_all: true + } + }, + { + group: `guest`, + row_level: { + allow_all: false + } + } + ] +}) +``` + + + +#### Conditional `row_level` + +You can make `row_level` conditional so that different filters apply depending +on the [security context][ref-sec-ctx] or user attributes. In YAML, attach +[`conditions`](#conditions) to a policy so its `row_level` is skipped when the +conditions don't match. In JavaScript, you can additionally make `row_level` a +function of `securityContext` and return different filters at evaluation time. +When a policy's `row_level` is skipped, other matching policies still apply; +if no policy matches, access is denied by default. See the [conditional +row-level access recipe][ref-recipe-conditional-row-level] for worked examples. + Note that access policies also respect [row-level security][ref-rls] restrictions configured via the `query_rewrite` configuration option. See [row-level access][ref-dap-rls] to learn more about policy evaluation. @@ -513,4 +630,5 @@ cube(`orders`, { [ref-mask-dim]: /reference/data-modeling/dimensions#mask [ref-rest-query-filters]: /reference/rest-api/query-format#filters-format [ref-rest-query-ops]: /reference/rest-api/query-format#filters-operators -[ref-rest-boolean-ops]: /reference/rest-api/query-format#boolean-logical-operators \ No newline at end of file +[ref-rest-boolean-ops]: /reference/rest-api/query-format#boolean-logical-operators +[ref-recipe-conditional-row-level]: /recipes/access-control/conditional-row-level-access \ No newline at end of file From 4b859f98c21529aecb0e0bb3c8928035bb0c34aa Mon Sep 17 00:00:00 2001 From: AvilaJulio Date: Thu, 2 Jul 2026 09:46:07 -0500 Subject: [PATCH 2/2] docs: correct conditional row-level access & allow_all claims Fixes invalid claims in the conditional row-level access docs, validated against Cube 1.6.65 (Docker + Postgres) and the schema-compiler source: - YAML `{ ... }` expressions are parsed as Python and only support and/or/not, parentheses, member access, and method calls. Replaced `in` and `>=` (which throw "Unsupported Python multiple children node" and can silently deny access) with `.includes(...)` and boolean attributes; documented the unsupported operators. - Removed the "make `row_level` a function of securityContext" guidance (rejected by CubeValidator: rowLevel is object-only; the core change was reverted in #10767). Replaced with the working pattern of computing a filter's member/values from securityContext in JavaScript. - Removed `allow_all: false` (invalid: allowAll only accepts `true`, xor with filters); documented deny-by-default instead. - Fixed broken link to the data-access-policies guide (dropped the non-existent `/access-control/` path segment). Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01T11gd3wgtSz7WGVnZ2ewPW --- .../conditional-row-level-access.mdx | 62 +++++++++---------- .../data-modeling/data-access-policies.mdx | 59 +++++++++--------- 2 files changed, 58 insertions(+), 63 deletions(-) diff --git a/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx b/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx index 9bf3352bd9a31..9c51d741bcf70 100644 --- a/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx +++ b/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx @@ -39,7 +39,7 @@ cubes: access_policy: - group: analyst conditions: - - if: "{ security_context.groups and 'emea' in security_context.groups }" + - if: "{ security_context.groups and security_context.groups.includes('emea') }" row_level: filters: - member: region @@ -48,7 +48,7 @@ cubes: - group: analyst conditions: - - if: "{ security_context.groups and 'amer' in security_context.groups }" + - if: "{ security_context.groups and security_context.groups.includes('amer') }" row_level: filters: - member: region @@ -97,28 +97,9 @@ cube(`orders`, { -In JavaScript, you can also express the same pattern by making `row_level` -itself a function of `securityContext` and returning different filters -depending on the caller: - - - -```yaml title="YAML" -cubes: - - name: orders - # ... - - access_policy: - - group: analyst - conditions: - - if: "{ security_context.groups and ('emea' in security_context.groups or 'amer' in security_context.groups) }" - row_level: - filters: - - member: region - operator: equals - values: - - "{ 'EMEA' if 'emea' in security_context.groups else 'AMER' }" -``` +In JavaScript, you can collapse the two policies into one by computing the +filter `values` from `securityContext` at evaluation time — the `values` array +is evaluated per request, so a ternary can pick the region for the caller: ```javascript title="JavaScript" cube(`orders`, { @@ -145,7 +126,14 @@ cube(`orders`, { }) ``` - + +This single-policy form is JavaScript-only. YAML `{ ... }` expressions don't +support inline conditionals (Python `if`/`else`) or comparison operators, so in +YAML use one policy per region as shown above. Note that `row_level` itself is +always a static object — only the `member` and `values` inside a filter are +evaluated against `securityContext`; you can't replace `row_level` with a +function. + ### Admin override with `allow_all` @@ -215,16 +203,16 @@ cube(`orders`, { ### Composing boolean logic with `conditions` -`conditions` accept full boolean logic, so you can switch which `row_level` +`conditions` accept boolean logic, so you can switch which `row_level` applies based on combined checks against the security context and user attributes. In YAML, use `and`, `or`, `not`, and parentheses inside `{ ... }`. In JavaScript, use `&&`, `||`, and `!`. Multiple `conditions` entries on a single policy are combined with _AND_ semantics; multiple matching policies are combined with _OR_ semantics. -In the following example, full-time analysts who are _either_ admins _or_ -owners and are _not_ contractors get unrestricted row access; everyone else -in the `analyst` group falls back to the region-restricted policy above. +In the following example, full-time senior analysts who are _either_ admins +_or_ owners and are _not_ contractors get unrestricted row access; everyone +else in the `analyst` group falls back to the region-restricted policy above. @@ -236,9 +224,9 @@ cubes: access_policy: - group: analyst conditions: - - if: "{ user_attributes.is_full_time_employee and user_attributes.tenure_years >= 2 }" + - if: "{ user_attributes.is_full_time_employee and user_attributes.is_senior }" - if: "{ user_attributes.is_admin or user_attributes.is_owner }" - - if: "{ not (security_context.groups and 'contractors' in security_context.groups) }" + - if: "{ not (security_context.groups and security_context.groups.includes('contractors')) }" row_level: allow_all: true ``` @@ -251,7 +239,7 @@ cube(`orders`, { { group: `analyst`, conditions: [ - { if: userAttributes.is_full_time_employee && userAttributes.tenure_years >= 2 }, + { if: userAttributes.is_full_time_employee && userAttributes.is_senior }, { if: userAttributes.is_admin || userAttributes.is_owner }, { if: !(securityContext.groups && securityContext.groups.includes(`contractors`)) } ], @@ -265,6 +253,14 @@ cube(`orders`, { + +YAML `{ ... }` expressions are parsed as Python and support `and`, `or`, `not`, +parentheses, member access, and method calls like `.includes(...)`. They do +**not** support comparison operators (`==`, `>=`, `in`) or inline `if`/`else` +conditionals — use boolean [user attributes][ref-sec-ctx] or method calls +instead. The JavaScript form has no such restriction. + + ## Result With these policies in place: @@ -280,5 +276,5 @@ combines with the regional policy via _OR_ semantics. [ref-ref-dap]: /reference/data-modeling/data-access-policies [ref-ref-dap-conditions]: /reference/data-modeling/data-access-policies#conditions [ref-ref-dap-row-level]: /reference/data-modeling/data-access-policies#row-level -[ref-dap-rls]: /docs/data-modeling/access-control/data-access-policies#row-level-access +[ref-dap-rls]: /docs/data-modeling/data-access-policies#row-level-access [ref-sec-ctx]: /docs/data-modeling/access-control/context diff --git a/docs-mintlify/reference/data-modeling/data-access-policies.mdx b/docs-mintlify/reference/data-modeling/data-access-policies.mdx index 5ab02668a91e1..bc4b9130dc421 100644 --- a/docs-mintlify/reference/data-modeling/data-access-policies.mdx +++ b/docs-mintlify/reference/data-modeling/data-access-policies.mdx @@ -210,12 +210,16 @@ cube(`orders`, { #### Boolean logic in `if` expressions -`if` expressions support full boolean logic so you can compose checks against +`if` expressions support boolean logic so you can compose checks against the [security context][ref-sec-ctx] and user attributes: -- In YAML, expressions inside `{ ... }` use Jinja-style operators: `and`, `or`, -`not`, and parentheses for grouping. -- In JavaScript, expressions use native operators: `&&`, `||`, and `!`. +- In YAML, expressions inside `{ ... }` are parsed as Python and support the +`and`, `or`, and `not` operators, parentheses for grouping, member access, and +method calls such as `.includes(...)`. Comparison operators (`==`, `>=`, `in`) +and inline `if`/`else` conditionals are **not** supported — use boolean user +attributes or method calls instead. +- In JavaScript, expressions use native operators: `&&`, `||`, `!`, and any +valid JavaScript expression. - Multiple `conditions` entries on a single policy are combined with _AND_ semantics — every entry must evaluate to `true` for the policy to take effect. - Multiple policies that match the same group are combined with _OR_ semantics — @@ -234,9 +238,9 @@ cubes: access_policy: - group: manager conditions: - - if: "{ user_attributes.is_full_time_employee and user_attributes.tenure_years >= 2 }" + - if: "{ user_attributes.is_full_time_employee and user_attributes.is_senior }" - if: "{ user_attributes.is_admin or user_attributes.is_owner }" - - if: "{ not (security_context.groups and 'contractors' in security_context.groups) }" + - if: "{ not (security_context.groups and security_context.groups.includes('contractors')) }" member_level: includes: "*" ``` @@ -249,7 +253,7 @@ cube(`orders`, { { group: `manager`, conditions: [ - { if: userAttributes.is_full_time_employee && userAttributes.tenure_years >= 2 }, + { if: userAttributes.is_full_time_employee && userAttributes.is_senior }, { if: userAttributes.is_admin || userAttributes.is_owner }, { if: !(securityContext.groups && securityContext.groups.includes(`contractors`)) } ], @@ -509,14 +513,17 @@ You can also use `and` and `or` parameters to combine multiple filters into #### `allow_all` -Use the `allow_all` parameter to make the row-level intent of a policy explicit -without listing any filters: +Use `allow_all: true` to make the row-level intent of a policy explicit without +listing any filters. It grants the policy access to all rows and is equivalent +to omitting `row_level` from the policy — useful when you want the policy to +clearly state that no row-level restriction applies, or as an admin override +that combines with more restrictive policies via [_OR_ semantics][ref-dap-rls]. -- `allow_all: true` grants the policy access to all rows. It is equivalent to -omitting `row_level` (or omitting `filters`) and is useful when you want the -policy to clearly state that no row-level restriction applies. -- `allow_all: false` denies the policy access to all rows. Other matching -policies (if any) still apply on top — see [row-level access][ref-dap-rls]. +A `row_level` block must contain either `filters` or `allow_all` — the two are +mutually exclusive. `allow_all` only accepts `true`; `allow_all: false` is not a +valid value. To deny a group all rows, don't grant it a matching policy: access +policies are deny-by-default, so any member not granted by a matching policy is +inaccessible. @@ -529,10 +536,6 @@ cubes: - group: admin row_level: allow_all: true - - - group: guest - row_level: - allow_all: false ``` ```javascript title="JavaScript" @@ -545,12 +548,6 @@ cube(`orders`, { row_level: { allow_all: true } - }, - { - group: `guest`, - row_level: { - allow_all: false - } } ] }) @@ -561,13 +558,15 @@ cube(`orders`, { #### Conditional `row_level` You can make `row_level` conditional so that different filters apply depending -on the [security context][ref-sec-ctx] or user attributes. In YAML, attach +on the [security context][ref-sec-ctx] or user attributes. Attach [`conditions`](#conditions) to a policy so its `row_level` is skipped when the -conditions don't match. In JavaScript, you can additionally make `row_level` a -function of `securityContext` and return different filters at evaluation time. -When a policy's `row_level` is skipped, other matching policies still apply; -if no policy matches, access is denied by default. See the [conditional -row-level access recipe][ref-recipe-conditional-row-level] for worked examples. +conditions don't match, and define separate policies for the different filters +you want to apply. In JavaScript, you can additionally compute a filter's +`member` or `values` from `securityContext` at evaluation time (for example, +with a ternary), which lets a single policy vary its filter per request. When a +policy's `row_level` is skipped, other matching policies still apply; if no +policy matches, access is denied by default. See the [conditional row-level +access recipe][ref-recipe-conditional-row-level] for worked examples. Note that access policies also respect [row-level security][ref-rls] restrictions configured via the `query_rewrite` configuration option. See [row-level access][ref-dap-rls] to