Skip to content

feat(providers): publish the nine wire-compatible engines a live probe measured (#424) - #426

Merged
cevheri merged 4 commits into
mainfrom
feat/phase0-wire-compat
Aug 18, 2026
Merged

feat(providers): publish the nine wire-compatible engines a live probe measured (#424)#426
cevheri merged 4 commits into
mainfrom
feat/phase0-wire-compat

Conversation

@cevheri

@cevheri cevheri commented Aug 18, 2026

Copy link
Copy Markdown
Member

Phase 0 of #424. Eleven drivers, but a MariaDB user had no way to know that MySQL is the right button. This adds a compatibility registry, a hint in the connection dialog and a docs table - all reading one source - covering the nine engines that were connected to and measured, and nothing else.

What is here

  • src/lib/db/compatibility.ts - the single source of truth: name, the driver that serves it, the support tier, the version a live probe reported, and the caveats it found.
  • src/components/WireCompatibilityHint.tsx - renders under the driver selector in the connection dialog.
  • docs/providers/README.md#wire-compatible-engines - the per-engine table, with a reproduction command.
  • database-compose.yml - the ten instances the probes ran against, behind profiles: ["compat"], plus a redis service that was missing.
  • Unit, component and e2e coverage for all of it.

The measurements

Engine Connect as Support Version probed Failing surfaces
MariaDB mysql Full 12.3.2-MariaDB-ubu2404 0 / 15
Citus postgres Full citus 14.1-1 on PostgreSQL 18.4 0 / 15
Valkey redis Full Valkey 9.1.1 0 / 15
DragonflyDB redis Full df-v1.40.1 0 / 15
KeyDB redis Full KeyDB 6.3.4 0 / 15
FerretDB mongodb Full FerretDB 2.7.0 (MongoDB 7.0.77 wire) 0 / 11
CockroachDB postgres Partial CockroachDB CCL v26.2.5 8 / 15
Materialize postgres Query editor only Materialize 26.37.0 11 / 15
RisingWave postgres Query editor only RisingWave 3.0.3 11 / 15

Each probe ran through the shipped provider - never a native CLI - and called all fifteen introspection surfaces separately, because a compatible engine answers the connection and then diverges exactly there. PostgreSQL 18 and MySQL 26.7.0 were probed first as baselines, both clean, so every number is a delta against a known-good run.

Three things worth a reviewer's attention

A recorded assumption in #424 was refuted. The issue said CockroachDB's pg_stat_* surface was the risk. Every pg_stat-driven surface answered; all eight failures are missing size/uptime/tablespace builtins (pg_total_relation_size, pg_size_pretty, pg_postmaster_start_time, pg_tablespace_location). Narrower and more fixable than what we wrote down.

The data refuted a boolean, so tier exists. Citus matches PostgreSQL surface for surface while Materialize answers no introspection call at all. Publishing both as "compatible" is the overclaim the issue forbids, so the dialog prints the qualifier next to the name.

"Full" can still mean wrong numbers. Citus answers everything, and its answers are silently incorrect for a distributed table: 0 rows / 8 KB against a real 50 rows across 32 shards. A missing panel is honest; a populated wrong one is not - hence the caveat.

Claim discipline, as a test rather than a paragraph

tests/unit/db/compatibility.test.ts fails on an entry without a probed version string, and on a query-only or partial entry with no caveat. #424 says a name counts only after a live probe; that rule is now a CI gate.

What is not here

Six names with a plausible local path did not clear gate 4 (YugabyteDB, TimescaleDB - pulls exceeded budget; TiDB - needs a PD + TiKV cluster; SingleStore - licence key; StarRocks, OceanBase - multi-GB images), and every managed-only service has no credentials on this machine. None is ticked or published. TimescaleDB is the tempting one: assuming it works because it is "real PostgreSQL" is exactly what gate 4 refuses.

Verified count moves from 11 to 20 against a Phase 0 ceiling of 47. The README headline still says "ten engines" on purpose - a query-only engine is not an engine with a full interface, so the compatible names are a separate, qualified claim.

Verification

All six local gates pass, plus the coverage gate:

bun run format    Checked 853 files. No fixes applied.
bun run lint      0 errors (125 pre-existing warnings)
bun run typecheck clean
bun run knip      clean
bun run test      All 30 groups passed
bun run build     clean
bun run coverage:check  OK - 36981/36981 lines (100.00%)

The e2e spec (e2e/wire-compatibility.spec.ts) covers the hint in a real browser, including the negative case: SQLite has no wire protocol, so it must show no hint at all.

Findings in full: #424 (comment)

…e measured (#424)

Eleven drivers, but a MariaDB user had no way to know that MySQL is the right
button. This adds a compatibility registry, a hint in the connection dialog and a
docs table - all from one source - covering the nine engines that were connected
to and measured, and nothing else.

The registry records what a probe found, not what a vendor claims:

- `probedVersion` is the string the server itself returned. A unit test fails on
  an entry without one, which turns #424's "connects is not supported" rule into
  a CI gate instead of a paragraph.
- `tier` exists because the data refuted a boolean. Citus answers all fifteen
  introspection surfaces; Materialize answers none while still running SQL fine.
  Publishing both as "compatible" is the overclaim the issue forbids, so
  query-only and partial engines are marked as such in the dialog itself.
- `caveats` carry what breaks or misleads. Citus is the sharpest case: every
  surface answers, and the row counts it answers with are silently WRONG for a
  distributed table.

A recorded assumption did not survive contact with the engine. #424 said
CockroachDB's `pg_stat_*` surface was the risk; every pg_stat-driven surface
answered, and the eight failures are all missing size/uptime/tablespace builtins
(`pg_total_relation_size`, `pg_size_pretty`, `pg_postmaster_start_time`,
`pg_tablespace_location`). That is a narrower and more fixable shape than the one
we wrote down.

Also fixes the one hole in the shipped set: `redis` had no `database-compose.yml`
service, so its own gate-4 probe could not be reproduced on a clean machine. The
compat instances sit behind `profiles: ["compat"]`, so a plain `up` is unchanged.

Six names with a possible local instance stayed unprobed (image budget, cluster
requirements, a licence key) and every managed-only service has no credentials
here. None of them is ticked or published - untested is recorded as untested.
…#424)

`dialog.locator("text=PostgreSQL")` matched a substring, so it broke the moment
the dialog gained the compatibility hint: three probed version strings mention
PostgreSQL ("citus 14.1-1 on PostgreSQL 18.4", "advertises PostgreSQL 9.5",
"advertises PostgreSQL 13.14.0"), and Playwright refused four matches.

The assertion always meant "the driver selector offers PostgreSQL", so it now says
that: getByRole("button", { name: "PostgreSQL" }). Narrowing the version strings
instead would have deleted measured facts to accommodate a fragile locator.
…try (#424)

The compatibility table in docs/providers/README.md is hand-written prose beside
machine-readable data, which is exactly how the two drift. The new test asserts
every registry entry appears in the table with its probed version - the tri-sync
rule applied to compatible names, which have no doc page of their own to sync.

It found a drift on its first run: the table listed DragonflyDB's version as
"df-v1.40.1" while the registry says "DragonflyDB df-v1.40.1". Fixed.

Two other corrections from review:

- database-compose.yml now says that CockroachDB's `network_mode: host` is Linux
  only. On Docker Desktop `host` is the VM, not the machine, so 127.0.0.1:26257
  never answers there and the entry looks broken for a reason nothing explains.
- sonar-project.properties excludes compatibility.ts from copy-paste detection,
  with the reason written down. Nine entries sharing one key sequence read as 56
  duplicated lines; compressing them into tuples plus a mapper would satisfy the
  detector and make an auditable published claim unreadable.
… have (#424)

Two corrections from review, both about a claim being wider than the thing it
describes.

The docstring said the README, docs and channel listings "all quote this number".
They do not: they are markdown and quote it as prose, so the function has no runtime
consumer at all. It stays because the arithmetic deserves one definition that a test
pins rather than three hand-counts, but the comment now says that instead of
implying a wiring that does not exist.

The component fixture used TiDB as an invented query-only engine with an invented
version. TiDB is a name #424 records as explicitly NOT measured, so the fixture
contradicted the record it sits beside and read like a probe result to anyone
skimming. Renamed to ExampleStore, which cannot be mistaken for a product.
@sonarqubecloud

Copy link
Copy Markdown

@cevheri
cevheri merged commit 48e7c79 into main Aug 18, 2026
23 checks passed
@cevheri
cevheri deleted the feat/phase0-wire-compat branch August 18, 2026 21:03
cevheri added a commit that referenced this pull request Aug 21, 2026
…ts to 32 (#454)

The login hero derived its engine pills from `DB_UI_CONFIG` and so was already
current - Apache Cassandra and Trino were on the page. Two things were not.

The claim counted the wrong set. `HERO_CLAIMS` read `listShowcaseDatabases().length`,
which includes `libredb`: the embedded store this app carries, not a database anyone
points it at. The page therefore published one external engine more than the product
has. `EXTERNAL_DATABASE_TYPES` now defines the split beside `SHIPPED` in
`compatibility.ts`, as an exhaustive `Record<DatabaseType, boolean>` so a new type-id
cannot join without someone answering the question, and the claim reads 14. The pill
stays and is marked `(embedded)`: it is a provider the connection picker offers, so
hiding it would put the login page at odds with the app.

The eighteen wire-compatible relatives were nowhere. MariaDB, Citus, TimescaleDB,
Valkey, Vitess, FerretDB and the rest were published in README.md and the docs
compatibility table but on no surface a visitor meets first. `WireCompatibleLine`
names all eighteen from `WIRE_COMPATIBLE_ENGINES`, with the count as a `.length`, on
both the desktop hero and the mobile block. It carries no tier word: the per-engine
tier belongs to the connection dialog's hint, which has room to qualify it, so the
line claims a measurement instead of parity.

`verifiedEngineCount()` becomes `connectableProductCount()`, and the rename is the
fix. It summed the shipped drivers, so it answered 33 while README.md published 32
for the same claim - a count is wrong when its denominator is unstated, not when its
digit is stale.

Two things found on the way. `tests/components/WireCompatibilityHint.test.tsx`
shipped with #426 and was in no run group, so its seven tests had never run in CI
once; it gets its own group, because it mocks `@/lib/db/compatibility` and
`mock.module` is process-wide. And `TOTAL_GROUPS` read 30 against 32 calls, so every
green summary reported a count no run had.

Measured on the built app rather than argued: at 1440x900 and 1920x1080 the page does
not scroll, and the sign-in card is above the fold at every size tested. At 1280x800
it now scrolls 56px, because that column measured exactly 800px before this change -
zero slack - so anything added there costs height. 104px of it was reclaimed by
folding the line into the pills' block, `leading-snug`, and a shorter lead sentence.
The residual, with its numbers and the candidates for the rest, is U18 in
docs/BACKLOG.md.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant