{
  "repo": "tidbcloud/dataapps",
  "binary": "chat2queryapi",
  "binary_path": "cmd/chat2queryapi/main.go",
  "dependencies": {
    "Runtime Chat2QueryLifecycle.LoadConfig": {
      "infrastructure": {
        "filesystem": {
          "conditions": [
            "Always"
          ],
          "operations": [
            {
              "operation": "READ FILE",
              "trigger": "Load the central config file before any database or gRPC client initialization",
              "conditions": [
                "config-path flag is provided or the default /etc/dbaas/config.yaml is present"
              ],
              "implementation": "config.InitConfig(configPath) -> viper.ReadInConfig()"
            }
          ]
        },
        "environment": {
          "conditions": [
            "Always"
          ],
          "operations": [
            {
              "operation": "LOAD ENV OVERRIDES",
              "trigger": "Allow environment variables to override config values after reading the YAML file",
              "conditions": [
                "Always"
              ],
              "implementation": "config.InitConfig(configPath) -> viper.AutomaticEnv()"
            }
          ]
        }
      },
      "services": []
    },
    "Runtime Chat2QueryLifecycle.SetupObservability": {
      "infrastructure": {},
      "services": [
        {
          "name": "sentry",
          "target_interface": "Sentry client initialization",
          "operation_type": "sdk_init",
          "target_repo": "getsentry/sentry-go",
          "conditions": [
            "Always during startup"
          ],
          "operations": [
            {
              "operation": "INIT CLIENT",
              "trigger": "Initialize the process-wide Sentry client before the HTTP servers start",
              "conditions": [
                "Always"
              ],
              "implementation": "sentry.SetupLoggerAndSentry(dsn, env, logLevel) -> sentry.Init(opts)"
            }
          ]
        },
        {
          "name": "jaeger",
          "target_interface": "InitJaeger(componentName)",
          "operation_type": "tracing_init",
          "target_repo": "tidbcloud/tiinf",
          "conditions": [
            "Always during startup"
          ],
          "operations": [
            {
              "operation": "INIT TRACING",
              "trigger": "Initialize Jaeger tracing for chat2queryapi",
              "conditions": [
                "Always"
              ],
              "implementation": "titracing.InitJaeger(componentName)"
            }
          ]
        }
      ]
    },
    "Runtime Chat2QueryLifecycle.ConnectDatabase": {
      "infrastructure": {
        "mysql": {
          "conditions": [
            "Always during startup"
          ],
          "operations": [
            {
              "operation": "OPEN DB HANDLE",
              "trigger": "Initialize the shared GORM connection used later for message and oplog persistence",
              "conditions": [
                "mysql.host and mysql.password are present in config"
              ],
              "implementation": "database.Connect(ctx, centralConfig) -> gorm.Open(mysql.Open(url), &gorm.Config{...})"
            }
          ]
        }
      },
      "services": []
    },
    "Runtime Chat2QueryLifecycle.RegisterPublicRoutes": {
      "infrastructure": {},
      "services": []
    },
    "Runtime Chat2QueryLifecycle.RegisterInternalRoutes": {
      "infrastructure": {},
      "services": []
    },
    "Runtime Chat2QueryLifecycle.StartMetricsServer": {
      "infrastructure": {},
      "services": []
    },
    "Runtime Chat2QueryLifecycle.StartInternalHTTPServer": {
      "infrastructure": {},
      "services": []
    },
    "Runtime Chat2QueryLifecycle.StartPublicHTTPServer": {
      "infrastructure": {},
      "services": []
    },
    "HTTP GET /healthz": {
      "infrastructure": {},
      "services": []
    },
    "HTTP POST /api/:api_ver/apps/:app_id/:app_ver/chat2data": {
      "infrastructure": {
        "mysql": {
          "conditions": [
            "Only after AI generation and downstream SQL execution both succeed or fail far enough to schedule async oplog persistence"
          ],
          "operations": [
            {
              "operation": "INSERT",
              "trigger": "Persist the generated SQL execution oplog asynchronously after ExecSqlDirectly returns",
              "conditions": [
                "parseChat2QueryParam(...) succeeds",
                "service.Chat2Data(...) reaches executeSql(...)",
                "the background goroutine in executeSql(...) runs"
              ],
              "implementation": "service.Chat2Data -> executeSql -> go CreateOplog(...) -> repository.CreateOplog -> DB.Table(\"sql_editor_oplog\").Save(&param)"
            }
          ]
        }
      },
      "services": [
        {
          "name": "dataservices-dataapi",
          "target_interface": "DataAPIService.AuthAPIKey + ShowDataApp",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/dataservices",
          "conditions": [
            "The request first passes CheckPathVersion",
            "api-key header is present",
            "app_id path parameter is present"
          ],
          "operations": [
            {
              "operation": "gRPC AuthAPIKey",
              "trigger": "Authenticate the external API key before the handler is entered",
              "conditions": [
                "AuthApiKey middleware runs on all public chat2query routes"
              ],
              "implementation": "api.AuthApiKey -> doAuthApiKey -> grpc.AuthAPIKey(ctx, req)"
            },
            {
              "operation": "gRPC ShowDataApp",
              "trigger": "Resolve org_id and project_id from the external dataapp so the handler can build Chat2QueryAuthInfo",
              "conditions": [
                "AuthAPIKey succeeded"
              ],
              "implementation": "api.AuthApiKey -> parseAppInfo -> grpc.ShowDataApp(ctx, req)"
            },
            {
              "operation": "gRPC ExecSqlDirectly",
              "trigger": "Execute the AI-generated SQL against the target TiDB cluster",
              "conditions": [
                "parseChat2QueryParam(c, true, true) succeeds",
                "service.Chat2Data -> ChatBotWithParam succeeds",
                "service.executeSql is reached"
              ],
              "implementation": "service.Chat2Data -> executeSql -> grpc.ExecSqlDirectly(ctx, &dataapi.BasicEndpointReq{...})"
            }
          ]
        },
        {
          "name": "aipower",
          "target_interface": "ChatBotService.ChatBot",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/aipower",
          "conditions": [
            "parseChat2QueryParam(c, true, true) succeeds",
            "instruction is non-empty and <= 1024 chars",
            "cluster_id is non-zero",
            "database is non-empty"
          ],
          "operations": [
            {
              "operation": "gRPC ChatBot",
              "trigger": "Generate SQL for the chat2data request",
              "conditions": [
                "Always once Chat2Data reaches service.Chat2Data"
              ],
              "implementation": "service.Chat2Data -> ChatBotWithParam(\"chat2data\", param) -> grpc.ChatBot(ctx, botReq)"
            }
          ]
        }
      ]
    },
    "HTTP POST /api/:api_ver/apps/:app_id/:app_ver/chat2question": {
      "infrastructure": {},
      "services": [
        {
          "name": "dataservices-dataapi",
          "target_interface": "DataAPIService.AuthAPIKey + ShowDataApp",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/dataservices",
          "conditions": [
            "The request first passes CheckPathVersion",
            "api-key header is present",
            "app_id path parameter is present"
          ],
          "operations": [
            {
              "operation": "gRPC AuthAPIKey",
              "trigger": "Authenticate the external API key before the handler is entered",
              "conditions": [
                "AuthApiKey middleware runs on all public chat2query routes"
              ],
              "implementation": "api.AuthApiKey -> doAuthApiKey -> grpc.AuthAPIKey(ctx, req)"
            },
            {
              "operation": "gRPC ShowDataApp",
              "trigger": "Resolve org_id and project_id from the external dataapp so the handler can build Chat2QueryAuthInfo",
              "conditions": [
                "AuthAPIKey succeeded"
              ],
              "implementation": "api.AuthApiKey -> parseAppInfo -> grpc.ShowDataApp(ctx, req)"
            }
          ]
        },
        {
          "name": "aipower",
          "target_interface": "ChatBotService.ChatBot",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/aipower",
          "conditions": [
            "parseChat2QueryParam(c, false, true) succeeds",
            "cluster_id is non-zero",
            "database is non-empty"
          ],
          "operations": [
            {
              "operation": "gRPC ChatBot",
              "trigger": "Generate suggested follow-up questions directly in service.Chat2Question",
              "conditions": [
                "(config.server.enableStreaming && param.Async) || !config.server.genQuestionConcurrently"
              ],
              "implementation": "service.Chat2Question -> ChatBotWithParam(\"chat2question\", param) -> grpc.ChatBot(ctx, botReq)"
            },
            {
              "operation": "gRPC ChatBot",
              "trigger": "Generate candidate question arrays concurrently and then de-duplicate them",
              "conditions": [
                "config.server.enableStreaming == false or param.Async == false",
                "config.server.genQuestionConcurrently == true"
              ],
              "implementation": "chat2QuestionConcurrency -> chat2QuestionRoutine -> service.Chat2Question -> grpc.ChatBot(ctx, botReq)"
            }
          ]
        }
      ]
    },
    "HTTP POST /api/:api_ver/apps/:app_id/:app_ver/chat2chart": {
      "infrastructure": {
        "mysql": {
          "conditions": [
            "Only after AI generation reaches executeSql(...) and the async oplog goroutine runs"
          ],
          "operations": [
            {
              "operation": "INSERT",
              "trigger": "Persist the generated SQL execution oplog asynchronously after ExecSqlDirectly returns",
              "conditions": [
                "parseChat2QueryParam(...) succeeds",
                "service.Chat2Chart(...) reaches executeSql(...)"
              ],
              "implementation": "service.Chat2Chart -> executeSql -> go CreateOplog(...) -> repository.CreateOplog"
            }
          ]
        }
      },
      "services": [
        {
          "name": "dataservices-dataapi",
          "target_interface": "DataAPIService.AuthAPIKey + ShowDataApp + ParseOneStmt + ExecSqlDirectly",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/dataservices",
          "conditions": [
            "The request first passes CheckPathVersion",
            "api-key header is present",
            "app_id path parameter is present"
          ],
          "operations": [
            {
              "operation": "gRPC AuthAPIKey",
              "trigger": "Authenticate the external API key before the handler is entered",
              "conditions": [
                "AuthApiKey middleware runs on all public chat2query routes"
              ],
              "implementation": "api.AuthApiKey -> grpc.AuthAPIKey(ctx, req)"
            },
            {
              "operation": "gRPC ShowDataApp",
              "trigger": "Resolve org_id and project_id from the external dataapp so the handler can build Chat2QueryAuthInfo",
              "conditions": [
                "AuthAPIKey succeeded"
              ],
              "implementation": "api.AuthApiKey -> grpc.ShowDataApp(ctx, req)"
            },
            {
              "operation": "gRPC ParseOneStmt",
              "trigger": "Reject non-SELECT SQL before executing the generated chart query",
              "conditions": [
                "service.Chat2Chart generated JSON that can be unmarshaled into Chat2ChartInfo"
              ],
              "implementation": "service.Chat2Chart -> GetStmtType -> grpc.ParseOneStmt(ctx, &dataapi.ParseOneStmtReq{Sql: sql})"
            },
            {
              "operation": "gRPC ExecSqlDirectly",
              "trigger": "Execute the generated SELECT SQL to produce the chart dataset",
              "conditions": [
                "GetStmtType returned dataapi.StmtType_Select"
              ],
              "implementation": "service.Chat2Chart -> executeSql -> grpc.ExecSqlDirectly(ctx, &dataapi.BasicEndpointReq{...})"
            }
          ]
        },
        {
          "name": "aipower",
          "target_interface": "ChatBotService.ChatBot",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/aipower",
          "conditions": [
            "parseChat2QueryParam(c, true, true) succeeds",
            "instruction is non-empty and <= 1024 chars"
          ],
          "operations": [
            {
              "operation": "gRPC ChatBot",
              "trigger": "Generate chart SQL plus chart metadata",
              "conditions": [
                "Always once Chat2Chart reaches service.Chat2Chart"
              ],
              "implementation": "service.Chat2Chart -> ChatBotWithParam(\"chat2chart\", param) -> grpc.ChatBot(ctx, botReq)"
            }
          ]
        }
      ]
    },
    "HTTP POST /api/:api_ver/apps/:app_id/:app_ver/data2column-match": {
      "infrastructure": {},
      "services": [
        {
          "name": "dataservices-dataapi",
          "target_interface": "DataAPIService.AuthAPIKey + ShowDataApp",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/dataservices",
          "conditions": [
            "The request first passes CheckPathVersion",
            "api-key header is present",
            "app_id path parameter is present"
          ],
          "operations": [
            {
              "operation": "gRPC AuthAPIKey",
              "trigger": "Authenticate the external API key before the handler is entered",
              "conditions": [
                "AuthApiKey middleware runs on all public chat2query routes"
              ],
              "implementation": "api.AuthApiKey -> grpc.AuthAPIKey(ctx, req)"
            },
            {
              "operation": "gRPC ShowDataApp",
              "trigger": "Resolve org_id and project_id from the external dataapp so the handler can build Chat2QueryAuthInfo",
              "conditions": [
                "AuthAPIKey succeeded"
              ],
              "implementation": "api.AuthApiKey -> grpc.ShowDataApp(ctx, req)"
            }
          ]
        },
        {
          "name": "aipower",
          "target_interface": "ChatBotService.ChatBot",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/aipower",
          "conditions": [
            "parseChat2QueryParam(c, false, false) succeeds"
          ],
          "operations": [
            {
              "operation": "gRPC ChatBot",
              "trigger": "Generate column descriptions from sample data or schema hints",
              "conditions": [
                "Always once Data2ColumnMatching reaches service.Data2ColumnMatching"
              ],
              "implementation": "service.Data2ColumnMatching -> ChatBotWithParam(\"data2columnMatching\", param) -> grpc.ChatBot(ctx, botReq)"
            }
          ]
        }
      ]
    },
    "HTTP GET /api/:api_ver/apps/:app_id/:app_ver/streaming": {
      "infrastructure": {},
      "services": [
        {
          "name": "dataservices-dataapi",
          "target_interface": "DataAPIService.AuthAPIKey + ShowDataApp",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/dataservices",
          "conditions": [
            "The request first passes CheckPathVersion",
            "api-key header is present",
            "app_id path parameter is present"
          ],
          "operations": [
            {
              "operation": "gRPC AuthAPIKey",
              "trigger": "Authenticate the external API key before the handler is entered",
              "conditions": [
                "AuthApiKey middleware runs on all public chat2query routes"
              ],
              "implementation": "api.AuthApiKey -> grpc.AuthAPIKey(ctx, req)"
            },
            {
              "operation": "gRPC ShowDataApp",
              "trigger": "Resolve org_id and project_id from the external dataapp so the handler can build Chat2QueryAuthInfo",
              "conditions": [
                "AuthAPIKey succeeded"
              ],
              "implementation": "api.AuthApiKey -> grpc.ShowDataApp(ctx, req)"
            }
          ]
        },
        {
          "name": "aipower",
          "target_interface": "ChatBotService.QueryCompletionByJobID",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/aipower",
          "conditions": [
            "QueryStreamResultReq binds successfully from the query string",
            "req.BotType is one of chat2sql, data2columnMatching, or chat2question"
          ],
          "operations": [
            {
              "operation": "gRPC QueryCompletionByJobID",
              "trigger": "Fetch the stored streaming completion result for a previous async AI request",
              "conditions": [
                "req.BotType is allowed by streamEnabledAIModels"
              ],
              "implementation": "sqleditor.QueryStreamResultByJobID -> grpc.QueryStreamResponse(ctx, &req)"
            }
          ]
        }
      ]
    },
    "HTTP POST /api/v1/chat2data": {
      "infrastructure": {
        "mysql": {
          "conditions": [
            "Only after AI generation and downstream SQL execution both succeed or fail far enough to schedule async oplog persistence"
          ],
          "operations": [
            {
              "operation": "INSERT",
              "trigger": "Persist the generated SQL execution oplog asynchronously after ExecSqlDirectly returns",
              "conditions": [
                "InternalChat2Data JSON binding succeeds",
                "service.Chat2Data(...) reaches executeSql(...)"
              ],
              "implementation": "sqleditor.InternalChat2Data -> service.Chat2Data -> executeSql -> go CreateOplog(...) -> repository.CreateOplog"
            }
          ]
        }
      },
      "services": [
        {
          "name": "aipower",
          "target_interface": "ChatBotService.ChatBot",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/aipower",
          "conditions": [
            "InternalChat2DataReq JSON binding succeeds"
          ],
          "operations": [
            {
              "operation": "gRPC ChatBot",
              "trigger": "Generate SQL for the trusted internal chat2data request",
              "conditions": [
                "Always once InternalChat2Data reaches service.Chat2Data"
              ],
              "implementation": "sqleditor.InternalChat2Data -> service.Chat2Data -> ChatBotWithParam(\"chat2data\", param) -> grpc.ChatBot(ctx, botReq)"
            }
          ]
        },
        {
          "name": "dataservices-dataapi",
          "target_interface": "DataAPIService.ExecSqlDirectly",
          "operation_type": "grpc_unary",
          "target_repo": "tidbcloud/dataservices",
          "conditions": [
            "InternalChat2DataReq JSON binding succeeds",
            "service.Chat2Data -> ChatBotWithParam succeeds"
          ],
          "operations": [
            {
              "operation": "gRPC ExecSqlDirectly",
              "trigger": "Execute the AI-generated SQL without AuthApiKey middleware because the internal listener is trusted",
              "conditions": [
                "service.executeSql is reached"
              ],
              "implementation": "sqleditor.InternalChat2Data -> service.Chat2Data -> executeSql -> grpc.ExecSqlDirectly(ctx, &dataapi.BasicEndpointReq{...})"
            }
          ]
        }
      ]
    },
    "HTTP GET /metrics": {
      "infrastructure": {},
      "services": []
    }
  },
  "notes": [
    "Public chat2query routes are all gated by CheckPathVersion, AuthApiKey, and request-size middleware before the controller code runs.",
    "The old scan incorrectly promoted middleware helper AuthApiKey to a fake standalone method key; the fresh scan keeps those calls attached to each public route as pre-handler conditions.",
    "Both chat2data and chat2chart persist execution oplogs asynchronously through executeSql(...), so the MySQL write is a side effect of the request path rather than a synchronous controller call."
  ]
}
