[ Security · trust ]

No custody. No trust required.

PayGate402 doesn't hold your money. The escrow runs in attested code, every settlement event is signed by a publicly-verifiable key, and receipts are single-use replay-protected. Math, not trust.

Coordinator signing key (Ed25519)

Verify the audit chain yourself

Every audit event includes a base64url-encoded Ed25519 signature over the canonical event JSON. Pull the chain from /api/v1/transactions/<tx_id>/audit-chain and verify each signature against this key. Tampering with any event breaks the chain — visibly.

GET /api/v1/coordinator/pubkey
live
{ "algorithm": "ed25519", "public_key_hex": "loading…" }
Open raw response
TEE attestation example

What the escrow proves about itself

simulator-mode in dev · real Nitro in prod
{
  "mode": "simulated",
  "backend": "tee_simulator",
  "digest": "sha256:8e2c1d…",
  "issued_at": "2026-05-15T01:42:11Z",
  "key_id": "sim_8e2c1dba9f3c4517",
  "warning": "This is a SIMULATED TEE attestation.
              Production = AWS Nitro Enclaves."
}

Production swaps the simulator for a real Nitro enclave that produces a signed PCR + measurement document. Same interface, no coordinator code changes — the audit chain references the attestation by digest so old sealed events stay verifiable.

🔐TEE-backed escrow

Funds are held by attested code (AWS Nitro Enclaves in production, simulator in dev). Neither agent nor provider can rug — the math is the third party.

📜Ed25519 audit chain

Every receipt → hold → release → settlement event is signed by the coordinator key. Anyone with a tx_id can independently verify the chain.

🔑Zero custody

We don't custody agent funds and we don't custody provider payouts. Coordinator is a verifier + escrow operator, not a wallet.

🛡️Replay-safe receipts

60-second TTL, single-use consume on verify. Every receipt has a fresh nonce. Replayed receipts return HTTP 410 + audit-logged.

Compliance posture

SOC 2 Type II + PCI-DSS evidence packs ship on Scale tier. Custom data residency + dedicated TEE enclaves available.

🔏Signed webhooks

Outbound provider webhooks are HMAC-SHA256 signed. Replay-protected with timestamp window. Forensic-grade per-event audit trail.

SOC 2 Type IIScale tier · external audit on request
PCI-DSS evidence packScale tier · NDA required
1-year audit retentionGrowth + Scale tiers · CSV/JSON export
Custom data residencyScale tier · choose region

What's deterministic. What's an LLM.

Anywhere money moves is math and cryptography — not a model guessing. LLMs sit at the edges (advisory, UX). The rail is auditable and replayable line-by-line.

🔒 Deterministic

The rail itself

  • Ed25519-signed receipts — public key on /security; verify in your browser
  • Hash-chained audit log — every event has prior_event_id + signature
  • Hard caps — $0.05/tx, $1/run; refused at the gate before any rail call
  • Spend grants — per-merchant / per-route caps, pure if/then
  • Counter-offer band — accept ≥ floor, reject < floor; no LLM "judges" the price
  • Idempotency-Key — same key + body → cached response; replay-safe
  • Receipt single-use — 60s TTL in Redis, consumed atomically
  • Kill switch — operator-token gated, instant freeze, DB-persistent
  • Rail verify — Stripe + Coinbase signatures; cryptographic check
🧠 LLM at the edges

UX + advisory, never policy

  • Anomaly detector — 2-stage: fast SQL pre-filter (deterministic) for obvious wallet-drain patterns, then Gemini 2.5-flash as judge only for ambiguous cases. Flags only — never auto-acts.
  • Pricing suggestions — Gemini reads counter-offer accept rate + refund rate; writes "try $0.0024 floor" in the dashboard. Operator decides. Doesn't change behavior on its own.
  • Voice agent (GPT-4.1 via Retell) — drives natural conversation, calls deterministic tools (add_to_cart, negotiate, checkout). Can't bypass policy: every tool hits the same caps + signatures.

Everything an LLM does is either advisory (suggestion that needs operator action) or a thin wrapper around a deterministic endpoint. The receipt minted from a voice-driven purchase is bit-for-bit identical to one from a curl request.

Self-improvement loop (live today)

  1. Every payment decision lands in audit_log with reasons
  2. Agent reputation increments per successful settlement
  3. Anomaly detector runs every 15 min, scans patterns, writes findings to anomalies table
  4. Pricing engine reads recent accept/reject patterns, surfaces suggested floors
  5. Operator (today) decides whether to act on findings — closed-loop auto-policy is on the Q3 roadmap

Evals running today

  • make e2e — full handshake (issue → verify → release → audit) + replay-protection invariant + expired-receipt 410 + handler-5xx refund path
  • ✅ Multi-provider parallel — 1 agent → 3 providers → 23 calls settle in <500ms wall-clock
  • pytest tests/ — health, cache prefix, Stripe rail, webhook HMAC
  • 🟡 AgentPayBench v0 — synthetic adversarial scenarios (planned; eval suite scaffolded)
  • 🟡 LLM-as-judge precision/recall — once anomaly detector has a labeled set

Verify a PayGate receipt yourself.

Don't trust this UI. Don't trust the coordinator. Paste any PayGate receipt URL or ID below — the browser re-derives the Ed25519 signature against the published public key, in your own session. The code snippets underneath do the exact same check from your terminal.

Runs entirely in your tab: fetch(receipt) JSON.stringify(sorted) nacl.sign.detached.verify().
Python · 8 linespip install pynacl httpx
import base64, json, httpx
from nacl.signing import VerifyKey

r = httpx.get("https://api.paygate.agentglass.dev/api/v1/receipts/<paste_receipt_id>").json()
sig = base64.urlsafe_b64decode(r["signature"] + "=" * (-len(r["signature"]) % 4))
msg = json.dumps(r["canonical_payload"], sort_keys=True, separators=(",", ":")).encode()
vk = VerifyKey(bytes.fromhex(r["public_key_hex"]))
vk.verify(msg, sig)  # raises if invalid; prints nothing on success
print(f"✓ receipt {r['id']} verified — ${r['amount_micro_usd']/1e6:.4f} {r['rail']}")
JavaScript · 10 linesnpm i tweetnacl
import nacl from "tweetnacl";
const r = await (await fetch("https://api.paygate.agentglass.dev/api/v1/receipts/<paste_receipt_id>")).json();
const b64ToU8 = s => Uint8Array.from(atob(s.replace(/-/g,"+").replace(/_/g,"/") + "===".slice((s.length+3)%4)), c => c.charCodeAt(0));
const hexToU8 = h => new Uint8Array(h.match(/../g).map(x => parseInt(x,16)));
const sortKeys = (o) => Object.keys(o).sort().reduce((a,k) => (a[k]=o[k],a), {});
const canon = new TextEncoder().encode(JSON.stringify(sortKeys(r.canonical_payload)));
const ok = nacl.sign.detached.verify(canon, b64ToU8(r.signature), hexToU8(r.public_key_hex));
console.log(ok ? "✓ verified" : "✗ INVALID");

The coordinator's current public key: GET api.paygate.agentglass.dev/api/v1/coordinator/pubkey. Rotate the key, every prior receipt still verifies because the public key is stamped on each signed receipt at mint time.

Threat model

Need a deeper security review?

I share full architecture diagrams, sample audit chains, key rotation policies, and incident response playbooks under NDA — usually a 30-minute call gets you what your security team needs to sign off.

Schedule a security review

Drop your email + your team's deepest concern. I'll prep specific answers + share the right artifacts.