What it does¶
You define who can see what as a Python function. sqla-authz compiles it into a database-level filter and applies it to your query:
from sqla_authz import READ, authorize_query, policy
from sqlalchemy import ColumnElement, or_, select, true
@policy(Post, READ)
def post_read(actor: User) -> ColumnElement[bool]:
if actor.role == "admin":
return true() # admins see all rows
return or_(Post.is_published == True, Post.author_id == actor.id)
stmt = select(Post).order_by(Post.created_at.desc())
stmt = authorize_query(stmt, actor=current_user, action=READ)
# SQL: SELECT ... FROM post WHERE (is_published = true OR author_id = :id)
Why it fits¶
sqla-authz is a SQLAlchemy-native authorization kernel for Python apps. It is strongest when you want authorization close to the query layer instead of spread across endpoint checks and post-query filtering.
- Explicit first — start with
authorize_query()so authorization stays visible and reviewable. - Deny by default — no policy for a
(model, action)pair meansWHERE FALSE, not a silent data leak. - Scopes for boundaries — tenant or org-wide restrictions are AND'd across matching policies.
- Point checks for instances — use
can(),authorize(), andauthorize_create()for object-specific decisions. - Optional automation — move to
authorized_sessionmaker()or FastAPIAuthzDeponce the explicit path is stable. - No DSL or sidecar — policies stay in Python and return normal SQLAlchemy expressions.
- Getting Started — Installation, first policy, core concepts
- Limitations — Known boundaries and project status
- API Reference — All public functions, classes, and types