syntax = "proto3";

package tidb_cloud_open_api.serverless.v1beta1;

import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/field_mask.proto";
// buf:lint:ignore IMPORT_USED
import "google/rpc/status.proto"; // This is used by `responses.value.schema.json_schema.ref` in the swagger definition.
import "protoc-gen-openapiv2/options/annotations.proto";
import "tidb_cloud_open_api/common/v1beta1/region.proto";
import "tidb_cloud_open_api/common/v1beta1/service_plan.proto";
import "tidb_cloud_open_api/common/v1beta1/tag.proto";
import "tidb_cloud_open_api/serverless/v1beta1/resources.proto";

option go_package = "tidb_cloud_open_api/serverless/v1beta1";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  swagger: "2.0"
  host: "serverless.tidbapi.com"
  base_path: "/v1beta1"
  info: {
    version: "v1beta1"
    title: "TiDB Cloud Starter and Essential API"
    description: "*TiDB Cloud API is in beta.*\n\nThis API manages [TiDB Cloud Starter](https://docs.pingcap.com/tidbcloud/select-cluster-tier/#tidb-cloud-serverless) and [TiDB Cloud Essential](https://docs.pingcap.com/tidbcloud/select-cluster-tier/#essential) clusters. For [TiDB Cloud Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier/#tidb-cloud-dedicated) clusters, use the [TiDB Cloud Dedicated API](https://docs.pingcap.com/tidbcloud/api/v1beta1/dedicated/). For more information about TiDB Cloud API, see [TiDB Cloud API Overview](https://docs.pingcap.com/tidbcloud/api-overview/).\n\n# Overview\n\nThe TiDB Cloud API is a [REST interface](https://en.wikipedia.org/wiki/Representational_state_transfer) that provides you with programmatic access to manage clusters and related resources within TiDB Cloud.\n\nThe API has the following features:\n\n- **JSON entities.** All entities are expressed in JSON.\n- **HTTPS-only.** You can only access the API via HTTPS, ensuring all the data sent over the network is encrypted with TLS.\n- **Key-based access and digest authentication.** Before you access TiDB Cloud API, you must generate an API key. All requests are authenticated through [HTTP Digest Authentication](https://en.wikipedia.org/wiki/Digest_access_authentication), ensuring the API key is never sent over the network.\n\n# Get Started\n\nThis guide helps you make your first API call to TiDB Cloud API. You'll learn how to authenticate a request, build a request, and interpret the response.\n\n## Prerequisites\n\nTo complete this guide, you need to perform the following tasks:\n\n- Create a [TiDB Cloud account](https://tidbcloud.com/free-trial)\n- Install [curl](https://curl.se/)\n\n## Step 1. Create an API key\n\nTo create an API key, log in to your TiDB Cloud console. Navigate to the [**API Keys**](https://tidbcloud.com/org-settings/api-keys) page of your organization, and create an API key.\n\nAn API key contains a public key and a private key. Copy and save them in a secure location. You will need to use the API key later in this guide.\n\nFor more details about creating API key, refer to [API Key Management](#section/Authentication/API-Key-Management).\n\n## Step 2. Make your first API call\n\n### Build an API call\n\nTiDB Cloud API call consists of the following components:\n\n- **A host**. The host for TiDB Cloud API is <https://serverless.tidbapi.com>.\n- **An API Key**. The public key and the private key are required for authentication.\n- **A request**. When submitting data to a resource via `POST`, `PATCH`, or `PUT`, you must submit your payload in JSON.\n\nIn this guide, you call the [List all clusters](#tag/Cluster/operation/ClusterService_ListClusters) endpoint. For the detailed description of the endpoint, see the [API reference](#tag/Cluster/operation/ClusterService_ListClusters).\n\n### Call an API endpoint\n\nTo get all clusters in your organization, run the following command in your terminal. Remember to change `YOUR_PUBLIC_KEY` to your public key and `YOUR_PRIVATE_KEY` to your private key.\n\n```shell\ncurl --digest \\\n --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n --request GET \\\n --url 'https://serverless.tidbapi.com/v1beta1/clusters'\n```\n\n## Step 3. Check the response\n\nAfter making the API call, if the status code in response is `200` and you see details about all clusters in your organization, your request is successful.\n\n# Authentication\n\nThe TiDB Cloud API uses [HTTP Digest Authentication](https://en.wikipedia.org/wiki/Digest_access_authentication). It protects your private key from being sent over the network. For more details about HTTP Digest Authentication, refer to the [IETF RFC](https://datatracker.ietf.org/doc/html/rfc7616).\n\n## API key overview\n\n- The API key contains a public key and a private key, which act as the username and password required in the HTTP Digest Authentication. The private key only displays upon the key creation.\n- The API key belongs to your organization and acts as the `Organization Owner` role. You can check [permissions of owner](https://docs.pingcap.com/tidbcloud/manage-user-access#configure-member-roles).\n- You must provide the correct API key in every request. Otherwise, the TiDB Cloud responds with a `401` error.\n\n## API key management\n\n### Create an API key\n\nOnly the **owner** of an organization can create an API key.\n\nTo create an API key in an organization, perform the following steps:\n\n1. In the [TiDB Cloud console](https://tidbcloud.com), switch to your target organization using the combo box in the upper-left corner.\n2. In the left navigation pane, click **Organization Settings** > **API Keys**.\n3. On the **API Keys** page, click **Create API Key**.\n4. Enter a description for your API key. The role of the API key is always `Organization Owner` currently.\n5. Click **Next**. Copy and save the public key and the private key.\n6. Make sure that you have copied and saved the private key in a secure location. The private key only displays upon the creation. After leaving this page, you will not be able to get the full private key again.\n7. Click **Done**.\n\n### View details of an API key\n\nTo view details of an API key, perform the following steps:\n\n1. In the [TiDB Cloud console](https://tidbcloud.com), switch to your target organization using the combo box in the upper-left corner.\n2. In the left navigation pane, click **Organization Settings** > **API Keys**.\n3. You can view the details of the API keys on the page.\n\n### Edit an API key\n\nOnly the **owner** of an organization can modify an API key.\n\nTo edit an API key in an organization, perform the following steps:\n\n1. In the [TiDB Cloud console](https://tidbcloud.com), switch to your target organization using the combo box in the upper-left corner.\n2. In the left navigation pane, click **Organization Settings** > **API Keys**.\n3. On the **API Keys** page, click **...** in the API key row that you want to change, and then click **Edit**.\n4. You can update the API key description.\n5. Click **Update**.\n\n### Delete an API key\n\nOnly the **owner** of an organization can delete an API key.\n\nTo delete an API key in an organization, perform the following steps:\n\n1. In the [TiDB Cloud console](https://tidbcloud.com), switch to your target organization using the combo box in the upper-left corner.\n2. In the left navigation pane, click **Organization Settings** > **API Keys**.\n3. On the **API Keys** page, click **...** in the API key row that you want to delete, and then click **Delete**.\n4. Click **I understand, delete it.**\n\n# Rate Limiting\n\nThe TiDB Cloud API allows up to 100 requests per minute per API key. If you exceed the rate limit, the API returns a `429` error. For more quota, you can [submit a request](https://support.pingcap.com/hc/en-us/requests/new?ticket_form_id=7800003722519) to contact our support team.\n\nEach API request returns the following headers about the limit.\n\n- `X-Ratelimit-Limit-Minute`: The number of requests allowed per minute. It is 100 currently.\n- `X-Ratelimit-Remaining-Minute`: The number of remaining requests in the current minute. When it reaches `0`, the API returns a `429` error and indicates that you exceed the rate limit.\n- `X-Ratelimit-Reset`: The time in seconds at which the current rate limit resets.\n\nIf you exceed the rate limit, an error response returns like this.\n\n```\n> HTTP/2 429\n> date: Fri, 22 Jul 2022 05:28:37 GMT\n> content-type: application/json\n> content-length: 66\n> x-ratelimit-reset: 23\n> x-ratelimit-remaining-minute: 0\n> x-ratelimit-limit-minute: 100\n> x-kong-response-latency: 2\n> server: kong/2.8.1\n\n> {\"details\":[],\"code\":49900007,\"message\":\"The request exceeded the limit of 100 times per apikey per minute. For more quota, please contact us: https://support.pingcap.com/hc/en-us/requests/new?ticket_form_id=7800003722519\"}\n```\n\n# API Changelog\n\nThis changelog lists all changes to the TiDB Cloud API.\n\n<!-- In reverse chronological order -->\n\n## 20250812\n\n- Initial release of the TiDB Cloud Starter and Essential API, including the following resources and endpoints:\n\n - Cluster:\n - [List TiDB Cloud Starter and Essential clusters](#tag/Cluster/operation/ClusterService_ListClusters)\n - [Create a new TiDB Cloud Starter or Essential cluster](#tag/Cluster/operation/ClusterService_CreateCluster)\n - [Get details of a TiDB Cloud Starter or Essential cluster](#tag/Cluster/operation/ClusterService_GetCluster)\n - [Delete a TiDB Cloud Starter or Essential cluster](#tag/Cluster/operation/ClusterService_DeleteCluster)\n - [Update a TiDB Cloud Starter or Essential cluster](#tag/Cluster/operation/ClusterService_PartialUpdateCluster)\n - [List available regions for an organization](#tag/Cluster/operation/ClusterService_ListRegions)\n - Branch:\n - [List branches](#tag/Branch/operation/BranchService_ListBranches)\n - [Create a branch](#tag/Branch/operation/BranchService_CreateBranch)\n - [Get details of a branch](#tag/Branch/operation/BranchService_GetBranch)\n - [Delete a branch](#tag/Branch/operation/BranchService_DeleteBranch)\n - [Reset a branch](#tag/Branch/operation/BranchService_ResetBranch)\n - Export:\n - [List export tasks for a cluster](#tag/Export/operation/ExportService_ListExports)\n - [Create an export task](#tag/Export/operation/ExportService_CreateExport)\n - [Get details of an export task](#tag/Export/operation/ExportService_GetExport)\n - [Delete an export task](#tag/Export/operation/ExportService_DeleteExport)\n - [Cancel an export task](#tag/Export/operation/ExportService_CancelExport)\n - Import:\n - [List import tasks for a cluster](#tag/Import/operation/ImportService_ListImports)\n - [Create an import task](#tag/Import/operation/ImportService_CreateImport)\n - [Get an import task](#tag/Import/operation/ImportService_GetImport)\n - [Cancel an import task](#tag/Import/operation/ImportService_CancelImport)\n"
  }
  schemes: HTTPS
  external_docs: {
    url: "https://docs.pingcap.com/tidbcloud/api-overview"
    description: "More about TiDB Cloud API"
  }
  consumes: "application/json"
  produces: "application/json"

  // Define the common error responses.
  responses: {
    key: "400"
    value: {
      description: "A request field is invalid."
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
  responses: {
    key: "401"
    value: {
      description: "The API key cannot be authenticated."
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
  responses: {
    key: "403"
    value: {
      description: "The API key does not have permission to access the resource."
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
  responses: {
    key: "429"
    value: {
      description: "You have exceeded the rate limit."
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
  responses: {
    key: "500"
    value: {
      description: "Internal server error."
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
};

// The ClusterService provides APIs for managing TiDB Cloud Starter and Essential clusters.
service ClusterService {
  // Create a new TiDB Cloud Starter or Essential cluster
  rpc CreateCluster(CreateClusterRequest) returns (Cluster) {
    option (google.api.http) = {
      post: "/clusters"
      body: "cluster"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["Cluster"]
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl --location 'https://serverless.tidbapi.com/v1beta1/clusters' \\\n--digest --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--data '{\n    \"displayName\": \"test\",\n    \"labels\": {\n        \"tidb.cloud/project\": \"2293484\"\n    },\n    \"region\": {\n        \"name\": \"regions/aws-us-east-1\"\n    }\n}'"}
                }
              }
            }
          }
        }
      }
    };
  }

  // List TiDB Cloud Starter and Essential clusters
  rpc ListClusters(ListClustersRequest) returns (ListClustersResponse) {
    option (google.api.http) = {get: "/clusters"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["Cluster"]
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl --location 'https://serverless.tidbapi.com/v1beta1/clusters' \\\n--digest --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n--header 'Accept: application/json'"}
                }
              }
            }
          }
        }
      }
    };
  }

  // Get details of a TiDB Cloud Starter or Essential cluster
  rpc GetCluster(GetClusterRequest) returns (Cluster) {
    option (google.api.http) = {get: "/clusters/{cluster_id}"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["Cluster"]
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl --location 'https://serverless.tidbapi.com/v1beta1/clusters/{cluster_id}' \\\n--digest --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n--header 'Accept: application/json'"}
                }
              }
            }
          }
        }
      }
    };
  }

  rpc BindTags(BindTagsRequest) returns (BindTagsResponse) {
    option (google.api.http) = {
      post: "/clusters/{cluster_id}:bindTags"
      body: "*"
    };
  }

  rpc UnbindTags(UnbindTagsRequest) returns (UnbindTagsResponse) {
    option (google.api.http) = {
      post: "/clusters/{cluster_id}:unbindTags"
      body: "*"
    };
  }

  // Delete a TiDB Cloud Starter or Essential cluster
  rpc DeleteCluster(DeleteClusterRequest) returns (Cluster) {
    option (google.api.http) = {delete: "/clusters/{cluster_id}"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["Cluster"]
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl --location --request DELETE 'https://serverless.tidbapi.com/v1beta1/clusters/{cluster_id}' \\\n--digest --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n--header 'Accept: application/json'"}
                }
              }
            }
          }
        }
      }
    };
  }

  // Update a TiDB Cloud Starter or Essential cluster
  rpc PartialUpdateCluster(PartialUpdateClusterRequest) returns (Cluster) {
    option (google.api.http) = {
      patch: "/clusters/{cluster.cluster_id}"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["Cluster"]
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl --location --request PATCH 'https://serverless.tidbapi.com/v1beta1/clusters/{cluster_id}' \\\n--digest --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--data '{\n  \"updateMask\": \"displayName\",\n  \"cluster\": {\n    \"displayName\": \"test\",\n    \"spendingLimit\": {\n      \"monthly\": 10000\n    },\n    \"automatedBackupPolicy\": {\n      \"startTime\": \"10:00\"\n    },\n    \"endpoints\": {\n      \"public\": {\n        \"disabled\": false,\n        \"authorizedNetworks\": [\n          {\n            \"startIpAddress\": \"0.0.0.0\",\n            \"endIpAddress\": \"255.255.255.255\",\n            \"displayName\": \"allow-all\"\n          }\n        ]\n      }\n    },\n    \"labels\": {\n      \"label1\": \"label1\"\n    },\n    \"auditLogConfig\": {\n      \"enabled\": true,\n      \"unredacted\": true\n    },\n    \"autoScaling\": {\n      \"minRcu\": 20000,\n      \"maxRcu\": 30000\n    }\n  }\n}'"}
                }
              }
            }
          }
        }
      }
    };
  }

  // Changes the root password of a specific TiDB Cloud Serverless cluster
  rpc ChangeRootPassword(ChangeRootPasswordRequest) returns (ChangeRootPasswordResponse) {
    option (google.api.http) = {
      put: "/clusters/{cluster_id}/password"
      body: "*"
    };
  }

  // Triggers an asynchronous root password rotation.
  //
  // This API is currently designed for TiDB Cloud Starter clusters with
  // `POSTGRESQL_COMPATIBLE` engine type.
  rpc RotateRootPassword(RotateRootPasswordRequest) returns (RotateRootPasswordResponse) {
    option (google.api.http) = {
      post: "/clusters/{cluster_id}:rotateRootPassword"
      body: "*"
    };
  }

  // Returns the current stored root password and indicates whether a rotation
  // task is still running.
  //
  // This API is currently designed for TiDB Cloud Starter clusters with
  // `POSTGRESQL_COMPATIBLE` engine type.
  rpc RedeemRootPassword(RedeemRootPasswordRequest) returns (RedeemRootPasswordResponse) {
    option (google.api.http) = {
      post: "/clusters/{cluster_id}:redeemRootPassword"
      body: "*"
    };
  }

  // List available regions for an organization
  //
  // Before creating a TiDB Cloud Starter or Essential cluster, you can use this endpoint to list available regions in your organization.
  rpc ListRegions(ListRegionsRequest) returns (ListRegionsResponse) {
    option (google.api.http) = {get: "/regions"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["Cluster"]
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl --location 'https://serverless.tidbapi.com/v1beta1/regions' \\\n--digest --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n--header 'Accept: application/json'"}
                }
              }
            }
          }
        }
      }
    };
  }

  // List available cloud providers for an organization
  rpc ListCloudProviders(ListCloudProvidersRequest) returns (ListCloudProvidersResponse) {
    option (google.api.http) = {get: "/regions:listCloudProviders"};
  }

  // Creates new TiDB Cloud Starter and Essential clusters in batch
  //
  // The operation is atomic: it fails for all clusters or succeeds for all clusters (no partial success).
  rpc BatchCreateClusters(BatchCreateClustersRequest) returns (BatchCreateClustersResponse) {
    option (google.api.http) = {
      post: "/clusters:batchCreate"
      body: "*"
    };
  }

  // Retrieves details of TiDB Cloud Starter and Essential clusters in batch
  //
  // The operation is atomic: it fails for all clusters or succeeds for all clusters (no partial success).
  // For situations requiring partial failures, ListClusters method should be used.
  rpc BatchGetClusters(BatchGetClustersRequest) returns (BatchGetClustersResponse) {
    option (google.api.http) = {get: "/clusters:batchGet"};
  }

  // Deletes TiDB Cloud Starter and Essential clusters in batch.
  rpc BatchDeleteClusters(BatchDeleteClustersRequest) returns (BatchDeleteClustersResponse) {
    option (google.api.http) = {
      post: "/clusters:batchDelete"
      body: "*"
    };
  }

  rpc ClaimClusterFromZero(ClaimClusterFromZeroRequest) returns (Cluster) {
    option (google.api.http) = {
      post: "/clusters:claimFromZero"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["Cluster"]
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl --location 'https://serverless.tidbapi.com/v1beta1/clusters:claimFromZero' \\\n--digest --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--data '{\n  \"claimToken\": \"your-claim-token\"\n}'"}
                }
              }
            }
          }
        }
      }
    };
  }

  rpc TakeoverClusterFromPool(TakeoverClusterFromPoolRequest) returns (Cluster) {
    option (google.api.http) = {
      post: "/clusters:takeoverFromPool"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["Cluster"]
    };
  }
}

