greenroom
Reference

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

FieldTypeRequiredMeaning
schemaVersion"1.0"yesSchema version, currently the literal "1.0".
classification"preview" | "staging" | "test"yesWhat kind of environment this is.
isolatedtrueyesYour 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"yesHow the app returns to a known state between walks. iOS requires "fresh_install".
networkControl"playwright" | "external_proxy" | "sandboxed_backend"yesHow network egress is governed. Web requires "playwright". iOS accepts "external_proxy" or "sandboxed_backend".
allowedHostsstring[], 1 to 50 entriesyesEvery host the app may reach during a walk. Include font CDNs, analytics, and crash reporters.
productionHostsstring[], up to 50 entriesno (default [])Hosts that are production. Declaring them lets Greenroom prove the walk never touched one.
sandboxPurchasesbooleanno (default false)Whether purchase flows run against a sandbox (StoreKit test configuration, Stripe test mode).
notesstring, up to 1000 charsnoFree-form context for reviewers of the manifest.
authobjectno (default { "mechanism": "signed_out" })How a walk that starts behind a sign-in wall gets its session: signed_out, or session_import with the secret name, the storage target and reset. iOS only. The contract is in testing authenticated apps.

Validation rules that bite

  • A host may not appear in both allowedHosts and productionHosts. 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 declare playwright (the browser enforces the allowlist in-line). iOS runs must declare external_proxy or sandboxed_backend; playwright is 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.

Third-party SDKs and public keys in the test build

A third-party SDK the test build leaves unconfigured (no key) usually makes no requests; list its host under productionHosts so the walk proves it stayed silent. One configured with a production key contacts its host and must be either allowlisted with a test project or left unconfigured.

Some SDKs will not let the app start without a key (RevenueCat's configure throws, and the startup chain after it never runs). The test build then needs a test project's public SDK key, exported in the workflow's prepare block through a GitHub Actions variable (export REVENUECAT_API_KEY_IOS=${{ vars.REVENUECAT_TEST_PUBLIC_KEY }}), with the SDK's host in allowedHosts. Public SDK keys are the ones the vendor designs to ship inside the app binary (RevenueCat public keys, PostHog project tokens, Stripe publishable keys); they are allowed in prepare. A private key, secret, service-role or signing key never is: prepare runs with no credentials, cannot read repository secrets, and is readable by anyone with the repository. The setup check refuses a value that looks like a credential and any secrets reference in prepare.

Sentry: the ingest host is only knowable from the DSN. A test build compiled without a DSN sends nothing, so list no Sentry host; only when the test build carries a DSN, list its exact host.

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. Greenroom does not intercept or record simulator traffic; the guarantee is the build configuration. 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.

On this page