Environment manifest
Field-by-field reference for .greenroom/environment.json.
The environment manifest is your attestation of what environment Greenroom's virtual user is allowed to touch. It lives at .greenroom/environment.json, is validated strictly (unknown fields are rejected), and is always read from the PR's base revision, so a pull request cannot change its own policy.
Fields
| Field | Type | Required | Meaning |
|---|---|---|---|
schemaVersion | "1.0" | yes | Schema version, currently the literal "1.0". |
classification | "preview" | "staging" | "test" | yes | What kind of environment this is. Runs on the internal_canary release channel additionally require "test". |
isolated | true | yes | Your attestation that this environment holds no production data. The literal true is required; there is no way to run against a non-isolated environment. |
resetStrategy | "fresh_install" | "test_hook" | "ephemeral_deployment" | yes | How the app returns to a known state between walks. iOS requires "fresh_install". |
networkControl | "playwright" | "external_proxy" | "sandboxed_backend" | yes | How network egress is governed. Web requires "playwright". iOS accepts "external_proxy" or "sandboxed_backend". |
allowedHosts | string[], 1 to 50 entries | yes | Every host the app may reach during a walk. Include font CDNs, analytics, and crash reporters. |
productionHosts | string[], up to 50 entries | no (default []) | Hosts that are production. Declaring them lets Greenroom prove the walk never touched one. |
sandboxPurchases | boolean | no (default false) | Whether purchase flows run against a sandbox (StoreKit test configuration, Stripe test mode). |
notes | string, up to 1000 chars | no | Free-form context for reviewers of the manifest. |
Validation rules that bite
- A host may not appear in both
allowedHostsandproductionHosts. The comparison is case-insensitive and the manifest is rejected outright, because an allowlisted production host would mean the virtual user can reach real customer data. - The platform constrains
networkControl. Web runs must declareplaywright(the browser enforces the allowlist in-line). iOS runs must declareexternal_proxyorsandboxed_backend;playwrightis meaningless there and rejected. - iOS requires
resetStrategy: "fresh_install". Each walk starts from a clean install on a dedicated simulator. - An incomplete allowlist ends walks, correctly. Any request to an unlisted host is contained and the walk ends with the violation recorded. The fix is completing the allowlist, not relaxing policy: watch your app's first run and add what it legitimately needs.
Choosing networkControl for iOS
sandboxed_backend means your simulator build is compiled against a test or staging backend, so it cannot reach production by construction, and the walk's evidence records every network event for after-the-fact audit. This is the recommended path: it requires no infrastructure beyond the build configuration you likely already have.
external_proxy means an egress proxy or firewall on the CI host denies everything outside allowedHosts in-line. It is the strictest option, for teams that already operate one.