Farther ShoreDocs
Go to Farther Shore
Operate and verify a business
Apply & deploy
Releases
Apply Timeline
Environments
Choose how previews are createdWhat a rebuild does to the environment's subscribersCreate explicitlyEvery push reflashes the environmentFind the environment and test itProduction is differentDelete a preview
Platform access and roles
Customer operations
Observe and troubleshoot
Notifications
Webhooks
Test in a preview environment
Release to production
Diagnose billing and usage
Webhook event catalog
Status
Docs/Launch and operate/Environments

Environments

Create, update, test, and remove branch-bound preview environments without confusing them with production.

A business has production plus zero or more preview environments. A preview is an active platform target bound to one Git branch. Its compiled contract, runtime hostname, docs snapshot, frontend release, variables, backends, test personas, usage, and customers are scoped by environment where the corresponding surface supports it.

Those are per-environment operational records. The environment branch is the sole source of that environment's Business SDK contract. Plans, pricing, routes, permissions, meters, limits, policies, and frontend declarations are compiled from that branch and are never inherited from production. A plan that exists only on the default branch does not exist in the preview. Until the environment has accepted its first branch contract, contract-backed operations fail closed instead of borrowing the production snapshot.

Backend targets are the only fallback because origin URLs are operating state, not Business SDK declarations. A preview resolves a declared backend's stable slug to the production binding until a concrete environment override is bound. This reuses where requests run; it does not copy any production contract state.

Routes retain that stable slug across environments. The gateway resolves it to the inherited production backend or the concrete preview override at request time; physical backend IDs and credentials never leak across environments.

The Business program remains repository-owned in every environment. Environment rows, hostnames, bindings, credentials, and runtime state are platform-owned.

Choose how previews are created

bash
farthershore business preview-env set acme \
  --trigger branch-prefix \
  --branch-prefix env/ \
  --format json

farthershore business preview-env set acme --trigger pull-request --format json
farthershore business preview-env set acme --trigger disabled --format json
  • branch-prefix is the default. A push whose branch starts with the prefix creates the environment named by the remaining suffix. env/payments becomes payments; pushing the bare env/ prefix creates nothing.
  • pull-request creates previews only for same-repository pull requests into the default branch. Fork PRs and PRs into another base are skipped. Closing the PR tears its preview down.
  • disabled stops automatic creation.

In every mode, pushes to a branch that already has an environment row rebuild that environment. Deleting that tracked branch triggers teardown. Explicit CLI creation also remains available in every mode.

What a rebuild does to the environment's subscribers

An environment exists to match its branch exactly, so a push that changes the contract rebuilds the environment from scratch: its plans and compiled plans are replaced, and its subscriptions are deleted along with the API keys they own. Test personas survive as users, but the key each one held does not. Afterwards:

  • farthershore persona list <business> --env <name> reports the affected personas with revokedAt set and revokedReason: "env_reset".
  • A request that still presents one of those keys is denied 401 with code: "credential_env_reset" — distinct from credential_revoked, because nothing was revoked for cause and the product is healthy. Retrying the same key cannot succeed.
  • Recover by subscribing again, or, for a test persona, by running farthershore persona bootstrap with a fresh idempotency key.

A push that does not change the contract is a no-op for all of this. If the commit compiles to the contract the environment has already accepted and published — a comment, a README, a frontend-only change, or a re-push to retry CI — the apply reports No contract change and ENVIRONMENT_CONTRACT_UNCHANGED, nothing is rebuilt, and every subscription, key and persona keeps working. A frontend-only commit still triggers its frontend build.

A push whose build or compile fails performs no destructive work at all: the environment keeps serving its last published release, keys included.

Create explicitly

bash
farthershore env create acme \
  --name payments \
  --branch env/payments \
  --format json

Environment creation is convergent, not a replayed idempotency operation. On a timeout or interrupted response, run farthershore env list acme --format json and then repeat the same name-and-branch request if needed; the platform reads current state and repairs the managed branch before exposing the environment. Explicit creation accepts only the business's reserved preview namespace (normally env/) and durably claims that exact branch before GitHub creates or resolves it. A newly created environment reports branchCreated; a converged existing environment omits it. A successful response always has an exact managed branch head, and deleting that explicitly managed environment removes its claimed branch. Webhook and PR environments retain their external source branch ownership. If GitHub cannot create or resolve the branch, creation fails safely: restore GitHub access and repeat the same request.

