Boot

docs/admin-controls/BOOT.md · the same file GitHub renders ·Edit on GitHub ·Markdown

An emulator starts with whatever controls you give it. That starting point is also what a reset returns to.

Interface

Carrier How
In code createRuntime({ seed, adminControls }) · createServer({ seed, adminControls }) · idBase · settings
Command line serve --admin-controls <json|file> and one flag per control
Environment MOCKINGBIRD_ADMIN_CONTROLS · MOCKINGBIRD_SEED · MOCKINGBIRD_ID_BASE · MOCKINGBIRD_SETTINGS · MOCKINGBIRD_ADMIN_KEY · MOCKINGBIRD_ADMIN_PREFIX
Fleet adminControls in mockingbird.json, for every service or for one
Admin page Not a screen. Reset returns to whatever boot set

All of them take the same control document.

Admin page

Boot is how the process starts, so the admin page does not edit it. Overview → Reset namespace returns the selected namespace to that starting point.

In code

adminControls is an option of every emulator's createRuntime and createServer:

TypeScript
import { createRuntime } from "@crvouga/mockingbird-service-stripe"

const stripe = createRuntime({
  seed: 7,
  adminControls: {
    clock: { now: "2030-01-01T00:00:00Z", frozen: true },
    latency: "40ms",
    faults: [{ preset: "rate_limited", count: 1 }],
  },
})

A document that cannot be read throws a ControlError before the emulator exists.

Command line

Shell
npx mockingbird-stripe serve --seed 7 --clock 2030-01-01T00:00:00Z --freeze \
  --latency 40ms --fault rate_limited
npx mockingbird-stripe serve --admin-controls ./controls.json
npx mockingbird-stripe serve --admin-controls '{"latency": "40ms"}'
Flag Environment Sets Page
--admin-controls <json|file> MOCKINGBIRD_ADMIN_CONTROLS The whole document, inline or from a file Control document
--seed <seed> MOCKINGBIRD_SEED seed Seed and determinism
--clock <instant> clock.now Clock
--freeze clock.frozen Clock
--auto-advance <duration> clock.autoAdvance Clock
--latency <duration> latency.delay Latency and timeouts
--jitter <duration> latency.jitter Latency and timeouts
--virtual-time virtualTime Latency and timeouts
--fault <fault> One more entry in faults, in header syntax Faults
--snapshot <file> snapshot Snapshot and restore
--id-base <n|boot> MOCKINGBIRD_ID_BASE Where generated ids start, so a restart does not reissue the last boot's ids Seed and determinism
--settings <json|file> MOCKINGBIRD_SETTINGS The emulator's own settings (the ones createRuntime({ settings }) and PUT /__admin/settings take), for every namespace. Only emulators that have settings accept it Settings
--admin-key <key> MOCKINGBIRD_ADMIN_KEY Who may use the controls Reference
--admin-prefix <path> MOCKINGBIRD_ADMIN_PREFIX Where the controls live. Default /__admin Reference

How they combine:

  • --admin-controls is used instead of MOCKINGBIRD_ADMIN_CONTROLS when both are set.
  • A control flag replaces the matching key of the document. --fault adds to the document's faults instead of replacing them.
  • A value that cannot be read stops the command before anything listens, and names the flag or key.

Settings

Some emulators have settings of their own beyond the controls (Formbricks' legacyEnvironmentIds, for one). --settings boots one with them without a wrapper process or a PUT after boot:

Shell
npx mockingbird-formbricks serve --settings '{"legacyEnvironmentIds": {"env_old": "ws_main"}}'
npx mockingbird-formbricks serve --settings ./settings.json
MOCKINGBIRD_SETTINGS=./settings.json npx mockingbird-formbricks serve
  • The object is the emulator's settings document, checked by the emulator's own schema; a bad field stops the command before anything listens and names the field.
  • Every namespace starts from these settings, and a reset returns to them.
  • An emulator that has no settings refuses --settings instead of ignoring it.
  • --settings is for one emulator. In a fleet, give the service its own settings entry.

Per namespace, and by credential

At boot the document takes two keys it takes nowhere else:

JSON
{
  "latency": "5ms",
  "credentials": { "sk_test_tenant_a": "tenant-a" },
  "namespaces": { "tenant-a": { "latency": "50ms", "faults": [{ "status": 429 }] } }
}
Key Meaning
namespaces A control document per namespace key. Each applies on top of the shared controls: a key it names replaces the shared one for that namespace
credentials Maps a vendor credential to a namespace, as PUT /__admin/credentials does

Here every namespace has 5 ms of latency, except tenant-a, which has 50 ms and answers 429; requests authenticated with sk_test_tenant_a land in tenant-a.

Fleet

In a fleet's mockingbird.json, adminControls at the top level boots every HTTP service with it, and a service's own entry replaces the keys it names:

JSON
{
  "adminControls": { "clock": { "now": "2030-01-01T00:00:00Z", "frozen": true } },
  "services": {
    "stripe": { "port": 0, "seed": "fixture", "adminControls": { "latency": "40ms" } },
    "resend": { "port": 0 }
  }
}

A service entry also takes settings (the emulator's settings, as --settings does) and idBase; a top-level idBase is the default for every HTTP service. Flags and MOCKINGBIRD_ADMIN_CONTROLS apply on top of the file, and --id-base or MOCKINGBIRD_ID_BASE fills in a top-level idBase the file leaves out. See Fleets.

Rules

  • Every namespace boots the same way. A namespace is created on its first request, from the boot controls: the shared ones, then its own entry in namespaces.
  • Boot is what reset returns to. A reset namespace cannot be told apart from a freshly booted one.
  • A boot snapshot replaces the emulator's own seed data, in every namespace.
  • The boot clock sets the base clock that every namespace's clock follows. See Clock.
  • The seed option wins over adminControls.seed.
↑↓ to navigate↵ to open