Skip to main content

Building blocks for zanzibar style ReBAC

Project description

zanzipy ✨

Zanzibar‑style authorization for Python, with a tiny DSL to declare your schema and a simple client to write and check permissions. Friendly, lightweight, and practical.

Install 📦

Requires Python 3.14+.

pip install zanzipy
# Optional integrations used by the SQLAlchemy/Flask examples:
pip install "zanzipy[sqlalchemy]"
pip install "zanzipy[flask,sqlalchemy]"

Quick start 🚀

from zanzipy.dsl.builder import SchemaBuilder
from zanzipy.client import ZanzibarClient
from zanzipy.storage.repos import InMemoryRelationRepository, TenantId

# Define schema with the fluent DSL
registry = (
    SchemaBuilder()
        .namespace("user").done()
        .namespace("document")
            .relation("owner", subjects=["user"])  # direct
            .permission("can_view", union=["owner"])  # computed
            .done()
        .build()
)

# Use the tenant-scoped, revisioned in-memory repo for a zero-dependency start.
client = ZanzibarClient(
    schema=registry,
    relations_repository=InMemoryRelationRepository(),
    tenant=TenantId("default"),
)

write = client.write("document:readme", "owner", "user:alice")
assert client.check("document:readme", "can_view", "user:alice")
assert client.check_at_revision(
    "document:readme",
    "can_view",
    "user:alice",
    revision=write.token,
)

That’s it. All zanzipy relation storage is tenant-scoped and revisioned. RelationTuple stays tenant-free: a tuple is the logical authorization fact (object#relation@subject), while TenantId is part of read/write/evaluation context. The same logical tuple may exist independently in multiple tenants. Public convenience APIs use the client’s configured tenant and repository head revision by default; exact revision APIs accept tenant-scoped RevisionToken values and also allow a naked Revision interpreted within the client tenant. Add more relations/permissions with the DSL, and swap the repository when you’re ready to plug in durable storage.

Quick start with mixins 🧩

Zanzipy also provides convenient mixins for Pythonic integration with your domain models.

from dataclasses import dataclass

from zanzipy.client import ZanzibarClient
from zanzipy.dsl.builder import SchemaBuilder
from zanzipy.engine_integration import ZanzibarEngine, configure_authorization
from zanzipy.integration.mixins import AuthorizableResource, AuthorizableSubject
from zanzipy.storage.repos import InMemoryRelationRepository, TenantId

# Define a minimal schema (user + document)
registry = (
    SchemaBuilder()
        .namespace("user").done()
        .namespace("document")
            .relation("owner", subjects=["user"])  # direct relation
            .permission("can_view", union=["owner"])  # computed permission
            .done()
        .build()
)

# Wire up the engine used by the mixins.
client = ZanzibarClient(
    schema=registry,
    relations_repository=InMemoryRelationRepository(),
    tenant=TenantId("default"),
)
configure_authorization(ZanzibarEngine(client))

# Domain models using mixins
@dataclass
class User(AuthorizableSubject):
    id: str

    def get_subject_dict(self) -> dict:
        return {"namespace": "user", "id": self.id}


@dataclass
class Document(AuthorizableResource):
    id: str

    def get_resource_dict(self) -> dict:
        return {"namespace": "document", "id": self.id}


# Use high‑level helpers
alice = User(id="alice")
readme = Document(id="readme")

readme.grant(alice, "owner")  # writes a tuple: document:readme#owner@user:alice
assert readme.check(alice, "can_view")  # True via the computed permission

For a fuller mixins setup with groups, SQLAlchemy models, and caching, see examples/document_drive_sqlalchemy_and_mixins.py.

Examples

The repository examples cover the same document-drive authorization model at increasing integration levels:

  • examples/document_drive.py — zero-dependency in-memory repository and explicit schema objects.
  • examples/document_drive_sqlalchemy.py — SQLAlchemy-backed relation storage with explicit schema objects (zanzipy[sqlalchemy]).
  • examples/document_drive_sqlalchemy_and_dsl.py — the same SQLAlchemy setup using NamespaceBuilder/SchemaBuilder.
  • examples/document_drive_sqlalchemy_and_mixins.py — domain model helpers via AuthorizableResource, AuthorizableSubject, and ZanzibarEngine.
  • examples/document_drive_flask_sqlalchemy.py — Flask extension, request-scoped engine binding, mixins, and SQLAlchemy (zanzipy[flask,sqlalchemy]).

From a checkout, run the non-server examples with uv run python <path>. The Flask example starts a local server and prints IDs for curl requests, including a list_objects route that exercises reverse LookupResources.

Key features 🧰

  • ✨ DSL‑first schema authoring (SchemaBuilder, NamespaceBuilder).
  • 🔗 Zanzibar semantics: relations, permissions, union/intersection/exclusion, tuple‑to‑userset.
  • ✅ Correctness‑first evaluation: cycle detection and a shared max_depth traversal limit across check, expand, and lookup.
  • 🔎 Reverse lookup: list_objects walks subject-bucket edges, so nested usersets and caches work without candidate-object scans.
  • 🧩 Simple client API: write, delete, check, list_objects, expand.
  • Tenant-scoped revisioned storage: writes return WriteResult with a tenant-scoped RevisionToken; snapshot reads prefer the token and reject mismatched tenant tokens.
  • Storage-agnostic: implement tenant-scoped RelationRepository; start with in-memory. SQLite uses BEGIN IMMEDIATE to serialize revision allocation; SQLAlchemy retries transient tenant-revision insert/serialization conflicts and surfaces the database error if retries are exhausted.
  • ⚡ Optional tenant/revision-aware tuple cache and compiled rule cache for hot paths.

When should you use zanzipy? 🤔

  • You want ReBAC embedded in your Python app without running another service.
  • You prefer a human‑readable, declarative schema (via a tiny DSL).
  • Your app has shared resources (e.g., docs, folders, teams) and needs roles, groups, or nested access patterns.
  • You need cross‑resource edges (tuple‑to‑userset) and clear, testable authorization logic.

License

Apache‑2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zanzipy-0.4.0.tar.gz (60.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zanzipy-0.4.0-py3-none-any.whl (91.0 kB view details)

Uploaded Python 3

File details

Details for the file zanzipy-0.4.0.tar.gz.

File metadata

  • Download URL: zanzipy-0.4.0.tar.gz
  • Upload date:
  • Size: 60.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for zanzipy-0.4.0.tar.gz
Algorithm Hash digest
SHA256 850ea388bdb16e7802bb8f7fb1ca4f25a1a31275ab1e6499b20200744de09124
MD5 86e3dee1b239a5dfe6d822d93f1f46c8
BLAKE2b-256 a56b2d7f4a628e94125b0b553848a6f0e941506d49763d37c8e43933f58fd47b

See more details on using hashes here.

Provenance

The following attestation bundles were made for zanzipy-0.4.0.tar.gz:

Publisher: publish.yml on tylerchambers/zanzipy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file zanzipy-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: zanzipy-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 91.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for zanzipy-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b03b29a8fc7d8652038b7227bb8d18dae3d39f6a89246b1e5b5068aece2cf04d
MD5 f7fe2c861f41a1c1d99511d94c7c8fbc
BLAKE2b-256 b811df1d499147830767dd310d9d1b722a08ca2d57a18d72af954a25b67098d5

See more details on using hashes here.

Provenance

The following attestation bundles were made for zanzipy-0.4.0-py3-none-any.whl:

Publisher: publish.yml on tylerchambers/zanzipy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page