Metadata-Version: 2.4
Name: foxy-audit
Version: 1.0.0
Summary: Governance-as-Code SDK for AI compliance: local SHA-256 hashing + tamper-evident audit telemetry, with zero raw-text exfiltration.
Project-URL: Homepage, https://foxyaudit.tech
Project-URL: Documentation, https://foxyaudit.tech/docs.html
Project-URL: Source, https://github.com/fatimaatta-09/Foxy-Audit
Project-URL: Issues, https://github.com/fatimaatta-09/Foxy-Audit/issues
Author: Foxy Audit
License: MIT
Keywords: ai,audit,compliance,eu-ai-act,governance,hipaa,soc2
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
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 :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: requests<3,>=2.31
Provides-Extra: pii
Requires-Dist: presidio-analyzer>=2.2; extra == 'pii'
Requires-Dist: spacy>=3.7; extra == 'pii'
Provides-Extra: test
Requires-Dist: httpx>=0.27; extra == 'test'
Requires-Dist: pytest>=8; extra == 'test'
Description-Content-Type: text/markdown

# foxy-audit (SDK)

> Governance-as-Code for AI. One decorator → a tamper-evident, privacy-preserving audit trail.

The SDK hashes your LLM prompt + response **locally** (SHA-256), throws the raw text away, and
streams only metadata to the Foxy Audit backend. It also fires a best-effort local UDP ping so the
desktop "fox" companion reacts in real time (green on every logged call, red on a policy breach).

## Install

```bash
pip install -e .            # from this sdk/ folder, for local development
```

Runtime dependency: `requests` only.

## Use

```python
import os
from foxy_audit import FoxyClient

foxy = FoxyClient(api_key=os.getenv("FOXY_API_KEY"))   # or just rely on the env var

@foxy.audit(policy="hipaa_basic")
def ask_model(prompt: str) -> str:
    return llm_client.generate(prompt)     # your existing code — unchanged
```

Every call to `ask_model` is now hashed, logged, and graded. Or use the module-level decorator,
which builds a client from the environment:

```python
from foxy_audit import audit

@audit(policy="soc2")
def summarize(text: str) -> str:
    ...
```

### Attributing the model (`agent`)

Pass `agent=` to record *which* model produced the interaction. The backend folds it into the
tamper-evident hash chain, so the attribution can't be altered after the fact:

```python
@foxy.audit(policy="soc2", agent="gpt-4o")
def ask_model(prompt: str) -> str:
    ...
```

`agent` is optional — rows logged without it hash exactly as before, so existing chains keep
verifying.

## Configuration

| Setting        | Kwarg          | Env var             | Default                  |
|----------------|----------------|---------------------|--------------------------|
| API key        | `api_key`      | `FOXY_API_KEY`      | _(none → HTTP disabled)_ |
| Backend URL    | `endpoint`     | `FOXY_BACKEND_URL`  | `http://127.0.0.1:8000`  |
| Desktop ping   | `desktop_ping` | —                   | `True` (127.0.0.1:9999)  |

With no API key the SDK is a **graceful no-op for the cloud path**: it still runs your function and
still pings the desktop fox, but skips the HTTP upload — so you can see the fox react before any
backend exists.

## Guarantees

- **Never blocks** your function — the HTTP upload runs on a background daemon thread.
- **Never raises** its own errors into your app — all telemetry failures are swallowed.
- **Never sees raw text** server-side — only SHA-256 digests + token count + policy tag leave the host.
- Works with both **sync and async** functions; the return value is always passed through unchanged.

## What gets sent

To the backend (`POST /v1/logs`, `Authorization: Bearer <key>`):

```json
{"prompt_hash": "<64 hex>", "response_hash": "<64 hex>", "token_count": 123, "policy_tag": "hipaa_basic"}
```

To the desktop fox (UDP `127.0.0.1:9999`):

```json
{"event": "hash_ok", "policy": "hipaa_basic", "tokens": 123, "ts": 1719300000}
{"event": "policy_breach", "reason": "...", "risk_score": 87, "policy": "hipaa_basic", "ts": ...}
```
