feat: per-player erasure from transcripts & recordings (#118) #202
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/118-member-erasure"
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 #118. Third issue of v3.8.0 Privacy & Data Lifecycle.
A GM (their campaign) or admin can scrub a departed player's contributions from recorded material — leaning on the speaker-attribution already in the pipeline.
Backend (
653dacc)POST /campaigns/{id}/members/{member_id}/erase-recordings(GM-of-campaign OR admin; 403/404 otherwise) → enqueues the erasure task, 202.{regenerate_summaries: bool = false}.run_member_erasure(testable core): resolves the member's speaker labels (character name + Discord display name) and per session rewrites their transcript lines to[HH:MM:SS] <label>: [removed]— preserving the timeline skeleton; the generated FTS tsvector reindexes so erased words become unsearchable. Deletes the member's{discord_id}.wav(via verified PlatformLink), purgesLoreExtractCachefor affected sessions, deletes their attributed quote highlights (#116), and appends an erasure note to each affected session (newerasure_notesJSONB; migrationa2b3c4d5e6f7). Summaries left as-is unless the regenerate flag is set.member.recordings_erasedaudit entry attributed to the acting GM/admin (actor threaded endpoint→task→log_event), campaign/target + counts. Idempotent — a repeat run changes nothing and writes no second entry.Frontend (
<head>)erasure_notes.Tests
test_member_erasure.py) — transcript scrub + FTS-unsearchable (spoken content), quote deletion, cache-purge scoping, WAV deletion, no-link/missing-dir no-ops, erasure note + single actor-attributed audit + idempotent repeat, endpoint authz. Full suite 561 pass; migration round-trip verified.Notes
🤖 Generated with Claude Code
A GM (their campaign) or admin can scrub a member's contributions from recorded material — leaning on the speaker-attribution that already runs end to end. - POST /campaigns/{id}/members/{member_id}/erase-recordings (GM-of-campaign OR admin; 403/404 otherwise) → enqueues the erasure task, 202. Body {regenerate_summaries: bool = false}. - erase_member_recordings / run_member_erasure (testable core): resolves the member's speaker labels (character_name + Discord display name) and, per campaign session, rewrites transcript lines under those labels to "[HH:MM:SS] <label>: [removed]" — preserving the timeline skeleton; the generated FTS tsvector reindexes so erased words become unsearchable. Deletes the member's per-speaker WAV ({discord_id}.wav, via verified PlatformLink) from any retained audio dir; purges LoreExtractCache for affected sessions; deletes the member's attributed quote highlights (#116); appends an erasure note to each affected session (new erasure_notes JSONB, migration a2b3c4d5e6f7). Summaries left as-is unless regenerate flag set. - One member.recordings_erased audit entry — attributed to the acting GM/admin (actor threaded endpoint→task→log_event) with campaign/target + counts. Idempotent: a repeat run changes nothing and writes no second entry. Tests: +11 (test_member_erasure.py) — transcript scrub + FTS-unsearchable (spoken content), quote deletion, cache purge scoping, WAV deletion, no-Discord-link/missing-dir no-ops, erasure note + single actor-attributed audit + idempotent repeat, endpoint authz. Full suite 561 pass; migration round-trip verified. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>