# Starter/Essential v1 Staging Graph Contract

Status: Evidence contract for #554
Date: 2026-06-20
Parent: #480

## Purpose

#554 captures the Starter/Essential v1 graph contract before any implementation
change in the #480 train. The rule for this train is evidence first:
real staging is the source of truth, and the existing local Train A is only a
behavioral baseline to preserve and adapt.

This document reconciles:

- current real staging evidence collected with AWS CLI on 2026-06-20;
- the existing repo's prior read-only staging notes;
- current `main` behavior and config;
- the local Starter lifecycle train in
  `skills/starter-openapi/references/trains/01-starter-lifecycle-smoke.md`;
- the accepted Session Tiltfile direction in
  `docs/20260616-adr-session-tiltfile-runtime-graph.md`;
- the cloud-host compressed-staging direction in
  `docs/20260615-prd-cp9-cloud-dev-integration-substrate.md`.

## Evidence Scope

Fresh AWS evidence was collected from the staging AWS account
`385595570414` with a read-only SSO principal. The commands were restricted to
control-plane/resource metadata:

```bash
aws eks describe-cluster --profile sso --region us-west-2 --name staging-base-us-west-2
aws eks describe-cluster --profile sso --region us-east-1 --name staging-us-east-1-f01
aws eks list-nodegroups --profile sso --region us-east-1 --cluster-name staging-us-east-1-f01
aws eks describe-nodegroup --profile sso --region us-east-1 --cluster-name staging-us-east-1-f01 --nodegroup-name <sample>
aws resourcegroupstaggingapi get-resources --profile sso --region us-east-1 --tag-filters Key=usedby,Values=staging-us-east-1-f01
aws elbv2 describe-load-balancers --profile sso --region us-west-2
aws elbv2 describe-tags --profile sso --region us-west-2 --resource-arns <global-kong-lb-arns>
aws elbv2 describe-listeners --profile sso --region us-west-2 --load-balancer-arn <global-public-kong-alb>
aws elbv2 describe-load-balancers --profile sso --region us-east-1
aws elbv2 describe-tags --profile sso --region us-east-1 --resource-arns <regional-starter-vpc-lb-arns>
```

Fresh kubectl reads were attempted with kubeconfigs generated from the same SSO
principal, but the principal was not authorized for Kubernetes object reads:

```text
error: You must be logged in to the server (Unauthorized)
```

Therefore this contract uses current AWS metadata for fresh facts and uses the
repo's existing real-staging Kubernetes inventory only as previously collected
evidence. Any implementation that depends on exact Kubernetes manifests,
ConfigMaps, CRDs, or plugin objects must refresh those details through an
authorized kubectl principal or through source manifests before changing code.

No raw secrets, kubeconfig certificates, auth headers, SQL passwords, or API
keys are included here.

## Fresh Staging Facts

### Global Control Plane

Fresh AWS evidence confirms the global staging control plane:

| Fact | Evidence |
| --- | --- |
| EKS cluster | `arn:aws:eks:us-west-2:385595570414:cluster/staging-base-us-west-2` |
| Status / version | `ACTIVE`, Kubernetes `1.34` |
| VPC | `vpc-04fae643ef756e0b5` |
| EKS API endpoints | public and private access both enabled |
| Network shape | 6 subnets, 1 cluster security group, service CIDR `172.20.0.0/16` |
| Tags | `environment=staging`, `component=dbaas-control-plane-base`, `usedby=dbaas-control-plane-base` |

Fresh ELBv2 evidence in that VPC confirms the public Kong ingress seam:

| Load balancer | Type | Scheme | Kubernetes stack | Cluster tag | Listener evidence |
| --- | --- | --- | --- | --- | --- |
| `k8s-kongingressalb-d0d9d6d02e` | application | internet-facing | `kong-ingress-alb` | `staging-base-us-west-2` | HTTP 80 and HTTPS 443 |
| `k8s-kongingressalbinn-1878f47731` | application | internet-facing | `kong-ingress-alb-inner` | `staging-base-us-west-2` | not expanded for #554 |

Prior repo evidence from
`docs/20260615-prd-cp9-cloud-dev-integration-substrate.md` and
`docs/20260608-design-starter-full-regional-graph-classification.md` records
the Kubernetes side of this global CP: `kong/api-gateway-kong`,
`staging-ms/serverless-svc-*`,
`tidb-management-service/tidb-mgmt-portal`,
`tidb-management-service/tidb-mgmt-service-sts`,
`tidb-management-service/serverless-global-service-sts`, and
`tidb-management-service/serverless-global-regional-proxy`.

