Python policies. SQL enforcement.
Authorization that speaks SQLAlchemy.¶
Keep tenant data scoped and row permissions close to your models. Write a policy in Python, then use it for filtered ORM reads and explicit permission checks.
One policy definition¶
SQLAlchemy predicates power both collection filtering and explicit object checks. The database evaluates your rules.
A tenant per session¶
Bind an actor to a fresh session. Purview adds tenant criteria to ORM reads and checks tenant IDs during object writes.
Fits your Python stack¶
Use familiar models, queries, and tools. Add FastAPI dependencies when you need them. No separate policy service.
Start with a rule¶
This policy lets authors read their own posts. The session's tenant filter applies alongside it.
from purview import READ, Context, Policy
from purview.sqlalchemy import install
policy = Policy()
@policy.rule(Post, READ)
def read_posts(ctx: Context):
return [Post.author_id == ctx.user_id] if ctx.has_role("author") else []
pv = install(Base, policy, strict=True)
Bind the authenticated actor, then use an ordinary SQLAlchemy query:
async with sessions() as session:
pv.bind(session, Context(user_id=42, tenant_id=1, roles={"author"}))
posts = (await session.scalars(select(Post))).all()
Run the complete SQLite example →
Small API. Explicit boundaries.¶
Reads filter automatically on bound sessions. For writes, your application calls
authorize() before update or delete and validate_create() for create rules.
The normal ORM flush guard handles tenant stamping and cross-tenant checks.
The examples use strict=True to deny reads when a scoped model has no rule.
The default mode allows tenant-wide reads for such models. Raw SQL, bulk DML,
unbound sessions, and bypass blocks are outside automatic enforcement.
Understand the security boundary →
Find your next step¶
| You want to… | Read |
|---|---|
| Install the right database driver | Installation |
| See a working example end to end | Quickstart |
| Add roles, create rules, or custom tenant fields | Writing policies |
| Bind an actor to every API request | FastAPI integration |
| Understand a denied request or an open model | Debugging policies |
| Bring an existing Polar policy | Migrating from Oso |
| Check signatures and available methods | API reference |