Metadata-Version: 2.4
Name: eve-proof
Version: 0.2.1
Summary: EVE Proof SDK — Issue and verify Governed Decision Certificates
Project-URL: Homepage, https://eveaicore.com
Project-URL: Documentation, https://docs.eveaicore.com/proof
Author: EVE NeuroSystems LLC
License-Expression: LicenseRef-Proprietary
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Legal Industry
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
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: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.9
Provides-Extra: async
Requires-Dist: aiohttp>=3.8; extra == 'async'
Provides-Extra: test
Requires-Dist: cryptography>=41; extra == 'test'
Requires-Dist: pytest-cov>=4; extra == 'test'
Requires-Dist: pytest>=7; extra == 'test'
Provides-Extra: verify
Requires-Dist: cryptography>=41; extra == 'verify'
Description-Content-Type: text/markdown

# EVE Proof SDK

**eve-proof** issues and verifies Governed Decision Certificates — signed, auditable
records that prove a decision passed through (or was blocked by) EVE's governance
pipeline. The backend emits **v2** (HMAC-SHA256) and **v3** (Ed25519) certificates.

Every certificate is a tamper-evident receipt your audit team can verify **offline** with
`verify_certificate()` — recompute the content hash and check the signature locally, with
no call back to EVE. A **v3 (Ed25519)** certificate is independently verifiable with only
the published public key (no shared secret, cannot be forged); a **v2 (HMAC)** certificate
is symmetric and requires the shared signing key.

---

## Install

```bash
pip install eve-proof
```

No required runtime dependencies. Uses Python stdlib (`urllib`) only.
Optional async support via `aiohttp`:

```bash
pip install "eve-proof[async]"
```

---

## Quickstart

```python
from eve_proof import ProofClient

client = ProofClient(api_key="eve_sk_...")

# 1. Issue a signed certificate for a decision
cert = client.issue(
    decision_input={"action": "approve_wire_transfer", "amount": 125_000}
)
print(cert.certificate_id)     # cert_abc123
print(cert.decision)           # "allow" / "deny"
print(cert.schema_version)     # "2.0" (HMAC) or "3.0" (Ed25519)

# 2. Verify it INDEPENDENTLY, OFFLINE — recompute the content hash and check the
#    signature locally. No server call. For a v3 (Ed25519) cert you need only the
#    published public key (no shared secret); for a v2 (HMAC) cert, the shared key.
from eve_proof import verify_certificate

v = verify_certificate(cert, public_key_hex=PUBLIC_KEY_HEX)   # v3 / Ed25519
# v = verify_certificate(cert, signing_key=SHARED_KEY)        # v2 / HMAC
print(v.valid)                       # True
print(v.independently_verifiable)    # True for v3 (Ed25519), False for v2 (HMAC)
print(v.checks)                      # ['content_hash: OK', 'ed25519_signature: OK']

# 3. (Optional) Re-verify via the server instead of locally
result = client.verify(cert)         # convenience round-trip to EVE
print(result.valid)                  # True

# 4. Retrieve a stored certificate by ID (e.g., from an audit log)
same_cert = client.get(cert.certificate_id)
```

> `verify_certificate(...)` is the **offline** check (the reason `eve-proof` exists):
> it never calls EVE. `client.verify(...)` is a convenience that asks the server.

---

## Why Proof vs EVE CoreGuard

| Capability | eve-coreguard | eve-proof |
|---|---|---|
| Primary purpose | Block harmful AI outputs at the gate | Witness and certify decisions for audit |
| Primary buyer | AI/ML engineering teams | Compliance, audit, legal |
| Returns | Enforcement decision (ALLOWED / BLOCKED) | Signed certificate + verification result |
| Verification | Server-side, synchronous | Independent, offline-capable |
| Key question answered | "Should this AI output be allowed?" | "Can we prove what the AI decided?" |

Use **EVE CoreGuard** when you need to gate AI output before it reaches users.
Use **Proof** when regulators, auditors, or internal compliance teams need
verifiable records of what the AI decided and why.

---

## Certificate anatomy (schema v2 / v3)

The decision-critical fields live inside `signed_claims` — that object is what the
`content_hash` covers and what the signature protects. A v3 certificate is dual-signed
(Ed25519 **and** HMAC); a v2 certificate carries the HMAC signature only.

```json
{
  "certificate_id":      "cert_a1b2c3d4",
  "certificate_type":    "Governed Decision Certificate",
  "schema_version":      "3.0",
  "certificate_version": "v3",
  "decision":            "deny",
  "signed_claims": {
    "decision":   "deny",
    "policy_set": "lending_v1",
    "enforcement_detail": {
      "matched_vector": "v421",
      "pattern":        "airgap_ghost",
      "verdict":        "deny",
      "severity":       "critical",
      "payload_hash":   "sha256:deadbeef..."
    }
  },
  "content_hash":      "9f1c…",
  "ed25519_signature": "BASE64…",
  "key_id":            "ed25519:EtPSNZIdhxA3NATs",
  "signature":         "a1b2c3…",
  "signing_algorithm": "Ed25519",
  "issued_at":         "2026-06-18T12:00:00Z"
}
```

Fields:

