Skip to content

Commit c8026f6

Browse files
committed
test(rest): pin the dataset-query door parse, and the measurement behind it
Adds the shape measurement the card left open as a pinned test: a legal `DatasetSelection` is refused by `AnalyticsQueryRequestSchema` on `cube` and on all four dataset-only members, which is why the siblings' schema is projected from rather than reused. Covers both sides: the card's measured specimen (`not a range at all`) now answers 400 ANALYTICS_DATE_RANGE_UNRECOGNIZED without reaching the service, and a fully-loaded valid selection — all eleven members — still answers 200 with the caller's own object reaching `queryDataset` by identity. Replays every in-repo selection specimen through the door as the leniency sweep. Claude-Session: https://claude.ai/code/session_01DapQyvYrFb1MxSYe7BL2nt Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4ce08e9 commit c8026f6

1 file changed

Lines changed: 39 additions & 0 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
'@objectstack/rest': minor
3+
---
4+
5+
`POST /analytics/dataset/query` parses its `selection` at the door, the way its two siblings already do
6+
7+
The route checked one thing about the body it forwards — that
8+
`selection.measures` was a non-empty array — and forwarded everything else
9+
unexamined. `/analytics/query` and `/analytics/sql` Zod-parse their body at
10+
the entry and lift a malformed member to a 400 before the service is reached,
11+
so a client met two postures on one family depending on which door it knocked
12+
on, and a malformed member of `selection` travelled into `dataset-executor` to
13+
be answered by whatever the face behind it happened to do with it.
14+
15+
⚠️ **A 400 is newly reachable.** Requests that previously slipped through are
16+
now refused. Two shapes:
17+
18+
- A `timeDimensions[].dateRange` outside the closed preset vocabulary answers
19+
`400 ANALYTICS_DATE_RANGE_UNRECOGNIZED` — the same code, status and wording
20+
the sibling door has answered for the identical condition since the
21+
vocabulary closed. Measured on the tree before this change, the literal
22+
string `not a range at all` reached the executor under an ordinary `200`.
23+
- Anything else malformed answers `400 VALIDATION_FAILED` with
24+
`details.fields[]`, each entry naming the member as `selection.<path>`.
25+
26+
**What is NOT newly refused, deliberately.** `selection` is a
27+
`DatasetSelection`, which is *not* the `AnalyticsQuery` the siblings parse: it
28+
carries no `cube`, and `runtimeFilter`, `dateGranularity`, `compareTo` and
29+
`totals` are members of its own. Reusing the sibling schema would have refused
30+
every real dashboard widget. What the door parses is the projection of the
31+
seven members whose declaration on `DatasetSelection` *is* the `AnalyticsQuery`
32+
member of the same name — `dimensions`, `measures`, `timeDimensions` (declared
33+
there by reference), `order`, `limit`, `offset`, `timezone` — so the refusal
34+
set is exactly what the published interface already declared. The four
35+
dataset-only members are projected away before the parse and keep reaching the
36+
executor untouched.
37+
38+
Validation-only: the caller's `selection` object is what `queryDataset`
39+
receives, by identity, never a parse output.

0 commit comments

Comments
 (0)