Metadata-Version: 2.4
Name: gtv
Version: 2.3.4
Summary: Ground Truth Verification System — federated fact verifier for LLM agents
Author: Ground Truth contributors
License: Apache-2.0
License-File: LICENSE
License-File: LICENSE.commercial
License-File: NOTICE
Keywords: llm,mcp,rekor,rfc3161,sigstore,verification
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.12
Requires-Dist: asyncpg>=0.29
Requires-Dist: defusedxml>=0.7.1
Requires-Dist: fastapi>=0.115
Requires-Dist: httpx>=0.27
Requires-Dist: mcp>=0.1.0
Requires-Dist: opentelemetry-api>=1.41.0
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.41.0
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.62b0
Requires-Dist: opentelemetry-sdk>=1.41.0
Requires-Dist: prometheus-client>=0.25.0
Requires-Dist: pydantic>=2.8
Requires-Dist: pylatexenc>=2.10
Requires-Dist: python-dateutil>=2.9
Requires-Dist: pyyaml>=6.0
Requires-Dist: redis>=5.0
Requires-Dist: rfc3161-client>=0.0.5
Requires-Dist: sigstore>=3.0
Requires-Dist: structlog>=24.1
Requires-Dist: tomli-w>=1.0
Requires-Dist: uvicorn[standard]>=0.30
Provides-Extra: dev
Requires-Dist: hypothesis>=6.110; extra == 'dev'
Requires-Dist: ipykernel>=6.29; extra == 'dev'
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: nbclient>=0.10; extra == 'dev'
Requires-Dist: nbformat>=5.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: types-defusedxml; extra == 'dev'
Requires-Dist: types-python-dateutil; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: pymdown-extensions>=10.0; extra == 'docs'
Provides-Extra: s3
Requires-Dist: boto3>=1.26; extra == 's3'
Description-Content-Type: text/markdown

# Ground Truth Verification System (gtv)

A federated, open-source fact verifier that AI agents call as an MCP tool. Every response is evidence-backed, signed, and anchored in public transparency logs.

**See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for system design, threat model, and implementation details.**

## Status

**Phase 1 complete — v0.1.0 pilot release.**

- 757 tests passing, 20 skipped (live/opt-in), 0 failing.
- 73 source files, ruff + mypy-strict clean.
- 8 evidence adapters: arXiv, INSPIRE-HEP, Crossref, OpenAlex, Semantic Scholar, PubMed, NIST, Retraction Watch.
- 9 CLIs shipped (see below). Distroless Docker image published to `ghcr.io/groundtruth/gtv`, multi-arch, Cosign-signed.
- DID resolution: `did:web` + `did:key` (Ed25519, P-256, secp256k1).
- Federation: persistent SQLite trust registry with signed update log; tier-weighted consensus across independent verifiers.
- Revocation: signed revocation lists, 410 Gone enforcement.
- Audit: hash-chained, Ed25519-signed append-only log of admin actions.

See [`CHANGELOG.md`](CHANGELOG.md) for the full v0.1.0 changelog.

## What It Does

```
Claim: "The Higgs boson has a mass of 125 GeV."
       ↓
verdict: VERIFIED
confidence: 0.87
evidence: [3 peer-reviewed sources from Crossref + arXiv + INSPIRE-HEP]
signature: ECDSA-P256 (Sigstore keyless)
rekor_uuid: 24c05a...  (transparency log entry)
tsa_token: [RFC 3161 timestamp, primary + secondary]
prov_graph: [PROV-O JSON-LD trace: sources → evidence → verdict]
```

Every response is a sealed `Envelope`: signed over a canonical JSON form (RFC 8785), inclusion-proved in Rekor, and timestamped by two redundant RFC 3161 TSAs.

## Install

Requires Python 3.12+.

```bash
# Once v0.1.0 lands on PyPI:
pip install gtv

# Development install (editable + dev extras):
pip install -e '.[dev]'
# or: uv sync
```

Or run the prebuilt distroless image:

```bash
docker pull ghcr.io/groundtruth/gtv:v0.1.0
docker run --rm -p 8080:8080 ghcr.io/groundtruth/gtv:v0.1.0
```

See [`pyproject.toml`](pyproject.toml) for full dependency list and
[`CHANGELOG.md`](CHANGELOG.md) for release notes.

## Try it in 30 seconds

No server setup, no OIDC, no config:

```bash
pip install -e .
gtv-demo "The Higgs boson mass is 125 GeV"
```

Output:

```
Subclaim 1:
  The Higgs boson mass is 125 GeV

  Verdict: VERIFIED (87%)

  Evidence:
    - did:web:arxiv.org
      Stance: SUPPORTS
      URL: https://arxiv.org/abs/hep-ex/0302009
      Discovery of a Higgs boson candidate by the ATLAS collaboration...

    - did:web:inspire-hep
      Stance: SUPPORTS
      URL: https://inspirehep.net/record/1234567
      The Higgs boson: precision measurements from LHC...
```

