# Environments

An environment is a Postgres database (and its associated application services)
that Scribase provisions and manages. Each environment belongs to a project and
has a kind, a data mode, and a lifecycle managed through the control-plane API.

## Environment kinds

| Kind | Description |
|---|---|
| `production` | Long-lived, serves live traffic |
| `staging` | Long-lived pre-production environment |
| `preview` | Short-lived, typically one per pull request. Carries `ttl_hours` and is swept when it expires. |

## Data modes

| Mode | Description |
|---|---|
| `snapshot` | Cloned from the source environment's data |
| `sanitized` | Cloned, with sensitive columns and secrets scrubbed — the default for previews |
| `schema_only` | The schema with no rows |

---

## Endpoints

### POST /v1/environments

Create an environment. Returns `202 Accepted` with an operation to poll.

**Request body:**

```json
{
  "organization_id": "acme",
  "project_id": "store",
  "environment_id": "production",
  "kind": "production",
  "data_mode": "snapshot",
  "region": "us-east",
  "postgres_major": 17,
  "ttl_hours": null
}
```

`ttl_hours` is optional and only meaningful for `preview` environments. Set it
to have the environment automatically deleted after N hours.

**Response `202 Accepted`:**

```json
{
  "id": "op_01J...",
  "kind": "create_environment",
  "environment": { "organization_id": "acme", "project_id": "store", "environment_id": "production" },
  "state": "pending",
  "attempt_count": 0
}
```

**Headers required:** `Idempotency-Key`

**Example:**

```sh
scribase env create acme store production production snapshot us-east create-prod-001
# Preview with 72-hour TTL
scribase env create acme store pr-42 preview sanitized us-east create-pr42-001 72
```

---

### GET /v1/organizations/{org}/projects/{project}/environments/{env}

Read an environment record.

**Response `200 OK`:**

```json
{
  "organization_id": "acme",
  "project_id": "store",
  "environment_id": "production",
  "kind": "production",
  "data_mode": "snapshot",
  "region": "us-east",
  "phase": "ready",
  "postgres_major": 17
}
```

Preview environments also carry `ttl_hours` and `expires_at_epoch_seconds`.
The connection string is not part of the record; read it from the
`connection` endpoint below.

**Example:**

```sh
scribase env get acme store production
```

---

### POST /v1/organizations/{org}/projects/{project}/environments/{env}/suspend

Suspends a running environment. Returns `202 Accepted`.

**Headers required:** `Idempotency-Key`

```sh
scribase env suspend acme store production suspend-001
```

---

### POST /v1/organizations/{org}/projects/{project}/environments/{env}/resume

Resumes a suspended environment. Returns `202 Accepted`.

**Headers required:** `Idempotency-Key`

```sh
scribase env resume acme store production resume-001
```

---

### DELETE /v1/organizations/{org}/projects/{project}/environments/{env}

Deletes an environment. Returns `202 Accepted`. Deletion is permanent.

**Headers required:** `Idempotency-Key`

```sh
scribase env delete acme store production delete-001
```

---

### POST /v1/organizations/{org}/projects/{project}/environments/{env}/renew

Extend a preview's lifetime to `ttl_hours` from now, without recreating it.
Returns `200 OK` with the renewed expiry.

```sh
curl -X POST "$SCRIBASE_API_URL/v1/organizations/acme/projects/store/environments/pr-42/renew" \
  -H "Authorization: Bearer $SCRIBASE_ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"ttl_hours": 48}'
```

`ttl_hours` must be a positive integer; `0` is rejected with `invalid_ttl`.

---

### GET /v1/organizations/{org}/projects/{project}/environments/{env}/connection

Returns the environment's Postgres connection URI as
`{"connection_uri": "postgresql://..."}`. This is a server-to-server endpoint:
keep the URI out of browsers and logs.

---

### GET /v1/organizations/{org}/projects/{project}/environments/{env}/usage

The environment's flat-price usage envelope: the plan, its flat price, the
billing period, each hard cap with current use, and any capacity packs.

---

## Environment lifecycle

`phase` moves through:

```
requested → provisioning → ready ⟷ suspended
                 ↓            ↓
        failed_recoverable  updating → ready
                              ↓
                          deleting → deleted
```

All state transitions are asynchronous. Poll the operation returned by each
mutating call until `state` is `succeeded`, `failed`, or `cancelled`.

---

## Listing

`GET /v1/environments` lists an organization's environments as
`{"environments": [...]}`.

| Parameter | Description |
|---|---|
| `organization_id` | Organization to list (required) |
| `project_id` | Narrow to one project (optional) |
| `limit` | 1–200, default 100 |