| Field | Type | Description |
|---|---|---|
| `certificate_id` | string | Globally unique certificate identifier |
| `certificate_type` | string | e.g. `"Governed Decision Certificate"` |
| `schema_version` | string | `"2.0"` (HMAC) or `"3.0"` (Ed25519 + HMAC) |
| `certificate_version` | string | `"v2"` / `"v3"` marker (when present) |
| `decision` | string | Final governance verdict (e.g. `"allow"`, `"deny"`) — mirrored from `signed_claims` |
| `signed_claims` | object | The signed decision body the `content_hash` covers (verdict, policy, `enforcement_detail`, …) |
| `content_hash` | string | SHA-256 over `canonical(signed_claims)` — recompute offline with `recompute_content_hash()` |
| `ed25519_signature` | string | Base64 Ed25519 signature (v3 only; `""` for v2) |
| `key_id` | string | Published key id for the Ed25519 signature (v3 only) |
| `signature` | string | HMAC-SHA256 hex over the content hash (v2, and also on v3) |
| `signing_algorithm` | string | `"HMAC-SHA256"` (v2) or `"Ed25519"` (v3) |
| `issued_at` | string | ISO 8601 timestamp of issuance |

`enforcement_detail` is read from `signed_claims`; it may be `null` on a clean `allow`.

---

## Verifying a certificate from a file (offline, no account)

An auditor who has received a certificate as JSON can verify it with **no EVE
account, no API key, and no network call** — just the published public key (v3)
or the shared signing key (v2):

```python
import json
from eve_proof import Certificate, verify_certificate

# Load the certificate from an audit log or file
with open("cert_a1b2c3d4.json") as f:
    cert = Certificate.from_dict(json.load(f))

# v3 (Ed25519): independently verifiable with only the published public key.
v = verify_certificate(cert, public_key_hex=PUBLIC_KEY_HEX)

# v2 (HMAC): symmetric — pass the shared signing key instead.
# v = verify_certificate(cert, signing_key=SHARED_KEY)

print(f"Valid: {v.valid}  ({v.algorithm}, independent={v.independently_verifiable})")
for check in v.checks:
    print(f"  {check}")
if not v.valid:
    print(f"REJECTED: {v.reason}")   # never raises — tamper/wrong-key -> valid=False
```

`verify_certificate()` recomputes the `content_hash` from the certificate's own
`signed_claims` and checks the signature locally. Mutating any field of
`signed_claims` (or the stored hash/signature) makes verification fail. It never
raises — a tampered or unverifiable certificate returns `valid=False` with a reason.
The Ed25519 public key is published by your EVE deployment (raw hex); `cryptography`
is required for v3 (`pip install "eve-proof[verify]"`).

---

## Environment variables

| Variable | Required | Default | Description |
|---|---|---|---|
| `EVE_PROOF_API_KEY` | Yes (for CLI) | — | Your EVE API key |
| `EVE_PROOF_BASE_URL` | No | `https://api.eveaicore.com` | API base URL; use `http://localhost:8079` for local dev |

The SDK constructor accepts `api_key` and `base_url` directly.
Environment variables are only consumed by the CLI entry point (`eve-proof-demo`)
and the example script.

---

## Error types

| Exception | When raised |
|---|---|
| `ProofError` | Base exception; also raised for auth failures (401/403), rate limits (429), and malformed requests (4xx) |
| `CertificateInvalidError` | `verify()` with `raise_on_invalid=True` and server reports invalid signature/chain |
| `CertificateNotFoundError` | `get()` when no certificate with that ID exists (HTTP 404) |
| `TransportError` | Network failure or unrecoverable 5xx after all retries exhausted |

All exceptions expose `status_code: int` (0 for non-HTTP failures).
`CertificateInvalidError` adds `reason: str`.
`CertificateNotFoundError` adds `certificate_id: str`.

```python
from eve_proof import ProofClient, CertificateNotFoundError, ProofError

client = ProofClient(api_key="eve_sk_...")

try:
    cert = client.get("cert_does_not_exist")
except CertificateNotFoundError as exc:
    print(f"Not found: {exc.certificate_id}")
except ProofError as exc:
    print(f"API error {exc.status_code}: {exc}")
```

---

## Zero runtime dependencies

`eve-proof` uses only Python stdlib (`urllib.request`, `json`, `dataclasses`,
`uuid`, `datetime`). No `requests`, `httpx`, or `pydantic` required.

Optional `aiohttp` support is available for async usage in future SDK releases.

---

## ProofClient reference

```python
class ProofClient:
    def __init__(
        self,
        api_key: str,
        base_url: str = "https://api.eveaicore.com",
        timeout: float = 30.0,
        max_retries: int = 3,
        raise_on_invalid: bool = False,
    ): ...

    def issue(
        self,
        *,
        decision_input: dict,
        policy_set: str | None = None,
        tenant_id: str | None = None,
        idempotency_key: str | None = None,
    ) -> Certificate: ...

    def verify(
        self,
        certificate: Certificate | dict,
    ) -> VerificationResult: ...

    def get(self, certificate_id: str) -> Certificate: ...

    def issue_and_verify(
        self,
        *,
        decision_input: dict,
        policy_set: str | None = None,
        tenant_id: str | None = None,
    ) -> tuple[Certificate, VerificationResult]: ...
```

The `Transport` layer retries 5xx responses with exponential backoff
(base 0.5 s, doubling per attempt). 4xx responses are never retried.

---

## CLI smoke test

```bash
export EVE_PROOF_API_KEY=eve_sk_...
export EVE_PROOF_BASE_URL=http://localhost:8079   # local dev

eve-proof-demo
```

Outputs the certificate ID, decision, enforcement detail (if any), and
per-check verification results.

---

## Support

- Documentation: https://docs.eveaicore.com/proof
- Homepage: https://eveaicore.com
