From 05746ffaabf605cbf48373e93de6a57d2e053c12 Mon Sep 17 00:00:00 2001 From: ZacharyZhang Date: Sat, 28 Feb 2026 18:08:55 -0500 Subject: [PATCH] Update README with full API reference and CLI docs Co-Authored-By: Claude Opus 4.6 --- README.md | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 186 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 9640eca..ab9ef5e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Elydora Python SDK -Python SDK for the Elydora tamper-evident audit platform. +Official Python SDK for the [Elydora](https://elydora.com) tamper-evident audit platform. Build cryptographically verifiable audit trails for AI agent operations. ## Installation @@ -8,48 +8,219 @@ Python SDK for the Elydora tamper-evident audit platform. pip install elydora ``` +Requires Python 3.9+. + ## Quick Start ```python from elydora import ElydoraClient +# Authenticate +auth = ElydoraClient.login("https://api.elydora.com", "user@example.com", "password") + +# Create client client = ElydoraClient( - org_id="org_...", - agent_id="agent_...", + org_id=auth["user"]["org_id"], + agent_id="my-agent-id", private_key="", base_url="https://api.elydora.com", - token="", + token=auth["token"], ) # Create and submit an operation eor = client.create_operation( operation_type="data.access", - subject={"user_id": "u123"}, - action={"type": "read", "resource": "documents"}, - payload={"document_id": "doc_456"}, + subject={"user_id": "u-123", "resource": "patient-record"}, + action={"type": "read", "scope": "full"}, + payload={"record_id": "rec-456"}, ) response = client.submit_operation(eor) -print(response["receipt"]["receipt_id"]) +print("Receipt:", response["receipt"]["receipt_id"]) ``` -## Async Usage +## Async Support ```python from elydora import AsyncElydoraClient async def main(): client = AsyncElydoraClient( - org_id="org_...", - agent_id="agent_...", + org_id="org-123", + agent_id="agent-456", private_key="", - base_url="https://api.elydora.com", token="", ) + eor = client.create_operation( - operation_type="data.access", - subject={"user_id": "u123"}, - action={"type": "read", "resource": "documents"}, + operation_type="inference", + subject={"model": "gpt-4"}, + action={"type": "completion"}, ) response = await client.submit_operation(eor) await client.close() ``` + +## CLI + +The SDK includes a CLI for installing audit hooks into AI coding agents. + +```bash +elydora install \ + --agent claudecode \ + --org_id org-123 \ + --agent_id agent-456 \ + --private_key \ + --kid agent-456-key-v1 +``` + +### Commands + +| Command | Description | +|---------|-------------| +| `elydora install` | Install Elydora audit hook for a coding agent | +| `elydora uninstall` | Remove Elydora audit hook for a coding agent | +| `elydora status` | Show installation status for all agents | +| `elydora agents` | List supported coding agents | + +### Supported Agents + +| Agent | Key | +|-------|-----| +| Claude Code | `claudecode` | +| Cursor | `cursor` | +| Gemini CLI | `gemini` | +| Augment Code | `augment` | +| Kiro | `kiro` | +| OpenCode | `opencode` | + +## API Reference + +### Configuration + +```python +client = ElydoraClient( + org_id="org-123", # Organization ID + agent_id="agent-456", # Agent ID + private_key="", # Base64url-encoded Ed25519 seed + base_url="https://...", # API base URL (default: https://api.elydora.com) + ttl_ms=30000, # Operation TTL in ms (default: 30000) + max_retries=3, # Max retries on transient failures (default: 3) + token="", # Optional JWT bearer token +) +``` + +### Authentication + +```python +# Register a new user and organization +reg = ElydoraClient.register(base_url, email, password, display_name=None, org_name=None) + +# Login and receive a JWT +auth = ElydoraClient.login(base_url, email, password) +``` + +### Operations + +```python +# Create a signed EOR locally (no network call) +eor = client.create_operation( + operation_type="inference", + subject={"model": "gpt-4"}, + action={"type": "completion"}, + payload={"prompt": "Hello"}, +) + +# Submit to API +response = client.submit_operation(eor) + +# Retrieve an operation +op = client.get_operation(operation_id) + +# Verify integrity +result = client.verify_operation(operation_id) +``` + +### Agent Management + +```python +# Register a new agent +agent = client.register_agent({ + "agent_id": "my-agent", + "display_name": "My Agent", + "responsible_entity": "team@example.com", + "keys": [{"kid": "key-v1", "public_key": "", "algorithm": "ed25519"}], +}) + +# Get agent details +details = client.get_agent(agent_id) + +# Freeze an agent +client.freeze_agent(agent_id, reason="security review") + +# Revoke a key +client.revoke_key(agent_id, kid, reason="key rotation") +``` + +### Audit + +```python +import time + +results = client.query_audit( + agent_id="agent-123", + operation_type="inference", + start_time=int(time.time() * 1000) - 86400000, + end_time=int(time.time() * 1000), + limit=50, +) +``` + +### Epochs + +```python +epochs = client.list_epochs() +epoch = client.get_epoch(epoch_id) +``` + +### Exports + +```python +export = client.create_export( + start_time=start, + end_time=end, + format="json", +) + +exports = client.list_exports() +detail = client.get_export(export_id) +``` + +### JWKS + +```python +jwks = client.get_jwks() +``` + +## Error Handling + +```python +from elydora import ElydoraError + +try: + client.submit_operation(eor) +except ElydoraError as e: + print(e.code) # e.g. "INVALID_SIGNATURE" + print(e.message) # Human-readable message + print(e.status_code) # HTTP status code + print(e.request_id) # Request ID for support +``` + +## Dependencies + +- [requests](https://pypi.org/project/requests/) - Sync HTTP client +- [aiohttp](https://pypi.org/project/aiohttp/) - Async HTTP client +- [cryptography](https://pypi.org/project/cryptography/) - Ed25519 signing + +## License + +MIT