Skip to content

fix: refuse scene writes from clients older than 3.0 - #1387

Open
hweihwang wants to merge 1 commit into
feat/update-to-latest-excalidrawfrom
fix/reject-outdated-clients
Open

hweihwang wants to merge 1 commit into
feat/update-to-latest-excalidrawfrom
fix/reject-outdated-clients

Conversation

@hweihwang

@hweihwang hweihwang commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #1161; merge together with it.

A tab still running 2.x after the upgrade drops sticky notes when it saves. This stops that:

  • The server refuses saves from 2.x (400 client_upgrade_required).
  • 3.0 ignores what 2.x tabs send; while one is in the room, every 3.0 tab saves.
  • After a lost connection, a tab merges what others saved before it saves again.

Also fixes the recording code removing the collaboration code's connection listeners.

Tested with PHPUnit, vitest and Playwright on stable31, stable32 and master, and by hand with a 2.1 tab next to a 3.0 tab.

  • Prepared with AI assistance.
  • The AI-generated content was reviewed, comprehended and tested by a human.

@hweihwang
hweihwang added this pull request to stack #1388 October 14, 2026 07:55
@hweihwang
hweihwang marked this pull request as ready for review October 14, 2026 08:03
@hweihwang
hweihwang force-pushed the fix/reject-outdated-clients branch from cf4227c to 9fcead3 Compare October 21, 2026 06:59
A browser tab still running Whiteboard 2.x after the upgrade drops element
types it does not know, such as sticky notes, and the server builds the
saved scene from the incoming elements. Its saves would remove them.

- The server answers a scene write without schemaVersion 2 with
  400 client_upgrade_required, after the permission checks and before the
  sync lock (2.0 treats the lock's 409 as saved), and writes nothing.
- 3.0 clients send schemaVersion 2 with every write and scene broadcast,
  and ignore scene broadcasts without it. A restore broadcast only asks
  peers to reload from the server, so it is followed from any client.
- Once a 3.0 client sees such a broadcast, it saves too and sends the
  full scene to new joiners, because the elected saver may be the 2.x
  tab.
- A client that lost the connection writes to the server again only
  after it merged the saved board (retried until it loads), because the
  2.x tab's scene that used to bring it up to date is now ignored. An
  upload still waiting in the sync worker is dropped at the disconnect,
  and a periodic save reads the scene only after waiting for its token.
  Its local copy is still kept up to date.
- The recording hook removed every connect and disconnect listener of the
  socket, so the collaboration code never noticed a lost connection. It
  now removes only its own listeners. Following now also stops when the
  followed user left while this client was disconnected.

Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Hoang Pham <hoangmaths96@gmail.com>
@hweihwang
hweihwang force-pushed the fix/reject-outdated-clients branch from 9fcead3 to d8d1678 Compare October 22, 2026 12:33
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