Skip to content

Say which clock is wrong, and link to how to fix it (GRYT-282) - #157

Merged
sivert-io merged 1 commit into
mainfrom
claude/GRYT-282-clock-skew-message
Aug 14, 2026
Merged

Say which clock is wrong, and link to how to fix it (GRYT-282)#157
sivert-io merged 1 commit into
mainfrom
claude/GRYT-282-clock-skew-message

Conversation

@sivert-io

Copy link
Copy Markdown
Member

This server's identity proof had expired. Check the clock on both machines.

That asked somebody to inspect a machine they may not own, and made them work out which of the two was wrong. The client already knew — it had just compared the server's timestamp against its own to decide the proof had expired at all.

Now:

This server's clock is about 4 minutes behind yours, so its identity proof looked expired. If it is your server, turn on time sync.

Decisions worth checking

Measured from iat, not exp. That's the one instant both sides describe: the server says when it signed, we know when we read it. The gap is the skew plus a network round trip, and a round trip is milliseconds against a 60-second window, so what survives is the skew.

Rounded to something sayable — seconds, minutes, hours, days. Whether a clock is a minute out or a day out is the useful distinction: the first is a missing time sync, the second is usually a machine that came up with no working clock. A stray hundred milliseconds isn't worth rendering.

The help URL rides beside the sentence, not inside it. The refusal card gets a "How to fix this" link; the toast stays plain text, since a link in something that disappears after 12 seconds is no use. That meant threading refusalHelpUrl through useSocketsuseServerStateserverViewServerLoadingStates, alongside the reason that already goes that way.

Falls back cleanly when a proof carries no iat — a shorter sentence, and without the instruction to go and check two clocks.

Found the hard way

A fresh Debian VPS: System clock synchronized: no, NTP service: n/a, and timedatectl set-ntp true answering NTP not supported because systemd-timesyncd wasn't installed. RTC 65 seconds off the system clock, right past the 60-second window. Completely ordinary situation, and the old message pointed at it correctly while sounding like a client bug.

Verified

Ran serverProofErrorMessage against the real module for 65s each way, 4 minutes, 3 hours, 5 days, 1 second, and a missing iat. Wording and pluralisation correct in each. serverProofHelpUrl returns the link for expired and null for every other refusal, so unrelated failures don't sprout a misleading "how to fix" button.

yarn lint and yarn build clean.

Depends on Gryt-chat/docs#27 for the anchor — merge that first or the link 404s.

🤖 Generated with Claude Code

"This server's identity proof had expired. Check the clock on both
machines" asked somebody to inspect a machine they may not own, and made
them work out which of the two was wrong. The client already knew: it had
just compared the server's timestamp against its own to decide the proof
had expired at all.

It now says which side and by how much:

  This server's clock is about 4 minutes behind yours, so its identity
  proof looked expired. If it is your server, turn on time sync.

Measured from `iat` rather than `exp`, because that is the one instant both
sides describe — the server says when it signed, and we know when we read
it. The gap is the skew plus a network round trip, and a round trip is
milliseconds against a window of a minute.

Rounded to something sayable. Whether a clock is a minute out or a day out
is the useful distinction: the first is a missing time sync, the second is
usually a machine that came up with no working clock at all. A stray
hundred milliseconds is not worth showing.

The refusal card also gets a "How to fix this" link, which is where the
help URL rides alongside the sentence rather than inside it — the toast
stays plain text, since a link in a toast that vanishes is no use. It
points at the troubleshooting section added in Gryt-chat/docs#27.

Falls back to the old shape when a proof carries no `iat`, without the
instruction to go and check two clocks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sivert-io
sivert-io merged commit 0786ea3 into main Aug 14, 2026
2 checks passed
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