Row-access filters

Restrict which rows a user can see using semantic-layer access filters enforced in compiled SQL and by Postgres row-level security

Row-access filters restrict which rows a user sees, based on their attributes — so a regional manager only ever queries their own region's data. This page shows how to declare them and how they're enforced. Defining access filters is an admin/modeling task.

#How they work

You declare access_filters under a model's flax: key. Each filter pairs an org-authored SQL expression with a user attribute: at query time the compiler keeps only rows where the expression matches one of the caller's server-trusted values for that attribute.

models:
  - name: orders
    flax:
      access_filters:
        - sql: ${region}
          attribute: region

If the caller's region attribute is ["EMEA"], the compiler AND-s a predicate keeping only rows where region = 'EMEA' into the query — as a bind parameter, never interpolated text.

#Closed by default

Access filters fail safe. If a caller has no value for a filter's attribute, the compiler emits a 1=0 predicate, so the query returns no rows. There is no way to opt out of a filter by lacking the attribute.

Important

Because filters are closed by default, make sure every user who should see data actually has the required attribute set. A missing attribute means an empty result, not full access.

Models without any access_filters are unaffected — the filter only applies where you declare it.

#Defence in depth

Access filters are enforced in two independent layers:

  • In compiled SQL. The predicate is added to every query the semantic layer compiles, on every warehouse dialect.
  • By Postgres row-level security. For the Postgres-backed path, row-level security policies enforce the same restriction at the database, so the boundary holds even outside the normal query path.

The attribute values come from the caller's server-trusted principal — they are never taken from the client request, so a user cannot widen their own access.

#Where attributes come from

Filters reference user attributes, which are managed by admins. See: