You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(spec)!: close timeDimensions[].dateRange's string arm to the date-range preset vocabulary (#16041) (#16618)
* feat(spec): close timeDimensions[].dateRange's string arm to the date-range preset vocabulary (wip)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
* feat(spec): changeset, ADR-0087 registration and regenerated projections for the closed dateRange vocabulary (wip 2)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
* chore(spec): regenerate api-surface, export-origins, declaration-map and reference docs for AnalyticsDateRangePreset (wip 3)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
* test(spec): pin the two isomorphic dateRange aliases (ADR-0122) and compile the schema example (wip 4)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
* test(service-analytics): re-spell the single-day dateRange fixture in the array form
The closed string vocabulary for timeDimensions[].dateRange retires the
bare-date spelling this fixture authored, so the package's required
TypeScript Type Check went red on one line (TS2322 at line 187). The
fixture now writes the same single-day window as ['2026-01-20',
'2026-01-20']; the strategy lowers both spellings to the identical
$gte/$lte bounds, so the expected values are untouched. The test's
title still names the retired dialect on purpose: a comment above it
records that retiring the test belongs to the driver-alignment card,
together with the strategy's degeneration.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
* chore(spec): regenerate content/docs/references/index.mdx on the merged tree
Regeneration commit for the forward merge of origin/main (554a160) into
this branch, kept apart from the merge commit so the two can be read
separately. `gen:schema` + `gen:docs` on the merged tree changed exactly one
file: the references index, whose counts are now the union of both sides —
main's ResumeFailureDetails (API 436 -> 437) plus this branch's
AnalyticsDateRange / AnalyticsDateRangePreset (Data 166 -> 168), total
1575 -> 1577. No other generated artifact moved.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
* test(driver-memory): retire the 15 date-range pins whose input the closed dateRange contract no longer admits
Not a test disabled to get green. #16041 closed the string arm of
timeDimensions[].dateRange to the date-range-presets.ts vocabulary
(maintainer ruling, decision batch #57), and this retirement is the
maintainer's option-B decision of 2026-09-07, chosen over routing the
fixtures around the schema door because that would have kept a live pin
on the silent-widening fallback #16041 exists to abolish. The three
memory-analytics-date-range-{dst,timezone,utc-window} files fed the
retired relative dialect ('last 3 days', 'last 7 days', 'last 1 week',
'last 2 weeks', 'last 1 month', 'last 3 months', 'last 1 year') and one
garbage string through asQuery = AnalyticsQuerySchema.parse, so on this
branch they read 15 failed | 37 passed (52) plus three TS2322, on input
production can no longer deliver through any door.
Re-spelling was measured, not assumed: driving the built dist directly,
only 'today' produces a window; every other preset (last_7_days,
last_week, ...) falls to parseDateRangeString's [range, range] fallback
and matches every row, because the parser keys on startsWith('last ').
So 0 of the 15 cases are expressible until #16322 aligns the parser.
Form: it.todo per retired case, original title kept and suffixed with
the reason; a site comment at each naming #16041 and #16322 and stating
the coverage lost; the two surviving helpers' `range` parameter retyped
from string to AnalyticsDateRange (the closed contract), which is what
clears the TS2322. No surviving assertion changed. The dst file's driver
harness (CUBE / asQuery / probesSelected / probesFor) had no surviving
caller and is removed; its cell table and all eight controls survive.
COVERAGE LOST until #16322 reinstates it in preset form:
- dst: all 13 driver cells, i.e. the ENTIRE `last N UNIT` arithmetic-leg
DST coverage in driver-memory goes to zero: spring-forward and
fall-back, the day / week / month / year legs, both hemispheres, the
two non-whole-hour zones (St_Johns -03:30, Chatham +12:45).
- timezone: the one `last N` case anchoring on the SUPPLIED zone's
calendar day and midnight (Asia/Shanghai, 'last 7 days').
- utc-window: the fallback fence on 'not a range at all'; its
zone-independence was a property of an answer that matched every row,
and #16322 owes the driver-side refusal pin in its place.
What survives: the 'today' leg's DST and zone coverage, i.e. the 7
timezone cells including the 23-hour America/New_York spring-forward day
and the 11 utc-window cells, plus every control on the dst cell table.
Reinstatement note for #16322: last_7_days / last_30_days / last_90_days
are rolling day-leg windows; last_week / last_month / last_quarter /
last_year are calendar windows, not n units back, so the week / month /
year cells need re-measured transition instants under preset semantics.
Measured: driver-memory typecheck exit 2 (three TS2322) before, exit 0
after; the three files 15 failed | 37 passed before, 37 passed | 15 todo
after, also under TZ=America/New_York; full package 1095 passed | 15
todo (1110); spec and runtime pins unmoved (235/235, 37/37); dist
byte-identical under a forced rebuild, so the 16 dependents cannot
observe a test-only diff. The same 15 failures are what reddened
Temporal Conformance on d8a3fd2 (its non-SQL leg runs driver-memory
under TZ=America/New_York); the InnoDB line in that job's tail is the
MySQL container's echo of a passing negative test and appears in main's
green run too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
---------
Co-authored-by: Claude <noreply@anthropic.com>
feat(spec)!: `timeDimensions[].dateRange`'s string arm closes to the date-range preset vocabulary; any other string is refused with `400 ANALYTICS_DATE_RANGE_UNRECOGNIZED` (#16041)
Copy file name to clipboardExpand all lines: content/docs/references/api/analytics.mdx
+9-1Lines changed: 9 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -83,14 +83,22 @@ const result = AnalyticsEndpoint.parse(data);
83
83
|**measures**|`string[]`| ✅ | List of metrics to calculate |
84
84
|**dimensions**|`string[]`| optional | List of dimensions to group by |
85
85
|**where**|`any`| optional | Filtering criteria (canonical Query DSL FilterCondition). An authored `FilterArray` is lowered by `parseFilterAST` on the client before the wire; this field admits only the lowered `FilterCondition` (see `FilterArray` in `data/filter.zod.ts`). |
|**query**|`never`| optional |[REMOVED]`query` was removed from AnalyticsQueryRequest in @objectstack/spec 17.0.0. The `{ cube, query: {...} }` envelope was the dialect of the retired degraded analytics shim — the real engine never understood it. Move the query.* fields to the body top level: `{ cube, measures, dimensions?, where?, timeDimensions?, order?, limit?, offset?, timezone? }`. |
92
92
|**format**|`never`| optional |[REMOVED]`format` was removed from AnalyticsQueryRequest in @objectstack/spec 17.0.0. It was never implemented — every response is the JSON envelope. Delete the key; for CSV/XLSX use the export surface instead. |
|**dateRange**|`Enum<'today' \| 'yesterday' \| 'this_week' \| 'last_week' \| 'this_month' \| 'last_month' \| …> \| string[]`| optional | Time window for this dimension: a date-range PRESET name from the closed vocabulary in `data/date-range-presets.ts` (today, yesterday, this_week, last_week, this_month, last_month, this_quarter, last_quarter, this_year, last_year, last_7_days, last_30_days, last_90_days — e.g. `'last_7_days'`), or an explicit `[start, end]` array of ISO dates / `{date-macro}` tokens (e.g. `["2023-01-01", "2023-01-31"]`). Any other string is refused at the schema with `400 ANALYTICS_DATE_RANGE_UNRECOGNIZED`. |
Copy file name to clipboardExpand all lines: content/docs/references/api/contract.mdx
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -27,7 +27,7 @@ const result = ApiErrorSchema.parse(data);
27
27
28
28
| Property | Type | Required | Description |
29
29
| :--- | :--- | :--- | :--- |
30
-
|**code**|`Enum<'VALIDATION_ERROR' \| 'INVALID_FIELD' \| 'MISSING_REQUIRED_FIELD' \| 'INVALID_FORMAT' \| 'VALUE_TOO_LONG' \| 'VALUE_TOO_SHORT' \| 'VALUE_OUT_OF_RANGE' \| … +298 more>`| ✅ | Error code (e.g. VALIDATION_ERROR; StandardErrorCode ∪ the ledger the serving side registers — ERROR_CODE_LEDGER for framework packages) |
30
+
|**code**|`Enum<'VALIDATION_ERROR' \| 'INVALID_FIELD' \| 'MISSING_REQUIRED_FIELD' \| 'INVALID_FORMAT' \| 'VALUE_TOO_LONG' \| 'VALUE_TOO_SHORT' \| 'VALUE_OUT_OF_RANGE' \| … +299 more>`| ✅ | Error code (e.g. VALIDATION_ERROR; StandardErrorCode ∪ the ledger the serving side registers — ERROR_CODE_LEDGER for framework packages) |
31
31
|**declaredCode**|`string`| optional | The producer-declared code, verbatim, when it is not a member of the closed `code` vocabulary — the open, author-authored channel (app-specific spellings; ADR-0112) |
|**userMessage**|`string`| optional | Producer-marked user-facing refusal text, verbatim. Present exactly when the producer opted in at throw time; consumers render it to end users and keep their generic substitution for anything unmarked. Status-agnostic; never replaces `message`. |
@@ -93,6 +93,7 @@ const result = ApiErrorSchema.parse(data);
@@ -56,12 +98,20 @@ const result = AggregationMetricType.parse(data);
56
98
|**measures**|`string[]`| ✅ | List of metrics to calculate |
57
99
|**dimensions**|`string[]`| optional | List of dimensions to group by |
58
100
|**where**|`any`| optional | Filtering criteria (canonical Query DSL FilterCondition). An authored `FilterArray` is lowered by `parseFilterAST` on the client before the wire; this field admits only the lowered `FilterCondition` (see `FilterArray` in `data/filter.zod.ts`). |
|**dateRange**|`Enum<'today' \| 'yesterday' \| 'this_week' \| 'last_week' \| 'this_month' \| 'last_month' \| …> \| string[]`| optional | Time window for this dimension: a date-range PRESET name from the closed vocabulary in `data/date-range-presets.ts` (today, yesterday, this_week, last_week, this_month, last_month, this_quarter, last_quarter, this_year, last_year, last_7_days, last_30_days, last_90_days — e.g. `'last_7_days'`), or an explicit `[start, end]` array of ISO dates / `{date-macro}` tokens (e.g. `["2023-01-01", "2023-01-31"]`). Any other string is refused at the schema with `400 ANALYTICS_DATE_RANGE_UNRECOGNIZED`. |
|[Automation Protocol](/docs/references/automation)| 13 | 73 | Flows and their nodes, approvals, ETL pipelines, webhooks, state machines, execution records. |
0 commit comments