Metadata-Version: 2.4
Name: blackshield-sdk
Version: 0.1.1
Summary: Official Python SDK for the BlackShield Security Platform
Project-URL: Homepage, https://blackshield.chaplau.com
Project-URL: Documentation, https://blackshield.chaplau.com/en/docs
Author-email: BlackShield Security <contact@chaplau.com>
License-Expression: Apache-2.0
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
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: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx<1,>=0.27
Requires-Dist: pydantic<3,>=2.0
Provides-Extra: dev
Requires-Dist: mypy>=1.13; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest-cov>=6.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.22; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Description-Content-Type: text/markdown

# BlackShield Python SDK

Official Python SDK for the [BlackShield Security Platform](https://blackshield.chaplau.com).

## Installation

```bash
pip install blackshield-sdk
```

## Quick Start

```python
import blackshield

client = blackshield.BlackShield(api_key="bsk_live_...")

# List critical findings
page = client.findings.list(severity=["critical", "high"], page_size=10)
for f in page.items:
    print(f"{f.severity.value} | {f.title}")

# Get a specific finding
finding = client.findings.get("550e8400-e29b-41d4-a716-446655440000")

# Update finding status
client.findings.update_status(finding.id, status="in_progress", reason="Investigating")
```

## Async Usage

```python
import asyncio
from blackshield import AsyncBlackShield

async def main():
    async with AsyncBlackShield(api_key="bsk_live_...") as client:
        page = await client.findings.list(severity=["critical"])
        for f in page.items:
            print(f.title)

asyncio.run(main())
```

## Available Resources

| Resource | Description | Example |
|----------|-------------|---------|
| `client.findings` | List, get, update findings | `client.findings.list(severity=["critical"])` |
| `client.ingestion` | Ingest findings & assets | `client.ingestion.ingest_findings([...])` |
| `client.dashboard` | Stats, trends, usage | `client.dashboard.stats()` |
| `client.compliance` | Compliance overview & controls | `client.compliance.overview(framework="SOC2")` |
| `client.reports` | Summaries & CSV/PDF exports | `client.reports.export_findings_csv()` |
| `client.easm` | External attack surface | `client.easm.overview()` |
| `client.threat_intel` | Blocklist & indicator lookup | `client.threat_intel.lookup(indicator="1.2.3.4")` |
| `client.connectors` | Connector health monitoring | `client.connectors.freshness()` |
| `client.api_keys` | API key management | `client.api_keys.create(label="CI")` |
| `client.policies` | Policy guardrails & custom Rego | `client.policies.list_packs()` |
| `client.security_reviews` | Guided security reviews & templates | `client.security_reviews.get_default_template()` |
| `client.audit` | Tenant audit logs & evidence export | `client.audit.query(limit=50)` |
| `client.alerts` | Alerts & alert sync integrations | `client.alerts.list(severity=["critical"])` |
| `client.identity` | Identity, OIDC & mapping configs | `client.identity.list_oidc()` |
| `client.remediation` | Remediation & compensating controls | `client.remediation.get_policy("default")` |
| `client.ai_gateway` | AI Gateway client & usage logs | `client.ai_gateway.list_clients()` |

## Ingestion

```python
from blackshield.types.ingestion import UnifiedFinding, AffectedResource, SourceMeta

finding = UnifiedFinding(
    finding_type="vulnerability",
    title="CVE-2024-1234 in openssl 3.0.8",
    severity="critical",
    cve_id="CVE-2024-1234",
    affected_resource=AffectedResource(
        resource_type="container_image",
        resource_id="sha256:abc123",
        resource_name="myapp:latest",
    ),
    source=SourceMeta(scanner="trivy", scanner_version="0.50.0"),
    dedup_key="vuln:CVE-2024-1234:sha256:abc123",
)

result = client.ingestion.ingest_findings([finding])
print(f"Job ID: {result.job_id}, Status: {result.status}")

# Poll for completion
job = client.ingestion.get_job(result.job_id)
print(f"Created: {job.created}, Updated: {job.updated}")
```

## Error Handling

```python
import blackshield

try:
    finding = client.findings.get("nonexistent-id")
except blackshield.NotFoundError:
    print("Finding not found")
except blackshield.RateLimitError as e:
    print(f"Rate limited, retry after {e.retry_after}s")
except blackshield.AuthenticationError:
    print("Invalid API key")
except blackshield.BlackShieldError as e:
    print(f"API error: {e}")
```

## Configuration

```python
client = blackshield.BlackShield(
    api_key="bsk_live_...",
    base_url="https://api.blackshield.chaplau.com",  # or self-hosted URL
    timeout=60.0,       # request timeout in seconds
    max_retries=3,       # automatic retries on 429/5xx
)
```

## Development

```bash
cd sdk
pip install -e ".[dev]"
pytest -v --cov=blackshield
ruff check .
mypy .
```
