# Environments

FetchCatch treats each **deployment stage** as its own workspace and lets a single
`.fetchcatch/` project bind to several of them. That keeps `dev`, `staging`, and `prod`
configurations out of long-lived per-branch divergence — they live side by side as named
profiles in `project.json`, and you pick which one a command targets with `--env <name>`.

## Why workspaces, not branches?

Mixing config and code on the same branch makes "what's actually deployed?" depend on history
walks. Workspaces are isolated runtime resources (own API keys, own auth profiles, own runs),
which means:

- A staging API key cannot evaluate flows in production — even by accident.
- Run history, audit events, and quotas are scoped per-stage.
- Governance modes can differ: `Hybrid` in dev for rapid iteration, `CodeManaged` in prod.

## v2 `project.json`

```json
{
  "schemaVersion": 2,
  "apiBaseUrl": "https://api.fetchcatch.com",
  "tenantSlug": "acme",
  "tenantId": "…",
  "defaultEnvironment": "dev",
  "environments": {
    "dev":  { "workspaceSlug": "billing-dev" },
    "stg":  { "workspaceSlug": "billing-stg" },
    "prod": { "workspaceSlug": "billing-prod" }
  },
  "workspaceSlug": "billing-dev",
  "workspaceId":   "…"
}
```

- `environments` is a map of short labels → workspace bindings.
- `defaultEnvironment` is what `fcc apply` (without `--env`) targets.
- The legacy `workspaceSlug` / `workspaceId` fields at the top are kept in sync with the
  default for v1 compatibility (older `fcc` versions still work against the same project).
- Per-env `apiBaseUrl` is optional — useful when staging lives on a different region.

## Usage

```bash
fcc plan                      # dry-run against defaultEnvironment (dev)
fcc apply                     # push to dev
fcc apply --env stg           # push the same files to staging
fcc publish --env prod        # ship to production
fcc drift  --env prod         # nightly drift check, CI exits 2 on divergence
```

> `--env` is a per-command flag and never mutates the binding registry — `fcc apply --env stg`
> will *not* silently make `stg` your new default. To switch default, edit
> `defaultEnvironment` in `project.json` (or just re-init).

## Bootstrap

The simplest way to populate `environments` is to create one workspace per stage in the console
(**Sidebar → Workspaces → +**), then hand-edit `project.json`. Tag each workspace with its
`EnvironmentKind` (`Development` / `Staging` / `Production` / `Other`) from
**Settings → Workspaces → Settings** so the console badge matches the CLI label.

## Recommended governance + environment combos

| Environment | Suggested governance | Why |
|---|---|---|
| `dev`  | `Hybrid` or `DesignerOnly` | Iterate fast in the console; CLI is optional. |
| `stg`  | `Hybrid` | CLI seeds it from main; humans can still poke. |
| `prod` | `CodeManaged` | Every change is a reviewed PR. |

This produces the classic four-step lifecycle:

1. Edit and publish in `dev` from the console.
2. `fcc pull --env dev` to capture the change in git.
3. Open a PR; reviewer compares with `fcc diff` locally.
4. CI runs `fcc publish --env prod` after merge.

## Multi-environment CI snippet

```yaml
jobs:
  deploy:
    strategy:
      matrix:
        env: [stg, prod]
    steps:
      - uses: actions/checkout@v4
      - run: fcc apply  --env ${{ matrix.env }}
      - run: fcc publish --env ${{ matrix.env }}
        env:
          FETCHCATCH_TOKEN: ${{ secrets.FETCHCATCH_TOKEN }}
          CI: "true"
```

The `X-FCC-Git-Commit` header is captured automatically by the CLI from `GITHUB_SHA` (or
`git rev-parse HEAD` locally) and stamped onto every `FlowVersions` row that lands, so the
console history panel can show "ci-bot · v17 · commit a1b2c3d4".
