Skip to Content
Core concepts

Core concepts

Environment, sandbox, twin, world, receipt: the five terms the rest of these docs use.

Five terms run through the rest of these docs. An environment names a set of twins, a sandbox is one running copy of that environment, each twin holds a world, and a run through the proxy prints a receipt.

Environment

An environment is a named list of twins. You define it once and it outlives every run, so a name is the only thing a run needs. One comes from veris env create checkout --services stripe,postgres, recorded in .veris/twin.yaml and committed with the repository; veris env list shows the ones a project has, and veris env use picks the one this folder runs against. veris services is the catalog of every twin an environment can include.

Sandbox

A sandbox is one isolated running copy of an environment, ready in seconds. It has a time to live and is deleted when that expires whether or not anything is using it: --ttl, then the environment’s ttl_minutes in .veris/twin.yaml, then the control plane’s own default — the CLI carries none of its own. For a veris run --fresh sandbox that lifetime is a backstop for teardown never running, since --fresh deletes its sandbox when the run ends. One environment has many sandboxes: veris up starts one for this folder and veris down deletes it, and veris run --fresh does both around a single run. veris sandbox reset restores every twin to its boot seed, so the same test runs again from the same starting state.

Twin

A twin is one simulated vendor inside a sandbox. It holds state: a write persists, a later read reflects it, and an operation that is invalid for the current state is refused the way the vendor refuses it. Your code reaches a twin without changing, keeping the same hostname, the same credential and the same SDK. Where an address does move it moves through a variable your code already reads, never through an edit: setup’s direct tier points each vendor base URL at the sandbox that way, and a twin with no hostname to intercept — a data plane such as a database — has its URL handed to your command by veris run itself, under the variable that twin publishes. Either way the path under test is the shipped one. Twins covers what each one reproduces, down to error envelopes and scopes.

World

A world is what a twin holds: its rows, its files, its armed failures, and the clock it shares with the other twins in the same sandbox. A fresh sandbox is not empty, so your first test needs no seeding. The same person is the same person in every twin in the sandbox, which is what makes a test that spans two vendors possible. Read and write a world while the sandbox runs: veris sandbox data for rows, veris sandbox clock for time, or the twin’s own control_url over HTTP, which veris sandbox services get prints. Worlds covers seeding, faults, time and reset.

Receipt

A receipt is what the sandbox received during a run, printed when the run ends: veris: the sandbox received 14 request(s), counted per twin. It is what veris run reports, so it is the container tier’s record; the direct tier puts no proxy in front of the command and its evidence is the twin’s own trace instead. Test output is identical whether or not your suite reached its dependency, so a veris run --fresh, which deploys the sandbox it runs against, fails on an empty receipt even when every test passed. A service requirement fails a run the same way wherever it came from — --require-service on the command line, or proxy.require_service recorded in .veris/twin.yaml, which setup writes, so a repository setup wired already carries one. --require-service stripe:2 asserts a minimum count for a named twin, and where a requirement is in play it is what decides the run; attached to a sandbox that was already up, an empty receipt with none in play is a warning. Running tests covers veris run and what an empty receipt means.