Skip to content
Warrantv0.1

Sandbox vs production

Which keys reach real money.

The key prefix decides the environment and nothing else does — wr_test_ is sandbox, wr_live_ is production.

wr_test_...   sandbox
wr_live_...   production

Sandbox is the default

Every organisation starts in sandbox, and it is where everything in these docs runs. Balances are seeded, no real money exists, and the whole lifecycle behaves identically — the same state machine, the same policy engine, the same clause evaluation.

Production requires an explicit unlock. It is not a flag you can flip by accident on the way to shipping.

A key cannot reach the wrong environment

A wr_live_ key presented against a sandbox organisation resolves to no principal at all. That is a 401, not a 403: there is nobody to refuse.

It is the same answer a made-up key gets, and the same body, so probing tells you nothing about which half was wrong.

What differs, and what does not

SandboxProduction
Key prefixwr_test_wr_live_
MoneySeeded, not realReal
State machineIdenticalIdentical
Policy engineIdenticalIdentical
Clause evaluationIdenticalIdentical
Rate limitsSameSame

The engine being identical is the point of having a sandbox at all. A spec that passes there passes here, and POST /bench/run lets you check one without a key or a warrant.

Running the API locally

With no DATABASE_URL set and WARRANT_ENV on its sandbox default, the API boots an in-process PGlite database and seeds it. Data is real but ephemeral and is rebuilt on every restart.

pnpm --filter @warrant/api dev

Sign in at the console as owner@sandbox, admin@sandbox, operator@sandbox or viewer@sandbox to see each role's view.

That fallback is refused on a serverless deployment, where each cold start would get its own empty database — a failure that would look like data loss rather than like misconfiguration.

The chain flag is separate

WARRANT_CHAIN decides whether traces anchor to Rialo testnet. It defaults to mock, which keeps tests offline and deterministic.

WARRANT_CHAIN=mock    # MockRex + PostgresLedger (default)
WARRANT_CHAIN=rialo   # RialoRex + RialoLedger, live testnet

Under rialo, custody still delegates to the Postgres ledger. Anchoring is real; onchain settlement is not — see contracts.

Amounts do not change between environments

"8400000"    8.40 USDC
8400000      rejected — a JSON number
"8.40"       rejected — not the smallest unit

Integer strings of the smallest unit, ^[0-9]+$, in both.