feat(service): a person joins a workspace's chat once, and a read writes nothing
Merged
CH
8d ago+146+146+012345678901234567890123456789-22-22-01234567890123456789
Part of making workspace chat live over Neon Realtime. It's the bottom of the chat stack (stack 6), on luke/live-same-user (#4228). One change: a person joins a workspace's chat once, and reading the chat no longer writes anything.
Why
Every chat read used to run ensureMember, a locking transaction, and ensureGeneral. Both are writes. A live subscription can't write on every change, so joining has to become a one-time step before subscribing.
What changes
- Explicit join. The
messages.chatWriteprocedure (POST /api/workspaces/chat) now also takes{join: true}.- It creates the person's chat member and
#generalif they don't exist yet. - It answers
{self}. - New wire schemas:
chatJoinRequestSchemaandchatJoinAnswerSchema.
- It creates the person's chat member and
- Reads don't write.
workspaceChatPastfinds the reader's own member and makes nothing. Someone who hasn't joined gets not found. - Released desktops still work. The held GET still joins when it reads from the start cursor (
0). Released desktops never send a join, so they join once per read loop rather than on every read.
Tests
workspace-chat.test.ts: a read past the start by someone who hasn't joined is not found and creates no member. After a join it answers. Joining twice gives the same member, and a stranger's join is not found.- New JSON Schema goldens for the two new schemas.
- Checks run one at a time on the stack's top:
- tsc for each touched package
- biome, oxlint, knip
- discarded-effect
- repository checks
- the affected vitest suites