// The ShadowPoolService provides APIs for managing TiDB Cloud Starter shadow pools.
service ShadowPoolService {
  // Create a new shadow pool.
  //
  // Currently, only service plan `Starter` is supported.
  rpc CreateShadowPool(CreateShadowPoolRequest) returns (ShadowPool) {
    option (google.api.http) = {
      post: "/shadowPools"
      body: "shadow_pool"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["ShadowPool"]
    };
  }

  // List shadow pools.
  rpc ListShadowPools(ListShadowPoolsRequest) returns (ListShadowPoolsResponse) {
    option (google.api.http) = {get: "/shadowPools"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["ShadowPool"]
    };
  }

  // Get details of a shadow pool.
  rpc GetShadowPool(GetShadowPoolRequest) returns (ShadowPool) {
    option (google.api.http) = {get: "/shadowPools/{shadow_pool_id}"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["ShadowPool"]
    };
  }

  // Delete a shadow pool.
  rpc DeleteShadowPool(DeleteShadowPoolRequest) returns (DeleteShadowPoolResponse) {
    option (google.api.http) = {delete: "/shadowPools/{shadow_pool_id}"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["ShadowPool"]
    };
  }

  // Update mutable common fields of a shadow pool.
  //
  // Only `name`, `min_capacity`, and `enabled` are allowed in `update_mask`.
  rpc UpdateShadowPool(UpdateShadowPoolRequest) returns (ShadowPool) {
    option (google.api.http) = {
      patch: "/shadowPools/{shadow_pool.shadow_pool_id}"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["ShadowPool"]
    };
  }

  // Replace init SQLs of a shadow pool.
  rpc ReplaceShadowPoolInitSqls(ReplaceShadowPoolInitSqlsRequest) returns (ShadowPool) {
    option (google.api.http) = {
      post: "/shadowPools/{shadow_pool_id}:replaceInitSqls"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["ShadowPool"]
    };
  }

  // Replace instance demand configuration of a shadow pool.
  rpc ReplaceShadowPoolInstanceDemand(ReplaceShadowPoolInstanceDemandRequest) returns (ShadowPool) {
    option (google.api.http) = {
      post: "/shadowPools/{shadow_pool_id}:replaceInstanceDemand"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags: ["ShadowPool"]
    };
  }
}

