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
record validator: the temporal write arms trust Date.parse — date 2026-02-30 is stored verbatim (500 on PostgreSQL), datetime 2026-02-30T10:00:00Z rolls over to March 2, and a non-ISO datetime is read in the host zone #20525
Filing gate: ① a product defect with a named landing site and a measured reach:. Finding class (a). reach: is REST POST /api/v1/data/:object, measured on memory, SQLite and PostgreSQL 16.13 at base 0bbe4005e and at PR #20524's head 4c5740d2d by the #20481 dev (os-dev-report 5880394252, out_of_scope_findings[0] and [1]). ⛔ Not re-driven by the seat.
Filed by the domain:engine execution seat 1 (session_01N8TPEsoJxPsdSdNKGnNGEN, os-warren). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim. The two arms are folded into one card because they share one landing site and one cause (Date.parse leniency at the temporal write door). Triage may split them.
For datetime, canonicalUtcDatetime hands a non-ISO string to Date.parse, which reads it in the host's local zone.
Arm 2 is the datetime twin of #20481. The #20481 dispatch kept the datetime arm out of that card: measured and reported, not edited.
Suggested shape (⛔ not a ruling)
Arm 1: a leading YYYY-MM-DD is admitted only when it names a real calendar day, for date and for the day part of datetime. Anything else is refused with VALIDATION_FAILED / 400 before any driver write. ⛔ Never rolled over.
Dedupe words: date write impossible calendar day 2026-02-30 · datetime write day rollover March 2 · datetime write non-ISO string host timezone · canonicalUtcDatetime Date.parse local zone
Filing gate: ① a product defect with a named landing site and a measured
reach:. Finding class (a).reach:is RESTPOST /api/v1/data/:object, measured on memory, SQLite and PostgreSQL 16.13 at base0bbe4005eand at PR #20524's head4c5740d2dby the #20481 dev (os-dev-report5880394252,out_of_scope_findings[0]and[1]). ⛔ Not re-driven by the seat.Filed by the
domain:engineexecution seat 1 (session_01N8TPEsoJxPsdSdNKGnNGEN,os-warren). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim. The two arms are folded into one card because they share one landing site and one cause (Date.parseleniency at the temporal write door). Triage may split them.What happens (measured by the #20481 dev)
Arm 1: an impossible calendar day.
dateplaced_on: '2026-02-30''2026-02-30'(a day that does not exist)'2026-02-30'DATABASE_ERROR("date/time field value out of range")datetimeopened_at: '2026-02-30T10:00:00Z''2026-03-02T10:00:00.000Z'Arm 2: a non-ISO
datetimestring is read in the host's zone. These were measured with the process atTZ=America/New_York, on all three backends:'2026/07/15 10:00','07/15/2026 10:00'and'15 July 2026 10:00'each read back'2026-07-15T14:00:00.000Z', which is the process zone;'2026-07-15 10:00'reads back'2026-07-15T10:00:00.000Z'(UTC, ADR-0074);'07/08/2026'reads back'2026-07-08T04:00:00.000Z': month-first, plus the process zone.The stored instant depends on the deployment host.
Why
packages/objectql/src/validation/record-validator.ts, thedate/datetimearms:Date.parsereads an impossible ISO day by rolling it over.datestorage rule keeps a leadingYYYY-MM-DDverbatim, which PR fix(objectql)!: a date string is written in its YYYY-MM-DD form, or refused with VALIDATION_FAILED / invalid_date (#20481) #20524 (record validator: adatefield written as a non-ISO string ("2026/07/15") answers 201 and is stored verbatim as"2026/07/15", a non-day, on memory and SQLite, because thedatearm admits anyDate.parse-readable string #20481) keeps as the admission rule, so'2026-02-30'passes as a day.datetime,canonicalUtcDatetimehands a non-ISO string toDate.parse, which reads it in the host's local zone.Arm 2 is the
datetimetwin of #20481. The #20481 dispatch kept thedatetimearm out of that card: measured and reported, not edited.Suggested shape (⛔ not a ruling)
YYYY-MM-DDis admitted only when it names a real calendar day, fordateand for the day part ofdatetime. Anything else is refused withVALIDATION_FAILED/ 400 before any driver write. ⛔ Never rolled over.datefield written as a non-ISO string ("2026/07/15") answers 201 and is stored verbatim as"2026/07/15", a non-day, on memory and SQLite, because thedatearm admits anyDate.parse-readable string #20481 (5875651303, "refuse, never canonicalise") carries over todatetime. A non-ISO string is refused, not read in the host zone.datefield written as a non-ISO string ("2026/07/15") answers 201 and is stored verbatim as"2026/07/15", a non-day, on memory and SQLite, because thedatearm admits anyDate.parse-readable string #20481./import'sparseDateCell(packages/rest/src/import-coerce.ts) already emits ISO.Dedupe
search_issues, run by this seat inobjectstack-ai/objectstack, open and closed:datefield written as a non-ISO string ("2026/07/15") answers 201 and is stored verbatim as"2026/07/15", a non-day, on memory and SQLite, because thedatearm admits anyDate.parse-readable string #20481 is the non-ISOdatesibling. temporal values outside the years a four-digit text or a backend holds: adatetimecomparand for year 10000 or −1 misorders on memory/SQLite and 500s on PostgreSQL; adatein year 0000 500s on PostgreSQL; adatewrite stores+010000-…verbatim #20264 and coretemporalStorageForm: thedatearm leaves a year outside 1000..9999 unpadded — over REST the epoch-ms number for 0999-06-15 counts$gt0 /$lt7 on InMemoryDriver and SQLite (correct 6 / 0); its ISO string counts 6 / 0 #20240 are year-range and padding defects. None is this.datefield written as a non-ISO string ("2026/07/15") answers 201 and is stored verbatim as"2026/07/15", a non-day, on memory and SQLite, because thedatearm admits anyDate.parse-readable string #20481, plus driver-sql: every Field.date read from PostgreSQL is one day early when the process TZ is east of UTC — toDateOnly() reads UTC components off a local-midnight Date #11389, 【缺陷】数据导出(CSV/XLSX)日期时间列硬编码按 UTC 渲染,与界面时区不一致(@objectstack/rest export-format.ts formatDate) #8373, Console renders a datetime action param as zone-lessdatetime-localand posts it raw — the runtime validator then rejects every UI submission with 400 #5061, Field.date defaultValue NOW() records the server-timezone calendar day on Postgres — and the DDL is invalid on MySQL 8.0 #4022 and MySQL: Field.datetime maps to TIMESTAMP (range ends 2038-01-19) and binds a Date in the process-local timezone #3942, all closed and about other temporal classes. None is this.Dedupe words:
date write impossible calendar day 2026-02-30·datetime write day rollover March 2·datetime write non-ISO string host timezone·canonicalUtcDatetime Date.parse local zone