### Starter Regional CP+DP

Fresh AWS evidence confirms the Starter/Essential v1 regional staging cluster:

| Fact | Evidence |
| --- | --- |
| EKS cluster | `arn:aws:eks:us-east-1:385595570414:cluster/staging-us-east-1-f01` |
| Status / version | `ACTIVE`, Kubernetes `1.34` |
| VPC | `vpc-01797c91977e12ca8` |
| EKS API endpoints | public and private access both enabled |
| Network shape | 6 subnets, 1 cluster security group, service CIDR `172.20.0.0/16` |
| Tags | `environment=staging`, `servicetype=serverless`, `component=control-plane/k8s`, `usedby=staging-us-east-1-f01` |

The regional VPC has 209 `usedby=staging-us-east-1-f01` tagged resources in
the AWS Resource Groups Tagging API. Resource classes observed:

| Class | Count |
| --- | ---: |
| EBS volumes | 80 |
| EKS nodegroups | 69 |
| ELBv2 target groups | 13 |
| ELBv2 listeners | 13 |
| ELBv2 load balancers | 8 |
| security groups | 8 |
| subnets | 6 |
| VPC endpoints | 2 |
| SQS queues | 2 |
| S3 buckets | 5 |
| Lambda functions | 1 |
| EKS cluster | 1 |
| VPC | 1 |

Component tags observed from the same API include:

| Component tag | Count |
| --- | ---: |
| `data-plane/sc/default` | 27 |
| `control-plane/adhoc` | 16 |
| `data-plane/sc/gp3-500` | 15 |
| `control-plane/dedicated` | 10 |
| `compute/tidb` | 10 |
| `storage/tikv` | 7 |
| `control-plane/vpc` | 7 |
| `control-plane/burstable` | 4 |
| `data-plane/sc/tiflash-gp3-6000-600` | 3 |
| `control-plane/k8s` | 3 |
| `control-plane/critical-services` | 3 |
| `storage/tiflash-wn` | 2 |
| `manager/cluster/sqs` | 2 |
| `control-plane/tmp-worker` | 2 |
| `control-plane/import-pool` | 2 |
| `control-plane/dm-worker` | 2 |
| `compute/tiflash-cn` | 2 |

PVC namespace tags observed on EBS volumes include:

| Namespace | Count |
| --- | ---: |
| `tidb-serverless` | 59 |
| `monitoring-serverless` | 6 |
| `observability` | 5 |
| `tidb-admin` | 4 |
| `serverless-metering` | 4 |
| `tiflash-autoscale` | 2 |

Managed nodegroups exist for the main shared regional runtime families:

```text
adhoc m/r pools, dedicated pools, default/memory/guaranteed pools,
dm-worker, import/export pools, tidb on-demand/vip/standard pools,
tiflash compute/worker pools, tikv partitions, and tmp-worker pools
```

Representative nodegroup samples show concrete labels and capacity roles:

| Nodegroup family | Sample role labels / tags |
| --- | --- |
| TiDB | `serverless.tidbcloud.com/node=tidb`, `component=compute/tidb` |
| TiKV | `serverless.tidbcloud.com/node=tikv`, `component=storage/tikv` |
| TiFlash compute | `serverless.tidbcloud.com/node=tiflash-cn`, `component=compute/tiflash-cn` |
| DM worker | `serverless.tidbcloud.com/node=dm-worker`, `component=control-plane/dm-worker` |
| Import pool | `serverless.tidbcloud.com/node=import-pool`, `component=control-plane/import-pool` |

Fresh regional ELBv2 tags in the Starter VPC show these active load-balancer
stacks:

| Stack | Scheme | Evidence |
| --- | --- | --- |
| `tidb-admin/ai-gateway` | internet-facing | serverless/staging LB in `staging-us-east-1-f01` |
| `ingress-nginx/nginx-ingress-ingress-nginx-controller` | internet-facing | regional ingress controller LB |
| `tidb-admin/tidb-http-gateway` | internet-facing | HTTP gateway LB |
| `tidb-admin/tidb-gateway-new` | internal | SQL gateway LB |
| `tidb-admin/tidb-gateway-privatelink` | internal | PrivateLink gateway LB |
| `tidb-admin/tidb-gateway-privatelink-zr` | internal | PrivateLink ZR gateway LB |
| `regional-infra/regional-redis` | internal | regional Redis LB |
| blank stack, `servicetype=devtier` | internet-facing | unknown for #554, leave unclassified |

