# Column masking

> Mask expressions annotated onto the plan's output columns - nulling, hashing, partial reveal or rounding to a bucket - resolved by priority and applied at execution instead of by the client

Source: https://aipril.dev/docs/platform/access/column-masking

## The question it answers

Row rules decide **which rows**. Masking decides **which values in those rows** - the case where
somebody may legitimately work with a dataset but must not read a particular field at full fidelity.

A support analyst needs to match a customer without reading the full document number. A regional
manager needs salary distribution without individual salaries. Those are not row problems.

## What a mask can express

Masks are declared in a dialect-neutral form and evaluated at execution:

| Mask | Effect | Typical use |
|---|---|---|
| Null | The value is removed | A field that must not be read at all |
| Hash | A stable one-way digest | Joining and counting distinct values without reading them |
| Partial reveal | The first N characters, then a marker | Matching a record against a customer's own reference |
| Round to a bucket | Value rounded to a multiple | Distributions and cohorts without individual figures |

The hash case is worth noting: it preserves what analysis actually needs - equality and cardinality -
while removing what it does not need, which is the value itself.

## Conflicts resolve by priority

Where more than one mask applies to a column, the highest priority wins. One value per column per
caller, not an ambiguous stack.

## Applied in the plan

A mask annotates the output column in the query plan, and is applied during execution. It is not a
client-side transformation, which means:

- a dashboard, a page of an application, an MCP client and an AI agent are masked identically;
- an export contains masked values, because the export is the query result;
- and no caller can request the unmasked value by asking a different way, since there is no path where
  the mask is applied by the caller.

## Related

- [Row-level security](https://aipril.dev/docs/platform/access/row-level-security.md) - which rows, and how the decision is made.
- [Data engine](https://aipril.dev/docs/engine/under-the-hood.md) - where the plan is compiled and executed.
