# Premium Plan Replayer API Plan

## Background

Clinic UI needs to list manual Plan Replayer archives and obtain a short-lived
download URL for a TiDB-X Premium logical cluster. The regional NextGen API
already owns object discovery and URL signing. Clinic must remain the UI-facing
authorization boundary and must not read object storage or construct download
URLs itself.

The existing NGM `plan_replayer` endpoints serve the historical Clinic object
storage layout. They do not have the Mgmt or NextGen clients required by this
feature and must retain their current behavior.

## Goal and Target Contract

- Add authenticated Clinic API endpoints under the existing organization and
  cluster resource namespace for listing Plan Replayer files and generating a
  download URL.
- Verify the caller can read the requested Clinic cluster before any upstream
  call.
- Look up the logical cluster through Mgmt `ListClusters` and fail with HTTP
  403 when `plan_replayer_status.enabled` is false or absent.
- On an enabled cluster, proxy only the documented NextGen operations:
  `GET .../planReplayerFiles` and `POST ...:generatePlanReplayerFileDownloadURL`.
- Preserve NextGen pagination semantics, including an empty page with a
  non-empty `nextPageToken`; pass an opaque page token unchanged.
- Return the upstream file metadata and signed HTTPS URL without exposing the
  configured NextGen token or object-storage credentials.

## Affected Modules and Routes

- Go module: repository root, `github.com/pingcap-inc/clinic`.
- Executable and image: Clinic API, `cmd/server/main.go`, image `clinic`.
- API package: `pkg/api/cluster` with route registration in `pkg/api/org`.
- Shared upstream client: `pkg/nextgen_client`; Mgmt lookup remains in
  `pkg/datasource.RealtimeGetMgmtCluster`.
- Intended Clinic UI routes:
  - `GET /clinic/api/v1/orgs/{oid}/clusters/{cid}/plan-replayer/files`
  - `POST /clinic/api/v1/orgs/{oid}/clusters/{cid}/plan-replayer/files/download-url`
- Deployment ownership: Clinic CD `components=clinic`; app-delivery
  `clinic-api` application, workload `clinic`, staging and `prod-cloud` only.

## Current Configuration and Compatibility

- Clinic already reads `dbaas-config.mgmt-svc-addr` and
  `dbaas-config.nextgen-svc-addr` from the environment-specific `clinic-api`
  ConfigMap. The respective staging and production overlays supply distinct
  VPC endpoint addresses.
- `dbaas-config.nextgen-svc-token` is defined in Clinic configuration and is
  used as a Bearer token by `pkg/nextgen_client`, but it is not present in the
  currently rendered Clinic ConfigMap or the checked ExternalSecret mapping.
  A deployment must inject it through an approved Secret/ExternalSecret path;
  it must never be added to a ConfigMap or source control.
- The pinned Mgmt API Go module predates `Cluster.plan_replayer_status`.
  Upgrade it to the Mgmt API revision that exposes the output-only field before
  enforcing the gate. This is a wire-compatible additive proto change.

## Implementation Steps

1. Upgrade the pinned Mgmt API dependency to a revision containing
   `PlanReplayerStatus` and verify the generated getter is available.
2. Extend the shared NextGen REST client with typed list and generate-download
   operations, including page-size/token and request-body validation.
3. Add a narrow cluster service that performs read authorization, Mgmt status
   gating, and the NextGen calls. Do not modify the legacy NGM Plan Replayer
   implementation.
4. Register the two Clinic API routes and map disabled Plan Replayer access to
   the existing forbidden error contract.
5. Add focused unit/handler regressions for authorization, disabled status,
   page-token forwarding, empty-page continuation, valid signed-URL responses,
   and malformed request values.
6. Render the staging and production `clinic-api` overlays to verify existing
   endpoint addresses and record the separate secret-injection prerequisite.
7. Run `go mod tidy` and the repository Swagger generator after the Mgmt API
   upgrade and route annotations, then commit the resulting module checksum
   cleanup and Clinic Swagger artifacts.
8. Use the established internal Clinic service identity for the Mgmt status
   lookup. `RealtimeGetMgmtCluster` requires both `Internal=true` and a
   PingCAP email suffix; omitting the email causes the local datasource gate to
   fail before it reaches Mgmt.
9. Emit structured lifecycle logs for both endpoints. Every request log carries
   `trace_id`; include safe operation, gate, pagination, result-count, and
   error fields, but never log authorization data, signed URLs, file names, or
   opaque page tokens.

## Exclusions

- No Clinic UI change.
- No direct S3/OSS listing, object download, or URL signing by Clinic.
- No change to NGM's historical `plan_replayer` file-download endpoints.
- No automatic commit, push, pull request, deployment, merge, or production
  release.

## Test Plan

From the repository root:

```bash
go test ./pkg/nextgen_client ./pkg/api/cluster ./pkg/api/org
go test ./pkg/api/...
make check-mod
make check-swagger
git diff --check
```

Run the smallest focused commands first; report any private-module or local
Docker dependency blockers separately.

## Staging Verification

After authorization to publish and deploy:

1. Ensure staging supplies the approved `nextgen-svc-token` Secret value and
   retains its staging Mgmt and NextGen endpoint addresses.
2. Deploy Clinic CD with `environment=staging`, `components=clinic`, then wait
   for the app-delivery `clinic-api` PR and GitOps rollout.
3. Use an authorized Premium logical cluster with the feature enabled to verify
   list pagination and a generated URL download.
4. Verify a disabled cluster receives HTTP 403 and does not invoke NextGen.
5. Check the Clinic Pod image/readiness when approved EKS access is available
   and inspect redacted Clinic logs for the two request paths.

## Release Boundary

Local source changes require only the Clinic API image. Required deployment
module: `clinic` through Clinic CD, updating app-delivery `clinic-api`; no
`ngm-api`, Data Service, or Kong image deployment is required. The secret
injection change, if absent in the target overlay, is a separate app-delivery
change requiring review. Production is limited to `prod-cloud` and requires
explicit release and app-delivery PR merge authorization.
