{
  "repo": "tidbcloud/dataflow-service",
  "binary": "dataflow-ng",
  "binary_path": "dataflow-service-ng/cmd/dataflow/main.go",
  "dependencies": {
    "ChangefeedService.ListChangefeeds": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "Count and page biz changefeeds for the TiDB cluster", "conditions": ["Always"], "implementation": "BizChangefeedModelImpl.ListBizChangefeeds -> bizChangefeedRepo.Count/List"},
            {"operation": "SELECT", "trigger": "Load kernel TiCDC changefeeds to enrich statuses", "conditions": ["For returned biz changefeeds"], "implementation": "BizChangefeedModelImpl.listKernelChangefeeds -> changefeedModelRegionalImpl.ListChangefeeds -> changefeedRepo.List"}
          ]
        }
      },
      "services": []
    },
    "ChangefeedService.GetChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "Load the biz changefeed by ID", "conditions": ["Always"], "implementation": "BizChangefeedModelImpl.GetBizChangefeed -> bizChangefeedRepo.Load"},
            {"operation": "SELECT", "trigger": "Load the matching kernel TiCDC changefeed", "conditions": ["Always"], "implementation": "BizChangefeedModelImpl.queryKernelChangefeed -> changefeedModelRegionalImpl.QueryChangefeed -> changefeedRepo.Get"}
          ]
        }
      },
      "services": []
    },
    "ChangefeedService.DescribeSchemaTable": {
      "infrastructure": {},
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["After local table-filter syntax validation succeeds"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve tenant and region for the upstream TiDB cluster", "conditions": ["After local table-filter syntax validation succeeds"], "implementation": "bizChangefeedControllerImpl.DescribeSchemaTable -> mgmtSvcCli.GetClusterByID"}
          ]
        },
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /api/v1/verifyTable",
          "operation_type": "http_post",
          "conditions": ["After local table-filter syntax validation and mgmt cluster lookup both succeed"],
          "operations": [
            {"operation": "Regional precheck VerifyTable", "trigger": "Validate filter rules and inspect eligible/ineligible tables", "conditions": ["After local table-filter syntax validation and mgmt cluster lookup both succeed"], "implementation": "BizChangefeedModelImpl.DescribeSchemaTable -> cdcPreCheckCli.VerifyTable"}
          ]
        }
      ]
    },
    "ChangefeedService.GetAdminProfile": {
      "infrastructure": {},
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["Always"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve tenant, region, and cloud provider", "conditions": ["Always"], "implementation": "bizChangefeedControllerImpl.GetAdminProfile -> mgmtSvcCli.GetClusterByID"}
          ]
        },
        {
          "name": "regional-ticdc-service",
          "target_interface": "GET /api/v1/ticdcClusterRole",
          "operation_type": "http_get",
          "conditions": ["After mgmt cluster lookup succeeds"],
          "operations": [
            {"operation": "Regional GetTiCDCClusterRole", "trigger": "Fetch cloud account and external ID for the TiCDC cluster role", "conditions": ["After mgmt cluster lookup succeeds"], "implementation": "BizChangefeedModelImpl.DescribeAdminProfile -> cdcClusterModel.GetRole -> ticdcClusterCli.GetTiCDCClusterRole"}
          ]
        }
      ]
    },
    "ChangefeedService.ScaleChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Load always; state update only after spec changed, status allows scaling, and target spec is valid"],
          "operations": [
            {"operation": "SELECT", "trigger": "Load the biz changefeed before scaling", "conditions": ["Always"], "implementation": "BizChangefeedModelImpl.ScaleBizChangefeed -> bizChangefeedRepo.Load"},
            {"operation": "UPDATE", "trigger": "Persist the new specification code and operation status", "conditions": ["After specification code changed, biz status check passed, and target spec lookup succeeded"], "implementation": "BizChangefeedModelImpl.updateBizChangefeedEntityForScale -> bizChangefeedRepo.Update"}
          ]
        }
      },
      "services": [
        {
          "name": "workflow-engine",
          "target_interface": "RunDagWithTags",
          "operation_type": "workflow_submit",
          "conditions": ["After specification code changed, biz status check passed, target spec lookup succeeded, and DB update committed"],
          "operations": [
            {"operation": "Submit scale workflow", "trigger": "Schedule asynchronous TiCDC resource scaling", "conditions": ["After DB update inside the scaling transaction"], "implementation": "BizChangefeedModelImpl.createBizChangefeedWorkflow(workflow.DagScaleBizChangefeed)"}
          ]
        }
      ]
    },
    "ChangefeedService.CalChangefeedFee": {
      "infrastructure": {},
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["After specification code lookup succeeds"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve tenant, cloud provider, and region for billing labels", "conditions": ["After specification code lookup succeeds"], "implementation": "BizChangefeedModelImpl.CalBizChangefeedFee -> mgmtCli.GetClusterByID"}
          ]
        },
        {
          "name": "billing-service",
          "target_interface": "CalFee",
          "operation_type": "internal_client",
          "conditions": ["After specification code lookup and mgmt cluster lookup both succeed"],
          "operations": [
            {"operation": "Calculate fee", "trigger": "Convert RCU and duration into a billable amount", "conditions": ["After specification code lookup and mgmt cluster lookup both succeed"], "implementation": "BizChangefeedModelImpl.CalBizChangefeedFee -> billingHandler.CalFee"}
          ]
        }
      ]
    },
    "ChangefeedService.ResumeChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["After biz changefeed status allows resume"],
          "operations": [
            {"operation": "SELECT/UPDATE", "trigger": "Load the biz changefeed and persist resumed status", "conditions": ["Always load; update only after biz status precheck passes"], "implementation": "BizChangefeedModelImpl.ResumeBizChangefeed -> bizChangefeedRepo.Load/Update"},
            {"operation": "SELECT/UPDATE", "trigger": "Load the kernel TiCDC changefeed and mirror feed state", "conditions": ["After biz status precheck passes"], "implementation": "BizChangefeedModelImpl.resumeKernelChangefeed -> changefeedModelRegionalImpl.QueryChangefeed/ResumeChangefeed -> changefeedRepo.Get/Save"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /ticdc-service/api/v1/changefeeds/{changefeed_id}:resume",
          "operation_type": "http_post",
          "conditions": ["Kernel changefeed is not already normal"],
          "operations": [
            {"operation": "Regional ResumeChangefeed", "trigger": "Resume the kernel changefeed after local state transition", "conditions": ["After biz status precheck passes and queried kernel feed state is not normal"], "implementation": "changefeedModelRegionalImpl.resumeChangefeedByRegional -> changefeedCli.ResumeChangefeed"}
          ]
        }
      ]
    },
    "ChangefeedService.PauseChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["After biz changefeed status allows pause"],
          "operations": [
            {"operation": "SELECT/UPDATE", "trigger": "Load the biz changefeed and persist paused status", "conditions": ["Always load; update only after biz status precheck passes"], "implementation": "BizChangefeedModelImpl.PauseBizChangefeed -> bizChangefeedRepo.Load/Update"},
            {"operation": "SELECT/UPDATE", "trigger": "Load the kernel TiCDC changefeed and mirror feed state", "conditions": ["After biz status precheck passes"], "implementation": "BizChangefeedModelImpl.pauseKernelChangefeed -> changefeedModelRegionalImpl.QueryChangefeed/PauseChangefeed -> changefeedRepo.Get/Save"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /ticdc-service/api/v1/changefeeds/{changefeed_id}:pause",
          "operation_type": "http_post",
          "conditions": ["Kernel changefeed is not already stopped/failed"],
          "operations": [
            {"operation": "Regional PauseChangefeed", "trigger": "Pause the kernel changefeed after local state transition", "conditions": ["After biz status precheck passes and queried kernel feed state is not stopped"], "implementation": "changefeedModelRegionalImpl.pauseChangefeedByRegional -> changefeedCli.PauseChangefeed"}
          ]
        }
      ]
    },
    "ChangefeedService.CreateChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["After controller parsed downstream params and precheckCreateBizChangefeed started"],
          "operations": [
            {"operation": "SELECT", "trigger": "Check per-cluster quota and build entity metadata", "conditions": ["After mgmt cluster lookup succeeds"], "implementation": "BizChangefeedModelImpl.preCheckCreateBizChangefeed -> bizChangefeedRepo.List"},
            {"operation": "INSERT", "trigger": "Persist the new biz changefeed", "conditions": ["After upstream cluster is available, spec lookup succeeds, quota is not exceeded, downstream connectivity test passes, and downstream parameter precheck passes"], "implementation": "BizChangefeedModelImpl.CreateBizChangefeed -> bizChangefeedRepo.Create"},
            {"operation": "INSERT", "trigger": "Create sink endpoint usage if private link is selected", "conditions": ["After biz row insert succeeds and req.PrivateLinkEndpointID != 0"], "implementation": "BizChangefeedModelImpl.createSinkEndpointUsageIfNeeded -> sinkEndpointModel.CreateSinkEndpointUsage"}
          ]
        }
      },
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["After connector type is recognized by the controller"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve tenant, region, and shared pool for create-time validation", "conditions": ["After connector type is recognized by the controller"], "implementation": "bizChangefeedControllerImpl.CreateChangefeed -> mgmtSvcCli.GetClusterByID"}
          ]
        },
        {
          "name": "config-center",
          "target_interface": "UpdateClusterMeta",
          "operation_type": "grpc_unary",
          "conditions": ["Inside the asynchronous create workflow after the biz row has been inserted"],
          "operations": [
            {"operation": "Create changefeed config + URI config", "trigger": "Initialize config-center records for the new changefeed", "conditions": ["Inside the asynchronous create workflow after the biz row has been inserted"], "implementation": "changefeedConfigCenterImpl.Create -> configCenterGrpcCli.UpdateClusterMeta"}
          ]
        },
        {
          "name": "workflow-engine",
          "target_interface": "RunDagWithTags",
          "operation_type": "workflow_submit",
          "conditions": ["After biz row insert succeeds inside the create transaction"],
          "operations": [
            {"operation": "Submit create workflow", "trigger": "Schedule asynchronous resource creation", "conditions": ["After biz row insert succeeds inside the create transaction"], "implementation": "BizChangefeedModelImpl.createBizChangefeedWorkflow(workflow.DagCreateBizChangefeed)"}
          ]
        }
      ]
    },
    "ChangefeedService.EditChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Kernel changefeed must already be stopped and downstream type must remain unchanged"],
          "operations": [
            {"operation": "SELECT/UPDATE", "trigger": "Load and update the biz changefeed payload", "conditions": ["Always load; update only after kernel feed is stopped, downstream type matches, and biz status check passes"], "implementation": "BizChangefeedModelImpl.EditBizChangefeed -> bizChangefeedRepo.Load/Update"},
            {"operation": "SELECT", "trigger": "Load the kernel TiCDC changefeed and TiCDC cluster", "conditions": ["Always load before edit precheck"], "implementation": "BizChangefeedModelImpl.queryKernelChangefeed -> changefeedModelRegionalImpl.QueryChangefeed -> changefeedRepo.Get"}
          ]
        }
      },
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["After kernel feed stop check, downstream-type equality check, and biz status precheck all pass"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve cluster version for downstream validation", "conditions": ["After kernel feed stop check, downstream-type equality check, and biz status precheck all pass"], "implementation": "BizChangefeedModelImpl.EditBizChangefeed -> mgmtCli.GetClusterByID"}
          ]
        },
        {
          "name": "config-center",
          "target_interface": "GetClusterConfigurationFile",
          "operation_type": "grpc_unary",
          "conditions": ["After edit precheck passes and mgmt cluster lookup succeeds"],
          "operations": [
            {"operation": "Read changefeed config + URI config", "trigger": "Merge user edits with config-center defaults", "conditions": ["After edit precheck passes and mgmt cluster lookup succeeds"], "implementation": "changefeedModelRegionalImpl.assembleKernelChangefeedConfig -> changefeedConfigCenterImpl.Get"}
          ]
        },
        {
          "name": "regional-ticdc-service",
          "target_interface": "GET/PUT /ticdc-service/api/v1/changefeeds/{changefeed_id}",
          "operation_type": "http_client",
          "conditions": ["After edit precheck passes, mgmt cluster lookup succeeds, and config-center config is loaded"],
          "operations": [
            {"operation": "Regional GetChangefeed", "trigger": "Fetch current kernel config before patching", "conditions": ["After edit precheck passes, mgmt cluster lookup succeeds, and config-center config is loaded"], "implementation": "changefeedModelRegionalImpl.getChangefeedFromRegional -> changefeedCli.GetChangefeed"},
            {"operation": "Regional UpdateChangefeed", "trigger": "Push edited sink URI and replica config", "conditions": ["After current regional changefeed payload is fetched and merged with config-center defaults"], "implementation": "changefeedModelRegionalImpl.modifyChangefeedConfigByRegional -> changefeedCli.UpdateChangefeed"}
          ]
        }
      ]
    },
    "ChangefeedService.DeleteChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT/UPDATE", "trigger": "Load the biz changefeed and mark it deleting", "conditions": ["Always"], "implementation": "BizChangefeedModelImpl.DeleteBizChangefeed -> bizChangefeedRepo.Load/Update"},
            {"operation": "SELECT/DELETE", "trigger": "Remove sink endpoint usage for private-link changefeeds", "conditions": ["bizChangefeedEntity.BizPLEndpointID != 0"], "implementation": "BizChangefeedModelImpl.deleteSinkEndpointUsageIfNeeded -> sinkEndpointModel.DeleteSinkEndpointUsage"}
          ]
        }
      },
      "services": [
        {
          "name": "workflow-engine",
          "target_interface": "RunDagWithTags",
          "operation_type": "workflow_submit",
          "conditions": ["Precheck passed"],
          "operations": [
            {"operation": "Submit delete workflow", "trigger": "Schedule asynchronous regional cleanup", "conditions": ["After delete status update succeeds inside the delete transaction"], "implementation": "BizChangefeedModelImpl.createBizChangefeedWorkflow(workflow.DagDeleteBizChangefeed)"}
          ]
        }
      ]
    },
    "ChangefeedService.TestChangefeed": {
      "infrastructure": {},
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["After controller recognizes the requested downstream type"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve upstream cluster metadata for downstream validation", "conditions": ["After controller recognizes the requested downstream type"], "implementation": "BizChangefeedModelImpl.TestBizChangefeed -> mgmtCli.GetClusterByID"}
          ]
        },
        {
          "name": "downstream-sink",
          "target_interface": "connector-specific connectivity test",
          "operation_type": "network_probe",
          "conditions": ["Depends on req.ChangefeedType"],
          "operations": [
            {"operation": "TestConnection", "trigger": "Validate Kafka/MySQL/S3/GCS/Pulsar/Serverless TiDB connectivity", "conditions": ["After mgmt cluster lookup succeeds and controller-specific create params are parsed"], "implementation": "BizChangefeedModelImpl.TestBizChangefeed -> downstreamAdaptor.TestConnection"}
          ]
        }
      ]
    },
    "ChangefeedService.GetChangefeedDetail": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "Load biz and kernel changefeed IDs", "conditions": ["Always"], "implementation": "BizChangefeedModelImpl.GetChangefeedDetail -> bizChangefeedRepo.Load + queryKernelChangefeed"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "GET /ticdc-service/api/v1/changefeeds/{changefeed_id}",
          "operation_type": "http_get",
          "conditions": ["Always"],
          "operations": [
            {"operation": "Regional GetChangefeed", "trigger": "Fetch the full kernel changefeed payload", "conditions": ["Always"], "implementation": "changefeedModelRegionalImpl.GetChangefeedDetail -> changefeedCli.GetChangefeed"}
          ]
        }
      ]
    },
    "ChangefeedService.GetTiCDCCluster": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "Resolve the kernel changefeed and TiCDC cluster IDs", "conditions": ["Always"], "implementation": "BizChangefeedModelImpl.GetTiCDCCluster -> bizChangefeedRepo.Load + queryKernelChangefeed"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "GET /api/v1/ticdcClusters/{ticdc_cluster_id}",
          "operation_type": "http_get",
          "conditions": ["Always"],
          "operations": [
            {"operation": "Regional GetTiCDCCluster", "trigger": "Fetch the kernel TiCDC cluster payload", "conditions": ["Always"], "implementation": "changefeedModelRegionalImpl.GetTiCDCCluster -> cdcClusterCli.GetTiCDCCluster"}
          ]
        }
      ]
    },
    "ChangefeedService.ListTiCDCClusters": {
      "infrastructure": {},
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["Always"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve tenant/region/cloud provider for regional routing", "conditions": ["Always"], "implementation": "bizChangefeedControllerImpl.ListTiCDCClusters -> mgmtSvcCli.GetClusterByID"}
          ]
        },
        {
          "name": "regional-ticdc-service",
          "target_interface": "GET /api/v1/ticdcClusters",
          "operation_type": "http_get",
          "conditions": ["After mgmt cluster lookup succeeds"],
          "operations": [
            {"operation": "Regional ListTiCDCClusters", "trigger": "List TiCDC clusters for the TiDB cluster", "conditions": ["After mgmt cluster lookup succeeds"], "implementation": "changefeedModelRegionalImpl.ListTiCDCClusters -> cdcClusterCli.ListTiCDCClusters"}
          ]
        }
      ]
    },
    "ChangefeedSpecService.List": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "Load changefeed machine/spec definitions", "conditions": ["Always"], "implementation": "BizChangefeedModelImpl.ListBizChangefeedSpecifications -> machineManager.ListSpecifications"}
          ]
        }
      },
      "services": []
    },
    "OpsInternalService.ApplyConfigChanges": {
      "infrastructure": {
        "mysql": {
          "conditions": ["When req.ClusterType == CHANGEFEED_CLUSTER or TICDC_CLUSTER"],
          "operations": [
            {"operation": "SELECT", "trigger": "Load TiCDC cluster or kernel changefeed entities before applying config", "conditions": ["Depending on cluster type"], "implementation": "opsInnerControllerImpl.ApplyConfigChanges -> ticdcClusterModel.Load / ticdcChangefeedModel.QueryChangefeed"}
          ]
        }
      },
      "services": [
        {
          "name": "config-center",
          "target_interface": "UpdateClusterMeta/GetClusterConfigurationFile",
          "operation_type": "grpc_unary",
          "conditions": ["When req.ClusterType == TICDC_CLUSTER or CHANGEFEED_CLUSTER"],
          "operations": [
            {"operation": "Update TiCDC cluster config", "trigger": "Persist custom params/version/image tag for a TiCDC cluster", "conditions": ["When req.ClusterType == TICDC_CLUSTER"], "implementation": "opsInnerControllerImpl.applyTiCDCClusterConfig -> ticdcClusterConfigManager.Update"},
            {"operation": "Update changefeed config", "trigger": "Persist edited changefeed config-center params", "conditions": ["When req.ClusterType == CHANGEFEED_CLUSTER and req.ConfigurationFile is CHANGEFEED_FILE or SINK_URI"], "implementation": "opsInnerControllerImpl.updateChangefeedConfig -> changefeedConfigManager.Update"},
            {"operation": "Read changefeed config", "trigger": "Reload config-center defaults before rewriting the regional changefeed", "conditions": ["When req.ClusterType == CHANGEFEED_CLUSTER after config-center update succeeds"], "implementation": "changefeedModelRegionalImpl.assembleKernelChangefeedConfig -> changefeedConfigCenterImpl.Get"}
          ]
        },
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /api/v1/ticdcClusters/{id}:updateConfig or GET/PUT /ticdc-service/api/v1/changefeeds/{id}",
          "operation_type": "http_client",
          "conditions": ["Depends on req.ClusterType"],
          "operations": [
            {"operation": "Apply TiCDC cluster config", "trigger": "Push updated TiCDC cluster config to the regional control plane", "conditions": ["When req.ClusterType == TICDC_CLUSTER after config-center update succeeds"], "implementation": "clusterModelRegionalImpl.ApplyConfig -> ticdcClusterCli.UpdateTiCDCClusterConfig"},
            {"operation": "Pause + resume the kernel changefeed around config apply", "trigger": "Freeze the kernel changefeed while rewriting its config", "conditions": ["When req.ClusterType == CHANGEFEED_CLUSTER after kernel changefeed lookup succeeds"], "implementation": "opsInnerControllerImpl.applyTiCDCChangefeedConfig -> ticdcChangefeedModel.PauseChangefeed/ResumeChangefeed"},
            {"operation": "Apply changefeed config", "trigger": "Push updated changefeed config to the regional control plane", "conditions": ["When req.ClusterType == CHANGEFEED_CLUSTER after config-center update succeeds, config-center config is reloaded, and EditBizChangefeedForOps finishes cluster lookup"], "implementation": "changefeedModelRegionalImpl.ModifyChangefeedConfig -> changefeedCli.GetChangefeed/UpdateChangefeed"}
          ]
        },
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["When req.ClusterType == CHANGEFEED_CLUSTER"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve cluster metadata while editing the biz changefeed for ops", "conditions": ["CHANGEFEED_CLUSTER only"], "implementation": "BizChangefeedModelImpl.EditBizChangefeedForOps -> mgmtCli.GetClusterByID"}
          ]
        }
      ]
    },
    "OpsInternalService.UpdateTiCDCClusterStorage": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT/INSERT", "trigger": "Load TiCDC cluster metadata and persist custom storage overrides", "conditions": ["Always"], "implementation": "clusterModelRegionalImpl.UpdateStorage -> ticdcClusterRepo.Load + ticdcCustomStorageRepo.Save"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /api/v1/ticdcClusters/{ticdc_cluster_id}:updateStorage",
          "operation_type": "http_post",
          "conditions": ["After TiCDC cluster lookup and custom-storage save both succeed"],
          "operations": [
            {"operation": "Regional UpdateTiCDCClusterStorage", "trigger": "Apply the new storage size/iops/throughput", "conditions": ["After TiCDC cluster lookup and custom-storage save both succeed"], "implementation": "clusterModelRegionalImpl.updateStorage -> ticdcClusterCli.UpdateTiCDCClusterStorage"}
          ]
        }
      ]
    },
    "OpsInternalService.ListInternalChangefeeds": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "Load biz changefeeds, TiCDC clusters, and kernel changefeeds for assembly", "conditions": ["Always"], "implementation": "opsInnerControllerImpl.listTiCDCChangefeeds -> bizChangefeedModel.ListBizChangefeeds + ticdcClusterModel.List + ticdcChangefeedModel.ListChangefeeds"}
          ]
        }
      },
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["Only when ListBizChangefeeds returns at least one biz changefeed"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve shared pool information for the TiDB cluster", "conditions": ["Only when ListBizChangefeeds returns at least one biz changefeed"], "implementation": "opsInnerControllerImpl.listTiCDCChangefeeds -> mgmtCli.GetClusterByID"}
          ]
        }
      ]
    },
    "OpsInternalService.GetInternalChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "Load the kernel changefeed and the backing biz changefeed", "conditions": ["Always"], "implementation": "opsInnerControllerImpl.getTiCDCChangefeed -> ticdcChangefeedModel.QueryChangefeed + bizChangefeedModel.GetBizChangefeed"}
          ]
        }
      },
      "services": []
    },
    "OpsInternalService.RestartChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT/UPDATE", "trigger": "Load the kernel changefeed and mirror pause/resume state transitions", "conditions": ["Always"], "implementation": "opsInnerControllerImpl.RestartChangefeed -> ticdcChangefeedModel.QueryChangefeed/PauseChangefeed/ResumeChangefeed"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /ticdc-service/api/v1/changefeeds/{changefeed_id}:pause + :resume",
          "operation_type": "http_client",
          "conditions": ["After kernel changefeed lookup succeeds; resume only runs if pause succeeds"],
          "operations": [
            {"operation": "Regional Pause + Resume", "trigger": "Restart the kernel changefeed", "conditions": ["After kernel changefeed lookup succeeds; resume only runs if pause succeeds"], "implementation": "opsInnerControllerImpl.restartTiCDCChangefeed -> ticdcChangefeedModel.PauseChangefeed/ResumeChangefeed"}
          ]
        }
      ]
    },
    "OpsInternalService.PauseChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT/UPDATE", "trigger": "Load and pause the kernel changefeed", "conditions": ["Always"], "implementation": "opsInnerControllerImpl.PauseChangefeed -> ticdcChangefeedModel.QueryChangefeed/PauseChangefeed"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /ticdc-service/api/v1/changefeeds/{changefeed_id}:pause",
          "operation_type": "http_post",
          "conditions": ["After kernel changefeed lookup succeeds"],
          "operations": [
            {"operation": "Regional PauseChangefeed", "trigger": "Pause the kernel changefeed", "conditions": ["After kernel changefeed lookup succeeds"], "implementation": "changefeedModelRegionalImpl.pauseChangefeedByRegional -> changefeedCli.PauseChangefeed"}
          ]
        }
      ]
    },
    "OpsInternalService.ResumeChangefeed": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT/UPDATE", "trigger": "Load and resume the kernel changefeed", "conditions": ["Always"], "implementation": "opsInnerControllerImpl.ResumeChangefeed -> ticdcChangefeedModel.QueryChangefeed/ResumeChangefeed"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /ticdc-service/api/v1/changefeeds/{changefeed_id}:resume",
          "operation_type": "http_post",
          "conditions": ["After kernel changefeed lookup succeeds"],
          "operations": [
            {"operation": "Regional ResumeChangefeed", "trigger": "Resume the kernel changefeed", "conditions": ["After kernel changefeed lookup succeeds"], "implementation": "changefeedModelRegionalImpl.resumeChangefeedByRegional -> changefeedCli.ResumeChangefeed"}
          ]
        }
      ]
    },
    "OpsInternalService.GetInternalTiCDCCluster": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "Load the TiCDC cluster entity by ID", "conditions": ["Always"], "implementation": "opsInnerControllerImpl.GetInternalTiCDCCluster -> ticdcClusterModel.Query -> ticdcClusterRepo.Get"}
          ]
        }
      },
      "services": []
    },
    "OpsInternalService.RestartTiCDCCluster": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "Load TiCDC cluster routing metadata", "conditions": ["Always"], "implementation": "clusterModelRegionalImpl.Restart -> ticdcClusterRepo.Load"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /api/v1/ticdcClusters/{ticdc_cluster_id}:restart",
          "operation_type": "http_post",
          "conditions": ["After TiCDC cluster lookup succeeds"],
          "operations": [
            {"operation": "Regional RestartTiCDCCluster", "trigger": "Restart the TiCDC cluster", "conditions": ["After TiCDC cluster lookup succeeds"], "implementation": "clusterModelRegionalImpl.Restart -> ticdcClusterCli.RestartTiCDCCluster"}
          ]
        }
      ]
    },
    "OpsInternalService.PauseClusterChangefeeds": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "List biz changefeeds under the TiDB cluster before iterating", "conditions": ["Always"], "implementation": "opsInnerControllerImpl.PauseClusterChangefeeds -> bizChangefeedModel.ListBizChangefeeds"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /ticdc-service/api/v1/changefeeds/{changefeed_id}:pause",
          "operation_type": "http_post",
          "conditions": ["For each non-stopped/non-failed changefeed"],
          "operations": [
            {"operation": "Pause each kernel changefeed", "trigger": "Bulk-pause all active changefeeds in the cluster", "conditions": ["Per-item"], "implementation": "opsInnerControllerImpl.PauseClusterChangefeeds -> bizChangefeedModel.PauseBizChangefeed"}
          ]
        }
      ]
    },
    "OpsInternalService.ResumeClusterChangefeeds": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "List biz changefeeds under the TiDB cluster before iterating", "conditions": ["Always"], "implementation": "opsInnerControllerImpl.ResumeClusterChangefeeds -> bizChangefeedModel.ListBizChangefeeds"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /ticdc-service/api/v1/changefeeds/{changefeed_id}:resume",
          "operation_type": "http_post",
          "conditions": ["For each non-normal/non-warning changefeed"],
          "operations": [
            {"operation": "Resume each kernel changefeed", "trigger": "Bulk-resume changefeeds in the cluster", "conditions": ["Per-item"], "implementation": "opsInnerControllerImpl.ResumeClusterChangefeeds -> bizChangefeedModel.ResumeBizChangefeed"}
          ]
        }
      ]
    },
    "OpsInternalService.UpdateTableFilterOfClusterChangefeeds": {
      "infrastructure": {
        "mysql": {
          "conditions": ["len(req.Updates) > 0"],
          "operations": [
            {"operation": "SELECT/UPDATE", "trigger": "Read each biz changefeed and persist edited downstream params", "conditions": ["Per update item"], "implementation": "opsInnerControllerImpl.UpdateTableFilterOfClusterChangefeeds -> bizChangefeedController.GetChangefeed/EditChangefeed -> bizChangefeedRepo.Load/Update"}
          ]
        }
      },
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["Per update item after GetChangefeed succeeds and downstream type is supported"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve cluster metadata while rebuilding edited config", "conditions": ["Per update item after GetChangefeed succeeds and downstream type is supported"], "implementation": "bizChangefeedControllerImpl.EditChangefeed -> mgmtSvcCli.GetClusterByID"}
          ]
        },
        {
          "name": "config-center",
          "target_interface": "GetClusterConfigurationFile",
          "operation_type": "grpc_unary",
          "conditions": ["Per update item after EditChangefeed precheck passes and mgmt cluster lookup succeeds"],
          "operations": [
            {"operation": "Read changefeed config", "trigger": "Merge new table filters into the existing config-center defaults", "conditions": ["Per update item after EditChangefeed precheck passes and mgmt cluster lookup succeeds"], "implementation": "changefeedModelRegionalImpl.assembleKernelChangefeedConfig -> changefeedConfigCenterImpl.Get"}
          ]
        },
        {
          "name": "regional-ticdc-service",
          "target_interface": "GET/PUT /ticdc-service/api/v1/changefeeds/{changefeed_id}",
          "operation_type": "http_client",
          "conditions": ["Per update item after EditChangefeed precheck passes, config-center config is loaded, and regional changefeed fetch succeeds"],
          "operations": [
            {"operation": "Regional GetChangefeed + UpdateChangefeed", "trigger": "Apply the modified table-filter rules", "conditions": ["Per update item after EditChangefeed precheck passes, config-center config is loaded, and regional changefeed fetch succeeds"], "implementation": "changefeedModelRegionalImpl.ModifyChangefeedConfig -> changefeedCli.GetChangefeed/UpdateChangefeed"}
          ]
        }
      ]
    },
    "SinkEndpointService.CreateSinkEndpoint": {
      "infrastructure": {
        "mysql": {
          "conditions": ["req.SinkEndpoint must be present"],
          "operations": [
            {"operation": "SELECT", "trigger": "Check endpoint-name and root-domain conflicts", "conditions": ["After mgmt cluster lookup succeeds"], "implementation": "sinkEndpointImpl.preCheckCreateSinkEndpointReq -> bizPLEndpointRepo.List"},
            {"operation": "INSERT", "trigger": "Persist the sink endpoint entity", "conditions": ["Precheck passed"], "implementation": "sinkEndpointImpl.doCreateSinkEndpoint -> bizPLEndpointRepo.Save"}
          ]
        }
      },
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["Always"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve tenant/shared-pool/region metadata", "conditions": ["Always"], "implementation": "sinkEndpointImpl.CreateSinkEndpoint -> mgmtCli.GetClusterByID"}
          ]
        },
        {
          "name": "regional-ticdc-service",
          "target_interface": "POST /api/v1/ticdcSinkEndpoints + POST validate availability zones",
          "operation_type": "http_client",
          "conditions": ["After mgmt cluster lookup succeeds"],
          "operations": [
            {"operation": "ValidateEndpointAvailabilityZones", "trigger": "Check selected endpoint AZs", "conditions": ["After mgmt cluster lookup succeeds"], "implementation": "sinkEndpointImpl.preCheckCreateSinkEndpointReq -> cli.ValidateEndpointAvailabilityZones"},
            {"operation": "CreateTiCDCPrivateLink", "trigger": "Create the regional sink endpoint after the DB row is saved", "conditions": ["After endpoint conflict checks pass and DB insert succeeds"], "implementation": "sinkEndpointImpl.createRegionalEndpointIfNotExists -> cli.CreateTiCDCPrivateLink"}
          ]
        }
      ]
    },
    "SinkEndpointService.ListSinkEndpoints": {
      "infrastructure": {
        "mysql": {
          "conditions": ["After mgmt cluster lookup succeeds"],
          "operations": [
            {"operation": "SELECT", "trigger": "List non-deleting sink endpoints in the tenant/shared pool", "conditions": ["After mgmt cluster lookup succeeds"], "implementation": "sinkEndpointImpl.ListSinkEndpoint -> bizPLEndpointRepo.List"}
          ]
        }
      },
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["Always"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve tenant/shared-pool for filtering", "conditions": ["Always"], "implementation": "sinkEndpointImpl.ListSinkEndpoint -> mgmtCli.GetClusterByID"}
          ]
        }
      ]
    },
    "SinkEndpointService.GetSinkEndpoint": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Always"],
          "operations": [
            {"operation": "SELECT", "trigger": "Load the sink endpoint entity by ID", "conditions": ["Always"], "implementation": "sinkEndpointImpl.QuerySinkEndpoint -> bizPLEndpointRepo.Load"}
          ]
        }
      },
      "services": []
    },
    "SinkEndpointService.DeleteSinkEndpoint": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Delete request accepted; endpoint load/update only runs if precheck does not find any usages"],
          "operations": [
            {"operation": "SELECT", "trigger": "Check whether the endpoint is still referenced by any changefeed", "conditions": ["Always"], "implementation": "sinkEndpointImpl.preCheckDeleteSinkEndpointReq -> bizPLEndpointUsageRepo.List"},
            {"operation": "SELECT/UPDATE", "trigger": "Load the endpoint and mark it deleting", "conditions": ["Only when precheck finds no sink-endpoint usages"], "implementation": "sinkEndpointImpl.DeleteSinkEndpoint -> bizPLEndpointRepo.Load/Save"}
          ]
        }
      },
      "services": [
        {
          "name": "regional-ticdc-service",
          "target_interface": "DELETE /api/v1/ticdcSinkEndpoints/{ticdc_sink_endpoint_id}",
          "operation_type": "http_delete",
          "conditions": ["Endpoint exists"],
          "operations": [
            {"operation": "DeleteTiCDCPrivateLink", "trigger": "Delete the regional sink endpoint", "conditions": ["After precheck finds no usages and endpoint load succeeds"], "implementation": "sinkEndpointImpl.deleteRegionalEndpointIfExists -> cli.DeleteTiCDCPrivateLink"}
          ]
        }
      ]
    },
    "SinkEndpointService.ListSinkAvailabilityZones": {
      "infrastructure": {},
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["Always"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve tenant/shared-pool/region metadata", "conditions": ["Always"], "implementation": "sinkEndpointImpl.GetAvailabilityZones -> mgmtCli.GetClusterByID"}
          ]
        },
        {
          "name": "regional-ticdc-service",
          "target_interface": "GET /api/v1/ticdcSinkEndpoints/availableZones",
          "operation_type": "http_get",
          "conditions": ["After mgmt cluster lookup succeeds"],
          "operations": [
            {"operation": "GetAvailableZones", "trigger": "Fetch regional AZ choices for sink endpoints", "conditions": ["After mgmt cluster lookup succeeds"], "implementation": "sinkEndpointImpl.GetAvailabilityZones -> cli.GetAvailableZones"}
          ]
        }
      ]
    },
    "SinkEndpointService.GenerateSinkAdvertisedListener": {
      "infrastructure": {
        "mysql": {
          "conditions": ["After mgmt cluster lookup succeeds and a root domain has been generated"],
          "operations": [
            {"operation": "SELECT", "trigger": "Validate that the generated root domain does not conflict with existing endpoints", "conditions": ["After mgmt cluster lookup succeeds and a root domain has been generated"], "implementation": "sinkEndpointImpl.GenerateSinkAdvertisedListener -> validateRootDomainName -> bizPLEndpointRepo.List"}
          ]
        }
      },
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["Always"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve cloud provider and shared pool for domain generation", "conditions": ["Always"], "implementation": "sinkEndpointImpl.GenerateSinkAdvertisedListener -> mgmtCli.GetClusterByID"}
          ]
        }
      ]
    },
    "SinkEndpointService.ValidateSinkAdvertisedListenerDomain": {
      "infrastructure": {
        "mysql": {
          "conditions": ["Only when req.RootDomainName is non-empty"],
          "operations": [
            {"operation": "SELECT", "trigger": "Validate that the requested root domain does not conflict with existing endpoints", "conditions": ["Only when req.RootDomainName is non-empty"], "implementation": "sinkEndpointImpl.ValidateSinkAdvertisedListenerDomain -> validateRootDomainName -> bizPLEndpointRepo.List"}
          ]
        }
      },
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["Always"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve tenant/shared-pool metadata for domain validation", "conditions": ["Always"], "implementation": "sinkEndpointImpl.ValidateSinkAdvertisedListenerDomain -> mgmtCli.GetClusterByID"}
          ]
        }
      ]
    },
    "SinkEndpointService.GetSinkEndpointAuthInfo": {
      "infrastructure": {},
      "services": [
        {
          "name": "tidb-mgmt-svc",
          "target_interface": "ClusterService.ListClusters",
          "operation_type": "grpc_unary",
          "conditions": ["Always"],
          "operations": [
            {"operation": "gRPC GetClusterByID wrapper", "trigger": "Resolve tenant/shared-pool/region metadata", "conditions": ["Always"], "implementation": "sinkEndpointImpl.GetSinkEndpointAuthInfo -> mgmtCli.GetClusterByID"}
          ]
        },
        {
          "name": "regional-ticdc-service",
          "target_interface": "GET /api/v1/ticdcSinkEndpoints/authInfo",
          "operation_type": "http_get",
          "conditions": ["After mgmt cluster lookup succeeds"],
          "operations": [
            {"operation": "GetPrivateLinkAuthInfo", "trigger": "Fetch cloud account and AWS principal details", "conditions": ["After mgmt cluster lookup succeeds"], "implementation": "sinkEndpointImpl.GetSinkEndpointAuthInfo -> cli.GetPrivateLinkAuthInfo"}
          ]
        }
      ]
    }
  },
  "notes": [
    "This refresh converts the legacy aggregate mapping into method-keyed dependencies that match the 36 implemented gRPC methods in cmd/dataflow-ng.",
    "DPFeatureService is intentionally absent because the binary registers its grpc-gateway handler but never registers a matching gRPC server implementation.",
    "Most console methods delegate from controller layer into model implementations; the implementation strings above point at the first model/client methods that perform external reads, writes, or network calls."
  ]
}
