# cube-mcp — `dev` environment

The shared validation stack. Every change is deployed here and exercised
end-to-end against real infra *before* it is merged to `main` and shipped to
[`prod`](../prod/README.md).

- **AWS account / region:** `992382448282` / `us-west-2` — **the same account as prod** (see [divergence 3](#divergences-from-convention)).
- **Domain:** `cube-dev.edgescaleai-cube.com`
- **Deployed by:** `deploy-dev.yml` on every push to the `dev-main` branch (images tagged `:dev`).
- **State:** `s3://cube-mcp-terraform-state/cube-cloud-dev/terraform.tfstate`
- **Inputs:** [`environments/dev.tfvars`](../../environments/dev.tfvars)

> This directory is documentation only. The deployable Terraform is the flat
> root module in [`infra/terraform/`](../..); `dev` is produced by
> `terraform init -backend-config="key=cube-cloud-dev/terraform.tfstate"` +
> `terraform apply -var-file=environments/dev.tfvars`.

## What dev overrides

`dev` runs the same resource code as prod and differs only in these inputs
([`environments/dev.tfvars`](../../environments/dev.tfvars)); everything else
falls back to the defaults in [`variables.tf`](../../variables.tf):

| Variable | dev value | prod value | Why |
|---|---|---|---|
| `environment` | `dev` | `prod` | drives `name_prefix` = `cube-mcp-dev` |
| `domain` | `cube-dev.edgescaleai-cube.com` | `cube.edgescaleai-cube.com` | separate hostname |
| `desired_count` | `1` | `2` | single task is enough for validation |
| `tbot_config_secret` | `cube-mcp-dev/tbot-config` | `cube-mcp/tbot-config` | env-separated tbot config |
| `tbot_join_token` | `cube-mcp-dev-bot-iam` | `cube-mcp-bot-iam` | join token whose allow-rule lists the dev ECS task role |

## Resource registry (per-env, prefixed `cube-mcp-dev-`)

| Resource | Name | File |
|---|---|---|
| ECS cluster / service | `cube-mcp-dev-cluster` / `cube-mcp-dev-service` | [`ecs.tf`](../../ecs.tf) |
| ALB + HTTPS listener | `cube-mcp-dev-alb` (serves `cube-dev.edgescaleai-cube.com`) | [`alb.tf`](../../alb.tf) |
| DynamoDB | `cube-mcp-dev-api-keys`, `cube-mcp-dev-login-sessions` | [`dynamodb.tf`](../../dynamodb.tf) |
| Cognito user pool | `cube-mcp-dev-users` + one group per profile (see [`cognito.tf`](../../cognito.tf)) | [`cognito.tf`](../../cognito.tf) |
| ECS task IAM role | `cube-mcp-dev-ecs-task` | [`iam.tf`](../../iam.tf) |
| CloudWatch Logs | `/ecs/cube-mcp-dev` | [`ecs.tf`](../../ecs.tf) |
| Route53 records | `edgescaleai-cube.com` zone (`Z0571857327BEMX2EHNZU`) | [`route53.tf`](../../route53.tf) |

Resources **shared with prod** (ECR repos, `cube-mcp/profiles/*`,
`cube-mcp/groundcover/api-key`, the tbot config secret `cube-mcp/tbot-config`)
are listed in the
[`envs/` overview](../README.md#what-is-per-environment-vs-shared). The
`cube-mcp-dev/tbot-config` name is the `tbot_config_secret` **variable** value
(in [`dev.tfvars`](../../environments/dev.tfvars)), consumed by the ECS task env
var + IAM ARN — [`tbot.tf`](../../tbot.tf) itself creates one fixed, unprefixed
secret resource (`cube-mcp/tbot-config`), so the dev IAM grant points at a
`cube-mcp-dev/tbot-config` name this stack never creates (see
[prod/README.md](../prod/README.md#shared-resource-hazards)).

## Divergences from convention

Same set as prod (they share one root module) — see the
[summary table](../README.md#divergences-from-the-org-conventions--summary).
The divergences that bite hardest in *dev specifically*:

1. **No account isolation from prod (convention 3).** Dev and prod share
   account `992382448282`. A dev `apply` authenticates against the same
   account as prod; the only thing standing between a dev change and a prod
   resource is the `name_prefix`. The convention's whole point is that a
   wrong-account `apply` should fail at auth — here it would not.
2. **Shared, unprefixed resources (ECR / profile secrets / Groundcover key).**
   Because these are named `cube-mcp/…` with no environment segment, dev's
   deploy touches the *same physical resources* prod uses. Dev image churn
   filling the shared ECR repo is what triggered the June 2026 prod outage
   documented in [`ecr.tf`](../../ecr.tf).

Migrating dev to its own account (`esai-dev`) with the org
`esai-dev-terraform-state` backend is the reconciliation these two point to,
alongside the layout changes in the [overview](../README.md).
