Skip to content

docs(data-modeling): publish MySQL's two documented degradations as deployer-facing caveats - #9052

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-9029-mysql-support-caveats
Aug 16, 2026
Merged

docs(data-modeling): publish MySQL's two documented degradations as deployer-facing caveats#9052
os-project-manager merged 1 commit into
mainfrom
claude/issue-9029-mysql-support-caveats

Conversation

@os-project-manager

Copy link
Copy Markdown
Collaborator

Fixes#9029

Ruling item 2 of #8739 (maintainer 2026-08-15, comment 5302926756, provenance 「接受你的所有建议。」) declared MySQL a supported deployment target. That converts two known degradations from implementation notes into promises a deployer needs before choosing MySQL. Both lived only in source comments. Docs prose only — no source file, test or log message is touched, and neither degradation is relitigated.

Gate union re-derived and run at final HEAD d92adf3a4.

The placement decision, and how it is defended

The card left the page and format open ("No opinion on the page or format… is the docs owner's call"). The test it set is the one that matters: a deployer evaluating MySQL must meet both caveats before committing to it. A note only a reader who already chose MySQL will find has not moved anything out of the source comment.

So the substance lands in one place and the point of choice gets a pointer:

SiteWhat it getsWhy there
content/docs/data-modeling/drivers.mdxThe substance — a MySQL dialect caveats overview table plus two new sectionsThe page titled "Database Drivers", described as "Configuration reference for supported database drivers". It is where the choice is made.
— its Supported Drivers tableA caveat pointer on the MySQL rowPrecedent in the same table: MongoDB's row already reads mongodb | mongo (single-tenant only — see below). This is the affordance the page already uses to stop a reader committing before meeting a caveat, so MySQL gets it in the identical shape.
content/docs/deployment/environment-variables.mdxOne clause on the OS_DATABASE_DRIVER rowThe published knob the ruling itself cited as "the promise already made". The row below it (OS_DATABASE_SQLITE_JOURNAL_MODE) already links into this same page, so the pattern is established on that exact table.
content/docs/plugins/packages.mdxOne bullet on @objectstack/driver-sqlThe bluntest unqualified claim, measured and handed to the card by its filer (:159, "Supports: PostgreSQL, MySQL, SQLite"). The same file carries exactly this affordance for the sibling driver 30 lines below (Not supported: row-level tenant isolation … see Drivers → Multi-tenancy).

Substance in one place, pointers elsewhere. This is not the parity sweep the card fenced off — no page was audited for implying dialect parity; these are the sites where MySQL is chosen. One sweep-class finding was measured and filed separately rather than fixed here (below).

Two exhaustiveness claims this change makes false, corrected with it

The MySQL section asserted a count, and the count is now wrong. Both corrections are the same sentence I was editing, not scope growth:

  • "One behaviour genuinely differs, and it is a limit of the dialect rather than of this driver." → three do.
  • Heading upsert conflict targets: the one dialect limit…: the target MySQL cannot honour. Its anchor has no inbound links anywhere in content/, apps/, packages/ or examples/ (grepped before renaming), so the rename breaks nothing.

What the caveats say, re-derived from source rather than from the card

1 — Uniqueness indexes MySQL cannot build

The card pointed at view-definition-active-index.ts. Reading it turned up two more callers of the same probe, carrying the same degradation for different tables, so the published caveat covers all three rather than the one the card named:

TableMigrationGuarantee not enforced on MySQL
sys_metadataoverlay-index.tsADR-0005 overlay uniqueness — package-less rows stay NULL-distinct and can duplicate; getMetaItem has no defined answer for which row wins
sys_view_definitionview-definition-active-index.tsActive-row view-name uniqueness — the card's named site
sys_settingsys-setting-identity-index.tsNULL-safe row identity — SettingsService has no defined answer for which of two colliding rows wins

Two are partial (… WHERE state = '…', which MySQL has at no version) and all three use functional key parts (COALESCE(…)). The page also states the reassurance the sources are careful about and a caveat could easily lose: the probe-first order means MySQL is left holding exactly the index it already had — never an unconstrained table, never a failed boot — with the gap announced at error on every boot plus a duplicate-listing query.

