# 414 ECR floor merge

Account 414 owns the kernel and UI images every CP9 runtime account pulls and that `cp9-developer` publishes. Merge, never replace: a Put that lists only the new account revokes the other runtime accounts.

Live registry/repo policy is the SSOT. Floor statements *union* onto matching Sids: principals, actions, and resources. Keep every Sid live already has.

1. `get-registry-policy` / `get-repository-policy`. Empty policy is missing, not an error.
2. For each floor Sid, if live lacks it, append it. If live has it, union AWS principals and resources (including `repository/*` on `CP9RuntimePull`) and union actions.
3. Put the merged document. A Get that already contains the floor (superset) is `present` — skip Put.
4. Runtime principals are the full `.github/cp9-cleanup-accounts.json` set (account root + `cp9-developer`).

Pull actions (`CP9RuntimePull`): `BatchCheckLayerAvailability`, `BatchGetImage`, `DescribeImages`, `GetDownloadUrlForLayer`, `ListImages`. Publish actions (`CP9DeveloperPublish`): `BatchCheckLayerAvailability`, `CompleteLayerUpload`, `InitiateLayerUpload`, `PutImage`, `UploadLayerPart`. UI pull (`CP9RuntimeAccountPull`) omits Describe/List.

`ExistingCrossAccountAccess` (`ecr:*` on `repository/*`) principals stay and union: us-east-1 `946646677266`; us-west-2 `024848481520`, `296171618728`, `380838443567`, `510387698298`, `552185537300`, `886436925895`, `946646677266`.

Create a missing repository `tidbcloud/cp9-dbaas-ui` (immutable tags, scan-on-push, AES256, untagged expire 30d). Existing repositories stay.

Registry `CP9DeveloperPublish` resources (not `repository/*`):

- us-east-1: `dbaas/nightly/serverless-metering`, `dbaas/staging/serverless-metering`, `dbaas/aws-shared-provider-meta-server`, `dbaas/aws-shared-provider-vpa-agent`, `dbaas/aws-shared-provider-gateway-controller`, `dbaas/aws-shared-provider-tidb-http-gateway`, `dbaas/aws-shared-provider-manager`, `dbaas/aws-shared-provider-ops-service`, `dbaas/aws-shared-provider-tidb-gateway`, `dbaas/aws-shared-provider-tidb-worker`, `dbaas/aws-shared-provider-datacleaner`
- us-west-2: `dbaas/dev/cluster-proxy`, `tidbcloud/tidb-management-service`, `observability`, `tidbcloud/dm`, `tidbcloud/serverless/pd`, `tidbcloud/serverless/tidb`, `tidbcloud/serverless/tidb-operator`, `tidbcloud/serverless/tiflash`, `tidbcloud/serverless/tikv`

Repo-policy floors (same pull/publish Sids) on us-east-1 metering + aws-shared-provider set except `datacleaner`, and us-west-2 `dbaas/dev/cluster-proxy` + `tidbcloud/tidb-management-service`. Extra live Sids on those repos stay.
