Skip to Content
WorldsWorlds

Worlds

The state inside a sandbox: rows, files, armed failures and the clock.

A world is the state a twin holds: its rows, its files, its armed failures, and the clock it shares with the other twins in the sandbox. It is real tables in a real database, readable and writable over HTTP while the sandbox runs.

A fresh sandbox is not empty. Every twin boots with a default world already seeded, so your first test runs against a customer who exists, a card that declines and a list long enough to paginate, with no setup call in front of it.

What is already there

Seven people are seeded into a twin’s default world, and each one carries a situation you would otherwise have to build: a working case, no money, a blocked account, a brand new account, an unusual format, a failure in the history, and enough rows to force a second page.

Dates are anchored to when the sandbox started, so last month’s invoice is actually last month on every boot.

In the Stripe twin they land like this. Look ids up at runtime with veris sandbox data get stripe customers, or GET /veris/data?entity_type=customers; the email address is the stable handle.

PersonAlready true in the Stripe twinWhat you can test without seeding
Amara Osei
amara.osei@example.com
Two succeeded payment intents, and a visa ending 4242 valid to 12/2030The path that has to work
Ben Kowalski
ben.kowalski@example.com
A card ending 9995 that declines for insufficient fundsA 402 whose decline_code is insufficient_funds
Carmen Reyes
carmen.reyes@example.com
A card ending 4212 that expired 03/2024A 402 whose code is expired_card, at charge time rather than when the card was attached
Devi Sharma
devi.sharma@example.com
A customer with no payment method, no payment intent and no chargeEmpty lists, and the branch that runs for a customer with no history
Eiji Nakamura
eiji.nakamura@example.com
One payment intent for 3800 in jpy, a currency with no decimal placesAmount handling that assumes two decimal places
Fatima Al-Amin
fatima.alamin@example.com
A card ending 5126 whose refunds failA refund created succeeded that turns failed later, with failure_reason expired_or_canceled_card
Gus Thornton
gus.thornton@example.com
11 payment intents against a default page size of 10has_more: true, and the second trip round your pagination loop

Every twin covers those same seven situations in its own vendor’s shapes. Where a vendor has no way to hold one, that twin leaves it out rather than inventing it: Stripe has no way to block a person, so Carmen’s block sits on her card instead.

A few twins seed fewer than seven people, and the Postgres twin seeds none, because the tables in it are yours. veris sandbox data get <twin>, or GET /veris/data on that twin’s control URL, shows what it actually holds.

The same person in every twin

Amara Osei is one person across the sandbox, appearing in each vendor’s own shape: a Stripe customer, a GitHub user, a HubSpot contact, a Slack member. Same name, same employer, same story. That is what makes a cross-service test possible: a test that charges a customer and then posts about it is talking about one person, not two records that happen to match.

Her situation follows her too, in each vendor’s own terms. Carmen Reyes holds the blocked case everywhere: her Stripe card expired 03/2024, her GitHub account is suspended, her HubSpot contact is archived, her Slack member is deactivated.

One person is not one email address. Commerce twins such as Stripe, HubSpot and QuickBooks carry the personal address, amara.osei@example.com. Workspace and identity twins such as GitHub, Slack and Jira carry the work address, amara.osei@lakeshore-outfitters.example. Match on the address the twin you are querying uses; a lookup keyed on one address across both finds nothing in half the sandbox.

Reading it

veris sandbox data get <twin> # every table in that twin, with counts veris sandbox data get <twin> customers # a page of one table's rows

<twin> is a name from veris sandbox services list. $CONTROL_URL is that twin’s control URL, printed by veris sandbox services get <twin>.

curl "$CONTROL_URL/veris/data"
{ "counts": { "customers": 7, "payment_methods": 9, "payment_intents": 17, "charges": 16 } }

counts names every table in that twin. To read the rows of one:

curl "$CONTROL_URL/veris/data?entity_type=customers"

Rows come back newest first, 100 at a time over HTTP and 20 at a time in the CLI, with total, limit and offset for the rest; --limit, --offset and --all page through them. Table and column definitions come from veris sandbox data schema <twin>, or /veris/schema over HTTP, written for whoever is operating the sandbox. Read them rather than guessing field names.

The console’s Data tab browses the same thing with row counts and column descriptions, which is easier when you do not yet know what you are looking for.

Ids are stable within a sandbox, and stable across sandboxes only when the clock is frozen. Read them at runtime rather than pasting one from a previous sandbox into a test.