Metadata-Version: 2.4
Name: mafate
Version: 0.1.0
Summary: MAFATE Encryption as a Service — Python SDK
License: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.28
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"

# mafate — Python SDK

Official Python SDK for the **MAFATE Encryption as a Service (EaaS)** API.

- Python 3.9+
- Zero magic — plain `requests`, TypedDict types, full type hints
- Same developer experience as the Node.js SDK

---

## Install

```bash
pip install mafate
```

---

## Quick Start

```python
from mafate import Mafate

client = Mafate(api_key="eaas_dev_sk_...")

# Encrypt a string
encrypted = client.encrypt("données sensibles", key_id="key_abc123")
# encrypted is an EncryptedData dict:
# { ciphertext, wrapped_key, iv, key_id, key_version }

# Decrypt — pass the whole EncryptedData dict back
plaintext = client.decrypt(encrypted)
print(plaintext)  # "données sensibles"
```

Plaintext is **automatically** base64-encoded before sending and decoded after
receiving — you never handle base64 yourself.

---

## Configuration

```python
client = Mafate(
    api_key="eaas_dev_sk_...",
    base_url="https://api.mafate.io",  # default
    timeout=30.0,                       # seconds, default 30
)
```

For local development against a self-hosted instance:

```python
client = Mafate(api_key="eaas_dev_sk_...", base_url="http://localhost:3333")
```

---

## API Reference

### `client.health()`

Check API availability. Does not require authentication.

```python
health = client.health()
# { status: "healthy", database: "ok", cache: "ok", hsm: "ok" }
```

---

### `client.encrypt(plaintext, key_id)` → `EncryptedData`

Encrypt a UTF-8 string.

```python
encrypted = client.encrypt("secret data", key_id="key_abc")
# Store all fields — you need them all to decrypt
```

### `client.decrypt(encrypted_data)` → `str`

Decrypt and return the original UTF-8 string.

```python
plaintext = client.decrypt(encrypted)
```

---

### `client.keys`

| Method | Description |
|--------|-------------|
| `client.keys.list()` | List all encryption keys |
| `client.keys.get(key_id)` | Get key detail with versions |
| `client.keys.create(name, algorithm=None)` | Create a new key |
| `client.keys.rotate(key_id)` | Rotate key (new version) |
| `client.keys.disable(key_id)` | Disable a key |

```python
# List keys
keys = client.keys.list()

# Create a key
key = client.keys.create("my-database-key", algorithm="AES-256-GCM")

# Get key with version history
detail = client.keys.get(key["id"])
print(detail["versions"])

# Rotate
rotated = client.keys.rotate(key["id"])
print(rotated["current_version"])  # 2

# Disable
client.keys.disable(key["id"])
```

---

### `client.api_keys`

| Method | Description |
|--------|-------------|
| `client.api_keys.list()` | List all API keys |
| `client.api_keys.create(name, permissions, expires_at=None)` | Create API key |
| `client.api_keys.update(key_id, permissions=None, expires_at=None)` | Update API key |
| `client.api_keys.revoke(key_id)` | Revoke (delete) API key |

```python
# Create a scoped API key for a CI pipeline
new_key = client.api_keys.create(
    "github-actions",
    permissions=["encrypt", "decrypt"],
    expires_at="2027-01-01T00:00:00Z",
)
# new_key["secret"] is only available here — store it securely

# Update permissions
client.api_keys.update(new_key["id"], permissions=["encrypt"])

# Revoke
client.api_keys.revoke(new_key["id"])
```

---

### `client.audit`

| Method | Description |
|--------|-------------|
| `client.audit.list(filters=None)` | Query the audit log |

```python
from mafate import AuditFilters

logs = client.audit.list({
    "action": "encrypt",
    "key_id": "key_abc",
    "date_from": "2026-01-01T00:00:00Z",
    "date_to": "2026-12-31T23:59:59Z",
    "limit": 100,
    "offset": 0,
})

print(f"{logs['total']} total entries")
for entry in logs["logs"]:
    print(entry["action"], entry["actor"], entry["created_at"])
```

---

## Error Handling

All errors inherit from `MafateError`. API errors are `ApiError` with
`status`, `title`, and `detail` attributes (RFC 7807).

```python
from mafate import Mafate, ApiError, MafateError

client = Mafate(api_key="eaas_dev_sk_...")

try:
    client.keys.get("key_doesnt_exist")
except ApiError as e:
    print(e.status)   # 404
    print(e.title)    # "Key not found"
    print(e.detail)   # "No key with id key_doesnt_exist"
except MafateError as e:
    print("SDK error:", e)
```

---

## Running Tests

```bash
pip install -e ".[dev]"
pytest tests/ -v
```

---

## License

MIT — UNIVILE SAS