For offline testing (no network):

```bash
gtv-demo --offline "The speed of light is 299792458 m/s"
gtv-demo --json "Einstein's E=mc²"  # Machine-readable output
```

## Deploy a pilot (15 minutes)

For a commercial pilot, deploy gtv as a containerized service. No manual infrastructure setup required.

**Prerequisites:** Docker + Docker Compose (v2+).

```bash
git clone <repo>
cd gtv
cp .env.example .env
docker compose up -d
curl http://localhost:8080/health
```

That's it. The service is ready on port 8080. HTTP API, Prometheus metrics, and healthcheck are all live.

For federation setup, issuer DID, Sigstore keyless signing, RFC 3161 timestamping, and observability details, see [`docs/pilot-onboarding.md`](docs/pilot-onboarding.md).

## Quick Start

### HTTP API (FastAPI)

```bash
uvicorn gtv.mcp.server:app --reload --port 8080
```

POST to `/tools/verify_claim`:

```bash
curl -X POST http://localhost:8080/tools/verify_claim \
  -H 'Content-Type: application/json' \
  -d '{
    "claim": "E=mc^2",
    "domain": "physics",
    "max_sources": 5
  }' | jq .envelope
```

Response shape:
```json
{
  "envelope": {
    "verdict": "VERIFIED",
    "confidence": 0.87,
    "evidence": [
      {
        "source_did": "did:web:arxiv.org",
        "excerpt": "...",
        "stance": "SUPPORTS",
        "url": "https://...",
        "retrieved_at": "2026-04-21T..."
      }
    ],
    "signature": "<base64>",
    "rekor_uuid": "...",
    "rekor_log_index": 12345,
    "tsa_token": "<base64>",
    "anchor_proof": {
      "rekor_inclusion_proof": "{\"log_index\": 12345, ...}",
      "tsa_tsr_primary": "<base64>",
      "tsa_tsr_secondary": "<base64>"
    },
    "prov_graph": "<PROV-O JSON-LD>"
  }
}
```

### MCP over stdio

```bash
# List available tools
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | gtv-mcp

# Call verify_claim
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"verify_claim","arguments":{"claim":"Is water H2O?"}}}' | gtv-mcp
```

The `gtv-mcp` binary wraps the HTTP server logic over the MCP JSON-RPC protocol (via the official `mcp` SDK).

### CLI Verifier (Offline)

Save an envelope to `envelope.json`, then verify offline:

```bash
# Verify with all checks (except --allow-stub / --allow-unrooted flags)
gtv-verify envelope.json

# Allow stub signatures (development/testing)
gtv-verify --allow-stub envelope.json

# Trust the issuer without resolving its DID
gtv-verify --trust-issuer envelope.json

# Skip Rekor log-root trust check
gtv-verify --allow-unrooted envelope.json
```

Exit codes:

| Code | Meaning |
|------|---------|
| 0 | Envelope fully verified |
| 2 | Stub signature/proof detected (not cryptographically verifiable) |
| 3 | Signature verification failed |
| 4 | Rekor inclusion proof mismatch |
| 5 | Schema/JSON parse error |
| 6 | Rekor log-root key not trusted |
| 7 | Issuer identity verification failed |
| 64 | Usage error (e.g., missing envelope path) |

## Verdict Classes

- **VERIFIED**: Evidence from one or more sources supports the claim.
- **UNVERIFIED**: No evidence found supporting or refuting the claim.
- **CONTESTED**: Evidence both supports and refutes; magnitude differs.
- **OPINION**: Claim is subjective/normative; no factual verification performed.
- **CREATIVE**: Claim requests fictional or imaginative content.
- **OUT_OF_SCOPE**: Domain or content type outside this system's scope.

## Registered Adapters

All adapters are federated sources (we do not fabricate evidence). Each is assigned a trust tier.

| Adapter | Source | Type | Tier |
|---------|--------|------|------|
| arXiv | arXiv preprints | PREPRINT | TIER_2 |
| INSPIRE-HEP | High-energy physics papers | PEER_REVIEWED | TIER_1 |
| Crossref | Peer-reviewed metadata | PEER_REVIEWED | TIER_1 |
| OpenAlex | Multidisciplinary research | PEER_REVIEWED | TIER_2 |
| Semantic Scholar | Computer science / NLP | PEER_REVIEWED | TIER_2 |

Adapters fail loudly: on timeout or network error, they return an empty list (not fabricated results). The verdict engine handles missing evidence gracefully.

## Trust Model

An envelope is trustworthy if:

