Metadata-Version: 2.4
Name: vllm-openttt
Version: 0.1.0
Summary: TTTPS Proof-of-Time ASGI middleware for vLLM: cryptographic audit-trail timestamps for OpenAI-compatible completions via the public KPP Provenance API
License: MIT
Project-URL: Homepage, https://github.com/Helm-Protocol/OpenTTT
Project-URL: Repository, https://github.com/Helm-Protocol/OpenTTT
Project-URL: Issues, https://github.com/Helm-Protocol/OpenTTT/issues
Keywords: vllm,proof-of-time,provenance,temporal-attestation,audit-trail,llm-observability,asgi-middleware,opentelemetry
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT 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: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.24
Requires-Dist: starlette>=0.27

# vllm-openttt

TTTPS Proof-of-Time ASGI middleware for [vLLM](https://github.com/vllm-project/vllm).
Attaches a cryptographic audit-trail timestamp (a signed Proof-of-Time receipt) to
every non-streaming `/v1/chat/completions` and `/v1/completions` response served by
vLLM's OpenAI-compatible server, sealed against the public self-serve
[KPP Provenance API](https://kpp.kenosian.com).

This attaches a cryptographic audit-trail timestamp and integrity hash. It does
**not** certify legal or regulatory compliance (EU AI Act, FDA, and so on).
Treat it as an audit-trail timestamp, not a compliance claim.

## Install

```bash
pip install vllm-openttt
```

vLLM itself is not a dependency of this package. The middleware only needs the
ASGI contract, so it installs next to whatever vLLM version you already run.

## Usage

Mint a free key with `POST https://kpp.kenosian.com/v1/keys`, export it, and pass
the middleware to `vllm serve`:

```bash
export KPP_API_KEY=...

vllm serve Qwen/Qwen2.5-0.5B-Instruct \
    --middleware vllm_openttt.TTTPSMiddleware
```

vLLM imports the dotted path and, because it resolves to a class, registers it with
`app.add_middleware()`. Every sealed response then carries two extra headers:

```
X-TTTPS-Status: ok
X-TTTPS-Receipt: {"status":"ok","backend":"kpp","content_hash":"sha256:...",
                  "receipt_id":"...","receipt":"...","time":"...",
                  "time_source":"...","verify_url":"https://kpp.kenosian.com/v1/verify?receipt_id=...",
                  "overhead_ms":...}
```

Reading the receipt from a client:

```python
import json, requests

r = requests.post(
    "http://127.0.0.1:8000/v1/chat/completions",
    json={"model": "Qwen/Qwen2.5-0.5B-Instruct",
          "messages": [{"role": "user", "content": "hi"}]},
)
receipt = json.loads(r.headers["X-TTTPS-Receipt"])
print(receipt["receipt_id"], receipt["verify_url"])
```

A receipt can be re-checked at any time via `POST https://kpp.kenosian.com/v1/verify`
with `{"receipt_id": ...}`.

## Configuration

| Variable | Default | Meaning |
| --- | --- | --- |
| `KPP_API_KEY` | empty | Provenance key from `POST /v1/keys` |
| `KPP_BASE` | `https://kpp.kenosian.com` | Provenance API base URL |
| `TTTPS_TIMEOUT_S` | `1.0` | Fail-open deadline for the anchor call |
| `TTTPS_BACKEND` | `kpp` | `kpp`, or `openttt` for a self-hosted server |
| `TTTPS_POT_BASE` | empty | Base URL of your OpenTTT server, when `TTTPS_BACKEND=openttt` |
| `TTTPS_API_KEY` | empty | API key for that OpenTTT server |

### Self-hosted backend

Setting `TTTPS_BACKEND=openttt` mints receipts on your own
[OpenTTT](https://github.com/Helm-Protocol/OpenTTT) server instead of the public
API, which additionally chains each event into that server's hash chain and keeps
every anchor inside your own infrastructure.

## OpenTelemetry

If a request carries a W3C `traceparent` header, the trace and span ids are parsed
and echoed back in the receipt, so a trace and a receipt point at each other. On the
self-hosted backend the ids are also written into the signed Proof-of-Time hash
preimage and into the server's queryable event description.

`receipt_to_span_attributes()` maps a receipt onto span attribute names:

```python
from vllm_openttt import receipt_to_span_attributes

span.set_attributes(receipt_to_span_attributes(receipt))
# {"tttps.receipt_id": "...", "tttps.content_hash": "...", "tttps.trace_id": "...", ...}
```

Parsing prefers vLLM's own `vllm.tracing.extract_trace_context()` when running inside
a vLLM process, and falls back to a dependency-free W3C parser otherwise. No extra
dependency is added either way.

## Fail-open

A missing key, an unreachable or slow backend, a malformed `traceparent`, or any
unexpected error degrades the receipt to `{"status": "degraded", "reason": ...}`.
The response body, status code and media type are never altered, and no exception
ever escapes the middleware.

## Scope

Streaming responses (`stream: true`, server-sent events) are passed through
untouched. Sealing a live event stream needs a different approach and is not
attempted here.

## License

MIT
