> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formal.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction

> Formal's policy system, and how to create data access rules

## What are Policies?

Formal's policy system uses [Open Policy Agent (OPA)](https://www.openpolicyagent.org/), an open-source policy engine that enables you to express access control rules as code. Policies are evaluated in real-time as users connect to resources and execute queries.

Your policies can:

* **Block** connections to resources or specific tables/schemas
* **Redact** query results automatically
* **Encrypt and decrypt** data fields
* **Rewrite** queries before they reach the database
* **Filter and limit** result sets
* **Enforce MFA** for sensitive operations

## How Policies Work

Policies are written in [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/), OPA's purpose-built language for access control. They are evaluated at three stages:

1. **Session** - When a connection is established
2. **Request** - Before a query reaches the resource
3. **Response** - When data returns from the resource

Each stage has specific actions available based on when the policy is evaluated. See [Enforcement](/docs/guides/policies/enforcement) for details on available actions.

## Policy Structure

Every policy consists of these essential components:

<AccordionGroup>
  <Accordion title="Name" icon="tag">
    A **unique identifier** for the policy. No two policies can share the same
    name.
  </Accordion>

  <Accordion title="Description" icon="file-text">
    A **clear explanation** of the policy's purpose and scope. This helps other
    admins understand what the policy does.
  </Accordion>

  <Accordion title="Owners" icon="users">
    The **administrators responsible** for maintaining and enforcing the policy.
    Owners receive notifications when policies are triggered (if configured).
  </Accordion>

  <Accordion title="Code" icon="code">
    The **policy logic**, written in
    [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/), OPA's
    purpose-built language for access control.
  </Accordion>
</AccordionGroup>

## Policy Status

Policies can be in one of three states:

| Status      | Description                       | Use Case                                              |
| ----------- | --------------------------------- | ----------------------------------------------------- |
| **Draft**   | Under development, not enforced   | Writing and testing new policies                      |
| **Dry-run** | Logs violations without enforcing | Testing policies with real traffic before enforcement |
| **Active**  | Fully enforced and monitoring     | Production enforcement                                |

<Tip>
  Use **dry-run** mode to test policies against real traffic without impacting
  users. Review the logs to ensure the policy works as intended before
  activating it.
</Tip>

## Notifications

Configure notifications for policy triggers:

* **None**: No notifications sent
* **Consumer**: Notify the user who triggered the policy
* **Owners**: Notify policy owners
* **All**: Notify both user and owners

Notifications can be sent via:

* Email
* Slack (requires integration setup)

## End-User Identity Propagation

Formal can extract end-user identity from applications like Looker, Metabase, or Retool, enabling policies that work for both direct connections and application-mediated access:

* **Direct connection**: Alice uses `psql` to query a resource → user and end-user are both Alice
* **Application connection**: Katie uses Metabase → user is the machine user, end-user is Katie

This allows you to write policies that consider the actual person behind the query, even when they're using a BI tool.

## Quick Example

Block all connections by default, but allow admins using a specific machine user:

```rego theme={null}
package formal.v2

import future.keywords.if
import future.keywords.in

default session := {
  "action": "block",
  "type": "block_with_formal_message"
}

session := {
  "action": "allow",
  "reason": "Admin access via authorized app"
} if {
  "admin" in input.end_user.groups
  input.user.username == "idp:formal:machine:backoffice"
  not input.end_user.email == "john.doe@joinformal.com"
}
```

## Managing Policies

<Tabs>
  <Tab title="Web Console">
    1. Navigate to [Policies](https://app.formal.ai/policies)
    2. Click **New Policy**
    3. Fill in name, description, and owners
    4. Write Rego code in the editor
    5. Set status (Draft, Dry-run, or Active)
    6. Configure notifications
    7. Save the policy
  </Tab>

  <Tab title="Terraform">
    ```hcl theme={null}
    resource "formal_policy" "block_deletes" {
      name        = "block-production-deletes"
      description = "Prevent DELETE statements in production"
      status      = "active"

      code = <<-EOT
        package formal.v2

        import future.keywords.if

        request := {
          "action": "block",
          "type": "block_with_formal_message",
          "reason": "DELETE not allowed in production"
        } if {
          input.resource.environment == "production"
          input.query.statement_type == "DELETE"
        }
      EOT

      owners = ["admin@example.com"]

      notifications = "owners"
    }
    ```
  </Tab>
</Tabs>

## Best Practices

<AccordionGroup>
  <Accordion title="Start with Dry-Run" icon="flask">
    Always test new policies in dry-run mode first. Review logs to ensure they
    work as expected before activating.
  </Accordion>

  <Accordion title="Use Groups for User Policies" icon="users">
    Instead of writing policies for individual users, use groups. This makes
    policies scalable and easier to maintain.
  </Accordion>

  <Accordion title="Document Your Policies" icon="book">
    Write clear descriptions and use meaningful reason fields. Future you (and
    your team) will thank you during audits.
  </Accordion>

  <Accordion title="Leverage External Data" icon="database">
    Use Policy Data Loaders to fetch dynamic approval lists, compliance data, or
    business logic from external systems.
  </Accordion>
</AccordionGroup>

## Learn More

<CardGroup cols={2}>
  <Card title="Policy Evaluation" icon="magnifying-glass" href="/docs/guides/policies/evaluation">
    Input data, evaluation stages, and available context
  </Card>

  <Card title="Examples" icon="code" href="/docs/guides/policies/examples">
    Real-world policy examples and common use cases
  </Card>
</CardGroup>
