Metadata-Version: 2.4
Name: astraguard
Version: 1.3.0
Summary: Official AstraGuard SDK â€” license validation, HWID binding, and offline cache for Python server applications
Project-URL: Homepage, https://astraguard.io
Project-URL: Documentation, https://docs.astraguard.io
Project-URL: Repository, https://docs.astraguard.io
Author-email: AstraGuard Team <support@astraguard.io>
License: MIT
License-File: LICENSE
Keywords: api,drm,license,protection,security
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: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: cryptography>=41.0
Provides-Extra: async
Requires-Dist: httpx>=0.27; extra == 'async'
Provides-Extra: dev
Requires-Dist: cryptography>=41.0; extra == 'dev'
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# astraguard

Official AstraGuard SDK for Python - license validation, HWID binding, and AES-256-GCM offline cache for server-side applications.

> **Server-Side Only**
> This SDK is for Python **server** applications (Flask, FastAPI, Django, etc.).
> Do NOT embed it in client-side software - Python offers no meaningful anti-debug or anti-VM protection.
> For desktop protection use the C++ header or Rust SDK.

## Installation

```bash
pip install astraguard
```

Async support (FastAPI, asyncio):

```bash
pip install "astraguard[async]"
```

## Sync (Flask / Django)

```python
from astraguard import AstraGuardClient

client = AstraGuardClient(
    api_url="https://api.astraguard.io",
    product_id="your-product-id",
    # Response Key from Dashboard -> Products -> Response Key. Without this,
    # validate()/activate() refuse to trust any response (fail closed) -
    # see the Security section below.
    response_auth_key="YOUR-RESPONSE-KEY-BASE64",
)

result = client.validate("XXXX-XXXX-XXXX-XXXX")
if result.valid:
    print("License valid!")
```

## Async (FastAPI)

```python
from astraguard import AsyncAstraGuardClient

client = AsyncAstraGuardClient(
    api_url="https://api.astraguard.io",
    product_id="your-product-id",
    response_auth_key="YOUR-RESPONSE-KEY-BASE64",
)

result = await client.validate("XXXX-XXXX-XXXX-XXXX")
```

## Features

- validate() / activate() with fully typed responses
- HMAC-SHA256 response verification (fail-closed)
- AES-256-GCM encrypted offline cache (configurable grace period)
- Background heartbeat thread
- Cross-platform HWID (Windows registry, /etc/machine-id, IOPlatformUUID)
- validate_or_exit() for CLI tools
- has_feature() / get_variable() shortcuts
- Update check via /check-update
- Full type annotations + py.typed marker

## Error Handling

```python
from astraguard import NetworkError, ServerError, SignatureMismatch

try:
    result = client.validate(license_key)
except NetworkError:
    pass  # unreachable + no cache
except ServerError as e:
    print(f"HTTP {e.status}")
except SignatureMismatch:
    pass  # tampered response
```

## Security  -  Response Integrity

Every `/validate` response is signed by the server with
`X-AstraGuard-Signature: sha256=<hex>`, an HMAC-SHA256 over the exact response
body. Pass `response_auth_key` at construction time with the Response Key from
**Dashboard -> Products -> Security -> Response Key** to enable verification
(shown in both quick-start examples above).

- **Fail-closed:** without a configured key, `validate()`/`activate()` never
  trust a response - they raise `SignatureMismatch` instead of silently
  treating an unsigned reply as valid.
- **Whole-body coverage:** the signature check covers the entire response -
  features, cloud variables, security flags, everything - so a
  man-in-the-middle can't quietly alter a value in transit.
- **Server-side secret:** the Response Key must stay on the server - never
  send it to a browser or embed it in a distributed client. This SDK is
  already server-only (see the notice at the top of this README), so this
  is the natural place for it to live.

## Heartbeat

```python
import sys

client.start_heartbeat(
    license_key="XXXX-XXXX-XXXX-XXXX",
    interval=300,
    on_lapse=lambda: sys.exit(1),
)
```

## License

MIT

## Links

- Docs: https://docs.astraguard.io
- Dashboard: https://www.astraguard.io/dashboard
- Discord (live help): https://discord.gg/Zkcyy5GnQd
- Email: support@astraguard.io