1. **Hash integrity**: The canonical JSON hash (RFC 8785) matches the signed-over payload.
2. **Signature**: ECDSA-P256 signature verifies against the canonical hash using the issuer's Sigstore certificate.
3. **Transparency**: The signature is included in the public Rekor transparency log (RFC 6962 merkle tree proof).
4. **Time-stamping**: At least one RFC 3161 TSR (primary or secondary) verifies over the canonical hash.
5. **Issuer identity**: The certificate's identity (email/OIDC issuer) matches the issuer DID's DID document (federation registry lookup optional).

Evidence inside the envelope is not signed individually; only the summary and verdicts are signed. Verifiers must audit the evidence chain themselves.

## Federation Registry

When offline-verifying an envelope, the CLI checks that the issuer's DID is in the trusted registry. The registry is a JSON file:

```json
[
  {
    "did": "did:web:verify.groundtruth.example",
    "trust_tier": "TIER_1",
    "display_name": "Ground Truth Pilot",
    "expected_fulcio_oidc": "https://token.actions.githubusercontent.com",
    "expected_issuer_email": "github-actions@github.com",
    "notes": "GitHub Actions–based verifier."
  }
]
```

Set `GTV_FEDERATION_REGISTRY=/path/to/registry.json` to load on startup. If unset, falls back to a minimal default registry.

## Configuration

| Env Var | Default | Purpose |
|---------|---------|---------|
| `GTV_ISSUER_DID` | `did:web:verify.groundtruth.example` | This issuer's DID (used in signatures) |
| `GTV_SIGSTORE_ENABLED` | (unset) | Enable real Sigstore keyless signing; otherwise emit stub signatures |
| `GTV_TSA_ENABLED` | (unset) | Enable real RFC 3161 timestamping; otherwise stub tokens |
| `GTV_REKOR_URL` | `https://rekor.sigstore.dev` | Rekor server URL (prod) |
| `GTV_TSA_PRIMARY_URL` | `https://freetsa.org/tsr` | Primary TSA |
| `GTV_TSA_SECONDARY_URL` | `http://timestamp.digicert.com` | Secondary TSA (best-effort) |
| `GTV_FEDERATION_REGISTRY` | (unset) | Path to issuer registry JSON |
| `GTV_DISABLE_DEFAULT_ADAPTERS` | (unset) | If set, skip loading built-in adapters |

## Observability

All request paths record Prometheus metrics:
- `gtv_verdict_total` (counter): verdicts by class and confidence band.
- `gtv_adapter_call_duration_seconds` (histogram): per-adapter latency.
- `gtv_adapter_call_status_total` (counter): per-adapter success/timeout/error counts.

OpenTelemetry tracing is wired via the `opentelemetry-instrumentation-fastapi` package. Set `OTEL_EXPORTER_OTLP_ENDPOINT` to export.

## Testing

```bash
pytest -q                    # Default (stubs only)
GTV_LIVE=1 pytest            # Hit live adapters (network required)
GTV_SIGSTORE_ENABLED=1 pytest # Real Sigstore signing
GTV_TSA_ENABLED=1 pytest     # Real RFC 3161 timestamps
GTV_E2E_LIVE=1 pytest        # Full end-to-end with all services
```

CI runs all tiers nightly (see `.github/workflows/`).

## Design Principles

1. **Federate, don't invent.** We aggregate from trusted public sources; we never fabricate evidence.
2. **Standards only.** W3C VC 2.0, DIDs 1.0, PROV-O, Sigstore, RFC 3161, MCP. No proprietary formats.
3. **No blockchain.** No cryptocurrency. No token. No consensus layer.
4. **Evidence first.** If sources conflict, mark CONTESTED, not VERIFIED. Never suppress evidence.
5. **Fail loudly.** A missing Rekor key, a timeout TSA, a DID that won't resolve — all logged, not swallowed.

## Layout

```
src/gtv/
  mcp/         — FastAPI + MCP stdio server
  adapters/    — five federated source modules
  verdict/     — deterministic rule-based engine
  anchor/      — canonical JSON, Sigstore, Rekor, RFC 3161
  federation/  — issuer registry + DID resolution
  models.py    — Pydantic schemas (Claim, Evidence, Envelope, ...)
  obs/         — Prometheus + OpenTelemetry
cli/
  verify.py    — offline envelope verifier (< 300 LOC)
.github/workflows/
  ci.yml       — every PR: ruff, mypy, pytest
  nightly.yml  — all test tiers (adapters, Sigstore, TSA, E2E)
  docker.yml   — build, scan, sign image (on tag)
spec/schemas/  — JSON Schema for Envelope (CC0)
tests/         — pytest suite with fixtures
docs/          — architecture, ADRs, build spec
```

## License

Apache License 2.0. No CLA. All work is federated and open-source.
