Skip to content

wellknown-id/karu

Repository files navigation

Karu

Karu - Structural Pattern Matching for JSON

Karu is an embeddable policy engine focusing on structural pattern matching over arbitrary JSON data. It is the spiritual successor to the ideas found in logic-based policy languages, designed to solve complex hierarchical data validation that strict-schema engines cannot handle.

It came to be because a coming soon wellknown.id project needed an expressive policy engine as fast as Cedar. That internal project started with Cedar until we accidentally wrote an engine that ran much faster at Cedar than Cedar!. And so it stuck.

How Fast?

Benchmark Karu Cedar
WASM bundle size 319 KB 1.8 MB 5.6× smaller
Native eval (1 rule) 15 ns 1,108 ns 72× faster
WASM eval (precompiled) 465 ns 88,350 ns 190× faster
Complex (20 rules, native) 663 ns 14,137 ns 21× faster
Realistic authz (16 threads) 14.3M ops/sec 273K ops/sec 52× faster

Karu running in WASM (465 ns) is faster than Cedar running natively (1,108 ns). Full benchmarks →

Try it in the browser →

Core Philosophy

  • Structure over Schema: We do not enforce a schema on input data. We enforce patterns on the data we find.
  • Search, Don't Index: If you provide a list, we will search it. You shouldn't have to re-map your application data to fit the policy engine.
  • Partial Matching: A pattern {a: 1} matches {a: 1, b: 2}.
  • Optionally Strict: When you need Cedar-level rigor, flip a switch. Karu can enforce strict schemas, exhaustive matching, and static analysis - but only when you ask for it. RFCs shouldn't block good ideas.

Karu Language

Rules

Rules are allow or deny, with an optional if body:

allow public_access;

allow view if
    principal.role == "viewer" and
    action == "read";

deny delete if
    action == "delete" and
    not principal.role == "admin";

Conditions & Operators

Operator Example Description
== != action == "read" Equality / inequality
< <= > >= principal.age >= 18 Numeric comparison
and or not a == 1 and not b == 2 Logical combinators
in "editor" in user.roles Collection search
is actor is User Type guard (schema mode)
has resource has owner Field existence check

Pattern Matching

The in operator searches arrays with structural patterns — extra fields are ignored:

allow access if
    { name: "lhs", value: 10 } in resource.context.namedArguments;

Patterns can be literals ("alice", 42, true, null), wildcards (_), objects ({ key: value }), or arrays ([1, 2]).

Quantifiers

// Every item must match
allow bulk_read if
    forall item in resource.items: item.public == true;

// At least one item must match
allow has_permission if
    exists perm in user.permissions: perm.action == "write";

Schema Mode

Opt into strict typing with use schema; and mod blocks:

use schema;

mod MyApp {
    actor User { name String, role String };
    resource Document in Folder { owner User, title String };
    action "Delete" appliesTo { actor User, resource Document };
};

assert is_owner<User, action, Document> if actor.name == resource.owner.name;

allow delete if MyApp:Delete and resource is Document and is_owner;

Inline Tests

Policies can declare tests alongside rules:

test "alice can view" {
    principal { id: "alice" }
    action { id: "view" }
    expect allow
}

Multi-File Projects

import "shared/roles.karu";
import "rules.karu";

For architecture details, see docs/INTERNALS.md.

Comparison

Feature Cedar Rego Karu
List Search ❌ (Strict Schema) ✅ (Complex syntax) ✅ (Native in operator)
Pattern Matching
Strict Mode ✅ (Usually) ✅ (Optional)
Duck Typing
Syntax SQL-like Datalog Polar-like
Focus Performance/Safety Infrastructure Why not both?

Cedar Interop

Karu supports full round-trip conversion with Cedar policies and schemas. See Known Cedar Limitations for current gaps.

Even when running Cedar policies through Karu's import pipeline, evaluation is fast - Karu's native engine evaluates at ~19 million ops/sec, roughly 10× faster than the Cedar-WASM runtime for equivalent policies. For detailed numbers, see BENCHMARKS.md.

Quick Start

cargo add karu
use karu::{compile, rule::Effect};
use serde_json::json;

let policy = compile(r#"allow view if principal == "alice" and action == "view";"#).unwrap();
let input = json!({"principal": "alice", "action": "view", "resource": "doc"});
assert_eq!(policy.evaluate(&input), Effect::Allow);

For development setup and contribution guidelines, see CONTRIBUTING.md.

About

Embeddable policy engine for structural pattern matching over JSON. Cedar interop, LSP support, ~19M ops/sec.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors