modellerUpdated 2026-06-12

Column-Level Security

What this covers

Column-level security restricts which columns a persona can see. It works through data tag restrictions: you tag sensitive columns, then configure a persona to be restricted from specific tags. At query time, the persona gate either blocks the query (if a restricted column is explicitly requested) or silently excludes the column (if it would have been auto-included via SELECT *). This article explains how the mechanism works, how to configure it, and how it composes with row-level security.

How it works

Column-level security is a two-layer system:

  1. Data tags label columns by sensitivity (e.g. PII, Financial). See Data Tags.
  2. Persona tag restrictions define which tags a persona cannot access.

When a query arrives under a persona:

Hidden is not column security. A measure or column marked hidden (is_hidden) is dropped from browse lists and from SELECT *. Anyone who types the name can still query it. That is curation. To stop a Sales persona from reading cost, put the measure on a persona allow-list or restrict its column with a data tag. Then both SELECT fee_amount and SELECT SUM(fee_amount) return OBJECT_NOT_AVAILABLE. See Configure Personas.

Restrictions follow a column wherever it is used, not just when it is named directly:

Relationship to row-level security

Row security and column security are independent axes that compose:

AxisControlsMechanism
Row securityWhich rows a user seesWHERE clause filters injected by the security rule compiler
Column securityWhich columns a user seesColumn exclusion based on persona tag restrictions

A persona can have both row rules and column restrictions. They apply simultaneously: first the column gate narrows the visible columns, then the row security filter narrows the visible rows. Neither depends on the other.

Everything built from the model inherits this restriction

A restricted column is not just missing from a plain query. It is missing from the model itself, for that persona.

Everything else builds from that same smaller model too. This includes a named set, a saved Named Query, and a KPI. It also includes a summary table, a subtotal, a preview, and an export. It even includes an answer from the assistant. So the restricted column cannot appear in any of them either.

Some measures and KPIs are built from other columns. If one of them uses a restricted column, that measure or KPI is blocked too. You restrict the raw column once. You do not have to find and restrict everything built from it.

A summary table built with the restricted column is not served to that persona at all. Tessallite computes the answer live instead, from the model as the persona sees it. A named set built on a restricted measure is not offered to the persona in the picker. The assistant is grounded on the same restricted catalogue. So it cannot describe, name, or chart a column the persona could not query directly.

Restrict a column once, here. It stays restricted everywhere that column feeds into.

Setting restrictions

  1. Open the persona in the Personas panel (Toolbelt → Personas → click the persona name).
  2. Scroll to the Column Restrictions section.
  3. Toggle the data tags that this persona should NOT see. Each toggled tag restricts all columns assigned to it.
  4. Click Save.

What happens at query time

Explicit column request

If a persona restricted from PII runs:

SELECT customer_name, email, revenue FROM sales

And email is tagged PII, the query is rejected with:

403 OBJECT_NOT_AVAILABLE

The error does not name the column, the tag, or the persona.

SELECT * (auto-inclusion)

If the same persona runs:

SELECT * FROM sales

The email column is silently excluded from the result. The persona sees customer_name, revenue, and all other non-restricted columns. No error is raised.

Worked example

Scenario: An "External Partner" persona should not see PII data.

  1. Create the PII tag: In Data Tags, create a tag named PII.
  2. Assign columns: Tag customers.email, customers.phone, orders.shipping_address as PII.
  3. Create the persona: In Personas, create "External Partner".
  4. Set restrictions: In the persona's Column Restrictions, toggle PII to restricted.
  5. Test: Query as the persona. SELECT * returns all columns except email, phone, and shipping_address. SELECT email FROM ... returns OBJECT_NOT_AVAILABLE.

Pitfalls

Troubleshooting

SymptomLikely causeFix
SELECT * returns fewer columns than expectedOne or more columns carry a tag this persona is restricted fromCheck the column's data tags in Data Tags, and the persona's Column Restrictions
Query returns OBJECT_NOT_AVAILABLE for a column you expect to seeThe column, or a column feeding a calculated measure you queried, is tagged with a restricted tagRemove the restriction, or don't restrict the tag if this persona needs the column
A new column shows up for a persona that should not see itNew columns are untagged by default and visible until taggedTag the column and confirm the persona's Column Restrictions cover the tag
A named set, KPI, or summary table is missing for this persona but present for anotherIt reads a restricted column somewhere in its definitionExpected. It cannot be built from this persona's smaller model, so it is not offered
Restriction disappeared after importing a projectThe tag or the restriction was not part of the imported snapshotRe-check Data Tags and Column Restrictions after import. Both travel with the model snapshot. But they only travel if they existed at export time

Related