Skip to content

drivers(turso): assertSafeIdentifier still throws a bare Error with no code/status on the field, object, groupBy and DDL positions — an unsafe identifier on the remote transport is still an opaque 500 #14287

Description

@os-support-ai

Found during contract review of PR #14248 (#14113). Recorded by the review seat rather than folded into that PR, because picking the envelope is a judgement the landed evidence does not pin.

The gap

#14113 closed the false refusal on the alias position of RemoteTransport.aggregate (Turso remote mode) by escaping instead of gating. What it deliberately left alone: RemoteTransport.assertSafeIdentifier itself still throws a bare Error — no code, no status — for every position that still routes through it: the field and object positions in aggregate, the groupBy alias position (#14235 carries that one's gating question), and the DDL / backfill positions.

So a genuinely unsafe field or object identifier on the remote transport still reaches the caller as an opaque 500 out of mapDataError. That is the other half of the #11455 / #8931 shape this repo has been closing door by door — the same class #14113's title named, one position over.

Measured on PR #14248's head 689d223f: the alias position now refuses nothing (so no un-enveloped refusal remains there), and the regression controls in remote-transport-aggregation-alias-quoting.test.ts pin that the field and object positions still refuse — with the bare Error.

Why it is filed rather than patched

The right envelope is not obvious. An injection refusal is not self-evidently INVALID_QUERY / 400 (it is a refusal of the shape, not a malformed query), and whatever code is chosen changes the error surface for DDL and backfill callers too, not only aggregate. That is a contract choice, not a mechanical edit.

Suggested direction

Give assertSafeIdentifier (or its call sites) a platform error carrying a code from the declared vocabulary and a 4xx status, so mapDataError envelopes it. Decide the code once and apply it at the helper, so every position inherits the same answer — the same "one producer" argument #14143 / PR #14247 just made about the two action doors.

Refs: #14113 (the alias half, landed) · #14235 (the groupBy alias gating question) · #11455 / #8931 (the un-enveloped-500 family).

Unassigned and untriaged, per the single-producer rule for domain:*.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions