Metadata-Version: 2.4
Name: dpdpguard-sdk
Version: 1.0.0
Summary: DPDP Guard Server SDK (Python) - typed API client, consent gate, token broker, webhook verifier
Project-URL: Homepage, https://github.com/dpdp-guard-ai/dpdpguard-python-sdk
Project-URL: Spec, https://github.com/chintans/dpdpbot/blob/main/docs/specs/mobile-server-sdk.md
Author: DPDP Guard
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# dpdpguard-python-sdk

DPDP Guard Server SDK (Python) — typed API client, consent gate, token broker
helper, audit-hash verifier, and webhook signature verifier over DPDP Guard's
public `/api/v1` (spec §4.2).

PyPI distribution: `dpdpguard-sdk` · Import as: `dpdpguard`

Part of the DPDP Guard SDK family. See the design spec:
https://github.com/chintans/dpdpbot/blob/main/docs/specs/mobile-server-sdk.md

This SDK mirrors [`@dpdpguard/server`](https://www.npmjs.com/package/@dpdpguard/server)
(the Node/TypeScript reference implementation) method for method, so behavior —
auth modes, idempotency headers, error codes, audit-hash canonicalization — stays
identical across ecosystems (ADR-001's audit-uniformity goal).

## Install

```bash
pip install dpdpguard-sdk
```

## Usage

```python
import os
from dpdpguard import DpdpGuardClient, has_consent, verify_webhook_signature

client = DpdpGuardClient(
    "https://<your-deployment>.convex.site",
    api_key=os.environ["DPDP_SERVICE_API_KEY"],  # convex/apiKeys.ts, for broker_token() only
)

# Mint a brokered principal access token (ADR-004 D1/D2) for a known user.
client.broker_token(external_id)

# Now authenticated calls use that token automatically.
result = client.list_dsr_requests()
client.create_dsr_request(organization_id=org_id, type="erasure")

# Public reads need no auth at all.
org = client.get_organization("acme")
notices = client.get_notices(org["orgId"])

# Verify an inbound webhook (convex/webhooks.ts's X-DPDP-Signature header).
ok = verify_webhook_signature(webhook_secret, raw_body, request.headers.get("x-dpdp-signature"))
```

Use it as a context manager to close the underlying `httpx.Client` automatically:

```python
with DpdpGuardClient(base_url) as client:
    org = client.get_organization("acme")
```

Every non-2xx response raises a `DpdpGuardApiError` with a `code` from the
ADR-002 error catalog (`err.code`, e.g. `"NOT_FOUND"`) and the HTTP `status`.

### Consent gate

```python
from dpdpguard import has_consent

if not has_consent(consents, "Marketing"):
    return  # don't send the campaign
```

### Audit-hash verification

A holder of the platform's `DPDP_AUDIT_HASH_HMAC_SECRET` can independently
verify a `consentAuditTrail` row's `auditHash`:

```python
from dpdpguard import AuditHashInput, compute_audit_hash

input = AuditHashInput(
    organization_id="org_abc123",
    notice_id="notice_v1",
    notice_version=1,
    purpose="Newsletter",
    data_types=["email"],
    given_at=1700000000000,
    source="direct",
)
assert compute_audit_hash(input, secret) == stored_audit_hash
```

## Contract

This package vendors its wire contract from `dpdpbot`'s single source of
truth (ADR-001/002) rather than depending on a published `@dpdpguard/contract`
Python package (none exists yet):

- `src/dpdpguard/models.py` is hand-kept in sync with `openapi/v1.yaml`'s
  `components.schemas`.
- `src/dpdpguard/errors.py` loads `_data/error-catalog.json`, vendored
  verbatim from `@dpdpguard/contract/conformance/error-catalog.json`
  (ADR-002 D2).
- `tests/test_audit_hash.py` runs `_data/audit-hash-vectors.json` (vendored
  from `@dpdpguard/contract/conformance/audit-hash-vectors.json`) as a
  required CI gate (ADR-002 D5) — a failure means this SDK's `audit_hash.py`
  has drifted from `convex/lib/auditHash.ts`.

## Development

```bash
pip install -e ".[dev]"
ruff check .
mypy src
pytest --cov=src --cov-report=term-missing
```
