Add relationship-based access control to your app in minutes. Graph traversal decisions in under 5ms — with a full audit trail.
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"
Permissions flow through relationships. User → Group → Zone → Resource. Rune traces the path and gives you ALLOW or DENY.
In-process LRU cache + materialised permission index means most checks never touch the database. Median latency under 5ms.
Every decision includes a trace, a human-readable reason, and a suggested fix. Debug access issues in seconds, not hours.
Any error returns DENY, never ALLOW. API keys are SHA-256 hashed. BFS limits prevent graph bombs. Every query is tenant-isolated.
Built-in UI to view tuples, audit logs, cache stats, and run permission checks. Protected by a dedicated admin key.
The SDK uses native fetch only — zero external dependencies. Built-in circuit breaker, retry with backoff, and fluent API.
Define relationships. Rune traces the graph to resolve access.
"Can user:arjun read shipment:TN001?"
Rune traces: arjun is a member of chennai_managers, which owns zone:chennai, which has viewer access to shipment:TN001. Viewer grants read → ALLOW.
{
"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 | 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.
npm install @runeauth/sdk
import { Rune } from '@runeauth/sdk'
const rune = new Rune({
apiKey: process.env.RUNE_API_KEY,
baseUrl: 'https://rune-engine.onrender.com',
})
await rune.allow({
subject: 'user:alice',
relation: 'viewer',
object: 'doc:report',
})
const result = await rune.can('user:alice').do('read').on('doc:report')
if (result.status === 'ALLOW') {
// ✅ Access granted
}
// One-line route protection
app.get('/docs/:id',
rune.protect('read', 'doc:{{params.id}}'),
handler
)
Open-source. Self-hostable. Free forever.