Px/

Permissions

How resources and permissions are modelled — naming conventions, registration, default role bootstrapping, and the relationship between resources and RBAC/ABAC policies.

Edit this page on GitHub

In Permix, a resource is the unit of permission. Every access check resolves against a named resource, and policies (both RBAC and ABAC) are attached to resource names.

Resource naming#

Resources follow a service:action convention that makes the scope and intent explicit at a glance:

rounded-md border px-1.5 py-0.5 font-mono text-[0.82em]
invoice:read
invoice:write
invoice:delete
project:deploy
billing:refund
report:export

The colon separator is a convention, not a requirement. Any stable, unique string works. Keep names lowercase and hyphen-separated for readability.

Registering resources#

Resources must be registered before policies can be attached to them. The Java SDK registers them automatically on startup. For direct REST integrations:

bash
# Register a single resource
curl -X POST https://api.permix.dev/api/v1/resources \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name":         "invoice:read",
    "displayName":  "Read Invoice",
    "serviceName":  "invoice-service",
    "defaultRoles": ["finance", "admin"]
  }'
bash
# Register multiple resources in one call
curl -X POST https://api.permix.dev/api/v1/resources/list \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    { "name": "invoice:read",   "displayName": "Read Invoice",   "serviceName": "invoice-service", "defaultRoles": ["finance", "admin"] },
    { "name": "invoice:write",  "displayName": "Write Invoice",  "serviceName": "invoice-service", "defaultRoles": ["admin"] },
    { "name": "invoice:delete", "displayName": "Delete Invoice", "serviceName": "invoice-service", "defaultRoles": ["admin"] }
  ]'

Default roles#

The defaultRoles array bootstraps Casbin RBAC rules the first time a resource is registered. For "defaultRoles": ["finance", "admin"], the service creates:

rounded-md border px-1.5 py-0.5 font-mono text-[0.82em]
p, finance, *, invoice:read, read, allow
p, admin,   *, invoice:read, read, allow

These rules apply across all domains (*) and can be refined later with domain-scoped rules or ABAC conditions.

Listing resources#

bash
curl https://api.permix.dev/api/v1/resources \
  -H "Authorization: Bearer $TOKEN"

Returns all resources scoped to the caller's tenant.

Viewing policies for a resource#

bash
curl https://api.permix.dev/api/v1/resources/{resourceId}/policies \
  -H "Authorization: Bearer $TOKEN"

Returns all Casbin RBAC rules attached to that resource.

Resource scope#

Resources are tenant-scoped. A resource named invoice:read registered under tenant_acme is completely independent from the same name under tenant_northstar. Casbin domain isolation prevents any cross-tenant rule evaluation.

Relationship to RBAC and ABAC#

rounded-md border px-1.5 py-0.5 font-mono text-[0.82em]
Resource (invoice:read)
    │
    ├── RBAC rules   → (role, domain, invoice:read, action) → allow/deny
    │                  managed via /api/v1/resources/policies
    │
    └── ABAC policies → JSON condition trees evaluated against request attributes
                        managed via /api/v1/abac/policies

Both layers are evaluated on every POST /api/v1/check call. ABAC deny at higher priority overrides an RBAC allow. If neither layer produces a decision, the default is deny.

See RBAC and ABAC for detailed policy management.