// Message for requesting to create a TiDB Cloud Starter or Essential cluster.
message CreateClusterRequest {
  // The cluster to create.
  // (-- api-linter: core::0203::field-behavior-required=disabled
  //     aip.dev/not-precedent: https://github.com/grpc-ecosystem/grpc-gateway/issues/3058 --)
  // (-- api-linter: core::0133::request-resource-behavior=disabled
  //     aip.dev/not-precedent: --)
  Cluster cluster = 1;
}

// Message for requesting a list of TiDB Cloud Starter and Essential clusters.
message ListClustersRequest {
  // The maximum number of clusters to return. If not specified, at most 10 clusters will be returned. The maximum value is `100`. Values greater than `100` are set to `100`.
  int32 page_size = 1 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      default: "10"
      minimum: 1
      maximum: 100
    }
  ];

  // The pagination token received from a previous [List clusters](#tag/Cluster/operation/ClusterService_ListClusters) request. Use this token to retrieve the next page of results.
  //
  // **Note**: When paginating, all other parameters must match the original request.
  string page_token = 2 [(google.api.field_behavior) = OPTIONAL];

  // An expression that filters the list of clusters based on specific criteria. Uses Google AIP syntax with `=` and `AND` operators. You can filter by `region`, `state`, `projectId`, `clusterId`, `displayName`, and `labels`.
  //
  // **Available filters**:
  // - `region.provider`: the cloud provider where the cluster is located, such as `aws` or `alicloud`.
  // - `region.name`: the name of the region where the cluster is located, in the format of `regions/{provider}-{region}`, such as `regions/aws-us-east-1`.
  // - `state`: the state of the cluster state, such as `ACTIVE` or `CREATING`.
  // - `projectId`: the ID of the project ID. You can specify multiple values separated by commas.
  // - `clusterId`: the ID of the cluster. You can specify multiple values separated by commas.
  // - `displayName`: the display name of the cluster.
  // - `labels.{key}`: the labels of the cluster labels, such as `labels.environment=production`.
  //
  // **Examples**:
  // - `filter=region.provider="aws" AND state="ACTIVE"`
  // - `filter=projectId=12345 AND displayName="my-cluster"`
  string filter = 3 [(google.api.field_behavior) = OPTIONAL];

  // The number of individual resources to skip before starting to return results.
  string order_by = 4 [(google.api.field_behavior) = OPTIONAL];

  repeated string tags = 5 [(google.api.field_behavior) = OPTIONAL];

  // The number of clusters to skip before returning results. If the value exceeds the total number of clusters, the response is `200` with an empty list and no `nextPageToken`.
  int32 skip = 101 [(.google.api.field_behavior) = OPTIONAL];
}

