Metadata-Version: 2.4
Name: ethid
Version: 0.1.0
Summary: Zero-Knowledge Document Verification SDK for Python
Author-email: "ETH.id Contributors" <hello@eth.id>
License: MIT
Project-URL: Homepage, https://github.com/your-org/eth-id
Project-URL: Documentation, https://docs.eth.id
Project-URL: Repository, https://github.com/your-org/eth-id
Project-URL: Issues, https://github.com/your-org/eth-id/issues
Keywords: zero-knowledge,privacy,verification,zkp,document,llm
Classifier: Development Status :: 4 - Beta
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 :: Cryptography
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: black>=23.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"

# ETH.id Python SDK

Zero-Knowledge Document Verification SDK for Python.

## Installation

```bash
pip install ethid
```

## Quick Start

```python
from ethid import EthIdClient, LLMProvider

# Initialize client
client = EthIdClient(
    provider=LLMProvider.OPENAI,
    api_key="sk-your-key"
)

# Verify a document
result = client.verify(
    document_path="passport.pdf",
    claim="over 18 years old"
)

print(f"Answer: {result.answer}")
print(f"Confidence: {result.confidence}%")
print(f"Reasoning: {result.reasoning}")
```

## Features

- **Zero-Knowledge Verification**: Documents never leave your machine
- **Privacy-First**: Only minimal, claim-relevant data is processed
- **Multiple LLM Providers**: OpenAI, Claude, Ollama
- **Cryptographic Attestations**: Tamper-evident proof bundles
- **Audit Trail**: Complete verification history
- **Type-Safe**: Full type hints and dataclasses

## Usage

### Basic Verification

```python
from ethid import EthIdClient

client = EthIdClient()

# Age verification
result = client.verify(
    document_path="id.pdf",
    claim="maior de 18 anos"
)

if result.answer:
    print("Person is over 18")
```

### With Attestation

```python
# Generate cryptographic proof
result = client.verify(
    document_path="id.pdf",
    claim="over 21 years old",
    attest=True
)

# Get attestation bundle
bundle = client.get_attestation(result.session_id)

# Verify integrity
if bundle.verify_integrity():
    print("Attestation is valid")
```

### Offline Mode

```python
# Complete privacy with local LLM
client = EthIdClient(
    provider=LLMProvider.OLLAMA,
    offline=True
)

result = client.verify(
    document_path="document.pdf",
    claim="document is signed"
)
```

### Audit Log

```python
# List all verifications
entries = client.list_audit_log(limit=10)

for entry in entries:
    print(f"{entry.timestamp}: {entry.claim} -> {entry.answer}")

# Get specific entry
entry = client.get_audit_entry(session_id="...")
```

## Privacy Guarantees

### What is NEVER Sent

For age verification:
- ❌ Birth date
- ❌ Full name
- ❌ Address
- ✅ Only: "Age calculation result: true"

For CPF verification:
- ❌ Full CPF (123.456.789-00)
- ✅ Only: Masked (123.***.***-00)

## API Reference

### EthIdClient

```python
class EthIdClient:
    def __init__(
        self,
        cli_path: Optional[str] = None,
        provider: Optional[LLMProvider] = None,
        api_key: Optional[str] = None,
        offline: bool = False,
        debug: bool = False,
    )
```

#### Methods

**verify()**
```python
def verify(
    self,
    document_path: str,
    claim: str,
    provider: Optional[LLMProvider] = None,
    attest: bool = False,
    zk_only: bool = False,
) -> VerificationResult
```

**get_attestation()**
```python
def get_attestation(
    self,
    session_id: str,
) -> AttestationBundle
```

**list_audit_log()**
```python
def list_audit_log(
    self,
    limit: Optional[int] = None,
    filter_claim: Optional[str] = None,
) -> List[AuditEntry]
```

**configure()**
```python
def configure(
    self,
    provider: Optional[LLMProvider] = None,
    api_key: Optional[str] = None,
)
```

### Types

**VerificationResult**
```python
@dataclass
class VerificationResult:
    session_id: str
    answer: bool
    confidence: float
    reasoning: str
    proof_type: ProofType
    claim: str
    privacy_metadata: PrivacyMetadata
    timestamp: datetime
```

**AttestationBundle**
```python
@dataclass
class AttestationBundle:
    session_id: str
    document_hash: str
    claim: str
    result: VerificationResult
    proof_type: ProofType
    bundle_hash: str
    created_at: datetime
    
    def verify_integrity(self) -> bool
```

## Examples

### Age Verification

```python
result = client.verify(
    document_path="passport.pdf",
    claim="over 18 years old"
)

print(f"Over 18: {result.answer}")
```

### CPF Verification

```python
result = client.verify(
    document_path="brazilian_id.pdf",
    claim="CPF bate com 123.456.789-00"
)

# Only masked CPF is sent: 123.***.***-00
```

### Income Verification

```python
result = client.verify(
    document_path="income_proof.pdf",
    claim="renda acima de 5000"
)

# Only amount field is sent, no name/CPF
```

### Multiple Providers

```python
# OpenAI
client_openai = EthIdClient(provider=LLMProvider.OPENAI)

# Claude
client_claude = EthIdClient(provider=LLMProvider.CLAUDE)

# Ollama (offline)
client_ollama = EthIdClient(
    provider=LLMProvider.OLLAMA,
    offline=True
)
```

## Error Handling

```python
from ethid import (
    DocumentParsingError,
    ClaimParsingError,
    VerificationError,
)

try:
    result = client.verify(
        document_path="document.pdf",
        claim="over 18 years old"
    )
except DocumentParsingError as e:
    print(f"Failed to parse document: {e}")
except ClaimParsingError as e:
    print(f"Failed to parse claim: {e}")
except VerificationError as e:
    print(f"Verification failed: {e}")
```

## Requirements

- Python 3.8+
- ETH.id CLI installed (`cargo install --path .`)

## Development

```bash
# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black ethid/

# Type check
mypy ethid/
```

## License

MIT

## Links

- [Documentation](https://docs.eth.id)
- [GitHub](https://github.com/your-org/eth-id)
- [Issues](https://github.com/your-org/eth-id/issues)
