feat(harness): add readonly mysql tool
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# Decisions: single-react-mysql-readonly-tool
|
||||
|
||||
## Discover status
|
||||
|
||||
- Checkpoint: Discover
|
||||
- Capability source: `sm-flow` with local ISS-014, OpenSpec contracts, existing JDBC dependency/configuration and JSqlParser 4.6 already present in the local Maven cache.
|
||||
- Scale: complex, because this stage combines AST policy, authorization, JDBC resource limits, projection, and security cleanup.
|
||||
|
||||
## Evidence-driven findings
|
||||
|
||||
1. `MysqlToolRequest` and `MysqlToolResult` are already frozen under `harness.tool.contract`; no public DTO change is needed.
|
||||
2. The project already has MySQL JDBC/JPA dependencies, but no Agent-facing external read-only executor or SQL policy.
|
||||
3. JSqlParser 4.6 is available in the local Maven cache and exposes `CCJSqlParserUtil`, `Select`, `PlainSelect`, `Table`, `Column`, `Function`, `JdbcParameter` and visitor adapters compatible with Java 17.
|
||||
4. The current application datasource points to the Agent persistence database; the new Tool must use an independently configured logical datasource map and must not reuse that datasource implicitly.
|
||||
5. `scripts/query_mysql.py` currently defaults host/port/user values and contains a non-SELECT commit branch. This violates the ISS-014 security prerequisite and will be changed to read-only, environment-only behavior.
|
||||
|
||||
## Question pool
|
||||
|
||||
| Dimension | Question | Mode | Conclusion | Status |
|
||||
|---|---|---|---|---|
|
||||
| SQL language | Which SQL subset is executable? | evidence-driven | One SELECT, explicit columns, INNER/LEFT JOIN, predicates/group/order, parameter placeholders and allowlisted aggregates. | resolved |
|
||||
| Security | How is authorization decided? | evidence-driven | Independent exact schema/table/column allowlist; parser acceptance alone is insufficient. | resolved |
|
||||
| Data source | Can the Agent pass JDBC coordinates? | evidence-driven | No. Only logical data_source IDs are accepted; connection properties remain configuration/Secret data. | resolved |
|
||||
| Execution | Which JDBC controls are mandatory? | evidence-driven | PreparedStatement, readOnly connection, setMaxRows, query timeout and Run cancellation. | resolved |
|
||||
| Metadata | Can the Tool discover tables/columns? | evidence-driven | No. SHOW/DESCRIBE/information_schema are rejected. | resolved |
|
||||
| Compatibility | Does this cut over public runtime now? | evidence-driven | No. Add internal adapter/executor; Diagnosis Agent integration is stage 4. | resolved |
|
||||
|
||||
## User-confirmed direction
|
||||
|
||||
- Use the frozen `MysqlToolRequest`/`MysqlToolResult` contract.
|
||||
- Reuse the existing ToolBoundary and canonical invocation store.
|
||||
- Keep stage boundaries serial: archive and commit 3C before stage 4.
|
||||
- Do not pause for routine apply/archive/commit confirmation.
|
||||
|
||||
## Pre-apply research
|
||||
|
||||
### Existing implementations and dependencies
|
||||
|
||||
- `src/main/java/com/superbiz/agent/harness/tool/contract/MysqlToolRequest.java`
|
||||
- `src/main/java/com/superbiz/agent/harness/tool/contract/MysqlToolResult.java`
|
||||
- `src/main/java/com/superbiz/agent/harness/tool/boundary/ToolBoundary.java`
|
||||
- `src/main/java/com/superbiz/agent/harness/tool/adapter/QueryLogsToolAdapter.java`
|
||||
- `src/main/resources/application.yml`
|
||||
- `pom.xml` (`mysql-connector-j` already present; add JSqlParser 4.6)
|
||||
- `scripts/query_mysql.py`
|
||||
|
||||
### New classes
|
||||
|
||||
- `MysqlToolLimits`
|
||||
- `MysqlDataSourceDefinition` / allowlist value objects
|
||||
- `MysqlQueryPlan`
|
||||
- `MysqlSqlValidator`
|
||||
- `MysqlReadOnlyExecutor` and JDBC implementation
|
||||
- `MysqlResultProjector`
|
||||
- `MysqlToolAdapter`
|
||||
|
||||
### Risk controls
|
||||
|
||||
- Do not create a generic plugin/DSL layer.
|
||||
- Do not use regex or `startsWith` as SQL authorization.
|
||||
- Fail closed on parser/visitor uncertainty.
|
||||
- Keep raw result canonical-only and expose only bounded projection.
|
||||
|
||||
## Commit checkpoint preparation
|
||||
|
||||
- Proposal scope, design choices, frozen SQL subset, security script cleanup and acceptance scenarios are ready for Commit artifact generation.
|
||||
|
||||
## Commit audit
|
||||
|
||||
- Capability source: `sm-flow` and local OpenSpec CLI.
|
||||
- OpenSpec strict validation: passed for `single-react-mysql-readonly-tool`.
|
||||
- Cross-artifact alignment:
|
||||
- brief goals/non-goals -> proposal scope: aligned.
|
||||
- proposal SQL/security boundaries -> design architecture: aligned.
|
||||
- design validator/executor/projector decisions -> spec requirements: aligned.
|
||||
- spec scenarios -> tasks for dependency, policy, JDBC, projection, adapter and verification: aligned.
|
||||
- Interface impact: L2 internal Harness tool/adapter plus JSqlParser dependency and query-script behavior; no public protocol changes.
|
||||
- Preflight risk accepted: parser ambiguity, datasource isolation, driver cancellation behavior and sensitive result values all fail closed or remain Harness-only.
|
||||
|
||||
## Commit gate
|
||||
|
||||
- [x] proposal, design, specs and tasks exist.
|
||||
- [x] strict OpenSpec validation passes.
|
||||
- [x] all evidence-driven questions are resolved.
|
||||
- [x] no unresolved interface decision remains.
|
||||
- [x] `.committed` marker created for Apply.
|
||||
|
||||
## Apply result
|
||||
|
||||
- Added JSqlParser 4.6 and fail-closed `MysqlSqlValidator`.
|
||||
- Added immutable logical datasource/allowlist/limit/query-plan/raw-result models and independent `MysqlToolProperties` binding.
|
||||
- Added `JdbcMysqlReadOnlyExecutor` with read-only connection, PreparedStatement binding, query timeout, max rows, cell/result limits and Run cancellation callback.
|
||||
- Added `MysqlResultProjector` with sensitive-column redaction, row/cell/total UTF-8 bounds and `NO_EVIDENCE`.
|
||||
- Added `MysqlToolAdapter` through the existing ToolBoundary; invalid SQL is rejected before database execution.
|
||||
- Replaced `scripts/query_mysql.py` with environment-only, read-only transaction behavior and pre-connect write/metadata rejection.
|
||||
|
||||
## Apply conflicts and corrections
|
||||
|
||||
- `COUNT(*)` is represented by JSqlParser as an `AllColumns` parameter in this version; the visitor was corrected to permit only the explicit `COUNT(*)` exception.
|
||||
- JDBC metadata access cannot be used as a checked-exception stream method reference; the implementation uses an explicit column loop.
|
||||
- No OpenSpec/design conflict was found; both corrections were implementation details.
|
||||
|
||||
## Archive result
|
||||
|
||||
- Apply tasks complete and `.archive-ready` created.
|
||||
- OpenSpec archived at `openspec/changes/archive/2026-07-21-single-react-mysql-readonly-tool`.
|
||||
- Main capability specification added at `openspec/specs/mysql-readonly-tool/spec.md`.
|
||||
- Stage 4 may consume the internal adapter only after this stage is committed.
|
||||
Reference in New Issue
Block a user