Px/

ABAC — Attribute-Based Access Control

Define fine-grained JSON condition trees that are evaluated against namespaced request attributes at decision time.

Edit this page on GitHub

ABAC policies let you express access rules that depend on arbitrary attributes of the request — user department, resource owner, time-of-day, or any other context — rather than just roles. The ABAC engine sits alongside Casbin RBAC; both are evaluated on every POST /api/v1/check call.

Policy model#

An ABAC policy has these fields:

FieldTypeDescription
namestringHuman-readable policy name
resourcestringResource key this policy applies to (e.g. invoice:read)
effectstring"allow" or "deny"
priorityintHigher priority wins when multiple policies match (default 0)
enabledboolToggle without deleting
formatstring"json" (default) or "casbin"
rule_dataJSONThe condition tree (see below)
tenant_idstringAuto-set from the caller's JWT domain claim

Condition tree format#

Rules are expressed as nested AND / OR / CONDITION nodes. Attributes are referenced in dot-notation namespaces.

json
{
  "type": "AND",
  "conditions": [
    {
      "type": "CONDITION",
      "attribute": "user.department",
      "operator": "eq",
      "value": "Finance"
    },
    {
      "type": "OR",
      "conditions": [
        {
          "type": "CONDITION",
          "attribute": "resource.classification",
          "operator": "in",
          "value": ["internal", "public"]
        },
        {
          "type": "CONDITION",
          "attribute": "user.clearance_level",
          "operator": "gte",
          "value": 3
        }
      ]
    }
  ]
}

Supported operators#

OperatorDescription
eqEquals
neqNot equals
gt / gteGreater than / greater-or-equal
lt / lteLess than / less-or-equal
inValue is in an array
containsString contains substring
startsWithString starts with prefix

API — Create a policy#

bash
curl -X POST https://api.permix.dev/api/v1/abac/policies \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Finance read invoices",
    "resource": "invoice:read",
    "effect": "allow",
    "priority": 10,
    "rule_data": {
      "type": "CONDITION",
      "attribute": "user.department",
      "operator": "eq",
      "value": "Finance"
    }
  }'

Response 201:

json
{
  "id": "3f7a1b2c-...",
  "tenant_id": "tenant_prod_42",
  "name": "Finance read invoices",
  "resource": "invoice:read",
  "effect": "allow",
  "format": "json",
  "priority": 10,
  "enabled": true,
  "created_by": "user_123",
  "created_at": "2026-05-10T08:00:00Z",
  "rule_data": { ... }
}

API — Check access (combined RBAC + ABAC)#

bash
curl -X POST https://api.permix.dev/api/v1/check \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "user_123",
    "resource": "invoice:read",
    "action": "read",
    "domain": "tenant_prod_42",
    "attributes": {
      "user": {
        "department": "Finance",
        "clearance_level": 4
      },
      "resource": {
        "classification": "internal"
      }
    }
  }'

Attributes are grouped by namespace (e.g. user, resource, time). The engine flattens them to dot-notation internally (user.department).

List and filter policies#

bash
# List all policies for a resource
GET /api/v1/abac/policies?resource=invoice:read

# Filter by effect
GET /api/v1/abac/policies?effect=deny

Update a policy#

bash
curl -X PUT /api/v1/abac/policies/{id} \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "enabled": false,
    "priority": 5
  }'

Immutable resource field

The resource field cannot be changed after creation. To move a policy to a different resource, delete it and create a new one.

Priority and conflict resolution#

When multiple ABAC policies match a request, the engine applies them in descending priority order. A deny effect always overrides an allow at the same priority. If no policy matches, the engine falls through to the Casbin RBAC result.

PriorityEffectDecision
100deny❌ Denied immediately
50allow✅ Allowed (if no deny at higher priority)
10allowReached only if p=50 didn't match

Performance & caching#

The ABAC service uses an in-process policy cache per tenant (ABACPolicyCache) invalidated on every write. P95 evaluation latency is under 2ms for up to 500 active policies per tenant.