Metadata-Version: 2.4
Name: praxicraft-shared
Version: 0.6.0
Summary: Stateless cross-product Python utilities for Praxicraft backends
Author: Praxicraft
License: Proprietary
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: cryptography>=42.0.0
Requires-Dist: requests>=2.32.0
Requires-Dist: PyJWT[crypto]>=2.8.0
Requires-Dist: boto3>=1.34.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"

# praxicraft-shared

Stateless Python utilities shared by Praxicraft backends (Practice, auth, notifications, and future services). Products pin a **git tag**; no Django ORM, settings, or product business logic lives here.

**Planning & milestones:** [`Gamified-Application/docs/praxicraft-shared/README.md`](https://github.com/praxicraft-platform/praxicraft-practice/blob/staging/docs/praxicraft-shared/README.md)

## Prerequisites

- Python 3.11+
- GitHub access to this private repo (install via HTTPS + token)

## Install (in a product)

```text
praxicraft-shared @ git+https://github.com/praxicraft-platform/praxicraft-shared@v0.6.0
```

Builds need a token with `contents:read` (CI: `PRAXICRAFT_GH_TOKEN`).

Local editable (sibling checkout):

```bash
pip install -e ~/Desktop/praxicraft-shared
```

## Local development

```bash
cd ~/Desktop/praxicraft-shared
pip install -e ".[dev]"
ruff check src tests
pytest
```

## What’s in the package

| Module | Role |
| --- | --- |
| `jwt_utils` | Validate RS256 access JWTs (JWKS / PEM) |
| `auth_client` | HTTP client for `praxicraft-auth` (token exchange, me, …) |
| `billing_client` | HTTP client for `praxicraft-billing` (entitlements, checkout, cancel/resume) |
| `s3_client` | Injectable MinIO/S3 helpers (`make_s3_client`, put/get/presign, prefix download) |
| `notifications_client` | HTTP client for praxicraft-notifications internal send |
| `service_token` | Parse `product:token` / JSON service-token maps (no DRF) |
| `ai_service` | Thin client for `praxicraft-llm` (gateway + circuit-breaker fallback) |
| `error_envelope` | Standard success/error dict shapes |
| `events` | Event envelope helpers + `events/SCHEMA.md` |
| `email/` | Shared HTML/text email templates (rendered by notifications) |
| `secret_crypto` | Fernet encrypt/decrypt (inject key) |
| `work_email` | Email normalize / consumer-domain helpers |
| `hibp` | Have I Been Pwned password check |

Not shipped yet (planned): `org_client` (after auth A7).

## Hard rules

1. Stateless — no Django models, ORM, Celery, or package-owned Redis singletons  
2. No `django.conf.settings` — callers inject URLs and keys  
3. No product logic (XP, Assess scoring, Tutor mastery)  
4. Semver via git tags — breaking JWT/auth contracts = major bump  

## Related

- [praxicraft-auth](https://github.com/praxicraft-platform/praxicraft-auth)  
- [praxicraft-notifications](https://github.com/praxicraft-platform/praxicraft-notifications)  
- [praxicraft-llm](https://github.com/praxicraft-platform/praxicraft-llm)  
