Metadata-Version: 2.4
Name: postkit
Version: 0.11.0
Summary: Postgres-native application infrastructure: identity, configuration, metering, coordination, and messaging in one SQL install
Project-URL: Homepage, https://github.com/varunchopra/postkit
Project-URL: Repository, https://github.com/varunchopra/postkit
Project-URL: Documentation, https://github.com/varunchopra/postkit/tree/main/docs
Project-URL: Issues, https://github.com/varunchopra/postkit/issues
Author: Varun Chopra
License-Expression: Apache-2.0
Keywords: authentication,authorization,configuration,job-queue,lease,metering,outbox,postgresql,presence,rebac,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Database
Classifier: Topic :: Security
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: jsonschema>=4.0.0
Requires-Dist: psycopg>=3.1.0
Provides-Extra: binary
Requires-Dist: psycopg[binary]>=3.1.0; extra == 'binary'
Provides-Extra: dev
Requires-Dist: psycopg[binary]>=3.1.0; extra == 'dev'
Requires-Dist: pytest-randomly>=3.0; extra == 'dev'
Requires-Dist: pytest-xdist>=3.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

# postkit SDK

Python client for postkit.

## Installation

```bash
pip install postkit
```

## Usage

```python
import psycopg
from postkit.authz import AuthzClient
from postkit.authn import AuthnClient

conn = psycopg.connect("postgresql://...")
cursor = conn.cursor()

# Authorization
authz = AuthzClient(cursor, namespace="my-app")
authz.set_hierarchy("repo", "admin", "write", "read")
authz.grant("admin", resource=("repo", "api"), subject=("user", "alice"))
if authz.check(("user", "alice"), "read", ("repo", "api")):
    print("Access granted")

# Authentication
authn = AuthnClient(cursor, namespace="my-app")
user_id = authn.create_user("alice@example.com", password_hash="argon2...")
session_id = authn.create_session(user_id, token_hash="sha256...")
```

## Tenant Context and Transactions

Constructing a client calls `{module}.set_tenant(namespace)` immediately. The setting is transaction-scoped, so inside an open transaction the constructor taints that transaction's context for the module until commit or rollback; an unrelated client built mid-transaction can therefore change which rows a later raw SQL statement sees.

Every SDK call needs a transaction for that context. On autocommit connections each call runs in its own transaction and commits immediately. On non-autocommit connections each call joins the connection's open transaction: nothing is durable until you commit, and a rollback takes it all with it, including a queue claim from `pull()`. That is the intended model for transactional consumers; `nack`/`fail` accept the pending job a rollback leaves behind.

In CI, call `client.assert_rls_active()` during setup. A suite connecting as a superuser or `BYPASSRLS` role (the docker default) bypasses every RLS policy and exercises none of the tenancy model.

## Requirements

- PostgreSQL 14+
- The postkit SQL schema installed in your database

See the [main repository](https://github.com/varunchopra/postkit) for SQL installation instructions.
