Skip to content

driver-memory analytics resolves a string dateRange without ever reading the declared AnalyticsQuery.timezone #16042

Description

@zhuangjianguo

Found while working on #15825 (which UTC-ised the same function's calendar). ⛔ Deliberately NOT fixed there — that card's fence was the local-vs-UTC defect, and honouring a timezone is a capability change, not a spelling fix. Refs #15825.

The shape

AnalyticsQuerySchema declares the field, and its own comment says the absence of a value is meaningful because the engine resolves it (packages/spec/src/data/analytics.zod.ts):

/**
 * Reference timezone (IANA name) for date bucketing. OPTIONAL WITH NO
 * DEFAULT, deliberately (#4538): an ABSENT timezone is a meaningful state —
 * the engine resolves it (`selection.timezone ?? context.timezone ?? 'UTC'`,
 * ADR-0053 Phase 2) …
 */
timezone: z.string().optional(),

packages/drivers/driver-memory/src/memory-analytics.ts never reads it. Measured on origin/main at 2024eca4f:

git grep -n 'timezone' -- packages/drivers/driver-memory/src/memory-analytics.ts
(0 hits)

Positive control on the same file in the same session: git grep -c 'dateRange' → hits. So the zero is a real absence, not a broken grep.

⇒ A caller that sets timezone: 'Asia/Shanghai' and asks for dateRange: 'today' gets the UTC day. The request is accepted, no warning is emitted, and the answer silently ignores the field the caller set.

Why this is a card and not just "unimplemented"

This is the declared-≠-enforced shape of Prime Directive #10, not a missing feature request: the schema declares the knob, the contract text documents a resolution chain for it, and one implementation of that contract quietly drops it. Either the driver honours it, or the surface should stop advertising it on this path — a third state where it is accepted and ignored is the one that misleads.

Note this is genuinely orthogonal to #15825. That card made the path agree with the chain's terminal fallback (… ?? 'UTC'), which is the correct answer for every query that carries no timezone — the common case, and the one that was wrong in every non-UTC process. It left the case where a timezone IS supplied exactly as it found it.

Prior art already in the tree

@objectstack/core has the primitive and the tests for it — calendarPartsInTzOrUtc(now, timezone) and the proxyDay() pattern in packages/core/src/utils/filter-tokens.ts, whose header states the rule this would need:

Calendar arithmetic is done on a UTC "proxy" date built from the reference
timezone's calendar parts. Working in UTC keeps the math free of DST jumps
…; the zone only decides WHICH calendar day "now" is …

So the repair is likely small — but it changes which rows a query answers for anyone already passing timezone, so it wants a deliberate decision rather than a drive-by.

Open questions for triage

  1. Scope: is this driver-memory alone, or do the other analytics implementations (service-analytics' SQL compilers, driver-sql) drop it in the same place? Worth measuring across all of them before repairing one — the value of the fix is agreement, and one repaired implementation among several is a new disagreement.
  2. Related but separate: whether the token vocabulary itself should be shared with @objectstack/core's filter-token macros is tracked on driver-memory analytics silently accepts an unparseable dateRange and matches EVERY row — and the platform's own documented spelling 'Last 7 days' is one of them #16041, and the two would naturally be repaired together if that route is taken.

Unlabelled on purpose: routing, domain:*, type and priority belong to triage.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions