Skip to content

Commit 830a071

Browse files
committed
docs(spec): state the one-issue-per-slot dedupe at the reach it holds
The changeset and the semantic entry said a slot a face refuses never carries a second issue. That holds at the top level and in the combinators; inside a nested relation on an analytics carrier the schema door's own $icontains and date-preset arms still judge the slot beside the faces, so a nested $icontains with a refused comparand, or a nested one-bound $between of a preset name, can carry two issues. Text only; no verdict moves. Claude-Session: https://claude.ai/code/session_01Rjy9MeetSfq34PKn81CRiN Co-authored-by: Claude <noreply@anthropic.com>
1 parent 64dd083 commit 830a071

3 files changed

Lines changed: 17 additions & 7 deletions

File tree

‎.changeset/20116-filter-save-door-type-face-and-widget.md‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ as the comparand itself, as an implicit-equality comparand, or as an `$in` / `$n
2121

2222
Measured on `origin/main` `17bd3187` before the change: `FilterConditionSchema`, a dataset `filter`, a dataset measure `filter`, a dashboard widget `filter`, a report `runtimeFilter` and a joined report block `runtimeFilter` each parsed with `success: true` for `{ stage: { $eq: { a: 1 } } }`, `{ stage: { $in: [{ a: 1 }] } }` and a `Map` comparand, at the top level and inside a nested relation. The comparand-type face and the analytics `where` door refused each with `INVALID_FILTER` / 400. A dashboard widget `filter`, a report `runtimeFilter` and a joined report block `runtimeFilter` also parsed with `success: true` for the three nested-relation shapes above, which the analytics door refuses when they are charted.
2323

24-
**One slot, one issue — a dedupe; no verdict moves.** A slot raises the first refusal the query doors give, in their order: the comparand-shape face, then the comparand-type face, then the `$null` / `$exists` flag rule. So `{ stage: { $null: { a: 1 } } }` reads as the type face's refusal, as it does on chart. Where a face refuses a slot, the schema door's own `$icontains` and date-preset arms stay silent on it. Before, two issues could land for one defect: for example `{ created_at: { $between: ["last_7_days"] } }` reported the malformed range at `created_at.$between` AND the preset endpoint at `created_at.$between.0`; now it reports the range only, and the preset is reported once the range is fixed. Every document refused before is still refused, and every document accepted before is still accepted — only the second issue on an already-refused slot is gone.
24+
**One issue per slot at the top level and in the combinators — a dedupe; no verdict moves.** The faces' verdict on a slot is one refusal: the first the query doors give, in their order — the comparand-shape face, then the comparand-type face, then the `$null` / `$exists` flag rule. So `{ stage: { $null: { a: 1 } } }` reads as the type face's refusal, as it does on chart. At the top level of a filter and in its `$and` / `$or` / `$not` members, where a face refuses a slot the schema door's own `$icontains` and date-preset arms stay silent on it. Before, two issues could land there for one defect: `{ created_at: { $between: ["last_7_days"] } }` reported the malformed range at `created_at.$between` AND the preset endpoint at `created_at.$between.0`; now it reports the range only, and the preset is reported once the range is fixed.
25+
26+
Inside a nested relation on an analytics carrier (a dataset or measure `filter`, a widget `filter`, a report or joined-block `runtimeFilter`) a slot can still carry TWO issues. There the carrier's nested-relation walk asks the faces, while the schema door's own `$icontains` and date-preset arms keep judging nested slots as they did before this change. So `{ acct: { name: { $icontains: new Map() } } }` gets both the `$icontains` sentence and the type face's at `filter.acct.name.$icontains`, and `{ acct: { created_at: { $between: ["last_7_days"] } } }` gets the malformed range at `filter.acct.created_at.$between` and the preset endpoint at `….$between.0`. The document is refused either way; only the issue count differs.
27+
28+
Every document refused before is still refused, and every document accepted before is still accepted — the dedupe removes only a second issue on an already-refused slot at the top level and in the combinators.
2529

2630
**The words are the type face's**, less its location clause (`at where.<field>.<op>`), because the issue's path carries the location: for example `Filter comparand is a plain object ({"a":1}), which no driver can compare. A comparison value must be a string, number, bigint, boolean, null or Date. Refusing rather than guessing: …` at `filter.stage.$eq`, and at `filter.stage.$in.1` for a list member.
2731

‎packages/spec/src/migrations/entries/semantic/18.filter-comparand-types-and-widget-nested-slots-refused-at-save.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,12 @@ export const entry: SemanticMigration = {
5454
+ 'The save door now asks the type face itself, read-only, after the shape face, so it '
5555
+ 'refuses exactly what the face refuses and passes what it passes; one slot raises one '
5656
+ 'refusal, in the query doors\' order (shape, then type, then the flag rule), in the face\'s '
57-
+ 'own words less its location clause; a second issue on a slot a face already refused (the '
58-
+ 'schema door\'s own $icontains and date-preset arms) is no longer raised, which moves no '
59-
+ 'verdict. The widget filter and both report runtimeFilters declare the same '
57+
+ 'own words less its location clause. At the top level of a filter and in its $and / $or / '
58+
+ '$not members, a second issue on a slot a face already refused (the schema door\'s own '
59+
+ '$icontains and date-preset arms) is no longer raised; inside a nested relation on an '
60+
+ 'analytics carrier those two arms still judge the slot beside the faces, so a nested '
61+
+ '$icontains with a refused comparand, or a nested one-bound $between of a preset name, can '
62+
+ 'carry two issues. Neither moves a verdict. The widget filter and both report runtimeFilters declare the same '
6063
+ 'analytics-carrier filter as the dataset carriers, so their nested-relation slots are '
6164
+ 'judged by the same walk: every stored filter the analytics where door charts now refuses '
6265
+ 'on save what that door refuses on chart. Metadata AT REST is not rewritten and this entry adds no D2 '

‎packages/spec/src/migrations/registry.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9731,9 +9731,12 @@ const step18: MigrationStep = {
97319731
+ 'The save door now asks the type face itself, read-only, after the shape face, so it '
97329732
+ 'refuses exactly what the face refuses and passes what it passes; one slot raises one '
97339733
+ 'refusal, in the query doors\' order (shape, then type, then the flag rule), in the face\'s '
9734-
+ 'own words less its location clause; a second issue on a slot a face already refused (the '
9735-
+ 'schema door\'s own $icontains and date-preset arms) is no longer raised, which moves no '
9736-
+ 'verdict. The widget filter and both report runtimeFilters declare the same '
9734+
+ 'own words less its location clause. At the top level of a filter and in its $and / $or / '
9735+
+ '$not members, a second issue on a slot a face already refused (the schema door\'s own '
9736+
+ '$icontains and date-preset arms) is no longer raised; inside a nested relation on an '
9737+
+ 'analytics carrier those two arms still judge the slot beside the faces, so a nested '
9738+
+ '$icontains with a refused comparand, or a nested one-bound $between of a preset name, can '
9739+
+ 'carry two issues. Neither moves a verdict. The widget filter and both report runtimeFilters declare the same '
97379740
+ 'analytics-carrier filter as the dataset carriers, so their nested-relation slots are '
97389741
+ 'judged by the same walk: every stored filter the analytics where door charts now refuses '
97399742
+ 'on save what that door refuses on chart. Metadata AT REST is not rewritten and this entry adds no D2 '

0 commit comments

Comments
 (0)