Repository navigation
docs(deployment): self-hosting's OS_DATABASE_URL guidance omits mysql:// — the one page a production deployer reads never offers a now-supported target #9053
Description
Filed unassigned by the dev seat implementing #9029 (ruling item 2 of #8739 — publishing MySQL's documented degradations as deployer-facing caveats). Duplicate-searched first, keyword over open and closed issues: the two near hits (#5820, #6265) are both standalone-stack runtime defects about scheme detection, both closed, neither about this page. No existing card.
Filed rather than fixed in PR #9052: that PR's dispatch fenced the content/docs/** sweep explicitly, and this is the inverse of the caveat work — an omitted capability claim, not an unqualified one.
Measured on origin/main @ 2ce1eb41b
content/docs/deployment/self-hosting.mdx:37, the OS_DATABASE_URL row of the "secrets you must pin" table:
Use `postgres://…`, `mongodb://…`, `libsql://…`, or a mounted `file:…` path
mysql:// is absent. The same row goes out of its way to qualify the other targets — Turso's optional install, and MongoDB's single-tenant restriction with a link to Drivers → Multi-tenancy — so the omission reads as deliberate exclusion rather than brevity.
Why this is worth a card
The maintainer's 2026-08-15 ruling on #8739 (comment 5302926756) declared MySQL a supported deployment target, on the explicit reasoning that the docs are the promise already made. self-hosting.mdx is the page that promise is least visible on, and it is the one a production deployer actually reads: its own description is "Run a compiled ObjectStack app on your own infrastructure … plus Compose with Postgres, Kubernetes, and the bare Node.js fallback."
Two consequences, and the second is the one that motivated filing:
- A deployer on the self-hosting path never learns MySQL is an option at all.
- Because they never meet it here, they also never meet its caveats here. PR docs(data-modeling): publish MySQL's two documented degradations as deployer-facing caveats #9052 publishes those caveats at the three sites where MySQL is offered (
data-modeling/drivers.mdx,deployment/environment-variables.mdx,plugins/packages.mdx). This page is the fourth site — and the only one where the fix is to add the target, which is a capability claim rather than a caveat, and therefore outside that PR's scope.
Not claimed
- No defect. Nothing is wrong or broken; a supported target is simply unlisted on one page.
- Not swept. I checked this page because it is where a self-hosting deployer meets the database choice. I did not audit
content/docs/**for other pages that omit or over-claim a dialect — that sweep is still nobody's, and MySQL's documented degradations are still source comments, not published support-matrix caveats — ruling item 2 of #8739 has no card #9029's card says so in its own words. - No opinion on wording. Whether the row gains
mysql://…plus a caveat pointer, or the page grows a Compose example the way Postgres has one, is the docs owner's call.
Related
- MySQL's documented degradations are still source comments, not published support-matrix caveats — ruling item 2 of #8739 has no card #9029 / PR docs(data-modeling): publish MySQL's two documented degradations as deployer-facing caveats #9052 — ruling item 2, the caveats this page would point at.
- [finding]
error-leak.tsasserts "nobody here runs" MySQL — but CI stands up a live mysql:8.0 for a required check, and the claim is load-bearing for security reasoning #8739 — the ruling that made MySQL a supported deployment target.
Generated by Claude Code
Activity
os-project-manager commentedon Aug 16, 2026
Finding first-touch grading: promoted →
pm:queue(findingremoved); lands incontent/docs/deployment/self-hosting.mdx:37(theOS_DATABASE_URLrow) ⇒domain:devx; type Task (an omission, not a false statement — nothing on the page is wrong).Rationale: the maintainer's 2026-08-15 ruling on #8739 declared MySQL a supported deployment target on the explicit reasoning that the docs are the promise — a supported target missing from the one page a production deployer reads is the direct residue of that ruling, so promotion needs no new decision. Wording is the dev's call per the card (add
mysql://…to the row with a caveat pointer at minimum; whether the page also grows a Compose example is optional and may be declared out of scope in the PR).Serial note: PR #9052 (in flight, #9029) publishes the MySQL caveats at three other sites and does not touch this file — no same-file conflict; dev should link the landed caveat anchors from this row, so dispatch preferably after #9052 merges (soft ordering, not a block).
Size/model suggestion: S; sonnet.
本评论来自分诊座位(scheduled fire ~08:09Z 2026-08-16,session
session_015RsmSaKJXEy45yxFRnC2KA)。Generated by Claude Code
os-project-manager commentedon Aug 16, 2026
Claiming this card.
session_011RB4waLuNbdruCo6X9oobmclaude/issue-9053-self-hosting-mysql-urlorigin/main@2cb69c31cRe-read the comments before the first edit: the only prior comment is the triage seat's first-touch grading (
session_015RsmSaKJXEy45yxFRnC2KA), which is a grading note, not a dev claim. No earlier dev claim with a different session ID exists, so proceeding.Scope as dispatched: add
mysql://toself-hosting.mdx'sOS_DATABASE_URLrow in the shape the row already uses for the other targets, and point at the caveats PR #9052 landed indata-modeling/drivers.mdxrather than restating them. No sweep ofcontent/docs/**— #9029's fence stands; any further page with the same gap gets filed as its own unassigned issue.Generated by Claude Code
os-project-manager commentedon Aug 16, 2026
{ "issue": 9053, "status": "done", "branch": "claude/issue-9053-self-hosting-mysql-url", "pr": "https://github.com/objectstack-ai/objectstack/pull/9076", "premise_still_valid": true, "summary": "The premise held on current main: the OS_DATABASE_URL row of content/docs/deployment/self-hosting.mdx was still at line 37 on 2cb69c31c and still listed only postgres://, mongodb://, libsql:// and file:. Added mysql://... to the row's 'Use ...' list next to postgres:// (same SqlDriver), followed by a one-sentence caveat pointer in the shape the row already uses for MongoDB's single-tenant restriction, linking to /docs/data-modeling/drivers#mysql-dialect-caveats. The pointer's wording is character-identical to the one PR #9052 landed on the sibling deployment page (environment-variables.mdx), so the two cannot drift into two divergent statements of the same caveat -- the substance stays in drivers.mdx. Verified against what #9052 actually landed (2a20b99ad) rather than what the card expected: the heading it created says THREE caveats, not two (the pre-existing upsert conflict-target limit plus the two new ones), so the pointer says three. On the card's mysql2:// question the check changed the answer's basis: mysql2:// is genuinely accepted by the runtime (detectDriverFromUrl in packages/runtime/src/standalone-stack.ts matches /^mysql2?://i), and drivers.mdx's URL -> Driver Inference Table at line 49 does list it as a scheme -- but the table naming 'mysql | mysql2' in the card's description is the Supported Drivers table's OS_DATABASE_DRIVER-value column, not schemes. It is still deliberately not listed here, because this row names one canonical scheme per target and never spells an alias (postgres:// not postgresql:///pg://, mongodb:// not mongodb+srv://, libsql:// not the *.turso.io http form, file: not sqlite:); adding it would make MySQL the only target on the page with enumerated aliases. Docs prose only, 1 insertion 1 deletion in one file. No sweep -- #9029's fence stands, and the one adjacent gap met while verifying my own pointer's destination was filed, not fixed.", "tests": "No unit tests apply -- this is a one-row docs prose change touching no source, config or driver behaviour, so the verification is the gate union, not a test suite. Gate families derived AFTER the diff was final, not recalled: `node scripts/pm/dispatch-gates.mjs content/docs/deployment/self-hosting.mdx` -> check:docs-audit-scope, check:docs-redirects, check:role-word (all lint.yml). Ran that union plus two the derivation did not place but the diff plainly implicates -- check:doc-anchors (the edit adds a #fragment link) and check:nul-bytes (any edit owes it). All five green at the final commit 9d1c23539 (`git rev-parse --short HEAD` at the run), on a clean tree (`git status --porcelain` empty). Real output: check:docs-audit-scope -> 'docs-accuracy-audit scope is in sync with content/docs/: 178 hand-written doc(s).' + 'release-owned pages are in scope and read-only: 9 page(s)'; check:docs-redirects -> 'check-docs-redirects: OK (apps/docs/redirects.mjs: 92 entries -- 89 page destination(s) resolved against content/docs, 3 wildcard, 0 outside the /docs route space, 98 chain probe(s) matched)'; check:role-word -> 'check-role-word: OK (43 baselined file(s), no new occurrences).'; check:doc-anchors -> 'check-doc-anchors: 240 internal #fragment link(s) across 396 source file(s) all resolve to a real heading' -- this is the one that actually proves the new link resolves #mysql-dialect-caveats to a real heading; check:nul-bytes -> 'OK (scanned 5960 text file(s) -- 5960 tracked, 0 untracked-not-ignored; skipped 5 binary; no raw ASCII control bytes).' plus a targeted grep -naP over the edited file, clean. One process note worth flagging: check:doc-anchors first failed with ERR_MODULE_NOT_FOUND because I had not yet run pnpm install in the fresh worktree -- a false red, not a finding; it went green after install, and the four other gates were unaffected. The page-path half of the new link (/docs/data-modeling/drivers) belongs to the `Check Documentation Links` job, which runs lychee and is CI's; locally the target file's existence is confirmed and #9052 already landed the identical path from two other files through that gate. CI gate conclusions are still in_progress at report time -- reporting at draft-PR time per the dispatch contract rather than waiting.", "open_questions": [], "out_of_scope_findings": [ "filed as #9075: content/docs/deployment/environment-variables.mdx:50's OS_DATABASE_URL row omits mysql:// (and mysql2://) from its example scheme list, one row above the OS_DATABASE_DRIVER row where #9052 already added the MySQL caveat pointer. Filed unassigned, labelled `documentation` + `finding` with no pm:queue and no domain:* label, because that list is explicitly an `e.g.` list and states nothing untrue -- unlike self-hosting.mdx's closed 'Use ...' instruction. Met only while verifying where my own pointer sends a deployer (self-hosting.mdx links that page as 'the full catalog'), not from a sweep; duplicate-searched first, no existing card." ] }Labels on PR #9076 read back after bots settled, not merely written:
documentation,size/xs,skip-changeset. PR is a draft with basemain, head9d1c2353968f9c8cabc873740ffbf54d687a84fc, unqueued — the merge queue is yours to arm. Worktree torn down unforced (git worktree removeexit 0); the other agents' worktrees are untouched.Generated by Claude Code
docs(deployment): list mysql:// on self-hosting's OS_DATABASE_URL row…