# Proposal: single-react-mysql-readonly-tool ## Problem 阶段 1 已冻结 `query_mysql` 的逻辑请求和有界结果契约,但当前仓库没有一个能把 SQL 安全地转换为可执行查询的实现。直接把 Agent 生成的 SQL 交给 JDBC 会允许写操作、元数据探测、通配符泄漏、allowlist 绕过和无界结果。 ## Proposed change - 引入 JSqlParser 4.6,解析单条 SQL 并对保守的 SELECT 子集执行 fail-closed AST 校验。 - 增加逻辑数据源定义和静态 `schema -> table -> column` 精确 allowlist;Agent 只能传逻辑数据源 ID。 - 增加参数绑定、占位符数量校验、函数 allowlist、显式列校验、JOIN/过滤/分组/排序字段校验和受控 LIMIT。 - 增加 JDBC 只读执行器:只使用配置映射的 DataSource,设置 `readOnly`、`PreparedStatement`、`setMaxRows`、查询超时,并在 Run 取消时中止执行。 - 增加 MySQL 结果 projector:限制行数、单元格和总 UTF-8 字节,脱敏敏感列,产生 `MysqlToolResult` 和 `NO_EVIDENCE`。 - 通过阶段 3A `ToolBoundary` 接入 canonical invocation store、Run budget、生命周期、`evidence_status` 和框架 `tool_call_id`。 - 把 `scripts/query_mysql.py` 收敛为仅允许 SELECT/受控 SHOW 的只读查询脚本,移除默认外部连接参数和 commit 分支;凭据与连接信息全部从环境变量读取。 ## Scope ### In scope - SQL AST validator and validated query plan. - Static logical data-source/allowlist model. - JDBC read-only executor abstraction and implementation. - MySQL result projector and ToolBoundary adapter. - Security, truncation, timeout/cancellation, no-evidence and boundary tests. - Query script safety cleanup required by the ISS-014 security prerequisite. ### Out of scope - Diagnosis Agent cutover or public Chat/AIOps/SSE changes. - Querying the application's own persistence database through the Agent-facing Tool. - Metadata discovery (`SHOW TABLES`, `SHOW COLUMNS`, `DESCRIBE`, `information_schema`). - Tenant/row-level authorization, dynamic allowlists, arbitrary SQL functions, real production business datasource provisioning. ## Frozen SQL subset - One `SELECT` statement only. - Explicit projection columns; `COUNT(*)` is the only star exception. - `INNER JOIN` and `LEFT JOIN`, normal predicates, `GROUP BY`, `HAVING`, `ORDER BY` and parameter placeholders. - No `WITH`, subquery, `UNION`, window function, `CROSS JOIN`, write statement, metadata query, transaction control, dangerous function, or unknown AST node. ## Constraints and risks - Parser acceptance is not authorization: every table and column used by projection, predicates, joins, grouping and ordering must pass the independent allowlist. - Unknown data source, schema, table, column, function, placeholder mismatch or parser failure fails closed before JDBC execution. - JDBC row/cell/byte limits are enforced in addition to ToolBoundary limits; oversized results are projected with `truncated=true` or become a safe error when no valid bounded result can be produced. - The adapter is not wired into the existing public runtime in this stage; later Diagnosis Agent work will select it through the internal Harness application use case. ## Acceptance direction - Valid explicit-column SELECT and `COUNT(*)` pass AST and allowlist validation. - Write statements, metadata, wildcard projection, nested/compound queries, unknown AST, allowlist bypass and placeholder mismatch are rejected without executor invocation. - JDBC executor uses read-only prepared statements, max rows, timeout and cancellation. - Agent receives only bounded `MysqlToolResult`; raw JDBC rows remain Harness-only canonical data.