Simple Zanzibar
Simple Zanzibar is a local, in-memory Rust authorization engine inspired by Google's Zanzibar paper. It provides relationship-based access control (ReBAC), a small policy DSL, consistency tokens, lock-free snapshot reads, compact snapshot artifacts, and public APIs for check, expand, lookup, and policy review workflows.
The crate is intentionally a local library, not a distributed Zanzibar service. It is useful when an
application wants Zanzibar-style semantics in-process and can distribute policy/relationship data as
text or prebuilt .szsnap artifacts.
Current Capabilities
- Schema-first DSL with direct relations, computed usersets, tuple-to-userset inheritance, union, intersection, and exclusion.
- Validated relationship strings such as
doc:readme#viewer@group:eng#member. - Single-writer actor with bounded queue; readers use immutable published snapshots through
arc-swapand do not take a service-level lock. - Consistency tokens for exact-snapshot reads across retained revisions.
- Indexed compact relationship storage for resource-side and subject-side lookup paths.
check,expand,lookup_resources,lookup_subjects,lookup_permissions, andlookup_object_permissionsAPIs.- Deterministic policy text import/export and raw or zstd-compressed snapshot save/load.
- Optional
serdefeature with validated public request/response DTO deserialization. - Optional
tracingfeature for structured API spans.
Architecture
Client / application
│
▼
┌───────────────────────────────┐
│ ZanzibarEngine public API │
│ - validates request DTOs │
│ - starts tracing spans │
└───────────────┬───────────────┘
│
┌───────────┴───────────┐
│ │
▼ ▼
Read path Write path
ArcSwap snapshot bounded writer actor
check/expand/lookup schema + relationship mutation
│ │
▼ ▼
Compiled schema IR publish new revision token
Indexed store view retain exact snapshots
│ │
└───────────┬───────────┘
▼
`.szsnap` save/load
raw or zstd wrapper
Quick Start
Add the crate to your Cargo.toml:
[]
= "0.2.1"
Basic permission check:
use ;
Exact consistency after a write:
use ;
#
DSL Reference
namespace <namespace_name> {
relation <relation_name> {
rewrite <userset_expression>
}
}
Supported userset expressions:
this: direct relationships for the current object relation.computed_userset(relation: "owner"): another relation on the same object.tuple_to_userset(tupleset: "parent", computed_userset: "viewer"): follow related objects and evaluate a relation on each related object.union(expr1, expr2, ...): any expression may allow access.intersection(expr1, expr2, ...): all expressions must allow access.exclusion(base, exclude): allowbaseexcept subjects inexclude.
Example:
namespace group {
relation member {}
}
namespace folder {
relation viewer {}
}
namespace doc {
relation owner {}
relation parent {}
relation banned {}
relation viewer {
rewrite exclusion(
union(
computed_userset(relation: "owner"),
tuple_to_userset(tupleset: "parent", computed_userset: "viewer")
),
computed_userset(relation: "banned")
)
}
}
Public API Overview
use ;
String convenience methods are available for ergonomic setup:
add_dsl/add_dsl_with_tokencreate_relationshiptouch_relationshipdelete_relationshipcheck_relationexpand_relation
Policy Text and Snapshot Artifacts
Reviewable policy text is deterministic and grouped by resource type:
use ;
#
Snapshots are the fastest whole-state distribution format:
use ;
#
Testing and Verification
Common checks:
The Makefile keeps common automation discoverable:
The test suite includes unit, integration, property, snapshot-corruption, public API completeness,
concurrent-runtime, e2e policy-to-snapshot, and benchmark harness coverage. The current performance
report is in docs/perf/phase-15-complete-benchmark-2026-05-25.md.
Performance Notes
- Relationship data is stored in compact indexed snapshots, not a linear
HashSetscan on hot paths. - Reads acquire a published immutable snapshot through
arc-swapand reuse request-local evaluator state where possible. - Writes are serialized through one bounded actor per engine; batch writes are much faster than many single-relationship writes.
- Raw
.szsnapfiles optimize load speed. Zstd-wrapped snapshots optimize distribution size and are decoded under a configured byte cap. IndexProfile::CheckOnlycan reduce artifact size when subject-side reverse lookup APIs are not needed.
Repository Map
src/api.rs: public engine, writer actor, tenant sharding, public error model.src/domain.rs: validated identifiers and relationship grammar.src/schema/: schema compiler and resolver.src/relationship.rs: compact relationship store and snapshot index encoding.src/eval.rs: check, expand, lookup, memoization, and lookup planning.src/snapshot.rs: raw and zstd snapshot save/load with validation.specs/: product, design, performance, verification, and implementation specs.docs/perf/: recorded benchmark evidence and generated charts.
Non-Goals
- No persistent database backend in the current crate.
- No network server or gRPC API.
- No distributed consistency protocol.
- No cryptographic signature implementation for snapshots; callers can use external integrity and
then select
SnapshotIntegrityMode::Externalwhere appropriate.
License
This project is licensed under the MIT License. See LICENSE.md.
Acknowledgments
- Google's Zanzibar paper for the authorization model.
- SpiceDB for production implementation patterns studied in
docs/research/study-spicedb.md.