Metadata-Version: 2.4
Name: ciph4
Version: 1.1.0
Summary: CIPH4 Python SDK — zero-knowledge secret sharing, compliance, orgs, threats, audit, and webhooks
Home-page: https://ciph4.com
Author: CIPH4 Inc.
Author-email: support@ciph4.com
Project-URL: Documentation, https://ciph4.com/docs
Project-URL: Source, https://github.com/ciph4/python-sdk
Keywords: ciph4 secret sharing encryption zero-knowledge 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.8
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: Topic :: Security
Classifier: Topic :: Security :: Cryptography
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.28.0
Requires-Dist: cryptography>=41.0.0
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# CIPH4 Python SDK

Zero-knowledge secret sharing, plus the full CIPH4 platform API: drops,
orgs, compliance, reports, threats, webhooks, and audit. All drop
creation encrypts locally with AES-256-GCM — the CIPH4 server never sees
your plaintext.

## Install

```bash
pip install ciph4
```

## Quick start

```python
import ciph4

client = ciph4.Client("ck_your_api_key")
print(client.drops.create_text("postgres://prod:s3cret@db:5432/app"))
```

That prints a `https://ciph4.com/dd/.../#key=...` link. Send it to your
recipient and it self-destructs after one view.

## Sub-module overview

| Namespace                    | Purpose                                               |
| ---------------------------- | ----------------------------------------------------- |
| `client.drops`               | Create, list, revoke, archive, clone, bulk, receipt   |
| `client.user`                | Profile, plan, password, notifications                |
| `client.user.mfa`            | TOTP enrollment, backup codes                         |
| `client.user.account`        | GDPR deletion lifecycle                               |
| `client.user.api_keys_*`     | API key management (session-only auth)                |
| `client.user.sessions_*`     | Active session list / revoke                          |
| `client.file_requests`       | Public file-request landing pages (uploads in)        |
| `client.orgs`                | Orgs CRUD, drops, storage, enforcement                |
| `client.orgs.members`        | Member list / invite / role / remove / bulk           |
| `client.orgs.invites`        | Link invites, email invites, accept                   |
| `client.orgs.security_policies` | Consolidated Security & Policies (P-Feat-1/3/4)    |
| `client.orgs.mfa_policy`     | Org MFA policy                                        |
| `client.orgs.branding`       | Branding (logo, colors, disclaimer)                   |
| `client.orgs.byok`           | BYOK key configuration                                |
| `client.threats`             | Threat alerts, bulk actions, CSV export               |
| `client.threats.ip_rules`    | Allow / deny IP rules                                 |
| `client.compliance`          | Controls, policies, risks, vendors, evidence          |
| `client.reports`             | Generate / list / poll / download reports             |
| `client.audit`               | Audit feed + hash-chain verification                  |
| `client.receipts`            | Public Proof-of-Deletion receipt verifier + JWKS      |
| `client.webhooks`            | Webhook endpoints + deliveries                        |
| `client.billing`             | Stripe checkout & customer portal                     |
| `client.analytics`           | Usage analytics                                       |

## Zero-knowledge architecture

All drop encryption happens locally using AES-256-GCM. The CIPH4 server
only stores ciphertext. The encryption key is embedded in the URL
fragment (`#key=...`) which browsers never send to the server.

```
Your machine          CIPH4 server          Recipient
─────────────         ────────────          ─────────
Generate AES key
Encrypt locally
Send ciphertext ────→ Store ciphertext
Key in URL fragment   Never sees the key
Share link ──────────────────────────────→ Open link
                                           Decrypt in browser
                      Delete ciphertext ←─ Link self-destructs
```

## Examples

### Drops

```python
# Text drop with 24h expiry, 1 view
url = client.drops.create_text("db-pass-here", expires="24h", max_views=1)

# File drop with DRM (Enterprise)
url = client.drops.create_file(
    "q2-report.pdf",
    expires="7d",
    max_views=3,
    drm_enabled=True,
    drm_watermark=True,
    drm_no_print=True,
)

# List, revoke, archive
for d in client.drops.list():
    print(d["id"], d.get("fileName") or "Text", d["maxViews"])

client.drops.revoke("clx_abc123")
client.drops.archive("clx_abc123")

# Bulk archive
client.drops.bulk(["clx_a", "clx_b"], action="archive")

# Proof-of-Deletion receipt (Enterprise)
receipt = client.drops.receipt("clx_abc123")
```

### User & MFA

```python
profile = client.user.profile_get()
client.user.profile_update(name="New Name")
client.user.plan()

# TOTP MFA (session-only auth)
enroll = client.user.mfa.enroll()           # {qrCodeDataUrl, otpauthUrl, secret}
client.user.mfa.enroll_confirm("123456")    # returns 10 backup codes
client.user.mfa.status()

# API keys (session-only auth, Enterprise)
keys = client.user.api_keys_list()
new = client.user.api_keys_create("CI runner")  # plaintext returned once
client.user.api_keys_delete(new["id"])
```

### Organizations

