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:
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
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-controlsis used instead ofMOCKINGBIRD_ADMIN_CONTROLSwhen both are set.- A control flag replaces the matching key of the document.
--faultadds to the document'sfaultsinstead 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:
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
--settingsinstead of ignoring it. --settingsis for one emulator. In a fleet, give the service its ownsettingsentry.
Per namespace, and by credential
At boot the document takes two keys it takes nowhere else:
{
"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:
{
"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
snapshotreplaces the emulator's own seed data, in every namespace. - The boot
clocksets the base clock that every namespace's clock follows. See Clock. - The
seedoption wins overadminControls.seed.
Related
- Control document for the schema.
- Request headers and the admin API change the same controls after boot.