or
Status: runtime adapter implementation + strict contract wiring.
AINL MySQL Adapter Contract (v1, runtime-native)
Status: runtime adapter implementation + strict contract wiring.
This document describes the mysql runtime adapter contract for AINL. It follows the same design intent as sqlite and postgres: explicit verbs, strict SQL classification, table allow-lists, and safe parameter handling.
1. Purpose
The mysql adapter provides direct MySQL access for AINL workflows (tested against MySQL 8.x-compatible deployments).
The adapter is:
- runtime-native (registered via
ainl run --enable-adapter mysql), - explicitly gated by capability allow-lists and security profiles,
- parameter-safe (list/tuple/dict params only; never string interpolation),
- policy-aware (
allow_write, table allow-list, privilege tier metadata).
2. Configuration
2.1 Environment variables
AINL_MYSQL_URL(preferred DSN)AINL_MYSQL_HOSTAINL_MYSQL_PORT(default3306)AINL_MYSQL_DBAINL_MYSQL_USERAINL_MYSQL_PASSWORDAINL_MYSQL_SSL_MODE(defaultREQUIRED)AINL_MYSQL_SSL_CA(optional CA bundle path)AINL_MYSQL_POOL_MIN(default1)AINL_MYSQL_POOL_MAX(default5)
If AINL_MYSQL_URL is not set, host/db/user are required.
2.2 CLI flags
Enable adapter:
ainl run your.ainl --enable-adapter mysql
Key flags:
--mysql-url--mysql-host --mysql-port --mysql-db --mysql-user --mysql-password--mysql-ssl-mode --mysql-ssl-ca--mysql-timeout-s--mysql-pool-min --mysql-pool-max--mysql-allow-write--mysql-allow-table(repeatable)
3. Security and privilege model
Adapter metadata in tooling/adapter_manifest.json:
privilege_tier:networkdestructive:truenetwork_facing:truesandbox_safe:false
Security profile behavior:
sandbox_compute_and_store:mysqlis forbidden.sandbox_network_restricted:mysqlcan be enabled.
This adapter still respects runtime capability gating and strict contract checks.
4. Verbs and syntax
4.1 query
Read-only query execution.
L1:
R mysql.query "SELECT id, email FROM users WHERE id = %s" [42] ->rows
J rows
Returns: [{...row...}]
4.2 execute
Write/DDL execution, only when writes are enabled.
L1:
R mysql.execute "UPDATE users SET active = %s WHERE id = %s" [true, 42] ->out
J out
Returns: {rows_affected, lastrowid}
4.3 transaction
Atomic sequence of query/execute operations.
L1:
R mysql.transaction [
{"verb":"execute","sql":"INSERT INTO users(email) VALUES (%s)","params":["a@x.dev"]},
{"verb":"query","sql":"SELECT COUNT(*) AS c FROM users","params":[]}
] ->txn
J txn
Returns: {ok, results}
If any operation fails, transaction is rolled back and an adapter error is raised.
5. Validation and safety rules
querymust beSELECT/WITH/EXPLAIN SELECTshaped SQL.executemust be write/DDL shaped SQL and requiresallow_write=true.- CTE execution paths are checked for write verbs (
insert|update|delete|replace) when used withexecute. - Table allow-list is enforced by SQL reference scanning (
FROM/JOIN/INTO/UPDATE/TABLE), including backtick-quoted identifiers. - Params must be list/tuple/dict; untrusted values must flow through parameters.
6. Connection behavior
- Uses
pymysqlconnections. - Uses a small built-in queue-based pool for parity with postgres pool ergonomics.
- Falls back to direct per-call connection if pooling is unavailable/empty.
- TLS behavior supports
ssl_modeplus optionalssl_ca.
Implementation references:
adapters/mysql/adapter.pyadapters/mysql/sql_guard.py
7. Limitations and roadmap
Current limitations:
- No advanced replication/streaming primitives in adapter surface.
- No server-side prepared statement lifecycle API surface.
- Async-capable under the native async runtime loop (
AINL_RUNTIME_ASYNC=1or--runtime-async) withaiomysqlwhen installed; syncpymysqlremains fallback.
Related docs:
docs/reference/ADAPTER_REGISTRY.mdtooling/adapter_manifest.jsontooling/security_profiles.json
8. Running integration tests
By default, integration tests are skipped by the standard pytest profile (-m 'not integration').
Direct DSN path:
export AINL_MYSQL_URL='mysql://user:pass@localhost:3306/ainl_test'
pytest -m integration tests/test_mysql_adapter_integration.py --mysql-url "$AINL_MYSQL_URL"
Turnkey docker path (starts/stops the bundled compose fixture automatically):
AINL_TEST_USE_DOCKER_MYSQL=1 pytest -m integration tests/test_mysql_adapter_integration.py
# or
make mysql-it
Compose fixture file:
tests/fixtures/docker-compose.mysql.yml
When docker mode is enabled, tests auto-set AINL_MYSQL_URL for the session (mysql://ainl:ainl_test_pw_change_me@127.0.0.1:3306/ainl_test).
