fix: non-owner Resolve/Un-Resolve blocked in server-sync mode#31
Merged
Conversation
…22) - server: expand PATCH /threads/:id/resolve to handle both resolve (resolved=true) and un-resolve (resolved=false); no ownership check on this endpoint — collaborative action open to any user - client: add syncResolve(thread) that broadcasts to BC/P2P then calls PATCH /threads/:id/resolve; resolve button handler now calls syncResolve instead of syncThread, bypassing the ownership-gated POST /threads upsert - tests: add resolve-access.test.mjs (7 integration tests) — non-owner resolve, non-owner un-resolve, updatedAt bump, 404 on missing id; update server-sync E2E helper to await PATCH /resolve instead of POST - docs: remove closed item from Phase F future work and README roadmap; add to Phase G, REST API table, Key Implementation Notes, Shipped list, and sync checklist - bump version to 0.5.15; rebuild annotate.min.js Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Summary
syncThread(t), which sends a fullPOST /threadsupsert — an endpoint gated bycheckOwnership. Any non-owner click → 403. The failure was silent (aconsole.warn) so the resolved state appeared to toggle locally but never reached the server, creating an invisible inconsistency with offline/BC/P2P modes where resolve is open to everyonePATCH /threads/:id/resolvenow accepts{ resolved: boolean, resolvedBy?, resolvedAt? }and handles both directions —resolved=trueresolves,resolved=falseun-resolves; no ownership check on this endpointsyncResolve(thread)— same BC/P2P broadcast and dirty-flag cleanup assyncThread, but callsPATCH /threads/:id/resolveinstead ofPOST /threads; resolve button handler now callssyncResolveinstead ofsyncThread0.5.15; rebuiltannotate.min.jsType
Affected modes
Server-sync (Mode 3) only — the bug was a server-side ownership gate. Offline, BroadcastChannel, and P2P modes were already unrestricted and are unaffected.
Testing
New integration tests (
tests/integration/resolve-access.test.mjs— 7 tests):resolvedByandresolvedAtupdatedAtso incremental?since=pulls see the changeupdatedAtso incremental pulls see the changeUpdated E2E test (
tests/e2e/server-sync.spec.js):expectResolve()helper added — watches forPATCH .../resolveinstead ofPOST /threadsFull suite: 89 unit + integration ✅ · 15/15 E2E ✅
Breaking changes
None.
PATCH /threads/:id/resolvenow accepts aresolvedboolean field (previously it only resolved, never un-resolved). Callers that omitresolvedget the same behaviour as before (resolved=trueis the default path).Checklist
server/routes/threads.js— endpoint expanded and ownership check confirmed absentassets/js/annotate.js—syncResolve()added; resolve handler updatedtests/integration/resolve-access.test.mjs— 7 new teststests/e2e/server-sync.spec.js— resolve test updated to await PATCHannotate.min.jsrebuilt (npm run build)0.5.14→0.5.15)CLAUDE.mdupdated (Phase G, REST API table, Key Implementation Notes, Future work item removed)README.mdupdated (Roadmap item moved to Shipped, sync checklist updated)Closes #22
🤖 Generated with Claude Code