2 — The conflicting column is not named

Written to describe the decision, not to reopen it. unique-violation.ts explicitly refuses to derive a column from an index name and gives its reasons; the page carries those reasons (index names are free-form; a plausible wrong field is worse than none) and both consumers the source names — the import runner's form field, and #5495's autonumber retry where a wrong name is a wrong decision, not a vaguer message.

Two precisions taken from source that keep this honest rather than alarming:

  • The 409 UNIQUE_VIOLATION verdict is not degraded on MySQL. Only the column name is unavailable. isUniqueViolationError covers MySQL on all three channels (ER_DUP_ENTRY, errno 1062, duplicate entry), and UNIQUE_VIOLATION is a registered code (error-code-ledger.zod.ts:210).
  • This is not MySQL-only in principle. SQLite and PostgreSQL also decline when the violation reports an index rather than a column, or when the key is composite. MySQL is where going unnamed is the normal outcome, because its duplicate-entry message never carries a column at all. Stated in a callout so the caveat cannot be misread as "MySQL is broken".

The card's asymmetry claim, verified rather than copied

All three capability sites the card cites are live on origin/main, so the argument for publishing the caveats stands:

  • OS_DATABASE_DRIVER=mysqlenvironment-variables.mdx:52, cli.mdx:134 and :324
  • MysqlConfig as authorable datasource config — drivers.mdx:101 and references/data/driver-mysql.mdx
  • per-field MySQL DDL — types.mdx, incl. the per-type dialect table at :1064

And the asymmetry is real: neither degradation appears anywhere in content/docs today (grepped for partial-index and conflicting-column prose across the whole tree).

One correction to the routing implied by the card: references/data/driver-mysql.mdx is auto-generated from packages/spec/src/data/driver/mysql.zod.ts and carries a DO-NOT-EDIT banner, so it cannot be a caveat landing site.

Verification

check:doc-anchors is the gate that matters here — it validates cross-file anchors (/docs/x#fragment), which is exactly what the two new pointers are, and it computes slugs with the same github-slugger the site uses. Green, so all six links this change introduces resolve on both sides.

Check Documentation Links (lychee) is not runnable locally without a from-source Rust build. Its unique coverage beyond the anchor gate is page-path links without fragments, and this change introduces none — every new link carries a fragment and was validated by the anchor gate. The target file was confirmed to exist directly.

Not in this PR


Generated by Claude Code

…eployer-facing caveats (#9029)
Ruling item 2 of #8739 declared MySQL a supported deployment target, which
converts two known degradations from implementation notes into promises a
deployer needs before choosing MySQL. Both lived only in source comments.
- drivers.mdx gains a 'MySQL dialect caveats' overview at the point of choice
(the Supported Drivers row now carries a caveat pointer, matching the
MongoDB precedent in the same table), plus two new sections: the runtime
uniqueness indexes MySQL cannot build, and the unnamed conflicting column.
- The MySQL section's 'One behaviour genuinely differs' framing and the
'the one dialect limit' heading were exhaustive counts that this change
makes false; both are corrected.
- environment-variables.mdx and packages.mdx gain a pointer each, at the
other two published sites where MySQL is chosen.
Docs prose only. No source file, test or log message is touched, and neither
degradation is relitigated.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011RB4waLuNbdruCo6X9oobm
@github-actionsgithub-actionsBot added size/m documentation Improvements or additions to documentation labels Aug 16, 2026
@os-project-manageros-project-manager added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 16, 2026 — with Claude
@os-project-manager
os-project-manager marked this pull request as ready for review August 16, 2026 07:38
@os-project-manager
os-project-manager added this pull request to the merge queueAug 16, 2026
Merged via the queue into main with commit 2a20b99Aug 16, 2026
26 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-9029-mysql-support-caveats branch August 16, 2026 08:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MySQL's documented degradations are still source comments, not published support-matrix caveats — ruling item 2 of #8739 has no card

2 participants

@os-project-manager@claude