bash
git fetch origin env/payments
git switch --track origin/env/payments

Every push reflashes the environment

A push to a tracked environment branch does not patch the environment — it wipes and recompiles it. Test personas, subscriber API keys, and customer identity rows for that environment are destroyed and the contract is rebuilt from the new commit.

Re-mint the persona after every push, and never carry a credential across one: the API key that worked before the push is gone, not merely stale. Wait for the apply to report applied before minting, or the mint races the recompile and fails with TEST_PERSONA_ENVIRONMENT_NOT_READY.

If the branch already exists and the business has an accepted contract, explicit creation may queue its initial environment build immediately.

Find the environment and test it

bash
farthershore env list acme --format json
farthershore apply-timeline list acme --env payments --format json
farthershore business show acme --env payments --format json

env list returns active preview rows with their exact id, name, branch, runtimeHostname, portalHostname, and status. Use those returned values; do not construct hostnames from the environment name.

business show --env <name> returns the business-level accepted spec — the contract compiled from the default branch — not the environment's own accepted or edge state. To see whether an environment has accepted its branch contract, read its Apply Timeline entry; that is the authoritative per-environment view.

Wait until the branch's Apply Timeline entry reports applied and both Accept contract and Publish to edge report passed. A successful preview publish promotes its matching commercial release before subscriber credentials are issued or repinned; do not mint a persona against a still-running apply.

For an API business, issue a persona only in a test environment and exercise the preview runtime:

bash
farthershore persona bootstrap acme --env payments --plan pro --format json --idempotency-key <persisted-persona-bootstrap-attempt-key>
farthershore persona list acme --env payments --format json

For a customized frontend, inspect the environment's frontend state:

bash
farthershore frontend status acme --env <environmentId> \
  --ref "$(git rev-parse HEAD)" --wait --format json

frontend status and frontend rollback accept an environment name or id. Run the status command from the checkout at the commit pushed to that preview branch. The CLI resolves a name to the current environment id before it calls Core. Not every command accepts --env; run the exact command's --help rather than assuming a global environment flag exists.

Runtime tokens are scoped to backend rows, so create the environment's backend binding before minting its token, and pass --backend <backend-id> when the environment has more than one backend. backend list and backend tokens list are business-wide and accept no --env.

If a preview request returns origin_unavailable, the environment has no usable upstream for that route. Inspect both the logical slug and its effective binding: the preview uses its concrete override when present, otherwise the production backend. It never falls through to a different preview. An environment-only backend with no target still fails safely; do not weaken request verification.

Production is different

The repository default branch targets production. An ordinary push validates the contract, and a provably non-economic contract change may publish its runtime state immediately. Economic or indeterminate contract changes wait for a published GitHub Release. Production frontend and repository-docs artifacts also build from the release, not from a plain default-branch push.

Production is not returned as a deletable BusinessEnvironment row, and env delete is never a production rollback.

Delete a preview

bash
farthershore env delete acme payments --yes --format json

Deletion tries to remove edge state, any Git branch Core claimed for the environment, environment docs, in-flight workflows, personas and customer identity rows, compiled plans, environment-only permission inventory, backend credentials, usage-meter state, and the Core environment row. It is deliberately retryable. ENVIRONMENT_CLEANUP_FAILED means some cleanup did not complete; the environment row remains so you can run the same deletion again.

A live-provider environment with active subscriptions cannot be torn down. Move or end those subscriptions first. Test environments do not have that live subscription guard.

Deleting the environment is destructive operational work. It does not delete the Business program from repository history.

See Inspect an apply, Production releases, Test in a preview, and Infrastructure with OpenTofu for provisioning a separate backend deployment per environment.

PreviousApply TimelineNextPlatform access and roles

On this page

Choose how previews are createdWhat a rebuild does to the environment's subscribersCreate explicitlyEvery push reflashes the environmentFind the environment and test itProduction is differentDelete a preview