Skip to content

feat(metadata): add startOf to relative report dates - #466

Merged
dmealing merged 7 commits into
mainfrom
fm/mo-report-calendar-windows
Oct 26, 2026
Merged

dmealing merged 7 commits into
mainfrom
fm/mo-report-calendar-windows

Conversation

@dmealing

@dmealing dmealing commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

What Changed

  • Relative report dates accept an optional startOf (day, week ISO Monday, or month): { "now": "-P90D", "startOf": "day" } truncates to midnight UTC after the duration is applied. The loader refuses any other startOf value or extra key with ERR_BAD_ATTR_FILTER, in every port's validator (TS, C#, Java, Python). The registry manifest and metamodelVersion move 1.1 to 1.2.
  • The TypeScript report-view SQL generator (time-sql.ts) emits the truncation for Postgres, SQLite/D1 and MySQL. SQLite month and year shifts now clamp to the last day of the target month, matching Postgres and MySQL. This changes the SQL for existing SQLite relative dates that carry a month or year component, so meta migrate proposes recreating those views.
  • Adds conformance fixtures (reporting-relative-startof, error-relative-date-bad-startof, error-relative-date-extra-key), a persistence report-relative-date scenario, the cube-model fixture update, and the docs, CHANGELOG and roadmap updates for the new form.
Validation

Risk Assessment

✅ Low: The change adds one optional value key, startOf, with a closed three-unit set. All four ports validate it the same way, and fixtures pin that. I traced the lowerings on Postgres, SQLite and MySQL (after the round-1 and round-2 fixes) on concrete dates: ISO-Monday weeks, month clamping and the UTC wall clock all come out right. A model that does not use startOf is unaffected, apart from the SQLite month clamp that was decided earlier and is documented.

Testing

Baseline ci-local ts-fast/ts-unit already green. Drove SQLite startOf emission live at fixed clocks: month overflow on 31st/29th/Feb-leap, -P1Y month, day, Sunday and Monday week starts all match calendar answers (8/8). Targeted and full codegen-ts + metadata suites pass. Not driven live: Postgres instant+startOf DST fix and MySQL arm (no engine in sandbox); covered by unit tests only. Full repo-wide suite not rerun here (previously timed out on Docker).

  • Live validation: ✅ go - 5 of 8 scenarios driven live against the product
Scenario Result Live Evidence
SQLite month startOf does not overflow at month end (-P1M from 2026-03-31 gives 2026-02-01) ✅ pass live sqlite-window-live.txt
SQLite -P1M startOf month from 2026-05-31 and 2026-03-29 land on first of prior month ✅ pass live sqlite-window-live.txt
SQLite -P1Y startOf month from Feb 28 gives 2025-02-01 ✅ pass live sqlite-window-live.txt
SQLite -P90D startOf day gives midnight 90 days back ✅ pass live sqlite-window-live.txt
SQLite week startOf maps Sunday to prior Monday and Monday to itself ✅ pass live sqlite-window-live.txt
Postgres instant startOf stays correct across DST (UTC wall clock) ⏸️ untested no No Postgres engine reachable in sandbox (Docker unavailable for Testcontainers). Only SQL-string unit tests cover it. Needs a Postgres instance with TimeZone America/New_York to drive live.
MySQL startOf day/week/month lowering ⏸️ untested no No MySQL engine in sandbox. Covered by unit tests only, which do not count as a live result.
Full repo regression (codegen-ts + metadata suites) ⏸️ untested no Previous payload recorded 6798 pass via bun test on the two touched packages. That is a test run, not a drive of the live product, so it cannot be recorded as a live pass. Full monorepo suite not reru…
Evidence: SQLite fixed-clock live check output
PASS clock=2026-03-31T12:00:00 -P1M startOf=month got=2026-02-01 want=2026-02-01
PASS clock=2026-05-31T12:00:00 -P1M startOf=month got=2026-04-01 want=2026-04-01
PASS clock=2026-03-29T12:00:00 -P1M startOf=month got=2026-02-01 want=2026-02-01
PASS clock=2026-02-28T12:00:00 -P1Y startOf=month got=2025-02-01 want=2025-02-01
PASS clock=2026-03-08T23:30:00 -P90D startOf=day got=2025-12-08 want=2025-12-08
PASS clock=2026-03-11T15:00:00 -P0D startOf=week got=2026-03-09 want=2026-03-09
PASS clock=2026-03-08T15:00:00 -P0D startOf=week got=2026-03-02 want=2026-03-02
PASS clock=2026-03-09T15:00:00 -P0D startOf=week got=2026-03-09 want=2026-03-09
ALL PASS

Pipeline

Updates from git push no-mistakes

✅ **Intent** - passed

✅ No issues found.

🔧 **Rebase** - 1 issue found → auto-fixed ✅
  • ⚠️ CHANGELOG.md - merge conflict rebasing onto origin/main

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 5 of 8 scenarios driven live against the product
Scenario Result Live Evidence
SQLite month startOf does not overflow at month end (-P1M from 2026-03-31 gives 2026-02-01) ✅ pass live sqlite-window-live.txt
SQLite -P1M startOf month from 2026-05-31 and 2026-03-29 land on first of prior month ✅ pass live sqlite-window-live.txt
SQLite -P1Y startOf month from Feb 28 gives 2025-02-01 ✅ pass live sqlite-window-live.txt
SQLite -P90D startOf day gives midnight 90 days back ✅ pass live sqlite-window-live.txt
SQLite week startOf maps Sunday to prior Monday and Monday to itself ✅ pass live sqlite-window-live.txt
Postgres instant startOf stays correct across DST (UTC wall clock) ⏸️ untested no No Postgres engine reachable in sandbox (Docker unavailable for Testcontainers). Only SQL-string unit tests cover it. Needs a Postgres instance with TimeZone America/New_York to drive live.
MySQL startOf day/week/month lowering ⏸️ untested no No MySQL engine in sandbox. Covered by unit tests only, which do not count as a live result.
Full repo regression (codegen-ts + metadata suites) ⏸️ untested no Previous payload recorded 6798 pass via bun test on the two touched packages. That is a test run, not a drive of the live product, so it cannot be recorded as a live pass. Full monorepo suite not reru…
  • scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchains
  • cd server/typescript && bun test packages/codegen-ts/test/projection/time-sql.test.ts packages/metadata/test/reporting-validation.test.ts (224 pass)
  • A scratch script ran the emitted SQLite SQL in in-memory bun:sqlite at fixed clocks against a calendar oracle; 8/8 pass
  • cd server/typescript && bun test packages/codegen-ts packages/metadata (6798 pass, 0 fail)
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

…week, month)

A relative date filter value can carry startOf, truncating the shifted
instant to the start of a UTC calendar unit. Lowered in the report view
SQL for Postgres, SQLite/D1 and MySQL; validated in all four loaders;
pinned by shared conformance fixtures and the persistence
report-relative-date scenario. metamodelVersion 1.1 -> 1.2.
…ed 1.1.3 into [Unreleased]; other stale metamodelVersion and startOf docs already current.
@dmealing
dmealing force-pushed the fm/mo-report-calendar-windows branch from ef8db56 to 49fba60 Compare October 26, 2026 10:53
@dmealing
dmealing merged commit 0ec0e45 into main Oct 26, 2026
1 check passed
@dmealing
dmealing deleted the fm/mo-report-calendar-windows branch October 26, 2026 10:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant