Found while measuring #10792 (driver parity). Filed unassigned.
What
Booting a stack whose default datasource is MySQL (client mysql2) fails schema-sync for every platform object that carries an indexed string field. driver-sql maps a string/text field with no maxLength to a MySQL TEXT column, and MySQL refuses a TEXT/BLOB column in a key without a prefix length:
alter table `sys_user` add unique `uniq_sys_user_phone_number`(`phone_number`)
-> BLOB/TEXT column 'phone_number' used in key specification without a key length
The base CREATE TABLE may succeed, but the ALTER TABLE ... ADD [UNIQUE] INDEX fails, so the table lands without its indexes and the object stays registered-but-broken (the driver logs Schema sync FAILED for object ... its table/columns were NOT created or altered). Downstream effect: the dev-admin seed never lands, and the first sign-in returns 401 INVALID_EMAIL_OR_PASSWORD on a fresh MySQL database.
Evidence
Measured against a real MySQL 8.0.46 server (a minimal ObjectQL + DefaultDatasourcePlugin(driver: 'mysql') + PlatformObjects + Auth boot). ~30 platform objects failed schema-sync. A sample of the offending columns (all in a unique or ordinary index):
sys_user.phone_number (unique)sys_session.token (unique)sys_organization.slug (unique)sys_api_key.key (unique), sys_device_code.device_code (unique)sys_metadata unique (type, name, organization_id, package_id)sys_user_preference unique (organization_id, user_id, key)sys_oauth_*client_id / token / provider_id, sys_scim_provider, sys_team.name, etc.
The identical schema syncs cleanly on Postgres 16 (Postgres indexes text freely) and on SQLite (no such restriction). driver-sql stores string/text/textarea/html as TEXT (see the createColumn comment in sql-driver.ts, "Everything else createColumn stores as TEXT").
Why it matters (declared ≠ enforced)
MySQL is a declared-supported driver — createDefaultDatasourceDriverFactory maps mysql / mysql2 → @objectstack/driver-sql. But the CI Temporal Conformance (live PG + MySQL) job exercises only driver-sql's own suites, which build their tables with explicit knex .string() (VARCHAR); it never runs the platform-objects metadatasyncSchema on MySQL. So this path is untested there and is currently broken end-to-end: a MySQL deployment cannot stand up its own platform schema.
Direction (for triage — not prescribing a fix)
Two shapes, contract-first:
- an indexed string column should be emitted as
VARCHAR(n) on MySQL (a bounded length MySQL can index), rather than TEXT; and/or - the platform objects' indexed string fields should declare a
maxLength so the driver has a bound to emit.
Repro
Branch claude/issue-10792-remove-user-txn-driver-parity carries the boot probe packages/verify/src/issue-10792-driver-parity.probe.test.ts; run it with PROBE_DIALECT=mysql and OS_TEST_MYSQL_URL pointed at a MySQL 8.0 server. The schema-sync errors appear during beforeAll.
Generated by Claude Code
Found while measuring #10792 (driver parity). Filed unassigned.
What
Booting a stack whose
defaultdatasource is MySQL (clientmysql2) fails schema-sync for every platform object that carries an indexed string field.driver-sqlmaps astring/textfield with nomaxLengthto a MySQLTEXTcolumn, and MySQL refuses aTEXT/BLOBcolumn in a key without a prefix length:The base
CREATE TABLEmay succeed, but theALTER TABLE ... ADD [UNIQUE] INDEXfails, so the table lands without its indexes and the object stays registered-but-broken (the driver logsSchema sync FAILED for object ... its table/columns were NOT created or altered). Downstream effect: the dev-admin seed never lands, and the first sign-in returns401 INVALID_EMAIL_OR_PASSWORDon a fresh MySQL database.Evidence
Measured against a real MySQL 8.0.46 server (a minimal
ObjectQL + DefaultDatasourcePlugin(driver: 'mysql') + PlatformObjects + Authboot). ~30 platform objects failed schema-sync. A sample of the offending columns (all in a unique or ordinary index):sys_user.phone_number(unique)sys_session.token(unique)sys_organization.slug(unique)sys_api_key.key(unique),sys_device_code.device_code(unique)sys_metadataunique(type, name, organization_id, package_id)sys_user_preferenceunique(organization_id, user_id, key)sys_oauth_*client_id/token/provider_id,sys_scim_provider,sys_team.name, etc.The identical schema syncs cleanly on Postgres 16 (Postgres indexes
textfreely) and on SQLite (no such restriction).driver-sqlstoresstring/text/textarea/htmlasTEXT(see thecreateColumncomment insql-driver.ts, "Everything elsecreateColumnstores as TEXT").Why it matters (declared ≠ enforced)
MySQL is a declared-supported driver —
createDefaultDatasourceDriverFactorymapsmysql/mysql2→@objectstack/driver-sql. But the CITemporal Conformance (live PG + MySQL)job exercises onlydriver-sql's own suites, which build their tables with explicitknex .string()(VARCHAR); it never runs the platform-objects metadatasyncSchemaon MySQL. So this path is untested there and is currently broken end-to-end: a MySQL deployment cannot stand up its own platform schema.Direction (for triage — not prescribing a fix)
Two shapes, contract-first:
VARCHAR(n)on MySQL (a bounded length MySQL can index), rather thanTEXT; and/ormaxLengthso the driver has a bound to emit.Repro
Branch
claude/issue-10792-remove-user-txn-driver-paritycarries the boot probepackages/verify/src/issue-10792-driver-parity.probe.test.ts; run it withPROBE_DIALECT=mysqlandOS_TEST_MYSQL_URLpointed at a MySQL 8.0 server. The schema-sync errors appear duringbeforeAll.Generated by Claude Code