fix(timestamps): send ISO-8601 and drop the offset corrections that hid it - #151
Conversation
…id it Follow-up to #150, which fixed the scan-age bookmark at the reader while leaving the ambiguous wire format in place. `get_system_signatures/1` and `get_system_structures/1` serialised UTC as `%Y/%m/%d %H:%M:%S`, which carries nothing marking it as UTC, so `new Date` read it as local time. Two readers compensated by adding `getTimezoneOffset()` to *now* — `TimeLeft` and `getRowBackgroundColor` — which cancelled the error out and made the format look correct. Any reader that did not know the trick was silently wrong by the viewer's offset, which is how the bookmark came to sit at "0h". Both handlers now emit `DateTime.to_iso8601/1`, and both corrections are gone. They had to move together: either half alone leaves the readers double-correcting in the opposite direction. `signatureAge.ts` drops the format-sniffing branch #150 added, and its tests go with it — nothing in lib/ emits the zone-less format any more, so there is one parse path again. Structure timestamps have no frontend reader at all (`mapServerStructure` spreads them through untouched; the structure timers use a separate `end_time` field), so that half is hygiene, not a behaviour change. Verified: 1808 Elixir tests, 35 frontend tests, `mix format --check-formatted`, `mix compile --warnings-as-errors`, prettier, and no new tsc errors. The new tests fail against the old format — the backend one because `DateTime.from_iso8601/1` rejects it outright, the row-colour one because a signature added seconds ago was landing seven hours stale.
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 28 minutes Limit details: You’ve used all 3 included reviews currently available under your plan. You completed 75 included PR reviews in the past 7 days; at that activity level, included reviews refill at 3 reviews per hour. Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (8)
Comment |
🧪 Test Results Summary
Full output for the advisory checks is attached to this run as 🔧 Reproduce locallymix format
mix test
mix credo --strict
mix dialyzer🤖 Auto-generated by GitHub Actions |
Follow-up to #150, which fixed the scan-age bookmark at the reader and deliberately left the ambiguous wire format alone.
What was wrong
get_system_signatures/1andget_system_structures/1serialised UTC as%Y/%m/%d %H:%M:%S— nothing in that string says UTC, sonew Dateread it as local time. Two readers compensated by addinggetTimezoneOffset()to now:TimeLeft.tsx:34(the signature table's "Added"/"Updated" columns)getRowBackgroundColor.ts:12(the new-signature row highlight)Those two cancelled the error out, which is what made the broken format look fine. Any reader that did not know the trick was silently wrong by the viewer's offset — that is exactly how the scan-age bookmark ended up pinned at
0h.Both handlers now emit
DateTime.to_iso8601/1and both corrections are gone. These had to change together: either half alone leaves the readers double-correcting in the opposite direction, which is why #150 did not touch the serialiser.signatureAge.tsdrops the format-sniffing branch #150 added, along with its tests — nothing inlib/emits the zone-less format any more, so there is a single parse path again.Scope check
I surveyed every consumer before touching the shared components, and two findings shaped the change:
getRowBackgroundColoris a second copy of the same correction. It was not in the original plan; missing it would have left row highlighting broken while everything else was fixed.TimeAgocaller is affected. Passages, pings, comments and connection times are already ISO-8601 from raw Ash structs, andTimeAgohas no correction — so they were correct before and stay correct.mapServerStructurespreads them through untouched and the structure timers use a separateend_timefield. That half is hygiene, not behaviour.Transition note
getActualSigscomparesupdated_atas a string to detect changes, andgetActualStructuresdoes aJSON.stringifycomparison. A tab held open across the deploy can compare a pre-deploy string against a post-deploy one and mark signatures changed once. It self-heals on the next refetch and nothing is written back — the server never reads these fields (create_timestamp/update_timestampown them).Tests
Both new tests fail against the old format:
DateTime.from_iso8601/1rejects2026/08/16 23:09:52outright, so the assertion is red before the change.getRowBackgroundColor: a signature added five seconds ago was landing seven hours stale under the pinned test timezone, so it got no highlight at all.1808 Elixir tests, 35 frontend tests,
mix format --check-formatted,mix compile --warnings-as-errors, prettier clean, no new tsc errors.