Prior repo evidence from
`docs/20260608-design-starter-full-regional-graph-classification.md` records
the Kubernetes workload names seen in this regional context:
`new-serverless-regional-service`, `tidb-admin/manager`,
`tidb-admin/gateway-controller`, `tidb-admin/serverless-meta-server`,
`tidb-admin/meta-store`, `tidb-admin/tidb-gateway-inner`,
`tidb-admin/tidb-http-gateway`, `regional-infra/regional-redis`,
`serverless-metering`, `tidb-serverless`, and `tidb-worker/scaler`.

## Graph Classification

Classifications are implementation decisions for the #480 issue train. They do
not grant permission to use shared staging as a runtime dependency. Shared
staging remains read-only source material.

| Component group | Evidence behind classification | #480 classification |
| --- | --- | --- |
| Global CP substrate | Fresh AWS confirms `staging-base-us-west-2` EKS and public Kong ingress ALB. PRD says compressed staging merges this into the session cloud-host substrate. | Generated substrate, staging source material |
| Global api-gateway / Kong public entrypoint | Fresh ELBv2 confirms `kong-ingress-alb` HTTP/HTTPS public ALB; PRD requires every persona to enter through api-gateway. | Live service plus generated session config |
| `tidb-mgmt-portal` | Operation map says cluster APIs are hosted here; prior staging notes place it in global CP. Current `cp9.starter-full.example.yaml` marks it source. | Source |
| `serverless-service` | Operation map says branch/SQL-user APIs are hosted here; prior staging notes place `serverless-svc-*` in global CP. Current config marks it source. | Source |
| `tidb-mgmt-service` and `serverless-global-service` | Prior staging notes and current config include these global services. | Source |
| Account and billing dependencies | Current Starter design and config use deterministic stubs for off-path account/billing. | Stub |
| Regional CP+DP substrate | Fresh AWS confirms `staging-us-east-1-f01` EKS, tagged VPC resources, 69 nodegroups, data-plane/storage/control-plane component tags, and regional LBs. | Generated compressed-staging substrate, staging source material |
| `serverless-regional-service` | Prior staging notes identify `new-serverless-regional-service`; current contract/config mark service as source on regional runtime. | Source |
| `manager` | Prior staging notes identify `tidb-admin/manager`; current contract/config mark manager as source. | Source |
| `tidb-gateway-inner` and `tidb-worker-scaler` | Prior staging notes identify gateway and worker roles; current config marks both source. Fresh ELB tags confirm regional gateway LBs. | Source |
| `serverless-meta-server`, `gateway-controller`, `tidb-http-gateway` | Prior staging notes and fresh ELB tags confirm regional gateway/meta/http gateway roles. | Live service plus generated config |
| `regional-redis` | Fresh ELB tags confirm `regional-infra/regional-redis` internal LB; current config classifies Redis as live. | Live or generated session Redis |
| TiDB/TiKV/TiFlash shared pools and keyspace pools | Fresh nodegroup/resource tags confirm TiDB/TiKV/TiFlash, data-plane storage classes, `tidb-serverless`, and related PVC namespaces. | Live regional runtime plus generated/session-owned config |
| O11y/autoscale metric source | Existing Starter design requires an AWS-hosted deterministic o11y stub for first autoscale proof; fresh staging evidence only confirms monitoring/observability resources exist. | Stub/generated |
| RDS/MySQL/metadb, certs, TLS, Redis auth, KMS/PCA, API keys | Starter design forbids staging secrets and requires cp9-generated/session-scoped values unless explicitly reviewed. | Generated or stub |
| Import/export/backup/BR/Lightning paths | Staging has import/export resource families, but local Train A does not prove these flows. | Not needed for #558 unless an implementation dependency appears |
| Premium/Dedicated services such as `cluster-service-ng`, `dataplane-manager`, `nextgen-global-service` | Prior classification explicitly excludes Premium/Essential v2 graph for Starter/Essential v1. | Not needed |
| Exact Kubernetes manifests, CRDs, plugin objects, and route CRs | Fresh kubectl read failed with Unauthorized. Prior repo notes record high-level workload names only. | Unknown until authorized kubectl/source evidence refresh |
| Regional `servicetype=devtier` internet-facing LB with blank Kubernetes stack | Fresh ELB tag evidence does not identify a Starter/Essential role. | Unknown; do not use without more evidence |

