# Design: cp9 Billing Persona Dogfood

Issue: <https://github.com/tidbcloud/controlplane9/issues/254>

Design:
[`20260527-design-cp9-billing-persona.md`](./20260527-design-cp9-billing-persona.md)

This is the dogfood design and manual operator contract for the Billing persona. Implementation
PRs must replace Phase 0 placeholders with concrete commands and prove this
flow repeatedly before the Billing side of #254 can close.

## Finish Line

1. Start cp9 with the `billing` persona.
2. Run real Billing source services through Tilt.
3. Drive local TiDB Cloud usage/business facts into Billing.
4. Query a concrete Billing artifact.
5. Prove one negative/edge Billing case.
6. Hot reload a Billing source edit in the same session.
7. Clean up local/AWS resources created by the run.

## Prerequisites

Use the repo skills before dogfood. Read
`skills/get-started/SKILL.md`, `skills/get-started/references/safety-and-ownership.md`,
and the comments in repository-root `cp9.dev-full.remote-ec2-k3d.example.yaml`
before mutating local or cloud state. The
Billing dogfood flow extends those cp9 safety and closeout rules; it does not
replace them with ad hoc commands.

Use the current cp9 command surface:

```bash
bin/cp9 setup config=cp9.yaml
bin/cp9 doctor config=cp9.yaml
bin/cp9 up dry-run=true config=cp9.yaml
bin/cp9 up config=cp9.yaml
bin/cp9 status config=cp9.yaml
bin/cp9 logs config=cp9.yaml service=<service>
bin/cp9 destroy config=cp9.yaml
```

Deprecated helper commands are not part of this workflow.

Required local tools:

- `git`
- `go`
- `docker`
- `k3d`
- `kubectl`
- `helm`
- `tilt`
- `aws`
- `jq`
- `rg`

Authenticate AWS only when the selected Billing proof creates cloud resources:

```bash
aws sso login --profile sso
aws configure export-credentials --profile sso --format process >/dev/null
```

## Checkout Layout

Recommended sibling layout:

```text
work/
  controlplane9/
  tidb-management-service/
  cluster-service-ng/
  config-center/
  billing/
```

Refresh heads and verify clean trees:

```bash
cd ~/work/controlplane9 && git fetch origin main && git checkout main && git pull --ff-only && git status --short
cd ~/work/tidb-management-service && git fetch origin main && git checkout main && git pull --ff-only && git status --short
cd ~/work/cluster-service-ng && git fetch origin main && git checkout main && git pull --ff-only && git status --short
cd ~/work/config-center && git fetch origin master && git checkout master && git pull --ff-only && git status --short
cd ~/work/billing && git fetch origin main && git checkout main && git pull --ff-only && git status --short
```

Record SHAs before proof:

```bash
git -C ~/work/controlplane9 rev-parse HEAD
git -C ~/work/billing rev-parse HEAD
```

## Staging Seed Input

Staging is seed/config input only. It is not the runtime success path.

For the Billing DB seed, connect only from the `staging-base-us-west-2`
Kubernetes context and use `cp9 db dump-init` to capture sanitized init SQL for
local replay. Do not paste or commit database passwords, full database URIs,
ExternalSecret payloads, Stripe keys, marketplace credentials, or Salesforce
credentials.

The implementation PR must record:

- the command used to produce the sanitized init SQL;
- which Billing tables were retained for local seed;
- which rows or fields were removed, redacted, or regenerated;
- why the remaining seed is sufficient for the selected Billing workflow.

## Create Config

```bash
cd ~/work/controlplane9
cp cp9.billing.example.yaml cp9.yaml
```

The source example is `cp9.billing.example.yaml`.

Edit at least:

- `name`: unique session, for example `cp9-<yourname>-billing-1`;
- `tilt.port`: unused local port;
- `services.source.*.repo`: local Billing/source checkout paths;
- owner/session/account/region/TTL fields.

Keep staging as seed/config input only. Do not point runtime dependencies at
staging RDS, Redis, queues, or provider sandboxes.

## Preflight

```bash
bin/cp9 setup config=cp9.yaml
bin/cp9 doctor config=cp9.yaml
bin/cp9 up dry-run=true config=cp9.yaml
```

Before `up`, inspect the generated plan once the implementation exists:

```bash
SESSION=cp9-<yourname>-billing-1
TILT_DIR=.cp9/$SESSION/tilt

rg 'billing2|billing2-api|billing2-worker' "$TILT_DIR/Tiltfile" "$TILT_DIR/inputs"
rg 'fake|local-adapter|recorder' "$TILT_DIR/inputs" || true
! rg 'go-build-overlay|go-build-patches|go build -overlay' "$TILT_DIR"
! rg 'staging|prod-ms|staging-ms' "$TILT_DIR/inputs"
```

## Start

```bash
bin/cp9 up config=cp9.yaml
bin/cp9 status config=cp9.yaml
kubectl --kubeconfig .cp9/$SESSION/kubeconfig.yaml get pods -A
```

Open Tilt if needed:

```bash
open http://127.0.0.1:<tilt.port>
```

## Billing Product Proof

Phase 0 must replace this block with concrete Billing commands.

```bash
# CONTRACT: drive local usage/business facts into Billing.
curl -fsS -X POST "$BILLING_LOCAL_BASE_URL/<billing-input-endpoint>" \
  -H 'content-type: application/json' \
  --data @artifacts/billing-input.json | jq .

# CONTRACT: query the Billing artifact produced by real Billing code.
curl -fsS "$BILLING_LOCAL_BASE_URL/<invoice-or-usage-or-credit-endpoint>" | jq .

# CONTRACT: negative/edge case for the selected Billing workflow.
curl -sS -o /tmp/cp9-billing-negative.json -w '%{http_code}\n' \
  "$BILLING_LOCAL_BASE_URL/<negative-case-endpoint>"
cat /tmp/cp9-billing-negative.json | jq .
```

The proof packet must include:

- source SHAs;
- input payload;
- produced artifact query and fields;
- negative/edge case response;
- local fake adapter logs for payment, marketplace, Salesforce, queue, object
  storage, or Account/Auth boundaries;
- cleanup evidence.

## Hot Reload Proof

```bash
# Make a tiny Billing source edit with observable local behavior.
tilt trigger billing2
tilt trigger billing2-api
tilt trigger billing2-worker
bin/cp9 logs config=cp9.yaml service=billing2 since=5m

# Re-run the Billing artifact query in the same session.
curl -fsS "$BILLING_LOCAL_BASE_URL/<invoice-or-usage-or-credit-endpoint>" | jq .
```

## Repeatability

Before closing the Billing implementation, run two fresh sessions from clean
heads with no live patches:

```bash
bin/cp9 destroy config=cp9.yaml
bin/cp9 setup config=cp9.yaml
bin/cp9 doctor config=cp9.yaml
bin/cp9 up config=cp9.yaml
```

## Cleanup

```bash
bin/cp9 destroy config=cp9.yaml
```

If the run created cloud resources, verify the current cp9 cleanup contract:
EKS, VPC graph, active instances, volumes, ENIs, LBs/TGs, S3, Route53, and any
other cp9-owned Billing resources must be zero or not found for the exact owner,
session, account, and region.
