Skip to content

Commit 98b536f

Browse files
committed
chore(changeset): the closed now-anchor at every filter door
Claude-Session: https://claude.ai/code/session_01WGufzf89Y8Q23nPngB94Bo Co-authored-by: Claude <noreply@anthropic.com>
1 parent 38a5ac6 commit 98b536f

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
'@objectstack/spec': minor
3+
---
4+
5+
fix(spec)!: every filter door refuses a `{ $now, addDays }` anchor that carries any other key, as `NowAnchorSchema` already declares, instead of running it on the `addDays` reading alone
6+
7+
`NowAnchorSchema` is closed: `{ $now: true, addDays: -30, subDays: 7 }` fails to parse on its own. But the comparand-type walk every filter door runs (`normalizeFilterComparandTypes`, through `FilterConditionSchema` and `parseFilterAST`) judged an anchor by its `addDays` alone, so the extra key was kept, every executor ignored it, and the query answered the `addDays` reading with no word. The walk now refuses an anchor with any key other than `$now` and `addDays`, with the existing `INVALID_FILTER` / 400 envelope, and the refusal names the key: `it carries an undeclared key "subDays" — the anchor takes $now and addDays only (there is no subDays: a negative addDays subtracts)`.
8+
9+
Clause-②: no (narrowing) — every filter door refuses a `$now` anchor carrying a key beyond `$now` / `addDays`, which it ran before. Nothing is widened.
10+
11+
Metadata-protocol: narrowed (a filter saved through `FilterConditionSchema` may no longer carry a key beside `$now` and `addDays` on a now-anchored comparand)
12+
13+
<!-- adr-0087: not-required (no-migration-prescription) No key of any schema is added, removed or renamed: NowAnchorSchema declared exactly $now and addDays since it shipped, and this aligns the walk with that declaration. An extra key never had a meaning at any executor, so there is no rewrite that keeps what the author meant; the author decides, and the refusal names the key. -->
14+
15+
**BREAKING** accept-set narrowing at the filter comparand-type walk (`@objectstack/spec`), served at every filter door.
16+
17+
- **Before.** `engine.find()` / `count()` / `update()` in object or array form, `aggregate()`'s `where`, `aggregations[i].filter`, `having`, and a filter saved through `FilterConditionSchema` all kept `{ $now: true, addDays: N, subDays: M }` or `{ …, note: 'x' }`. The query ran on `addDays` alone.
18+
- **Now.** Each of them answers `INVALID_FILTER` / 400 (a save fails its parse), naming the undeclared key.
19+
- **Unchanged.** A well-formed anchor, `{ $now: true, addDays: <integer | { $field }> }`, and its resolved form (`$now` holding the pinned ISO instant) run as before at every door. The refusals for a missing or malformed `addDays` keep their wording.
20+
- **Who sees it.** An author who wrote an extra key on an anchor. That key was ignored before, so the rows answered were the `addDays` rows.
21+
22+
**The remedy.** Drop the extra key. To move the instant back, give `addDays` a negative value; to read the offset off a column, use `addDays: { $field: 'numeric_column' }`.

0 commit comments

Comments
 (0)