Open source · Apache 2.0

trust()your AI spend

Budget holds, audit trails, and spend limits for every LLM call. Keep your keys, keep your billing. Add trust in one line.

One line

Wrap any client.
Keep your keys.

Your API keys. Your billing. Your provider. trust() adds budget holds and audit trails on top — nothing changes except now you have control.

  • One await trust(client) call — nothing else changes
  • Returns the same interface as the original SDK
  • Every response includes a receipt with hash-chained proof
example.ts
import { trust } from "usertrust"
import Anthropic from "@anthropic-ai/sdk"

// Your keys. Your billing. Now trusted.
const client = await trust(new Anthropic())

const { response, receipt } = await client.messages.create({
  model: "claude-sonnet-4-20250514",
  messages: [{ role: "user", content: "Hello" }]
})

receipt.auditHash       // SHA-256 hash-chained audit link
receipt.cost            // 0.0032
receipt.settled         // true
receipt.model           // "claude-sonnet-4-20250514"

What you get

Not observability.
Governance.

Observability tells you what happened. Governance prevents what shouldn't.

PENDING → POST / VOID

Two-phase settlement

Budget held before execution. Settled on success. Voided on failure. Like a credit card hold at a gas pump.

12 OPERATORS · YAML RULES

Policy engine

Spend limits, model allowlists, PII blocking, rate limits. Enforced before the call — not after.

SHA-256 · RFC 6962 MERKLE

Hash-chained audit

Every transaction links to its predecessor via SHA-256. Tamper-evident by construction. SOC 2 ready.

ZERO MIGRATION · ZERO LOCK-IN

Bring your own keys

Keep your API keys. Keep your billing. trust() wraps your existing client — nothing changes.

OPEN SOURCE · NO SAAS

Apache 2.0 licensed

Run locally with JSON receipts. No account needed. No SaaS dependency. Read every line of code.

IMPORT · WRAP · DONE

Three lines to ship

No config files, no dashboard setup, no SDK initialization ceremony. One function call.

Under the hood

The two-phase lifecycle

Every trust() call follows the same settlement pattern used by payment networks worldwide. No step may be skipped.

PENDINGEXECUTEPOST / VOIDRECEIPT
FIG 1.1trust(client)estimateCost()BUDGET CHECKInsufficientBalanceErrorAVAILABLEbalance: 50,000− hold: 3,200remaining: 46,800DRRESERVEDhold: 3,200status: PENDINGtransferId: u128CRAtransferId+ PENDING hold+ estimatedCostDOUBLE-ENTRY

PENDING

Budget hold creation

Before any LLM call executes, trust() reserves tokens from the user's budget — the same hold pattern banks use for credit card authorizations.

  • Double-entry debit from AVAILABLE, credit to RESERVED
  • Estimated cost calculated from the 20-model pricing table
  • Returns a transferId that tracks the hold through its lifecycle

Must never: execute the LLM call, skip budget verification, allow negative balances

transferId + PENDING hold + estimatedCostHold is active — budget reserved before execution

EXECUTE

Policy gate + LLM call

The policy gate evaluates every request before it reaches the provider. PII detection, model allowlists, rate limits, and spend caps — all enforced before the call, not after.

  • 12 field operators for flexible policy rules (YAML or JSON)
  • Duck-typed provider detection — Anthropic, OpenAI, Google, any SDK
  • Response includes token usage for actual cost settlement

Must never: forward without a PENDING hold, bypass policy evaluation, cache responses

FIG 1.2ActionRequesthold activePOLICYGATEPII checkmodel allowlistrate limitspend limitDENY→ PolicyDeniedErrorALLOWLLMProviderAnthropicOpenAI / GoogleLLM Response+ usage (input/output tokens)→ POST or VOIDHOLD ACTIVE
LLM Response + usage (tokens, latency)Branches to POST (success) or VOID (failure)
FIG 1.3LLM SuccessACTUAL COSTinput_tokens × rateoutput_tokens × rateactualCost = 2,847(est: 3,200)PENDING → POSTEDΔ refund: 353→ AVAILABLEprevHashevent[n-1]SHA-256event[n] ← CURRENTnext...APPEND-ONLY AUDIT CHAINB

POST

Settlement on success

On success, the hold is settled at the actual cost — calculated from real token usage, not the estimate. Any overage is refunded immediately.

  • Actual cost = input tokens × rate + output tokens × rate
  • Delta between estimate and actual refunded to AVAILABLE
  • Receipt appended to SHA-256 hash chain (tamper-evident)

Must never: settle without a preceding PENDING, skip audit chain append

FIG 1.4LLM FailureERROR CLASSIFYtransient | permanent | timeouterror propagated to callerPENDING → VOIDEDRESERVEDhold: 3,200→ RELEASEDAVAILABLE+ 3,200 restoredbalance: 50,000DLQ fallback(if audit write fails)C$0.00 chargedRELEASE

VOID

Release on failure

On failure, the entire hold is released — zero charge. The error is classified and recorded in the audit trail, never suppressed.

  • Full hold amount returned to AVAILABLE immediately
  • Error classified: transient, permanent, or timeout
  • Dead-letter queue fallback if audit write fails after void

Must never: charge partial amounts on failure, suppress errors, skip DLQ

POST xor VOID : exactly one outcome per transferId · never both
GovernanceReceipt + auditHashImmutable proof of settlement or release
FIG 1.5GOVERNANCE RECEIPTtransferIdtx_m8k2f_a1b2c3modelclaude-sonnet-4cost2,847 UT ($0.2847)settledtrueinput_tokens1,204output_tokens847auditHasha7f3...9e2d (SHA-256)hash[n-2]c4e1...hash[n-1]f8b2...hash[n]a7f3...n+1TAMPER-EVIDENT · APPEND-ONLYGENESIS(64 zeros)

RECEIPT

Hash-chained audit proof

Every call produces an immutable receipt — a hash-chained proof that links to every prior transaction. Tamper-evident by construction.

  • Each SHA-256 hash covers the previous event's hash
  • Chain anchored from GENESIS_HASH (64 zeros)
  • RFC 6962 Merkle proofs for public verifiability

Must never: modify historical receipts, break the hash chain, skip the GENESIS anchor

Connection Index
PENDINGEXECUTEtransferId + budget hold + estimatedCost
EXECUTEPOSTLLM success + token usage
EXECUTEVOIDLLM failure + error classification
POSTRECEIPTsettled hold + actual cost + audit hash
VOIDRECEIPTvoided hold + error event + audit hash
TigerBeetledouble-entry ledger, two-phase transfers
Audit ChainSHA-256 hash-linked JSONL, Merkle proofs
Policy Gate12 operators, PII detection, scope globs

5 PHASES · 3 STORAGE SYSTEMS · 1 UNIVERSAL JOIN KEY (transferId)

Your keys. Your billing.
Our trust layer.

trust() wraps your existing provider client. No proxy. No routing. No new accounts. Just trust on top of what you already use.

AnthropicClaude SDK
OpenAIGPT SDK
GoogleGemini SDK
xAIGrok SDK
GroqFast inference
+ moreAny provider

Read every line

Your trust layer shouldn't be a black box. UserTrust is open source under the Apache 2.0 license.