fix(driver-turso): refuse auto_number writes on the remote transport (#6944) - #7089
Merged
os-zhuang merged 2 commits intoAug 9, 2026
Merged
Conversation
…6944) WIP checkpoint — refusal + dedicated suite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UtmF8wiWUuHFcezsXhYygb
…6944) Remote overrides the write path to RemoteTransport, which builds its own INSERT and never enters fillAutoNumberFields — so auto_number slots were silently written NULL on that face while local/replica generated numbers. Triage ruled disposition B (explicit refusal, per #3724). - TursoDriver.create / bulkCreate / upsert refuse with NOT_IMPLEMENTED/501 when a slot the driver would have had to fill is empty. Raised on the driver, not the transport: RemoteTransport.create(object, data) sees no schema, while the driver's autoNumberFields IS populated in remote mode. - Caller-supplied numbers (seed replay / preserveAudit import) and merging upserts are deliberately untouched. - The two absence-assertions from #6932/#6943 are rewritten to pin the refusal rather than deleted, keeping the transport-surface guard. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UtmF8wiWUuHFcezsXhYygb
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 6 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
August 9, 2026 15:18
This was referenced Aug 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #6944.
Ruling carried out
Triage ruled this card at 06:46Z on 2026-08-09 (comment 5230216863): disposition B — explicit refusal, per the #3724 precedent for "a driver face that boots but silently fails to deliver a declared capability". Implementing autonumber on the remote transport (A) stays behind the appetite door. The issue body still poses A-or-B; it is stale and the comment governs.
The defect
TursoDriverpicks its transport fromurl. Local and embedded-replica inheritSqlDriver's write path and issue record numbers from_objectstack_sequences. Remote overrides the write path toRemoteTransport, which builds its ownINSERTand never entersfillAutoNumberFields— soauto_numberwas only a column mapped toTEXTthere. Measured onmain@2f3e79351:Nothing upstream catches it:
supports.autonumberistrueon this face (inherited via...super.supports), so the engine defers generation to the driver and never runs its own fallback.The change
TursoDriver.create/bulkCreate/upsertrefuse, in remote mode, a write that would need a number this face cannot issue —NOT_IMPLEMENTED/ 501, the same class this package already gives an uncompilable aggregate function (#5907) or an unemittable date bucket (#6212), per ADR-0112. Refused before the statement is built, so it costs no round trip.Raised on the driver, not the transport — measured, not assumed.
RemoteTransport.create(object, data)takes no schema and caches none (arity pinned in the suite), so it cannot tell anauto_numbercolumn from any otherTEXTone.TursoDrivercan:registerRemoteFieldMetadata→registerExternalObjectclassifies fields at remote schema-sync time and populatesautoNumberFields— verified live in remote mode.Deliberately not refused: a caller-supplied number (seed replay /
preserveAuditimport — the generate predicate isfillAutoNumberFields' own, reused verbatim); and a merging upsert, which keeps the number already in the column. Only the provably-inserting upsert shape is refused. The residue — an id-bearing upsert that turns out to insert — is pinned as a[known residue, not fixed]assertion rather than left in a comment.The two absence-assertions, rewritten rather than deleted
#6932 (
turso-autonumber-resync.test.ts) and #6943 (turso-autonumber-batch-resync.test.ts) each pinned "RemoteTransporthas no autonumber surface at all". Deleting either would remove the only guard against a future silent half-implementation inside the transport; leaving them unchanged would keep a green assertion beside a claim that no longer holds. Both keep the surface probe verbatim and gain the refusal pin (codeandstatus, never a baretoThrow— ADR-0112 / #6144).Scope
packages/drivers/driver-tursoonly. All three faces pinned (#6203): local and replica still generate.driver-memory/driver-mongodbare inside the #5499 freeze, declare nosupports.autonumber, and are unrelated.Reverse verification
Predicted before running: with the refusal body emptied, every REMOTE refusal case fails through the harness's "it resolved" branch, not on a
code/statuscomparison; everything else stays green. Measured:8 failed | 923 passed— the 6 cases in the new suite plus the 2 rewritten pins, all through "it resolved"/"expected a refusal", and each failure message reprints the defect with"case_number":nullinside it.🤖 Generated with Claude Code
https://claude.ai/code/session_01UtmF8wiWUuHFcezsXhYygb
Generated by Claude Code