fix(server): make Yjs sole writer of Document.content - #86
Merged
Conversation
REST update/create could overwrite the Yjs-derived content mirror, silently discarding collaborative edits (last-writer-wins). Strip content from both endpoints; also write snapshot + mirror atomically in dbPersistence.store so they cannot drift on partial failure. Closes #47
4 tasks
Alimedhat000
added a commit
that referenced
this pull request
Aug 25, 2026
Squash-merge of develop (15 commits) onto main: Security/fixes: - Yjs as sole writer of Document.content (#86) - Scope collaboration request decisions to route document (#85) - Accept email when adding collaborators (#80) - Fix stale 'view' share link on permission switch (#78) - Fix deleting shared documents (FK RESTRICT) (#77) - Re-land WS authentication + exact-ID document resolution (#74) Features/chore: - Rate-limit auth endpoints (#79) - Client quality passes a-f: infra, structure, rules, seams, stories, CI (#66-#73) - Remove leftover debug console.log calls (#75) Conflicts resolved in favor of develop's supersets (collaborators dropdown/stories/toolbar, use-collaborators hook, document tests); pnpm-lock.yaml regenerated.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #47
Problem
Document.contenthad two competing writers:dbPersistence.ts)PUT /document/:idwrote bodycontentstraight to PrismaLast-writer-wins silently discarded collaborative edits.
createDochad the same disease in reverse: it accepted initial content that no reader ever saw (the editor loads from Yjs only) and the first sync wiped it.Fix — Option A: keep the mirror, single writer
updateDoc: stripscontent; REST updates are metadata-only (title,isPublic). The dormant client autosave path (use-document.ts handleSave, Reconcile dead autosave hook #35) can be re-wired later without resurrecting the bug.createDoc: no longer accepts acontentparam; initializes to''.dbPersistence.store(): snapshot + mirror writes now run in oneprisma.$transaction(both branches) so they can't drift on partial failure.Yjs is now the sole writer of
content. Read-only consumers are tracked in #84 (search via tsvector, previews, export).Verification
server/test/document.test.ts) proves PUT cannot change content: red before, green afterws-auth.test.tscollaboration round-trips proving Yjs→content persistence still works