{
  "repo": "tidbcloud/dataservices",
  "binary": "adminapi",
  "binary_path": "cmd/adminapi/main.go",
  "dependencies": {
    "AdminAPILifecycle.LoadConfigAndDatabase": {
      "infrastructure": {
        "filesystem": {
          "conditions": [
            "Always at startup"
          ],
          "operations": [
            {
              "operation": "READ FILE",
              "trigger": "Load the service config before database and tiinf runtime initialization",
              "conditions": [
                "Always"
              ],
              "implementation": "config.InitConfig(configPath)"
            }
          ]
        },
        "mysql": {
          "conditions": [
            "Always at startup"
          ],
          "operations": [
            {
              "operation": "CONNECT",
              "trigger": "Create the shared SQL connection used by eventbus and admin service helpers",
              "conditions": [
                "Always"
              ],
              "implementation": "database.Connect(ctx, ...)"
            }
          ]
        }
      },
      "services": []
    },
    "AdminAPILifecycle.StartEventbus": {
      "infrastructure": {
        "mysql": {
          "conditions": [
            "Only when local mode is disabled"
          ],
          "operations": [
            {
              "operation": "SUBSCRIBE / RUN LOOP",
              "trigger": "Run the dataservice_adminapi eventbus consumer",
              "conditions": [
                "!config.IsLocalMode()"
              ],
              "implementation": "eventbusStartup(ctx, db)"
            }
          ]
        }
      },
      "services": []
    },
    "AdminAPILifecycle.InitDynamoDB": {
      "infrastructure": {
        "dynamodb": {
          "conditions": [
            "Only when local mode is disabled"
          ],
          "operations": [
            {
              "operation": "CONNECT",
              "trigger": "Initialize DynamoDB-backed helpers consumed by central/admin workflows",
              "conditions": [
                "!config.IsLocalMode()"
              ],
              "implementation": "ddb.Init(ctx, config)"
            }
          ]
        }
      },
      "services": []
    },
    "AdminAPILifecycle.CreateTiinfRuntime": {
      "infrastructure": {},
      "services": []
    },
    "AdminAPILifecycle.RegisterGrpcServices": {
      "infrastructure": {},
      "services": []
    },
    "AdminAPILifecycle.RegisterHttpGateway": {
      "infrastructure": {},
      "services": [
        {
          "name": "account-provider",
          "target_repo": "tidbcloud/account",
          "target_interface": "Auth account client initialization",
          "operation_type": "grpc_connect",
          "conditions": [
            "Always when HTTP gateway is configured"
          ],
          "operations": [
            {
              "operation": "INITIALIZE ACCOUNT CLIENT",
              "trigger": "Enable HTTP auth + permission middleware before mounting grpc-gateway",
              "conditions": [
                "Always"
              ],
              "implementation": "SetupHttpServer -> auth.InitAccountClientByEndpoint(cfg.TiInfConfig.RPCConnConfig.AccountProvider, 0)"
            }
          ]
        },
        {
          "name": "adminapi-local-grpc",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "ApiKeyService|ApiSpecService|DataAppsService|DataSourcesService|EndpointsService|DeploymentsService",
          "operation_type": "grpc_gateway_proxy",
          "conditions": [
            "Always"
          ],
          "operations": [
            {
              "operation": "REGISTER grpc-gateway",
              "trigger": "Expose /v1beta1/*any as REST over the local gRPC services",
              "conditions": [
                "Always"
              ],
              "implementation": "registerGrpcGateway -> Register*Handler(context.Background(), mux, conn)"
            }
          ]
        }
      ]
    },
    "AdminAPILifecycle.RunTiinfRuntime": {
      "infrastructure": {
        "tcp": {
          "conditions": [
            "Always at startup"
          ],
          "operations": [
            {
              "operation": "LISTEN",
              "trigger": "Run the tiinf-managed HTTP and gRPC listeners",
              "conditions": [
                "Always"
              ],
              "implementation": "inf.Run()"
            }
          ]
        }
      },
      "services": []
    },
    "HTTP GET /healthz": {
      "infrastructure": {},
      "services": []
    },
    "Runtime AdminAPIGateway.RouteV1beta1": {
      "infrastructure": {},
      "services": [
        {
          "name": "adminapi-local-grpc",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "All adminapi gRPC services",
          "operation_type": "grpc_gateway_proxy",
          "conditions": [
            "Only after auth middleware, permission checks, and CheckApiKeyAppPermission all pass"
          ],
          "operations": [
            {
              "operation": "REST TO gRPC",
              "trigger": "Forward REST calls to the corresponding adminapi gRPC handler",
              "conditions": [
                "The request path matches /v1beta1/*any"
              ],
              "implementation": "router.Any(\"v1beta1/*any\", gin.WrapF(mux.ServeHTTP))"
            }
          ]
        }
      ]
    },
    "DataAppsService.CreateDataApp": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "CreateDataApp",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after org/project ids and cluster ids parse successfully"
          ],
          "operations": [
            {
              "operation": "CREATE DATAAPP",
              "trigger": "Create the dataapp and its initial clusters/endpoints through the shared central service layer",
              "conditions": [
                "App type is DATAAPP or CHAT2QUERY",
                "All cluster ids are valid"
              ],
              "implementation": "DataAppService.CreateDataApp -> service.CreateDataApp(ctx, orgId, projectId, createdBy, &input)"
            }
          ]
        }
      ]
    },
    "DataAppsService.ListDataApps": {
      "infrastructure": {
        "mysql": {
          "conditions": [
            "Always after request validation"
          ],
          "operations": [
            {
              "operation": "SELECT APP-CLUSTER LINKS",
              "trigger": "Enrich each listed dataapp with its bound clusters",
              "conditions": [
                "For each dataapp in the result page"
              ],
              "implementation": "dataappEntity2GrpcEntity -> repository.ListAppClusterByAppId(ctx, app.ID)"
            }
          ]
        }
      },
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "ListDataApps",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after project id and page token validation succeed"
          ],
          "operations": [
            {
              "operation": "LIST DATAAPPS",
              "trigger": "Fetch the project's dataapp list",
              "conditions": [
                "projectId parsed successfully"
              ],
              "implementation": "DataAppService.ListDataApps -> service.ListDataApps(ctx, projectId, appTypeList...)"
            }
          ]
        }
      ]
    },
    "DataAppsService.GetDataApp": {
      "infrastructure": {
        "mysql": {
          "conditions": [
            "Only after innerAppId resolution succeeds"
          ],
          "operations": [
            {
              "operation": "SELECT APP-CLUSTER LINKS",
              "trigger": "Enrich the returned dataapp with its bound clusters",
              "conditions": [
                "Dataapp was found"
              ],
              "implementation": "dataappEntity2GrpcEntity -> repository.ListAppClusterByAppId(ctx, app.ID)"
            }
          ]
        }
      },
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId resolution succeeds"
          ],
          "operations": [
            {
              "operation": "GET DATAAPP",
              "trigger": "Load the dataapp by inner app id",
              "conditions": [
                "innerAppId present in gRPC metadata"
              ],
              "implementation": "DataAppService.GetDataApp -> service.GetDataApp(ctx, innerAppId)"
            }
          ]
        }
      ]
    },
    "DataAppsService.UpdateDataApp": {
      "infrastructure": {
        "mysql": {
          "conditions": [
            "Only after update succeeds and the fresh entity is reloaded"
          ],
          "operations": [
            {
              "operation": "SELECT APP-CLUSTER LINKS",
              "trigger": "Enrich the updated dataapp with its bound clusters",
              "conditions": [
                "service.GetDataApp succeeded"
              ],
              "implementation": "dataappEntity2GrpcEntity -> repository.ListAppClusterByAppId(ctx, app.ID)"
            }
          ]
        }
      },
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "UpdateDataApp + GetDataApp",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId resolution succeeds"
          ],
          "operations": [
            {
              "operation": "UPDATE DATAAPP",
              "trigger": "Persist the editable dataapp fields",
              "conditions": [
                "innerAppId present in gRPC metadata"
              ],
              "implementation": "DataAppService.UpdateDataApp -> service.UpdateDataApp(ctx, innerAppId, &entity.UpdateDataAppParam{...}, createdBy)"
            },
            {
              "operation": "RELOAD DATAAPP",
              "trigger": "Fetch the post-update entity before returning it",
              "conditions": [
                "UpdateDataApp succeeded"
              ],
              "implementation": "DataAppService.UpdateDataApp -> service.GetDataApp(ctx, innerAppId)"
            }
          ]
        }
      ]
    },
    "DataAppsService.DeleteDataApp": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "DeleteDataApp",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId resolution succeeds"
          ],
          "operations": [
            {
              "operation": "DELETE DATAAPP",
              "trigger": "Delete the dataapp under API key operator semantics",
              "conditions": [
                "innerAppId present in gRPC metadata"
              ],
              "implementation": "DataAppService.DeleteDataApp -> service.DeleteDataApp(ctx, innerAppId, createdBy, account.OperatorType_OPERATOR_TYPE_APIKEY)"
            }
          ]
        }
      ]
    },
    "DataAppsService.GetChat2QuerySettings": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp",
          "operation_type": "local_service_call",
          "conditions": [
            "Always before proxying to EDA"
          ],
          "operations": [
            {
              "operation": "LOAD DATAAPP",
              "trigger": "Resolve app metadata used to build the EDA proxy URL",
              "conditions": [
                "innerAppId present in gRPC metadata"
              ],
              "implementation": "DataAppService.GetChat2QuerySettings -> service.GetDataApp(ctx, innerAppId)"
            }
          ]
        },
        {
          "name": "eda-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GET /api/v1/dataservices/central/.../chat2query/settings",
          "operation_type": "http_get",
          "conditions": [
            "Only after app lookup succeeds"
          ],
          "operations": [
            {
              "operation": "HTTP GET",
              "trigger": "Fetch chat2query settings through the EDA proxy path",
              "conditions": [
                "service.GetDataApp succeeded"
              ],
              "implementation": "commonhttp.ProxyToEDAService(ctx, appInfo, httpReq, http.MethodGet, time.Second*60)"
            }
          ]
        }
      ]
    },
    "DataAppsService.UpdateChat2QuerySettings": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp",
          "operation_type": "local_service_call",
          "conditions": [
            "Always before proxying to EDA"
          ],
          "operations": [
            {
              "operation": "LOAD DATAAPP",
              "trigger": "Resolve app metadata used to build the EDA proxy URL",
              "conditions": [
                "innerAppId present in gRPC metadata"
              ],
              "implementation": "DataAppService.UpdateChat2QuerySettings -> service.GetDataApp(ctx, innerAppId)"
            }
          ]
        },
        {
          "name": "eda-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "PUT /api/v1/dataservices/central/.../chat2query/settings",
          "operation_type": "http_put",
          "conditions": [
            "Only after app lookup and payload marshaling succeed"
          ],
          "operations": [
            {
              "operation": "HTTP PUT",
              "trigger": "Persist chat2query settings through the EDA proxy path",
              "conditions": [
                "service.GetDataApp succeeded",
                "json.Marshal(req.Chat2QuerySettings) succeeded"
              ],
              "implementation": "commonhttp.ProxyToEDAService(ctx, appInfo, httpReq, http.MethodPut, time.Second*60)"
            }
          ]
        }
      ]
    },
    "DataAppsService.UpdateSystemEndpointConfig": {
      "infrastructure": {
        "mysql": {
          "conditions": [
            "Only within the surrounding transaction"
          ],
          "operations": [
            {
              "operation": "TRANSACTION",
              "trigger": "Persist and then immediately reload system endpoint config under one transaction",
              "conditions": [
                "service.GetDataApp succeeded"
              ],
              "implementation": "repository.Transaction(ctx, func(ctx context.Context) error { service.SaveSystemEndpointConfig(...); service.GetSystemEndpointConfig(...) })"
            }
          ]
        }
      },
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + SaveSystemEndpointConfig + GetSystemEndpointConfig",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId resolution succeeds"
          ],
          "operations": [
            {
              "operation": "SAVE + RELOAD SYSTEM ENDPOINT CONFIG",
              "trigger": "Update and return the system endpoint config atomically",
              "conditions": [
                "innerAppId present in gRPC metadata"
              ],
              "implementation": "DataAppService.UpdateSystemEndpointConfig -> service.GetDataApp / service.SaveSystemEndpointConfig / service.GetSystemEndpointConfig"
            }
          ]
        }
      ]
    },
    "DataAppsService.GetSystemEndpointConfig": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + GetSystemEndpointConfig",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId resolution succeeds"
          ],
          "operations": [
            {
              "operation": "GET SYSTEM ENDPOINT CONFIG",
              "trigger": "Load app metadata and then fetch the persisted system endpoint config",
              "conditions": [
                "innerAppId present in gRPC metadata"
              ],
              "implementation": "DataAppService.GetSystemEndpointConfig -> service.GetDataApp(ctx, innerAppId); service.GetSystemEndpointConfig(ctx, res.ID)"
            }
          ]
        }
      ]
    },
    "DataSourcesService.CreateDataSource": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataAppByExtId + CreateAppCluster + GetAppCluster",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after external app id and cluster id validation succeed"
          ],
          "operations": [
            {
              "operation": "CREATE APP-CLUSTER LINK",
              "trigger": "Bind the app to a cluster and return the new datasource view",
              "conditions": [
                "clusterID parsed successfully"
              ],
              "implementation": "DataSourceService.CreateDataSource -> service.GetDataAppByExtId / service.CreateAppCluster / service.GetAppCluster"
            }
          ]
        }
      ]
    },
    "DataSourcesService.GetDataSource": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetAppCluster",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId and cluster id resolution succeed"
          ],
          "operations": [
            {
              "operation": "GET APP-CLUSTER LINK",
              "trigger": "Load the datasource representation by cluster id",
              "conditions": [
                "params.ClusterId > 0"
              ],
              "implementation": "DataSourceService.GetDataSource -> service.GetAppCluster(ctx, innerAppId, params.ClusterId)"
            }
          ]
        }
      ]
    },
    "DataSourcesService.ListDataSources": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataAppByExtId + ListAppCluster",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after external app id and page token validation succeed"
          ],
          "operations": [
            {
              "operation": "LIST APP-CLUSTER LINKS",
              "trigger": "List cluster bindings for the target dataapp",
              "conditions": [
                "service.GetDataAppByExtId succeeded"
              ],
              "implementation": "DataSourceService.ListDataSources -> service.GetDataAppByExtId / service.ListAppCluster(ctx, dto.ListAppClusterReq{DataappID: appInfo.ID})"
            }
          ]
        }
      ]
    },
    "DataSourcesService.DeleteDataSource": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "DeleteAppCluster",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId and cluster id resolution succeed"
          ],
          "operations": [
            {
              "operation": "DELETE APP-CLUSTER LINK",
              "trigger": "Remove the datasource binding from the dataapp",
              "conditions": [
                "params.ClusterId > 0"
              ],
              "implementation": "DataSourceService.DeleteDataSource -> service.DeleteAppCluster(ctx, dto.DeleteAppClusterReq{...})"
            }
          ]
        }
      ]
    },
    "EndpointsService.ListEndpoints": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + ListEndpointsWithPreID + LoadEndpointPublishID",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId and page-token validation succeed"
          ],
          "operations": [
            {
              "operation": "LIST ENDPOINTS",
              "trigger": "Load endpoints and enrich them with publish id metadata",
              "conditions": [
                "innerAppId present in gRPC metadata"
              ],
              "implementation": "EndpointsService.ListEndpoints -> service.GetDataApp / service.ListEndpointsWithPreID / service.LoadEndpointPublishID"
            }
          ]
        }
      ]
    },
    "EndpointsService.CreateEndpoint": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + CheckDataAppHasCluster + SaveEndpoint",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId and optional cluster id validation succeed"
          ],
          "operations": [
            {
              "operation": "CREATE ENDPOINT",
              "trigger": "Persist a new endpoint under the dataapp",
              "conditions": [
                "dataapp is not chat2query",
                "cluster membership check passes when clusterID > 0"
              ],
              "implementation": "EndpointsService.CreateEndpoint -> service.GetDataApp / service.CheckDataAppHasCluster / service.SaveEndpoint"
            }
          ]
        }
      ]
    },
    "EndpointsService.GetEndpoint": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + GetEndpoint + LoadEndpointPublishID",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after endpoint id resolution succeeds"
          ],
          "operations": [
            {
              "operation": "GET ENDPOINT",
              "trigger": "Load endpoint details and its publish metadata",
              "conditions": [
                "params.EndpointId > 0"
              ],
              "implementation": "EndpointsService.GetEndpoint -> service.GetDataApp / service.GetEndpoint / service.LoadEndpointPublishID"
            }
          ]
        }
      ]
    },
    "EndpointsService.UpdateEndpoint": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + CheckDataAppHasCluster + GetEndpoint + SaveEndpoint",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after endpoint id resolution succeeds"
          ],
          "operations": [
            {
              "operation": "UPDATE ENDPOINT",
              "trigger": "Persist endpoint edits, applying allowed-key restrictions for system/chat2query endpoints",
              "conditions": [
                "params.EndpointId > 0",
                "cluster membership check passes when clusterID > 0"
              ],
              "implementation": "EndpointsService.UpdateEndpoint -> service.GetDataApp / service.CheckDataAppHasCluster / service.GetEndpoint / service.SaveEndpoint"
            }
          ]
        }
      ]
    },
    "EndpointsService.DeleteEndpoint": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "DeleteEndpoint",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after endpoint id resolution succeeds"
          ],
          "operations": [
            {
              "operation": "DELETE ENDPOINT",
              "trigger": "Delete the endpoint from the dataapp",
              "conditions": [
                "params.EndpointId > 0"
              ],
              "implementation": "EndpointsService.DeleteEndpoint -> service.DeleteEndpoint(ctx, innerAppId, params.EndpointId, createdBy)"
            }
          ]
        }
      ]
    },
    "EndpointsService.TestEndpoint": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + PublishTest",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after endpoint id resolution succeeds"
          ],
          "operations": [
            {
              "operation": "TEST ENDPOINT",
              "trigger": "Run the draft endpoint test flow through the central service layer",
              "conditions": [
                "params.EndpointId > 0",
                "req.Args parsed into []entity.TestEndpointArgs"
              ],
              "implementation": "EndpointsService.TestEndpoint -> service.GetDataApp / service.PublishTest(ctx, entity.TestEndpointParamV2{...})"
            }
          ]
        }
      ]
    },
    "DeploymentsService.CreateDeployment": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + TriggerDataAppDeployFromUI",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId resolution succeeds"
          ],
          "operations": [
            {
              "operation": "TRIGGER DEPLOYMENT",
              "trigger": "Create a UI-origin deployment log and kick off deployment",
              "conditions": [
                "dataapp is not chat2query"
              ],
              "implementation": "DeploymentsService.CreateDeployment -> service.GetDataApp / service.TriggerDataAppDeployFromUI(ctx, innerAppId, createdBy, req.Deployment.Description)"
            }
          ]
        }
      ]
    },
    "DeploymentsService.ListDeployments": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + ListDataAppDeployLogsWithPager",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId and page-token validation succeed"
          ],
          "operations": [
            {
              "operation": "LIST DEPLOYMENTS",
              "trigger": "List deployment logs for the dataapp",
              "conditions": [
                "innerAppId present in gRPC metadata"
              ],
              "implementation": "DeploymentsService.ListDeployments -> service.GetDataApp / service.ListDataAppDeployLogsWithPager(ctx, innerAppId, token.Prev, int(pageSize)+1)"
            }
          ]
        }
      ]
    },
    "DeploymentsService.GetDeployment": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + GetDataAppDeployLogs",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after deployment id resolution succeeds"
          ],
          "operations": [
            {
              "operation": "GET DEPLOYMENT",
              "trigger": "Load a single deployment log by id",
              "conditions": [
                "params.DeploymentId > 0"
              ],
              "implementation": "DeploymentsService.GetDeployment -> service.GetDataApp / service.GetDataAppDeployLogs(ctx, innerAppId, params.DeploymentId)"
            }
          ]
        }
      ]
    },
    "ApiKeyService.ListApiKeys": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "RbacListApiKeys",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId resolution succeeds"
          ],
          "operations": [
            {
              "operation": "LIST API KEYS",
              "trigger": "Load the RBAC API key list and page it locally",
              "conditions": [
                "innerAppId present in gRPC metadata"
              ],
              "implementation": "ApiKeyService.ListApiKeys -> service.RbacListApiKeys(ctx, innerAppId, true)"
            }
          ]
        }
      ]
    },
    "ApiKeyService.CreateApiKey": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "GetDataApp + RbacCreateApikey",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId resolution and role/ttl validation succeed"
          ],
          "operations": [
            {
              "operation": "CREATE API KEY",
              "trigger": "Create an API key with app-type-specific role validation",
              "conditions": [
                "grpcRole2RbacRole succeeded",
                "TTL validation passed when expire option sets TTL"
              ],
              "implementation": "ApiKeyService.CreateApiKey -> service.GetDataApp / service.RbacCreateApikey(...)"
            }
          ]
        }
      ]
    },
    "ApiKeyService.GetApiKey": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "RbacGetApiKey",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after apiKeyId resolution succeeds"
          ],
          "operations": [
            {
              "operation": "GET API KEY",
              "trigger": "Load a single RBAC API key by id",
              "conditions": [
                "params.ApiKeyId > 0"
              ],
              "implementation": "ApiKeyService.GetApiKey -> service.RbacGetApiKey(ctx, innerAppId, params.ApiKeyId)"
            }
          ]
        }
      ]
    },
    "ApiKeyService.UpdateApiKey": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "RbacGetApiKey + RbacUpdateApikey",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after apiKeyId resolution and role/ttl validation succeed"
          ],
          "operations": [
            {
              "operation": "UPDATE API KEY",
              "trigger": "Fetch the old key, validate editability, update it, and reload the new view",
              "conditions": [
                "params.ApiKeyId > 0",
                "oldRbacApiKey is not expired"
              ],
              "implementation": "ApiKeyService.UpdateApiKey -> service.RbacGetApiKey / service.RbacUpdateApikey / service.RbacGetApiKey"
            }
          ]
        }
      ]
    },
    "ApiKeyService.DeleteApiKey": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "RbacGetApiKey + RbacDeleteApikey",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after apiKeyId resolution succeeds"
          ],
          "operations": [
            {
              "operation": "DELETE API KEY",
              "trigger": "Load the key to recover role metadata and then delete it",
              "conditions": [
                "params.ApiKeyId > 0"
              ],
              "implementation": "ApiKeyService.DeleteApiKey -> service.RbacGetApiKey / service.RbacDeleteApikey"
            }
          ]
        }
      ]
    },
    "ApiSpecService.GetApiSpec": {
      "infrastructure": {},
      "services": [
        {
          "name": "central-service",
          "target_repo": "tidbcloud/dataservices",
          "target_interface": "AuthorizeOpenApiSpecification + GenerateOpenApiSpecification",
          "operation_type": "local_service_call",
          "conditions": [
            "Only after innerAppId resolution and caller metadata extraction succeed"
          ],
          "operations": [
            {
              "operation": "GENERATE API SPEC",
              "trigger": "Authorize and render the OpenAPI document in the requested format",
              "conditions": [
                "service.AuthorizeOpenApiSpecification succeeded"
              ],
              "implementation": "ApiSpecService.GetApiSpec -> service.AuthorizeOpenApiSpecification / service.GenerateOpenApiSpecification(ctx, innerAppId, cred, convertFormat(req.Format))"
            }
          ]
        }
      ]
    }
  }
}
