Skip to content

Purge collected people, authors and task transcripts with their project - #404

Merged
egeozin merged 1 commit into
mainfrom
fix/purge-collected-people
Oct 13, 2026
Merged

egeozin merged 1 commit into
mainfrom
fix/purge-collected-people

Conversation

@egeozin

@egeozin egeozin commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

What and why

Deleting a project keeps the project and run rows for the billing ledger, so foreign-key cascades from projects and workflow_runs never fire. purge_project_data didn't list these tables, so they outlived the project:

  • connection_collection_jobs, connection_collection_pages and connection_collection_account_leases: the people LinkedIn collection gathered (names, headlines, up to 3,000 characters of page text each);
  • project_authors: author bindings;
  • project_task_entries: task transcripts. chat_messages were already purged; these weren't.

A collection interrupted mid-lease also stopped deletion from completing. The job still pointed at its extension device (lease_device_id, no ON DELETE). Deleting integration_connections cascades to the devices, so that foreign key failed and the purge transaction rolled back.

The purge now deletes those rows, with collection jobs going before the connections. tests/test_project_purge.py adds two tests:

  • A schema guard. After the real migrations, every table holding project data must either be cleaned by deletion (named in the purge, or cascading from a purged table) or be listed in KEPT with a reason. A new table that forgets the purge fails CI.
  • A purge test. It seeds an interrupted collection, an author and a task entry, then purges twice. Everything is gone, another project's author stays, and the run row stays.

Verification

  • The new tests fail on main: the guard names the missing tables, and the purge test hits the connection_collection_jobs_lease_device_id_fkey violation. Both pass with the fix.
  • ruff format --check, ruff check and lint-imports are clean.
  • Ran serially against a disposable local Postgres 14: test_project_purge, test_project_deletion, test_project_deletion_api, test_x_project_purge, test_connection_collection, test_run_lifecycle_regressions. All passed. Running them in parallel locally exhausted Postgres shared memory, which is an environment issue.

Notes

  • paid_ads_campaigns and paid_ads_proposals are listed as kept. They hold no personal data, and whether Tin keeps its record of the Google Ads campaigns it created is a separate decision.
  • Projects deleted before this change still hold their collected people. Cleaning them up is a separate, confirmed data step.

🤖 Generated with Claude Code

Deleting a project kept the project and run rows for billing, and the purge
didn't list the LinkedIn collection tables, project_authors or
project_task_entries, so collected people, author bindings and task
transcripts outlived it. A collection interrupted mid-lease made it worse:
the job still referenced its extension device, so deleting the connections
failed on that foreign key and the deletion never completed.

The purge now removes those rows, collection jobs before the connections.
A schema test fails whenever a table holding project data is neither
purged nor listed as kept on purpose.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@egeozin
egeozin requested a review from a team as a code owner October 13, 2026 07:24
@egeozin
egeozin merged commit d9d7870 into main Oct 13, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant