Attest402
by paulos-sudo
README.md
# Attest402
**Cryptographically signed and timestamped evidence of a public web or API response.**
Agent-native, paid per call via [x402](https://x402.org) — 0.20 USDC on Base. No accounts, no API keys.
An agent submits a public HTTPS URL → Attest402 fetches it securely, hashes body/headers/redirects,
signs the canonical record with Ed25519, anchors it with an independent RFC-3161 timestamp and
returns a **portable evidence package** that verifies fully offline.
> The evidence confirms the integrity of the captured data and Attest402's observation at the
> stated time. It does not certify the truth, legality or authorship of the captured content.
## Quickstart (local)
```bash
pip install -r requirements.txt
cp .env.example .env # defaults: dev mode, Base Sepolia
uvicorn app.main:app --reload
# → http://localhost:8000 (landing page, /openapi.json, /llms.txt)
```
Disable the paywall for local experiments with `X402_ENABLED=false`.
## API
| Endpoint | Method | Price | Function |
|---|---|---:|---|
| `/v1/attest` | POST | 0.20 USDC | Create an evidence package |
| `/v1/verify` | POST | free | Verify attestation (+ optional body) |
| `/v1/verify/{id}` | GET | free | Attestation metadata (90 d retention) |
| `/v1/evidence/{id}` | GET | free | Download evidence package (24 h retention) |
| `/.well-known/attest-keys.json` | GET | free | Ed25519 public keys (old keys permanent) |
| `/.well-known/x402.json` | GET | free | x402 discovery manifest |
| `/llms.txt` | GET | free | Agent-readable description |
| `/health` | GET | free | Healthcheck |
## Architecture
```
app/
main.py FastAPI app, routes, retention loop
payments.py x402 middleware (exact/USDC/Base) + Bazaar discovery extension
fetcher.py SSRF-hardened fetcher (DNS-pinned, 2 MB cap, 3 redirects, 10 s)
ssrf.py URL/DNS/IP policy (blocks private, loopback, metadata, rebinding)
attest.py Pipeline: fetch → canonical record → sign → RFC-3161 → package
canonical.py Deterministic canonical JSON + SHA-256
signing.py Ed25519 key management (secret-store only, rotation-aware)
tsa.py RFC-3161 client (freetsa + DigiCert fallback)
evidence.py Evidence zip builder (offline-verifiable)
verify.py Verification logic (shared with /v1/verify)
mcp_server/ MCP server: attest_web_response / verify_attestation / get_attestation
scripts/ generate_keys.py · verify_offline.py (30-line standalone verifier)
docs/ DEPLOY.md · GO-LIVE-CHECKLIST.md · LISTINGS.md
listings/ Ready-to-submit listing materials (Bazaar, ecosystem PR, MCP registries)
```
## Payments (x402)
- Scheme `exact`, USDC, price `$0.20`, network Base Sepolia by default
- `X402_USE_MAINNET=true` flips to Base mainnet (feature flag, no code change)
- Settlement only after a successful capture — failed fetches are never charged
- `Idempotency-Key` header dedupes retried jobs
- Bazaar discovery metadata is declared on the paid route → automatic listing in the
x402 Bazaar after the first CDP-facilitator settlement on mainnet
## Verify an evidence package offline
```bash
python scripts/verify_offline.py attest_xxx-evidence.zip
```
Only needs `cryptography`. Checks canonical-record hash, Ed25519 signature,
body/headers/redirect hashes and the RFC-3161 token hash — no network access.
## Tests
```bash
python -m pytest tests/ -q # 45 tests: SSRF policy, canonical determinism,
# sign/verify roundtrips, API flow, idempotency
```
## Deploy
See [docs/DEPLOY.md](docs/DEPLOY.md) (Railway + Render, incl. mainnet switch and
key rotation) and [docs/GO-LIVE-CHECKLIST.md](docs/GO-LIVE-CHECKLIST.md).
Get listed: [docs/LISTINGS.md](docs/LISTINGS.md).
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues