Open-source authorization engine

Ship permissions,
not permission code.

Add relationship-based access control to your app in minutes. Graph traversal decisions in under 5ms — with a full audit trail.

index.ts
import { Rune } from '@runeauth/sdk'

const rune = new Rune({
  apiKey:  process.env.RUNE_API_KEY,
  baseUrl: 'https://rune-engine.onrender.com',
})

// One line. That's it.
const result = await rune.can('user:alice').do('read').on('doc:report')
console.log(result.status) // "ALLOW"
<5ms Median latency
170 Tests passing
0 Dependencies (SDK)
Features

Everything you need.
Nothing you don't.

BFS Graph Traversal

Permissions flow through relationships. User → Group → Zone → Resource. Rune traces the path and gives you ALLOW or DENY.

Sub-5ms Decisions

In-process LRU cache + materialised permission index means most checks never touch the database. Median latency under 5ms.

Full Explainability

Every decision includes a trace, a human-readable reason, and a suggested fix. Debug access issues in seconds, not hours.

Fail-Closed Security

Any error returns DENY, never ALLOW. API keys are SHA-256 hashed. BFS limits prevent graph bombs. Every query is tenant-isolated.

Admin Dashboard

Built-in UI to view tuples, audit logs, cache stats, and run permission checks. Protected by a dedicated admin key.

Zero-Dep SDK

The SDK uses native fetch only — zero external dependencies. Built-in circuit breaker, retry with backoff, and fluent API.

How It Works

Permissions as a graph.

Define relationships. Rune traces the graph to resolve access.

👤 user:arjun
member
👥 group:chennai_mgrs
owner
📍 zone:chennai
viewer
📦 shipment:TN001
✓ ALLOW

The question

"Can user:arjun read shipment:TN001?"

The answer

Rune traces: arjun is a member of chennai_managers, which owns zone:chennai, which has viewer access to shipment:TN001. Viewer grants read → ALLOW.

The response

{
  "status": "ALLOW",
  "trace": [
    { "node": "user:arjun", "result": "start" },
    { "node": "group:chennai_mgrs", "result": "connected" },
    { "node": "zone:chennai", "result": "connected" },
    { "node": "shipment:TN001", "result": "connected" }
  ],
  "latency_ms": 4.2
}
Relation Semantics

Four relations. Complete control.

Relation read edit delete manage
owner
editor
viewer
member

member is a traversal relation — it doesn't grant access itself, but lets the BFS continue to parent groups and zones.

Quickstart

Five minutes to production.

1

Install the SDK

npm install @runeauth/sdk
2

Initialize the client

import { Rune } from '@runeauth/sdk'

const rune = new Rune({
  apiKey:  process.env.RUNE_API_KEY,
  baseUrl: 'https://rune-engine.onrender.com',
})
3

Grant a permission

await rune.allow({
  subject:  'user:alice',
  relation: 'viewer',
  object:   'doc:report',
})
4

Check access

const result = await rune.can('user:alice').do('read').on('doc:report')

if (result.status === 'ALLOW') {
  // ✅ Access granted
}
5

Protect a route (Express / Fastify)

// One-line route protection
app.get('/docs/:id',
  rune.protect('read', 'doc:{{params.id}}'),
  handler
)

Ready to ship permissions?

Open-source. Self-hostable. Free forever.