---
title: "Policies (ABAC)"
---

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

# Policies (ABAC)

**ABAC** stands for **Attribute-Based Access Control**. While [roles](roles-and-permissions.html) answer the question _"can this user perform this action at all?"_, ABAC policies add context-dependent conditions: _"can this user perform this action **given the current circumstances**?"_

For example, a role might grant "approve purchase orders". A policy can refine that to "approve purchase orders **only under 2,000,000 DA and only if the user did not create the order themselves**".

Policies are the second layer of Beelocity's access control — they sit on top of roles and add conditional logic without requiring you to create dozens of highly specific roles.

## When to Use Policies

Policies are entirely optional — many organizations run fine with just roles. Consider adding policies when you need rules that depend on **context**, not just identity:

| Need                      | Example policy                                                                  |
| ------------------------- | ------------------------------------------------------------------------------- |
| **Monetary thresholds**   | Junior staff can only approve purchase orders under 500,000 DA                  |
| **Segregation of duties** | A user cannot approve their own purchase requests (the "four-eyes principle")   |
| **Warehouse scoping**     | Users can only perform inventory adjustments in their assigned warehouses       |
| **Time restrictions**     | Certain operations are only allowed during business hours (Sun-Thu, 8:00-17:00) |
| **IP-based rules**        | Sensitive financial actions restricted to corporate network access only         |

If none of these apply to you, skip policies entirely and revisit them later if the need arises.

## Policy Structure

Each policy is defined by five key fields:

| Field         | What it does                                                                                                                                                                       |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Name**      | A human-readable label that explains the policy's purpose (e.g., "PO approval limit — 2,000,000 DA"). Good names make the policy list self-documenting.                            |
| **Target**    | Which permission, module, resource, or action this policy applies to. A policy only evaluates when the user attempts something that matches its target.                            |
| **Condition** | A logical expression that must evaluate to **true** for the policy's effect to apply. This is where you define the "when" — the circumstances under which the rule kicks in.       |
| **Effect**    | **Allow** or **Deny**. Most policies are Deny rules ("deny approval if amount exceeds threshold"), but Allow rules are useful for granting exceptions.                             |
| **Priority**  | A number that determines evaluation order. Higher-priority policies are evaluated first. Use priority to ensure critical deny rules are checked before less important allow rules. |

## Evaluation Logic

When a user attempts an action, Beelocity evaluates all active policies that match:

1. **Find matching policies** — all policies whose target matches the attempted action.
2. **Evaluate conditions** — each matching policy's condition is checked against the current context (who is doing it, what they are doing it to, when, from where).
3. **Apply the deny-override rule:**
   - If **any** matching policy **denies** the action, access is denied — regardless of what other policies say. Deny always wins.
   - If at least one policy **allows** and none deny, access is granted.
   - If **no policies match** at all, the decision falls through to role-based permissions. ABAC is purely optional refinement — it does not replace roles.

This "deny wins" approach means you can confidently add allow policies without worrying about accidentally overriding a critical security rule.

## Condition Attributes

Conditions are expressions that reference attributes. These attributes are the building blocks of your rules:

| Category           | Available today | What it provides                               | Attributes                                                       |
| ------------------ | --------------- | ---------------------------------------------- | ----------------------------------------------------------------- |
| **User (subject)** | Yes             | Who is performing the action                   | `subject.id`, `subject.roles`, `subject.organization_id`, `subject.is_org_admin` |
| **Action**         | Yes             | What operation is being attempted              | `action.permission`, `action.method`                              |
| **Environment**    | Yes             | When the request is happening                  | `env.timestamp`, `env.hour`, `env.day_of_week` (1 = Monday)       |
| **Resource**       | **Not yet**     | The record being acted on                      | —                                                                 |

> **Resource attributes are not available yet.** A policy that mentions `resource.`
> anything is refused when you save it, with an explanation. This is deliberate: the
> system cannot currently look up the record being acted on while it is deciding
> permissions, so such a policy would sit in the list looking active and never actually do
> anything. Refusing it up front is safer than letting you rely on a rule that does not
> work. Build the rules you need from user, action, and environment attributes.

### Operators

The condition editor has two views. **Simple** builds the condition out of rules — an attribute, an
operator and a value — with **Rules to satisfy** set to **All of them** or **Any of them**. The
operator is picked from a list, and every one of them is a word:

| Operator                                                            | What it tests                                     | Example                                            |
| ------------------------------------------------------------------- | ------------------------------------------------- | -------------------------------------------------- |
| **is equal to**, **is not equal to**                                | an exact match                                    | `action.method` **is equal to** `DELETE`           |
| **is more than**, **is at least**, **is less than**, **is at most** | a number against a bound                          | `env.hour` **is at least** `8`                     |
| **is one of**                                                       | the value appears in a list you give              | `action.method` **is one of** `POST`, `PUT`        |
| **contains**                                                        | an attribute holding several values includes this one | `subject.roles` **contains** `Warehouse Manager` |
| **is between**                                                      | a number inside a range, both ends included       | `env.hour` **is between** `8` and `17`             |
| **matches**                                                         | text against a pattern                            | `action.permission` **matches** `^PROCUREMENT_`    |

**They are words and never comparison signs, in any language.** A sign like ≥ reverses direction when
the page is read right to left, so an Arabic screen would show the opposite of the rule you saved —
silently, with nothing on the screen to give it away.

**Advanced** is the second view, for the conditions the simple one cannot draw — a group inside a
group, or a negation. It takes the same operators written as short codes, listed under the box, plus
`and`, `or` and `not` to join them. Whichever view you build in, the policy is read back to you as a
sentence in your own language, on the policy page and in the list.

If a condition cannot be worked out — it names an attribute the request did not carry, or
has a typo in an operator — it counts as **not met**, so the policy does not fire either
way. Typos and unknown attributes are caught when you save the policy, so this should not
happen in practice.

## Creating a Policy

1. Go to **Settings → Policies** and click **New**.
2. Set the **target** — choose which permission or module/resource/action combination this policy should evaluate against.
3. Define the **condition** — describe when this policy should take effect.
4. Choose the **effect** — Allow or Deny.
5. Set the **priority** — higher numbers are evaluated first. Use this to control evaluation order when multiple policies could apply to the same action.
6. Save.

The **Policies** list narrows on its **filter button** by **Effect**, **Active**, a **Priority** range, or the exact target **Module**, **Resource** or **Action** — every Deny in one module is two picks ([Working with lists](../getting-started/working-with-lists.html#narrowing-the-list)).

## Tips

- **Start with deny rules** — the most common use case is restricting what roles already allow. "Deny approval over X amount" or "Deny if user created the record" are typical first policies.
- **Name policies descriptively** — when you have 10 or 20 policies, clear names like "PO approval limit — junior staff — 500K DA" are much easier to manage than "Policy 7".
- **Test with a low-privilege user** — after creating a policy, verify it works by checking what happens when the affected user attempts the restricted action.
- **Use priority carefully** — in most cases, the default priority works fine. Only adjust it when you have multiple policies on the same target and need to control which one is evaluated first.

Source: https://docs.beelocity.com/en/access-control/policies/index.mdx