// Responses message to the request for listing of TiDB Cloud Starter and Essential clusters.
message ListClustersResponse {
  // A list of clusters that match the query.
  repeated Cluster clusters = 1;

  // The token to retrieve the next page of results. Use this value as the `pageToken` parameter in the next request. This field is empty when there are no more pages.
  string next_page_token = 2;

  // The total number of clusters that match the query.
  uint32 total_size = 3;
}

// Message for requesting to retrieve a specific TiDB Cloud Starter or Essential cluster.
message GetClusterRequest {
  // The ID of the cluster to retrieve.
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];

  // The detail level of the cluster information to return.
  //
  // - `BASIC`: returns only basic cluster information.
  // - `FULL`: returns complete cluster details.
  ClusterView view = 2 [(google.api.field_behavior) = OPTIONAL];
}

message BindTagsRequest {
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  repeated string tags = 2 [(google.api.field_behavior) = REQUIRED];
}

message BindTagsResponse {
  repeated common.v1beta1.Tag tags = 1;
}

message UnbindTagsRequest {
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
  repeated string tags = 2 [(google.api.field_behavior) = REQUIRED];
}

message UnbindTagsResponse {
  repeated common.v1beta1.Tag tags = 1;
}

// Message for requesting the deletion of a TiDB Cloud Starter or Essential cluster.
message DeleteClusterRequest {
  // The ID of the cluster to delete.
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Message for requesting a partial update on a TiDB Cloud Starter or Essential cluster.
message PartialUpdateClusterRequest {
  PartialUpdateCluster cluster = 1 [(google.api.field_behavior) = REQUIRED];

  // Specifies which fields to update in the cluster.
  google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];

  // The updated cluster configuration.
  message PartialUpdateCluster {
    // The ID of the cluster to update.
    string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];

    // The user-defined name of the cluster.
    string display_name = 2 [(google.api.field_behavior) = OPTIONAL];

    // The [spending limit](https://docs.pingcap.com/tidbcloud/tidb-cloud-glossary/#spending-limit) for the cluster.
    Cluster.SpendingLimit spending_limit = 3 [(google.api.field_behavior) = OPTIONAL];

    // The schedule and retention rules for automated database backups.
    Cluster.AutomatedBackupPolicy automated_backup_policy = 4 [(google.api.field_behavior) = OPTIONAL];

    // The connection endpoints for accessing the cluster.
    Cluster.Endpoints endpoints = 5 [(google.api.field_behavior) = OPTIONAL];

    // The labels for the cluster.
    //
    // - `tidb.cloud/organization`: the ID of the organization where the cluster belongs.
    // - `tidb.cloud/project`: the ID of the project where the cluster belongs.
    map<string, string> labels = 6 [(google.api.field_behavior) = OPTIONAL];

    // The audit log configuration for the cluster.
    Cluster.AuditLogConfig audit_log_config = 7 [(google.api.field_behavior) = OPTIONAL];

    // The auto-scaling configuration for the cluster.
    Cluster.AutoScaling auto_scaling = 8 [(google.api.field_behavior) = OPTIONAL];
  }
}

