Metadata-Version: 2.4
Name: flametrench-identity
Version: 0.3.0
Summary: Identity primitives for Flametrench: users, credentials (Argon2id-pinned passwords, passkeys, OIDC), and user-bound sessions with rotation on refresh.
Author: NDC Digital, LLC
License: Apache-2.0
Project-URL: Homepage, https://flametrench.dev
Project-URL: Repository, https://github.com/flametrench/identity-python
Project-URL: Specification, https://github.com/flametrench/spec
Keywords: flametrench,identity,users,credentials,sessions,argon2id,passkey,oidc
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 :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Security :: Cryptography
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: flametrench-ids>=0.3.0
Requires-Dist: argon2-cffi>=23.1.0
Requires-Dist: cryptography>=42.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: psycopg[binary]>=3.1; extra == "dev"
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3.1; extra == "postgres"
Dynamic: license-file

# flametrench-identity

[![CI](https://github.com/flametrench/identity-python/actions/workflows/ci.yml/badge.svg)](https://github.com/flametrench/identity-python/actions/workflows/ci.yml)

Python SDK for the [Flametrench](https://github.com/flametrench/spec) identity specification: users, credentials (Argon2id-pinned passwords, passkeys, OIDC), user-bound sessions with rotation on refresh, and v0.2 multi-factor authentication ([ADR 0008](https://github.com/flametrench/spec/blob/main/decisions/0008-mfa.md), [ADR 0010](https://github.com/flametrench/spec/blob/main/decisions/0010-webauthn-rs256-eddsa.md)) — TOTP (RFC 6238), recovery codes, and WebAuthn assertion verification across ES256 / RS256 / EdDSA.

**Status:** v0.2.0 (stable). Includes the production-ready `PostgresIdentityStore` alongside the in-memory reference store. Per ADR 0014 the `User` entity carries an optional `display_name` with a partial-update `update_user` operation; per ADR 0015 `list_users` provides cursor-paginated user enumeration with a credential-identifier substring filter; per ADR 0013 the Postgres adapter cooperates with adopter-side outer transactions via savepoints when nested (psycopg3 `connection.transaction()` handles this automatically).

The same fixture corpus that gates `@flametrench/identity` (Node), `flametrench/identity` (PHP), and `dev.flametrench:identity` (Java) runs here. The cross-language Argon2id parity test is mechanical interop verification — a PHC hash produced by any of the four SDKs verifies identically here.

```python
from flametrench_identity import InMemoryIdentityStore

store = InMemoryIdentityStore()
user = store.create_user()
cred = store.create_password_credential(
    user.id, "alice@example.com", "correcthorsebatterystaple"
)
verified = store.verify_password("alice@example.com", "correcthorsebatterystaple")
assert verified.usr_id == user.id

session_with_token = store.create_session(user.id, cred.id, ttl_seconds=3600)
# Carry session_with_token.token in Authorization: Bearer; only the SHA-256
# hash is ever persisted server-side.
```

## Installation

```bash
pip install flametrench-identity
```

Requires Python 3.11+. Dependencies:
- `flametrench-ids` — for usr_/cred_/ses_ id generation.
- `argon2-cffi` — the canonical Python binding to libargon2. Pinned to the spec floor (m=19456 KiB, t=2, p=1).

## Spec invariants enforced

- **Argon2id at the OWASP floor** — `m=19456 KiB, t=2, p=1`. Hashes produced here verify under Node's `argon2` and PHP's `password_verify(PASSWORD_ARGON2ID)` and vice versa.
- **Cascade on revoke** — revoking a user revokes all their active credentials AND terminates all their active sessions. Suspending preserves credentials but terminates sessions.
- **Rotation revokes the old** — `rotate_password` etc. mark the old credential `revoked`, link the new with `replaces=old.id`, and terminate every session bound to the old credential.
- **Tokens are not session ids** — `create_session` returns `(session, token)`. Only the SHA-256 hash of the token is persisted; `verify_session_token` is constant-time.
- **Generic auth errors** — `verify_password` raises `InvalidCredentialError` for both unknown identifier and bad password. The message intentionally doesn't disclose which arm failed.

## Cross-language Argon2id parity

```bash
pytest tests/test_conformance.py -v
```

Runs the spec's `identity/argon2id.json` fixture. The fixture's PHC hash was generated by Node's `argon2` package; this harness verifies it via `argon2-cffi`. Both bindings wrap the reference Argon2 C library and produce identical output.

## License

Apache-2.0. See [LICENSE](./LICENSE) and [NOTICE](./NOTICE).

Copyright 2026 NDC Digital, LLC.
