# Data Policies Reference Guide

Data policies manage what users see when they query data in a table they are subscribed to. The data policies that governors, data source owners, or domain policy managers can author fall into two categories: [protect policies](#protect-policies) and [reveal policies](#reveal-policies).

## Protect policies

Protect policies restrict access to data once a user is subscribed to a data source. There are three different ways to restrict data access with protect policies:

* [Row-level](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/reference-guides/row-redaction-explained): Filter rows from certain users at query time.
* [Column masking](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/reference-guides/masking-matrix-functions): Mask values in a column at query time.
* [Cell masking](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#cell-level-masking): Mask specific cells in a column based on separate values in the same row at query time.

For all protect policies, you can establish the conditions for which they will be enforced:

* If the user is a **member of a group** (or several groups)
* If the user **possesses** **an** **attribute** (or several attributes)
* If the [user is **acting under a purpose**](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/reference-guides/limit-to-purpose-policies) (or several purposes) for which the data is allowed to be used

You can append multiple conditions to the protect policy, and these conditions can be directed as exclusionary or inclusionary, depending on the policy that's being enforced:

* **Exclusionary condition example:** Mask using hashing values in columns tagged `PII` on all data sources for everyone except users in the group `AUDIT`.
* **Inclusionary condition example**: Only show rows where user is a member of a group that matches the value in the column tagged `Department`.

  For all policies except [purpose-based restriction policies](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/reference-guides/limit-to-purpose-policies), inclusionary logic allows policy authors to vary policy actions with an otherwise clause. For example, you could mask values using hashing for users acting under a specified purpose while masking those same values by making null for everyone else who accesses the data.

### Data policy support matrix

The table below outlines the types of protect data policies supported for various data platforms. If a data platform isn't included in the table, that integration does not support any data policies.

Details about each of the data policy types are included in their linked reference guides.

|                                                                                                                                                                                                                                                                                                                                                                                         | Amazon Redshift      | Amazon Redshift Spectrum | Azure Synapse Analytics | Databricks Spark                                 | Databricks Unity Catalog                         | Google BigQuery      | Snowflake            | Starburst (Trino)    | Teradata             |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ------------------------ | ----------------------- | ------------------------------------------------ | ------------------------------------------------ | -------------------- | -------------------- | -------------------- | -------------------- |
| [Cell-level masking](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#cell-level-masking)                                                                                                                                                                                                              | :x:                  | :white\_check\_mark:     | :white\_check\_mark:    | :white\_check\_mark:                             | :white\_check\_mark:                             | :x:                  | :white\_check\_mark: | :white\_check\_mark: | :x:                  |
| [Custom functions](#user-content-fn-1)[^1] for [masking](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/reference-guides/masking-matrix-functions) or [row-level](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/reference-guides/row-redaction-explained) policies | :white\_check\_mark: | :white\_check\_mark:     | :white\_check\_mark:    | :white\_check\_mark:                             | :white\_check\_mark:                             | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | :x:                  |
| [Format preserving masking](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#format-preserving-masking)                                                                                                                                                                                                | :x:                  | :x:                      | :x:                     | :x:                                              | :x:                                              | :x:                  | :white\_check\_mark: | :x:                  | :x:                  |
| [Hashing](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#hashing)                                                                                                                                                                                                                                    | :white\_check\_mark: | :white\_check\_mark:     | :white\_check\_mark:    | :white\_check\_mark:                             | :white\_check\_mark:                             | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | :x:                  |
| [Limit to purpose](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/reference-guides/limit-to-purpose-policies)                                                                                                                                                                                                                 | :x:                  | :white\_check\_mark:     | :white\_check\_mark:    | :white\_check\_mark:                             | [Supported with caveats](#user-content-fn-2)[^2] | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | :x:                  |
| [Masking fields within STRUCT columns](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#complex-data-types-masking-fields-within-struct-columns)                                                                                                                                                       | :x:                  | :x:                      | :x:                     | :white\_check\_mark:                             | [Supported with caveats](#user-content-fn-3)[^3] | :x:                  | :x:                  | :x:                  | :x:                  |
| [Matching](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/row-redaction-explained#matching)                                                                                                                                                                                                                                   | :white\_check\_mark: | :white\_check\_mark:     | :white\_check\_mark:    | :white\_check\_mark:                             | :white\_check\_mark:                             | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: |
| [Minimize](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/row-redaction-explained#minimization)                                                                                                                                                                                                                               | :x:                  | :white\_check\_mark:     | :white\_check\_mark:    | :white\_check\_mark:                             | :white\_check\_mark:                             | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | :x:                  |
| [Only show data by time](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/row-redaction-explained#time-based-restrictions)                                                                                                                                                                                                      | :x:                  | :white\_check\_mark:     | :white\_check\_mark:    | :white\_check\_mark:                             | :white\_check\_mark:                             | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | :x:                  |
| [Randomized response](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#randomized-response)                                                                                                                                                                                                            | :x:                  | :x:                      | :x:                     | :x:                                              | :x:                                              | :x:                  | :white\_check\_mark: | :x:                  | :x:                  |
| [Regex](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#regular-expression-regex)                                                                                                                                                                                                                     | :x:                  | :white\_check\_mark:     | :x:                     | :white\_check\_mark:                             | :white\_check\_mark:                             | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | :x:                  |
| Replace with [NULL](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#null) or [constant](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#constant)                                                                   | :white\_check\_mark: | :white\_check\_mark:     | :white\_check\_mark:    | [Supported with caveats](#user-content-fn-4)[^4] | :white\_check\_mark:                             | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | :x:                  |
| [Reversible masking](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#reversibility)                                                                                                                                                                                                                   | :x:                  | :white\_check\_mark:     | :x:                     | :white\_check\_mark:                             | :x:                                              | :x:                  | :white\_check\_mark: | :white\_check\_mark: | :x:                  |
| [Rounding](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#rounding)                                                                                                                                                                                                                                  | :x:                  | :white\_check\_mark:     | :white\_check\_mark:    | :white\_check\_mark:                             | :white\_check\_mark:                             | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | :x:                  |
| [WHERE clause](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/reference-guides/custom-where-clause-functions)                                                                                                                                                                                                                 | :white\_check\_mark: | :white\_check\_mark:     | :white\_check\_mark:    | :white\_check\_mark:                             | :white\_check\_mark:                             | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: |

## Reveal policies

{% hint style="info" %}
Reveal policies are only supported for global masking policies.
{% endhint %}

Reveal policies are exceptions to column-level restrictions. However, unlike the exceptions included directly in protect policies, these exceptions stand alone as their own policy and are essentially on standby until a masking policy targets the same column. For example, the following reveal policy would be applied to all columns tagged `HR`:

> Reveal columns tagged `HR` for everyone who is a member of group `HR`.

However, the reveal policy wouldn't do anything until the following protect policy is applied to the same columns (because the data would already be in the clear):

> Mask all columns tagged `HR`.

Then, the reveal policy would combine with the protect policy on data sources with columns tagged `HR`:

> Mask all columns tagged `HR` except for users in group `HR`.

Because [reveal policies merge with other policies](#reveal-policy-merges), policy authors can build exceptions to policies without having to know or predict every protect policy. This design also allows you to selectively delegate policy authoring to users across your organization, so data governors could author overarching protect policies (like masking all PII) while domain delegates and data owners could author reveal policies specific to the data within their area of expertise.

See the [policy authoring strategy section](#policy-authoring-strategy) for guidance on when to author protect or reveal policies.

## Using protect and reveal policies

Protect and reveal policies allow you to define exceptions without having to consider existing masking policies in place. Instead, you can define what should be revealed at any granularity needed without creating a protect policy for every possible permutation of access someone might request.

For example, many organizations want to author protect policies that mask data like this:

> Mask columns tagged `Employee` for everyone except users in group `HR`.

Then, if other users need to access the table, administrators have to either

* Add users to the group `HR` when they need access to employee data (which gives them access to columns tagged `Employee` across all data sources) and then remove individual users from the group `HR` when their access should be removed.
* Create separate policies for each permutation of data access. Such as
  * Mask columns tagged `Employee` for everyone except users in group `HR`.
  * Mask columns tagged `Employee.Strictly Confidential` for everyone except users with attribute `Exception:Employee.Strictly Confidential`.
  * Mask columns tagged `Employee.Confidential` for everyone except users with attribute `Exception:Employee.Confidential`.

Both of these strategies are untenable because of inefficiency, role bloat, and users gaining too much access.

Reveal policies solve this problem by separating the data access restriction from the exception. Consequently, governors can be responsible for authoring restrictions that protect data while data owners and domain delegates can be responsible for authoring reveal policies that provide exceptions to those restrictions. The examples above transform into the [following policies](#user-content-fn-5)[^5]:

{% columns %}
{% column %}
**Protect policy**

> Mask columns tagged `Employee` except for users in group `HR`.
> {% endcolumn %}

{% column %}
**Reveal policy**

> Reveal columns tagged `Employee` for everyone who has an attribute key `Exception` with a value that matches any column tag.
> {% endcolumn %}
> {% endcolumns %}

Once this protect policy and reveal policy target the same column in a data source, Immuta automatically combines them:

* Columns tagged `Employee.Strictly Confidential` would have the following policy on them: Mask column for everyone except users in group `HR` or users who possess an attribute with key `Exception` and value `Employee.Strictly Confidential`.
* Columns tagged `Employee.Confidential` would have the following policy on them: Mask column for everyone except users in group `HR` or users who possess an attribute with key `Exception` and value `Employee.Confidential`.

This design simplifies policy authoring processes and enables uninterrupted data access for your data users.

See the [Multiple policies on a single data source section](#multiple-policies-on-a-single-data-source) for details and examples of how protect and reveal policies merge when they apply to the same data source.

### Policy authoring strategy

Although protect policies combine with the exceptions in reveal policies when they target the same column, you can also build exceptions directly into protect policies. To determine whether you should include exceptions within your protect policies over authoring separate reveal policies, consider the following:

* Knowledge
  * Who is the expert of your organization's governance policies?
  * Who is the expert of the data and knows the users who need to access it?
* Exceptions
  * Are the policy exceptions static, or do they often change?
  * Will policy exceptions need to be combined?

Use the comparison below to navigate these decision points.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th align="center"></th><th></th></tr></thead><tbody><tr><td><strong>Masking policy with exceptions</strong></td><td><blockquote><p>Mask columns tagged <code>highly restricted</code> for everyone except <code>admins</code>.</p></blockquote></td><td align="center"><br><em>Admins get access to all highly restricted data.</em></td><td><p><br>Recommended when</p><ul><li>Users are exempt <strong>based on the masking rule itself</strong>, not the data it applies to: users should get exempted from all masking this policy applies.</li><li>You use a <strong>centralized</strong> <strong>governance</strong> approach: one team owns all masking rules and exceptions.</li><li>Exceptions are <strong>only valid</strong> <strong>for a given rule</strong>: if a masking rule on a column changes, previous exceptions should be invalidated.</li></ul></td></tr><tr><td><strong>Reveal policy</strong></td><td><blockquote><p>Reveal columns tagged <code>highly restricted</code> and <code>Finance</code> for everyone who possesses attribute <code>Finance.Allowed</code>.</p></blockquote></td><td align="center"><em>Users with attribute <code>Finance.Allowed</code> get access to highly restricted finance data only.</em></td><td><p>Recommended when</p><ul><li>Users are exempt <strong>based on certain data</strong> the masking rule applies to, not the entire rule itself: users should get exempted from the masking this policy applies for a subset of data.</li><li>You use a <strong>decentralized</strong> <strong>governance</strong> approach: one team owns masking rules, but exceptions are managed by individual domain teams.</li><li>Exceptions are <strong>valid no matter what masking rule applies</strong>: if the masking rule changes on a column, previous exceptions should carry over.</li></ul></td></tr></tbody></table>

## Multiple policies on a single data source

More than one data policy may apply to a data source. When this happens, the policies will either merge or conflict, depending on the type of policy they are.

* Reveal policies will merge with other global policies with OR. See the [section below](#reveal-policy-merges) for details about how they will merge.
* Protect policies
  * Row-level policies will merge with AND. See the [section below](#row-level-policy-merges) for details about how they will merge.
  * Masking policies will conflict. See the [section below](#masking-policy-conflicts) for details about how the masking policy is selected.
  * Purpose-based policies will merge with AND. See the [section below](#purpose-based-policy-merges) for details about how they will merge.

### Reveal policy merges

Reveal policies merge with existing global protect policies and other reveal policies with OR, which means that if multiple exceptions apply within the merged policy, users only need to meet one exception to see the data. For example, users in group `HR` or in group `Executive` would see data tagged `Employee.Internal` in the clear if the following policy were applied to a data source:

> Mask columns tagged `Employee.Internal` for everyone except users in group `HR` or in group `Executive`.

The table below illustrates how multiple protect and reveal policies apply to data sources:

<table data-header-hidden data-full-width="false"><thead><tr><th></th><th></th><th></th><th>Text</th><th></th></tr></thead><tbody><tr><td><br></td><td><strong>Protect policy</strong>: Mask columns tagged <code>Classified</code> for everyone except users with attribute <code>Access.Classified</code></td><td><strong>Reveal policy</strong>: Reveal columns tagged <code>Classified.Internal</code> for users with attribute <code>Access.Internal</code></td><td><strong>Reveal policy</strong>: Reveal columns tagged <code>Classified.Internal.Employee</code> for users acting under purpose <code>Quarterly review</code></td><td><strong>Merged policy</strong></td></tr><tr><td><p>Column A tag</p><ul><li><code>Classified</code></li></ul></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="26d4">⛔</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="26d4">⛔</span></td><td>Mask columns tagged <code>Classified</code> except for users with attribute <code>Access.Classified</code></td></tr><tr><td><p>Column B tag</p><ul><li><code>Classified.Internal</code></li></ul></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="26d4">⛔</span></td><td>Mask columns tagged <code>Classified.Internal</code> except for users with attribute <code>Access.Classified</code> OR <code>Access.Internal</code></td></tr><tr><td><p>Column C tag</p><ul><li><code>Classified.Internal.Employee</code></li></ul></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td>Mask columns tagged <code>Classified.Internal.Employee</code> except for users with attribute <code>Access.Classified</code> OR <code>Access.Internal</code> OR acting under purpose <code>Quarterly review</code></td></tr></tbody></table>

To combine exceptions with AND, the exceptions must be included in a single protect policy or a single action of a reveal policy:

{% columns %}
{% column %}
**Protect policy**

> Mask columns tagged `Classified.Internal` for everyone except when user possesses attribute `Access.Classified` AND `Access.Internal`.
> {% endcolumn %}

{% column %}
**Reveal policy**

> Reveal columns tagged `Classified.Internal` for users who possess attribute `Access.Classified` AND `Access.Internal`.
> {% endcolumn %}
> {% endcolumns %}

If a local policy is applied to a data source, the reveal policy will not merge with that local policy.

### Row-level policy merges

When two or more row-level policies target the same table, all row-level policies will be applied with AND, meaning the user will need to meet the conditions of all the policies to see any rows in the table at all. For example, these two row-level policies apply to the same data source:

> * Only show rows where user possesses an attribute `Classification` that matches the value in column `first_name` for everyone except when user possesses attribute with key `Classification` and value `Strictly Confidential`.
> * Only show rows where user possesses an attribute `Classification` that matches the value in column `first_name` for everyone except when user is a member of group with name `Managers`.

To see any rows in the table, the querying user must be a member of group `Managers` and have the attribute key-value pair `Classification: Strictly Confidential`.

To combine separate row-level policies with OR, build them into a [single Immuta policy using OR](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/how-to-guides/row-redaction-tutorial) to combine the conditions of the policy.

### Purpose-based policy merges

When two or more purpose-based policies target the same table, all purpose-based policies will be combined with AND, meaning the user will need to meet the conditions of all the policies to see any rows in the table. For example, these two purpose-based policies apply to the same data source:

> * Limit usage to purpose `Marketing Campaign` for everyone except when user is a member of the group `Marketing Execs` on data sources tagged `Customer Data`.
> * Limit usage to purpose `Distribution` for everyone except when user possesses attribute `Classification: Strictly Confidential` on data sources tagged `Customer Data.Address`.

To see any rows in the table, one of the following statements must be true for the user:

* The user must be working under the purpose `Marketing Campaign` AND `Distribution`.
* The user must be a member of the `Marketing Execs` group AND have the attribute `Classification: Strictly Confidential`

### Masking policy conflicts

In some cases, two conflicting global masking policies apply to a single data source. When this happens, the policy containing a tag deeper in the hierarchy will apply to the data source to resolve the conflict.

Consider the following global data policies created by a data governor:

{% columns %}
{% column %}
**Data policy 1**

> Mask columns tagged `PII` by making null for everyone on data sources with columns tagged `PII`.
> {% endcolumn %}

{% column %}
**Data policy 2**

> Mask columns tagged `PII.SSN` using hashing for everyone on data sources with columns tagged `PII.SSN`.
> {% endcolumn %}
> {% endcolumns %}

If a data owner creates a data source and applies the `PII.SSN` tag to a column, both of these global masking policies will apply to the column with that tag. Instead of having a conflict, the policy containing a deeper tag in the hierarchy will apply.

In this example, data policy 2 will be applied to the data source because `PII.SSN` is deeper and thus considered more specific than `PII`. If data owners wanted to use data policy 1 on the data source instead, they would need to disable data policy 2.

If two or more masking policies target the same column and have the same hierarchy depth, the policy that was authored first will be applied. This is a conservative approach that avoids the original policy being changed unexpectedly.

#### Masking policy intelligent fallbacks

When masking columns, the type of the column matters. For example, it is not possible to hash a numeric column, because the hash would render the number as a string.

Many data platforms make the user account for this by building separate data policies for every column type that could exist now or in the future, which is onerous.

Instead, Immuta has intelligent fallbacks. An intelligent fallback occurs when a masking type targets a column type that is incompatible with the masking type. In this case, Immuta will fall back to the most appropriate masking type that retains the level of privacy or better required by the previous type.

For example, if a hashing masking type hits a numeric type, it would intelligently fallback to nulling the column instead, since nulls are allowed in numeric types.

## Lockout policies

Sometimes a global data policy will target a table and the policy cannot be applied as written. This can happen for several reasons, but the most common is that the row-level policy logic is not relevant to the table in question.

For example, with the following policy

> `@attributeValuesContains('Attribute Name', 'SOME_COLUMN')`

If SOME\_COLUMN does not exist in the table, the row-level policy will not work. This is why it is always recommended to use the `@columnTagged('tag name')` function instead of hard coding column names.

In the case where an error such as this occurs with a global data policy, the lockout policy will kick in. The lockout policy is a row-level policy that blocks any rows from returning for any users. Since Immuta does not know how to apply the policy, the lockout policy avoids data leaks until the policy is edited to work correctly.

## New column added data policy

This templated policy pairs with [schema monitoring](https://documentation.immuta.com/SaaS/configuration/integrations/data-and-integrations/registering-metadata/schema-monitoring) to mask newly added columns to data sources until data owners review and approve these changes from the requests tab of their profile page.

When this policy is activated by a governor, it will automatically be enforced on data sources that have the `New` tag applied to them.

To learn how to activate this policy, navigate to the [Clone, activate, or stage a global policy how-to guide](https://documentation.immuta.com/SaaS/govern/secure-your-data/section-contents/how-to-guides/clone-activate-stage#activate-a-templated-policy).

## Custom data policy certifications

When building a global data policy, governors can [create custom certifications](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/how-to-guides/manage-policies-per-data-source#create-a-custom-certification-for-a-global-policy), which must then be acknowledged by data owners when the policy is applied to data sources.

For example, data governors could add a custom certification that states that data owners must verify that tags have been added correctly to their data sources before certifying the policy.

When a global data policy with a custom certification is cloned, the certification is also cloned. If the user who clones the policy and custom certification is not a governor, the policy will only be applied to data sources that user owns.

## Policy explainer

{% hint style="info" %} <i class="fa-sparkles">:sparkles:</i> [**AI-powered feature**](https://documentation.immuta.com/SaaS/configuration/application-configuration/reference-guides/immuta-ai-faq/immutas-ai-features)

This feature is currently only supported for global data policies.
{% endhint %}

The Policy explainer generates a summary of how a global data policy will affect users' access to a data source, which allows policy authors to verify the behavior of the policy before activating it.

To generate the [policy summary](#policy-summary), the Policy explainer sends the policy definition in JSON to AWS Bedrock. Then, it crafts an example table and scenarios based on mock data to simulate complex, real-world access decisions.

For example, if a user authored the policy

> Mask columns tagged **email** using **hashing** for everyone except when user is a member of group **Marketing**.

and clicked **Explain policy**, the following policy definition would be sent to AWS Bedrock:

<details>

<summary><strong>Policy definition JSON example</strong></summary>

```json
{
  "type": "masking",
  "extra": {
    "filteredDictionary": [],
    "currentTags": [
      {
        "name": "email",
        "displayName": "email",
        "hasLeafNodes": false,
        "source": "curated"
      }
    ]
  },
  "exceptions": {
    "operator": "and",
    "conditions": [
      {
        "type": "groups",
        "group": {
          "name": "Marketing"
        }
      }
    ]
  },
  "config": {
    "fields": [
      {
        "name": "email",
        "displayName": "email",
        "hasLeafNodes": false,
        "source": "curated"
      }
    ],
    "maskingConfig": {
      "type": "Consistent Value",
      "metadata": {}
    }
  }
}
```

</details>

Then, the Policy explainer would generate a policy summary for the user.

### Policy summary

The policy summary illustrates how a policy will affect various potential data consumers so that policy authors can see the policy's effect from different perspectives. The policy summary comprises distinct sections:

1. A brief explanation of the policy's intended behavior.
2. A sample table with mock data and columns.
3. A description of what happens when users with contrasting entitlements query that table.

Below is an example of a policy summary created by the Policy explainer for the following policy:

> Mask columns tagged **email** for everyone except when user is a member of group **Marketing**.

<details>

<summary><strong>Policy summary example</strong></summary>

This policy hashes the values in any column tagged **email**, so email addresses are replaced with a consistent cryptographic hash for most users. Members of the **Marketing** group are exempt, and they see the original email addresses. Here is an example of how this policy would affect users querying the same data:

1. The Data Source

Imagine a table named **Customer\_Details** that has the following data, where the `email` column is tagged with **email**:

| customer\_id | name  | email               |
| ------------ | ----- | ------------------- |
| 101          | Alice | <alice@example.com> |
| 102          | Bob   | <bob@example.com>   |
| 103          | Carol | <carol@example.com> |

2. User Scenarios

The output of a query (`SELECT * FROM Customer_Details;`) will vary based on the querying user's group membership:

**Scenario A: User is NOT in the Marketing group**

User: **User A** (Member of the *Analysts* group)

| customer\_id | name  | email                      |
| ------------ | ----- | -------------------------- |
| 101          | Alice | `a3f2b8c9d4e5f1a2b3c4d5e6` |
| 102          | Bob   | `7b9e4f1a2c8d9e0f1a2b3c4d` |
| 103          | Carol | `8e5f2d1c9b7a6e3f4a5b6c7d` |

**User A** is not in the **Marketing** group, so the policy is enforced. The `email` column is replaced with a cryptographic hash value, hiding the actual addresses while still allowing joins or counts on the hashed values.

**Scenario B: User IS in the Marketing group**

User: **User B** (Member of the *Marketing* group)

| customer\_id | name  | email               |
| ------------ | ----- | ------------------- |
| 101          | Alice | <alice@example.com> |
| 102          | Bob   | <bob@example.com>   |
| 103          | Carol | <carol@example.com> |

**User B** belongs to the **Marketing** group, so the exception is triggered. The policy is **not** enforced for them, and they see the original email addresses in clear text.

</details>

### Policy changes and activation

Policy authors dictate all changes to and activation of policies; the Policy explainer does not activate, deactivate, or change the content of a policy. The diagram below illustrates this delineation between the Policy explainer and the policy author:

<figure><img src="https://1751699907-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlWBda5Pt4s8apEhzXGl7%2Fuploads%2FZ5rZYxawNnUd0D5KPonw%2Fpolicy-explainer-diagram.png?alt=media&#x26;token=39562aec-f524-4ca1-bb8f-472fc6dadbf6" alt="The Policy explainer sends the policy definition in JSON to AWS Bedrock and returns a summary to the user, while the user is responsible for managing the actual policies that enforce access controls."><figcaption></figcaption></figure>

However, if the Policy explainer were to misrepresent the behavior of a policy, the user could activate policy changes that behave counter to what they intended. Therefore, policy authors should verify the accuracy of the explanation before activating the policy.

### Data protection

The Policy explainer does not query or send any of your actual data. The only data sent to AWS Bedrock is the policy definition (configured by the user) in JSON.

For details about data protection with the Policy explainer, see the [Immuta's AI features page](https://documentation.immuta.com/SaaS/configuration/application-configuration/reference-guides/immuta-ai-faq/immutas-ai-features#data-protection-with-policy-explainer).

## Audit

The following events related to policy certification are [audited](https://documentation.immuta.com/SaaS/govern/detect-your-data/audit/reference-guides/index/uam-schema) and can be found on the [audit page in the UI](https://documentation.immuta.com/SaaS/govern/detect-your-data/audit/how-to-guides/use-immuta-audit):

* [DatasourcePolicyCertificationExpired](https://documentation.immuta.com/SaaS/detect-your-data/audit/reference-guides/index/uam-schema#datasourcepolicycertificationexpired-event): The global policy certification on a data source is expired.
* [DatasourcePolicyCertified](https://documentation.immuta.com/SaaS/detect-your-data/audit/reference-guides/index/uam-schema#datasourcepolicycertified-event): A global policy is certified for a data source.
* [DatasourcePolicyDecertified](https://documentation.immuta.com/SaaS/detect-your-data/audit/reference-guides/index/uam-schema#datasourcepolicydecertified-event): A global policy is decertified for a data source.

[^1]: Poorly written functions can lead to data leaks.

[^2]: If you are using views in Databricks Unity Catalog, one of the following must be true for project-scoped purpose exceptions to apply to the views in Databricks: The view and underlying table are registered as Immuta data sources and added to a project or only the underlying table is registered as an Immuta data source and added to a project.<br>

    See the [Databricks Unity Catalog integration reference guide](https://documentation.immuta.com/SaaS/configuration/integrations/databricks/databricks-unity-catalog/unity-catalog-overview#project-scoped-purpose-exceptions-for-databricks-unity-catalog) for details.

[^3]: Databricks Unity Catalog ARRAY, MAP, or STRUCT type columns only support masking with NULL.

[^4]: On Databricks data sources, joins will not be allowed on data protected with replace with NULL or constant policies.

[^5]: The reveal policy example below leverages advanced masking exceptions. See the [Masking policies reference guide](https://documentation.immuta.com/SaaS/govern/secure-your-data/authoring-policies-in-secure/data-policies/masking-matrix-functions#advanced-masking-exceptions) for details.
