feat(harness): add readonly mysql tool

This commit is contained in:
zhuyongxin
2026-07-21 21:24:42 +08:00
parent 3e602781d6
commit 85029d96a7
31 changed files with 1896 additions and 53 deletions
@@ -0,0 +1,54 @@
# 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.