```python
orgs = client.orgs.list()
org = client.orgs.create(name="Acme Corp")

# Members
client.orgs.members.add(org["id"], "bob@acme.com", role="USER")
client.orgs.members.bulk(org["id"], ["a@acme.com", "b@acme.com"], role="USER")

# Invites (link invites)
inv = client.orgs.invites.create(org["id"], role="USER", expires_in_days=7)
print(inv["acceptUrl"])

# Security & Policies (P-Feat-1/3/4)
client.orgs.security_policies.update(
    org["id"],
    mfa_required=True,
    mfa_grace_days=7,
    domain_allowlist=["acme.com", "subsidiary.com"],
    max_expiry_hours=168,
    default_drm_enabled=True,
    default_drm_watermark=True,
)
```

### Threats

```python
client.threats.list(range="30d")
client.threats.bulk("resolve", ["alert_1", "alert_2"])

# IP rules
client.threats.ip_rules.create("203.0.113.5", type="deny", reason="brute force")
client.threats.ip_rules.list()

# CSV export (returns raw bytes)
csv_bytes = client.threats.export(range="30d")
open("threats.csv", "wb").write(csv_bytes)
```

### Compliance (Enterprise)

```python
dash = client.compliance.dashboard()
print(dash["score"], dash["kpis"])

# Update controls
client.compliance.control_update("ctrl_abc", status="passing", owner_id="clx_user")

# Policies
pol = client.compliance.policies_create(
    name="Acceptable Use",
    body_markdown="# Policy\n\n...",
    requires_ack=True,
)
client.compliance.policies_acknowledge(pol["id"])

# Risks
client.compliance.risks_create(
    title="Phishing exposure",
    severity="high",
    likelihood=3,
    impact=4,
)
```

### Reports

```python
# Async generation — poll until ready
job = client.reports.generate("soc2-trust-services", format="PDF")
while True:
    r = client.reports.get(job["id"])
    if r["status"] == "ready":
        break
    time.sleep(5)

pdf_bytes = client.reports.download(job["id"])
open("soc2.pdf", "wb").write(pdf_bytes)

# Scheduled (recurring) reports
client.reports.scheduled_create("soc2-trust-services", cadence="weekly",
                                format="PDF", deliver_emails=["auditor@acme.com"])
```

### Audit

```python
feed = client.audit.list(range="30d", limit=500)
verdict = client.audit.verify()
assert verdict["intact"]
```

### Receipts

```python
# Fetch JWKS for offline verification
jwks = client.receipts.jwks()

# Hosted verifier
receipt = client.drops.receipt("clx_abc123")  # signed deletion receipt
result = client.receipts.verify(receipt)
assert result["valid"]
```

### Webhooks

```python
client.webhooks.create(
    url="https://example.com/ciph4-webhook",
    events=["drop.viewed", "drop.burned", "drop.revoked"],
)
# The signing secret is in the response — store it now, it's only returned once.

client.webhooks.list()
client.webhooks.deliveries(take=50)
```

## Error handling

```python
from ciph4 import Client, CiphError, CiphAuthError

client = Client("ck_...")
try:
    client.drops.revoke("clx_nonexistent")
except CiphAuthError as e:
    print("Auth / permissions:", e.status_code, e.message)
except CiphError as e:
    print("API error:", e.status_code, e.message)
```

`CiphAuthError` is a subclass of `CiphError` raised specifically on 401
and 403 responses, so you can catch either with `except CiphError`.

## CLI

```bash
export CIPH4_API_KEY=ck_...

ciph4 share "my-database-password"      # share text, 24h, 1 view
ciph4 share ./report.pdf --expires 7d   # share file, 7 days
ciph4 list                              # list your drops
ciph4 revoke clx_abc123                 # revoke a link
ciph4 audit                             # verify the audit hash chain
```

The CLI wraps `client.drops.*` and `client.audit.*` and uses the same
zero-knowledge encryption path as the Python API.

## Legacy v1.0 compatibility

The v1.0 top-level methods still work as thin proxies to the new
namespaces — no code changes required to upgrade:

| v1.0 method                    | v1.1 equivalent                  |
| ------------------------------ | -------------------------------- |
| `client.share_text(...)`       | `client.drops.create_text(...)`  |
| `client.share_file(...)`       | `client.drops.create_file(...)`  |
| `client.list_drops()`          | `client.drops.list()`            |
| `client.revoke(id)`            | `client.drops.revoke(id)`        |
| `client.get_drop(id)`          | `client.drops.get(id)`           |
| `client.get_plan()`            | `client.user.plan()`             |
| `client.get_analytics(range)`  | `client.analytics.get(range)`    |
| `client.get_threats(range)`    | `client.threats.list(range)`     |
| `client.verify_audit_chain()`  | `client.audit.verify()`          |

## Version compatibility

| SDK version | CIPH4 API version | Notes                                    |
| ----------- | ----------------- | ---------------------------------------- |
| 1.1.0       | v1.0+             | Full 108-route wrapper, nested namespaces |
| 1.0.0       | v1.0+             | 10-method minimal wrapper                 |

## Further reading

The authoritative API reference is `API.md` at the repo root. It
documents all 108 routes including request/response shapes, error
codes, rate limits, and plan gating.

## License

MIT
