Metadata-Version: 2.4
Name: cleanlib-sdk
Version: 0.4.6
Summary: CleanLibrary Python SDK — HttpVerdictClient + HttpRemediationClient + HttpEnrichClient triad (sister-shape with @cleanstart/cleanlib-sdk v0.4.4)
Project-URL: Homepage, https://cleanlibrary.clnstrt.dev
Project-URL: Documentation, https://cleanlibrary.clnstrt.dev/docs/sdk-python
Project-URL: Bug Tracker, https://cleanlibrary.clnstrt.dev/support
Author: CleanStart
License: Proprietary
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# cleanlib-sdk

CleanLibrary Python SDK — `asyncio` + `httpx`; mirrors the Rust `cleanlib-client` HTTP surface.

**Status**: `v0.4.3` — production-ready.

## Install

```bash
pip install cleanlib-sdk
```

## Usage

```python
import asyncio
from cleanlib_sdk import Client, PolicyDenyError, RiskAcceptanceRequiredError

async def main() -> None:
    async with Client(
        endpoint="https://cleanapp.clnstrt.dev",
        api_key="clk_std_...",   # opaque CleanLibrary access key
    ) as c:
        try:
            v = await c.fetch_verdict("npm", "lodash", "4.17.21")
            print(f"{v.decision} composite_score={v.composite_score}")
            print(f"reasoning: {v.reasoning}")
        except PolicyDenyError as e:
            print(f"DENIED [{e.reason_code}]: {e.message}")
        except RiskAcceptanceRequiredError as e:
            print(f"RISK ACCEPT REQUIRED: {e.message}")
            if e.docs_url:
                print(f"see: {e.docs_url}")

asyncio.run(main())
```

## Error hierarchy

All errors descend from `CleanLibraryError`. Subclasses:

| Exception | HTTP | Triggered by |
|---|---|---|
| `PolicyDenyError` | 403 / 451 | `POLICY_DENY_VERDICT` / `POLICY_DENY_RULE_EXPLICIT` |
| `IntegrityFailureError` | 403 | `INTEGRITY_FAILURE` |
| `RateLimitExceededError` | 429 | tier-throttled; carries `retry_after_seconds` |
| `RiskAcceptanceRequiredError` | 403 | `RISK_ACCEPTANCE_REQUIRED` |
| `AuthenticationError` | 401 / 403 | `KEY_INVALID` / `KEY_EXPIRED` / `KEY_SCOPE_INSUFFICIENT` |
| `InsufficientDataError` | 403 | `INSUFFICIENT_DATA_FAIL_CLOSED` |
| `PackageNotFoundError` | 404 | not in catalog + ingest declined |
| `ServerError` | 5xx | retryable on 502/503/504 |
| `TransportError` | — | network / TLS / timeout / DNS |
| `ParseError` | — | response body shape mismatch |

## Development

```bash
pip install -e ".[dev]"
pytest
ruff check .
```

## Cross-references

- [CleanLibrary docs](https://cleanlibrary.clnstrt.dev) — customer documentation portal
- Rust SDK: [`cleanlib-client`](https://crates.io/crates/cleanlib-client) — reference implementation
- Go SDK: [`cleanlib-sdk-go`](https://pkg.clnstrt.dev/cleanlib-sdk-go)
- JavaScript SDK: [`@cleanstart/cleanlib-sdk`](https://www.npmjs.com/package/@cleanstart/cleanlib-sdk)

## License

Proprietary — CleanStart.
