fix(webapp): a pending wiki suggestion can't be read by id (#836) #838
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/proposal-read-leak"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #836.
The bug: a lore proposal (
LoreEntry.proposed_by_bot, cleared on approval) left out of the lists could still be read by any member who knew its id. Every lore read goes throughget_lore_entry, which filtered onlydeleted_at.The fix:
_hide_pending_proposal(entry, is_gm)inrouters/campaigns.py, applied to every read path a player can reach by id:GET /lore/{id}: a non-GM gets 404 with the same body as a missing entry.GET /lore/{id}/versions: the membership lookup moved ahead of the fetch, so a proposal is 404 rather than 403. A 403 would confirm it exists.GET /lore/relationships?entry_id=: a hidden proposal gives the same empty list as an unrelated id.Tests:
tests/test_proposal_read_leak.py, 11 tests.🤖 Generated with Claude Code
`get_lore_entry`, the getter almost every lore endpoint funnels through, only excluded trashed entries — not unaccepted bot proposals. A campaign member who knew or guessed a proposal's id could read its full body via GET /api/campaigns/{id}/lore/{entry_id} or its /versions history, and confirm it exists, before any GM had reviewed it. The proposal lists already filtered this correctly; the single-entry reads never did. Add `_hide_pending_proposal`, applied to every id-keyed read that can reach a lore entry: the single entry endpoint, its version history, and the approved relationships list when filtered by entry_id. A pending proposal now looks exactly like a missing id to a non-GM (same 404 body); a GM is unaffected. Tests in test_proposal_read_leak.py confirmed the leak before the fix (5 failures: player reads returned 200/403 instead of 404, and the leaking relationship result was non-empty) and pass after it, alongside the existing lore/wiki suite (120 total). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>