## Route Surfaces And Train A Baseline

The local train
`skills/starter-openapi/references/trains/01-starter-lifecycle-smoke.md` is
already a useful behavioral reference. It proves the operation order and
artifact expectations for local mode:

1. `ClusterService_ListClusters`
2. `ClusterService_CreateCluster`
3. `ClusterService_GetCluster`
4. `ClusterService_ChangeRootPassword`
5. `BranchService_ListBranches`
6. `BranchService_UpdateSqlUser`
7. host `mysql select 1`
8. `ClusterService_DeleteCluster`
9. post-delete verification and `cp9 destroy`

The operation map distinguishes two OpenAPI host surfaces:

| Surface | Hosted by | Train variable | Path rule |
| --- | --- | --- | --- |
| Management portal serverless OpenAPI | `tidb-mgmt-portal` | `TC_STARTER_OPENAPI_BASE_URL` | base includes `/v1beta1`; append `/clusters`, `/regions`, etc. |
| Serverless service OpenAPI | `serverless-service` | `TC_STARTER_SERVERLESS_BASE_URL` / legacy `TC_STARTER_BRANCH_BASE_URL` | append full `/v1beta1/clusters/...` paths from serverless swagger files |

Train A is not #480 acceptance. It uses caller-provided base URLs and can pass
without proving the cloud-host api-gateway public entrypoint, AWS
`804837308162`, compressed-staging runtime, or direct-zero cloud cleanup.

## Delta From Current Main To #480 Cloud-Host Proof

Current `main` still represents the older Starter shape:

- `cp9.starter-full.example.yaml` uses account `385595570414`, profile `cp9`,
  `appDelivery`, `services`, and `target.aws.remote_eks`.
- There is no `tilt.file` in the Starter example.
- There is no `personas/starter-full/example.Tiltfile`.
- `internal/startercontract/starter_full_staging.yaml` classifies the old
  local-global plus remote-EKS-regional graph, not the #480 cloud-host
  compressed-staging Session Tiltfile graph.
- Session Tiltfile runtime assets exist for Premium only.
- Current Starter route inventory lives in docs/skills, not in a first-class
  runtime api-gateway/Kong graph.
- No current evidence proves Starter/Essential v1 through AWS account
  `804837308162` with profile `dev-offline-afterworld`.

#480 therefore needs these changes after #554:

1. Hard-cut Starter/Essential config to `tilt.file` and reject the old
   `appDelivery`/`services` runtime graph on the active cloud-host path.
2. Make persona detection and substrate validation work without relying on
   `appDelivery.env == starter-full`.
3. Add Starter/Essential Session Tiltfile assets under `personas/starter-full/`.
4. Materialize api-gateway/Kong as a first-class public entrypoint, then route
   both `tidb-mgmt-portal` cluster APIs and `serverless-service` branch/SQL-user
   APIs through it.
5. Preserve Train A's operation order and artifact/cleanup shape, but run the
   acceptance proof through cloud-host compressed staging in account
   `804837308162`.
6. Prove Starter create to returned endpoint `mysql select 1`, then prove
   Essential parity on the same substrate.
7. Close #480 only with an auditable bundle: commit SHA, source/staging
   evidence, public route evidence, create/select1 proof, and direct-zero
   cleanup.

## Downstream Guardrails

- Do not use shared staging EKS, staging secrets, staging Redis, staging RDS,
  staging KMS/PCA, or staging kubeconfigs as runtime dependencies.
- Do not infer exact Kubernetes manifests from service names. Refresh with
  authorized kubectl or source manifests before changing graph assets.
- Do not collapse the two Starter OpenAPI surfaces into one backend.
- Do not treat local Train A as cloud-host acceptance.
- Leave unknowns fatal in doctor/render/up until evidence classifies them.
- Keep any cloud proof in AWS account `804837308162` and close it with
  `cp9 destroy` plus direct survivor evidence.
