Files
pad/internal
xarmian 74c786d590 fix(store,server): close codex round 2 — the wrapper must mirror its base
Seven findings; two were P1 and one of them was a real hole on Postgres only.

[P1] driver.Valuer bypassed the guard. checkParams type-asserted `string`, and
pgx implements NamedValueChecker — so it ACCEPTS a sql.NullString unchanged
rather than letting database/sql's converter unwrap it, and the guard never saw
the text. Measured before the fix: a NUL-bearing sql.NullString on Postgres
passed Layer A entirely and was refused by the server as SQLSTATE 22021, i.e. a
500, while the identical value on SQLite got the typed 400 — the dialect split
reappearing in the response shape. wiki_links.go binds sql.NullString today.

[P1] driver.DriverContext was dropped, so sql.Open used a legacy connector that
ignores the context and a cancelled request could leave a pgx dial running to
its 60-second timeout.

The rest share one cause, and it is the thing to remember: database/sql BRANCHES
on whether an optional interface is present, so a wrapper advertising one the
base lacks CHANGES behaviour rather than adding a no-op. Measured, the two
drivers differ — pgx has no Validator, sqlite has no conn NamedValueChecker and
no DriverContext — and the single wrapper type claimed all of them.

So the wrapper now MIRRORS its base: four conn variants over the two interfaces
that vary, a separate driver type for DriverContext, and the non-varying ones
asserted at registration so a driver bump fails loudly instead of degrading.

I made the same mistake inside the fix — implementing OpenConnector
unconditionally, which broke every SQLite open — and then a third time, where
guardConnector.Driver() returned the inner wrapper and a pgx pool reported no
DriverContext. The third was caught by a new parity test on its first run, not
by review: it asserts wrapped and base advertise EXACTLY the same interfaces.

Also: both gap guardrails SKIPPED when their slice was empty, so deleting an
entry made the suite green — the opposite of their purpose. They assert counts
now. And the oracle test compared the two walkers without pinning any answer,
which is how round 27 left both wrong about scalars; known answers are pinned
against Postgres, and doing that caught me re-pinning one from a stale comment.

Full Go suite green on SQLite and Postgres 17; lint 0 issues.

Claude-Session: https://claude.ai/code/session_01XLtX4dbjBpApbAv3SuBcTm
2026-09-01 13:57:07 +00:00
..
2026-03-26 01:52:36 +00:00