# 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.