Retention counts from a session's first processing, not its last edit (#791) #800
Loading…
Reference in a new issue
No description provided.
Delete branch "build/791-retention-anchor"
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 #791 (R1: the owner chose "from when the audio was first processed").
The bug
Both retention windows counted from
transcript_updated_at, which records when the transcript was last touched. A member erase rewrites it on every session it scrubs, and so does a reprocess. So erasing one member from a 25-day-old session under a 30-day policy kept everyone else's audio and words for another 30 days. A privacy control caused more to be kept.The fix
sessions.audio_processed_at.process_audio's success path stamps it only while it's NULL, so neither an erase nor a reprocess moves it.e1f2a3b4c5d6(on top ofd0e1f2a3b4c5, single head):transcript_updated_at, which is exactly the anchor each row had at upgrade time. Nothing is kept or deleted differently on upgrade day.app/retention.py:first_processed_at()reads the stamp. It falls back totranscript_updated_atonly for an unstamped import from a pre-#791 export.in_flight(): a session inprocessingis never caught, so the sweep can't bin audio out from under its own reprocess. A run that dies is moved tofailedafter 8 hours byunstick_lost_tasks, so this can't hold audio for ever.select_retention_catch.Tests
test_retention_anchor.py:process_audioseam: the first success stamps, a reprocess doesn't move the stamp, and a failure stamps nothing.run_member_erasureend to end: on day 25 of 30 nothing is caught; seven days later the preview and the sweep both catch it.test_audio_processed_at_migration.pyruns the realupgrade()/downgrade(): backfill, nothing else moves, the round trip, and idempotence.retention.py.Follow-ups filed
🤖 Generated with Claude Code