// Message for requesting a list of TiDB Cloud Starter and Essential regions.
message ListRegionsRequest {
  // If specified, only regions of the specified cloud provider will be returned.
  string cloud_provider = 1 [(google.api.field_behavior) = OPTIONAL];

  // If specified, only regions that support the specified service plan will be returned.
  common.v1beta1.ServicePlan service_plan = 2 [(google.api.field_behavior) = OPTIONAL];
}

// Responses message to the request for listing of available regions in TiDB Cloud Starter and Essential.
message ListRegionsResponse {
  // A list of available regions.
  repeated common.v1beta1.Region regions = 1;
}

message ListCloudProvidersRequest {}

message ListCloudProvidersResponse {
  // The list of cloud providers.
  repeated common.v1beta1.Region.CloudProvider cloud_providers = 1;
}

// Message for requesting to change the root password of a TiDB Cloud Starter or Essential cluster.
message ChangeRootPasswordRequest {
  // The ID of the cluster for which the password is to be changed.
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];

  // The new root password for the cluster.
  string password = 2 [(google.api.field_behavior) = REQUIRED];
}

// Responses message to the request for changing the root password of a TiDB Cloud Starter or Essential cluster.
message ChangeRootPasswordResponse {}

// Message for requesting asynchronous root password rotation.
message RotateRootPasswordRequest {
  // The ID of the cluster for which the root password should be rotated.
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Response for asynchronous root password rotation request.
message RotateRootPasswordResponse {
  // Whether a root password rotation task is running for this cluster.
  bool rotating = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Message for requesting the current root password and rotation status.
message RedeemRootPasswordRequest {
  // The ID of the cluster for which the root password should be redeemed.
  string cluster_id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Response for root password redemption.
message RedeemRootPasswordResponse {
  // Whether a root password rotation task is running for this cluster.
  bool rotating = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The current root password persisted in TiDB Cloud internal storage.
  string password = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Enum for the different types of detail view to be returned for a TiDB Cloud Starter or Essential cluster.
enum ClusterView {
  // The server default is used if unspecified.
  CLUSTER_VIEW_UNSPECIFIED = 0;

  BASIC = 1;

  FULL = 2;
}

// Message for requesting to create a batch of TiDB Cloud Starter and Essential clusters.
message BatchCreateClustersRequest {
  // The request message specifying the resources to create.
  // A maximum of 1000 clusters can be created in a batch.
  repeated CreateClusterRequest requests = 1 [(google.api.field_behavior) = REQUIRED];
}

// Responses message to the request for creating a batch of TiDB Cloud Starter and Essential clusters.
message BatchCreateClustersResponse {
  // Clusters created.
  repeated Cluster clusters = 1;
}

// Message for requesting to retrieve a batch of TiDB Cloud Starter and Essential clusters.
message BatchGetClustersRequest {
  // A maximum of 1000 clusters can be get in a batch.
  repeated string cluster_ids = 1 [(google.api.field_behavior) = REQUIRED];

  // The level of detail to return for the cluster.
  ClusterView view = 2 [(google.api.field_behavior) = OPTIONAL];
}

// Responses message to the request for retrieving a batch of TiDB Cloud Starter and Essential clusters.
message BatchGetClustersResponse {
  // Clusters created.
  repeated Cluster clusters = 1;
}

// Message for requesting to delete a batch of TiDB Cloud Starter and Essential clusters.
message BatchDeleteClustersRequest {
  // A maximum of 500 clusters can be deleted in a batch.
  repeated string cluster_ids = 1 [(google.api.field_behavior) = REQUIRED];
}

// Responses message to the request for deleting a batch of TiDB Cloud Starter and Essential clusters.
message BatchDeleteClustersResponse {
  // Total number of unique cluster IDs in this request.
  int32 total = 1;

  // Successfully deleted cluster IDs.
  repeated string success_cluster_ids = 2;

  // Failed cluster IDs.
  repeated string failed_cluster_ids = 3;
}

message ClaimClusterFromZeroRequest {
  Cluster cluster = 1 [(google.api.field_behavior) = REQUIRED];
  string zero_id = 2 [(google.api.field_behavior) = REQUIRED];

  ClaimMode claim_mode = 3 [(google.api.field_behavior) = OPTIONAL];
  bool validate_only = 100;

  enum ClaimMode {
    CLAIM_MODE_UNSPECIFIED = 0;
    // Claim a cluster from zero with data migration.
    // It will create a new cluster and migrate data from the original cluster to the new cluster.
    // The original cluster will be deleted after the migration is completed.
    CLAIM_MODE_MIGRATION = 1;
    // Claim a cluster from zero by taking over the original cluster.
    // It will directly take over the original cluster without data migration.
    // The original cluster's org id will be changed to the customer's organization.
    // The original cluster will be updated to the new cluster configuration.
    CLAIM_MODE_TAKEOVER = 2;
  }
}

message TakeoverClusterFromPoolRequest {
  string pool_id = 1 [(google.api.field_behavior) = REQUIRED];
  string root_password = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Message for requesting to create a shadow pool.
message CreateShadowPoolRequest {
  // The shadow pool to create.
  ShadowPool shadow_pool = 1 [(google.api.field_behavior) = REQUIRED];

  bool validate_only = 100 [(google.api.field_behavior) = OPTIONAL];
}

// Message for requesting a specific shadow pool.
message GetShadowPoolRequest {
  // The ID of the shadow pool to retrieve.
  string shadow_pool_id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Message for requesting a list of shadow pools.
message ListShadowPoolsRequest {
  // The maximum number of shadow pools to return.
  int32 page_size = 1 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      default: "10"
      minimum: 1
      maximum: 100
    }
  ];

  // The pagination token received from a previous list request.
  string page_token = 2 [(google.api.field_behavior) = OPTIONAL];
}

// Response for listing shadow pools.
message ListShadowPoolsResponse {
  // A list of shadow pools that match the query.
  repeated ShadowPool shadow_pools = 1;

  // The token to retrieve the next page of results.
  string next_page_token = 2;

  // The total number of shadow pools that match the query.
  uint32 total_size = 3;
}

// Message for updating mutable common fields of a shadow pool.
message UpdateShadowPoolRequest {
  // The target shadow pool and updated values.
  //
  // `shadow_pool_id` is required.
  ShadowPool shadow_pool = 1 [(google.api.field_behavior) = REQUIRED];

  // Specifies which fields to update.
  //
  // Allowed fields: `name`, `min_capacity`, `enabled`.
  google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
}

// Message for replacing init SQLs of a shadow pool.
message ReplaceShadowPoolInitSqlsRequest {
  // The ID of the shadow pool to update.
  string shadow_pool_id = 1 [(google.api.field_behavior) = REQUIRED];

  // SQL statements to execute during cluster initialization.
  repeated string init_sqls = 2 [(google.api.field_behavior) = REQUIRED];

  bool validate_only = 100 [(google.api.field_behavior) = OPTIONAL];
}

// Message for replacing instance demand of a shadow pool.
message ReplaceShadowPoolInstanceDemandRequest {
  // The ID of the shadow pool to update.
  string shadow_pool_id = 1 [(google.api.field_behavior) = REQUIRED];

  // The target instance demand configuration.
  ShadowPool.InstanceDemand instance_demand = 2 [(google.api.field_behavior) = REQUIRED];
}

// Message for deleting a shadow pool.
message DeleteShadowPoolRequest {
  // The ID of the shadow pool to delete.
  string shadow_pool_id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Response for deleting a shadow pool.
message DeleteShadowPoolResponse {}
