Metadata-Version: 2.5
Name: sahra-shared
Version: 0.2.2
Summary: Sahra Trans — shared kernel library
Project-URL: Homepage, https://github.com/Sahra-Trans/sahra-shared
Project-URL: Repository, https://github.com/Sahra-Trans/sahra-shared
Project-URL: Issues, https://github.com/Sahra-Trans/sahra-shared/issues
Author: Hycind Santhibhavan
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.13
Requires-Dist: cryptography>=42.0.0
Requires-Dist: fastapi>=0.115.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: nats-py>=2.7.0
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.24.0
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.45b0
Requires-Dist: opentelemetry-sdk>=1.24.0
Requires-Dist: prometheus-client>=0.20.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pyjwt[crypto]>=2.8.0
Requires-Dist: sqlalchemy>=2.0.0
Description-Content-Type: text/markdown

# sahra-shared

[![PyPI](https://img.shields.io/pypi/v/sahra-shared.svg)](https://pypi.org/project/sahra-shared/)
[![Python](https://img.shields.io/pypi/pyversions/sahra-shared.svg)](https://pypi.org/project/sahra-shared/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](#license)

**A reusable Python library — the shared kernel for Sahra Trans services.**

`sahra-shared` is a *library*, not a service. It has **no HTTP server, no database, no
port, no container and no entrypoint**. Nothing here starts; you `import` it. It is
published to PyPI and consumed by the Sahra Trans services as an ordinary dependency.

The import namespace is **`sahra_shared`**.

## Install

```bash
uv add sahra-shared
```

## Use

```python
from sahra_shared.auth import Capability, CapabilityGuards
from sahra_shared.events import NATSPublisher, SahraEvent
from sahra_shared.http import ProblemDetail, make_health_router
from sahra_shared.privacy import CountryPrivacyPolicy, PIIEmail
from sahra_shared.telemetry import AppLogger, setup_otel
from sahra_shared.tenancy import TenantScope, tenant_transaction
```

## What it provides

| Sub-package | Surface |
|---|---|
| `sahra_shared.auth` | `TokenClaims`, RS256 JWT verification against JWKS, the closed `Capability` vocabulary and deny-by-default `CapabilityGuards` |
| `sahra_shared.events` | `SahraEvent` (CloudEvents envelope), `NATSPublisher` / consumer helpers |
| `sahra_shared.http` | `ProblemDetail` (RFC 7807) and `make_health_router` — a router **factory** a service mounts; this library serves nothing itself |
| `sahra_shared.privacy` | PII types (`PIIEmail`, `PIIPhone`, …) and per-country privacy policies |
| `sahra_shared.telemetry` | OpenTelemetry setup, structured logging, `call_service` (propagates `traceparent`) |
| `sahra_shared.tenancy` | `TenantScope`, transaction-bound tenant context, row-level-security helpers |

Sub-packages are independent: they do not import one another (only `telemetry` is
depended upon in common). That boundary is enforced by
`tests/test_import_boundaries.py`.

## Requirements

Python **>= 3.13**.

## Development

This repository is **uv-only**. Do not use `pip`, `venv`, Poetry or Twine.

```bash
uv sync --all-groups        # install dev + test dependency groups
uv run pytest               # tests
uv run ruff check .         # lint
uv run ruff format --check .# format
uv run ty check             # type-check
uv build                    # build wheel + sdist
```

`uv.lock` is committed deliberately: the resolved dependency set is part of what a
release tag means.

## Documentation

Design notes, the tenancy/RLS reference and the logging integration guide live
in the project repository alongside the source, and are not shipped in the
distribution.

## Releasing

Releases are built and published to PyPI by GitHub Actions using **Trusted
Publishing (OIDC)**. There is no PyPI API token and no stored publishing
credential. A `vX.Y.Z` tag builds, gates and publishes; a `vX.Y.Z-rc1` tag runs
the identical gate and stops before publishing.

## License

MIT — see [`LICENSE`](LICENSE).
