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:*.
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.assertSafeIdentifieritself still throws a bareError— nocode, nostatus— for every position that still routes through it: thefieldandobjectpositions inaggregate, thegroupByalias 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 inremote-transport-aggregation-alias-quoting.test.tspin that thefieldandobjectpositions still refuse — with the bareError.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 onlyaggregate. 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, somapDataErrorenvelopes 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
groupByalias gating question) · #11455 / #8931 (the un-enveloped-500 family).Unassigned and untriaged, per the single-producer rule for
domain:*.