Implement soft delete for pivot records#1789
Conversation
📝 WalkthroughWalkthroughSoft-delete support for pivot definitions is added: models, DB schema, repository, and usecases track DeletedAt; delete operations soft-delete pivots; creation may restore matching soft-deleted pivots; ListPivots gains an includeDeleted flag propagated to call sites. ChangesSoft-Delete Pivot Preservation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
35c2ab6 to
e662d10
Compare
e662d10 to
f0dc52e
Compare
f0dc52e to
ec9cf49
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@repositories/migrations/20260611100000_soft_delete_data_model_pivots.sql`:
- Around line 14-23: Do not hard-delete soft-deleted pivots in the Down
migration: remove the "delete from data_model_pivots where deleted_at is not
null" and the blind "drop column deleted_at" steps; instead either (A) preserve
historical pivots by leaving deleted_at and recreate a unique index that
includes deleted_at (e.g. recreate data_model_pivots_base_table_id_idx on
data_model_pivots (organization_id, base_table_id, deleted_at)) so historical
pivot IDs remain valid for decisions.pivot_id, or (B) if you truly must remove
deleted_at, implement an explicit remapping check first (SELECT id FROM
data_model_pivots WHERE deleted_at IS NOT NULL AND id IN (SELECT pivot_id FROM
decisions)) and abort the migration with a clear error if any referenced
soft-deleted pivots exist, then perform safe remapping before dropping the
column; reference the data_model_pivots table, the index
data_model_pivots_base_table_id_idx, and decisions.pivot_id to locate the
relevant statements.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e1f8a6b1-7bc9-4676-a33e-6247eb654f52
📒 Files selected for processing (17)
mocks/data_model_repository.gomodels/data_model_pivot.gorepositories/case_repository.gorepositories/data_model_repository.gorepositories/dbmodels/db_data_model_pivot.gorepositories/migrations/20260611100000_soft_delete_data_model_pivots.sqlusecases/ast_eval/evaluate/evaluate_entity_annotation_check.gousecases/ast_eval/evaluate/evaluate_entity_annotation_check_test.gousecases/ast_eval/evaluate/evaluate_record_score.gousecases/data_model_destroy_usecase.gousecases/data_model_usecase.gousecases/data_model_usecase_test.gousecases/decision_usecase.gousecases/ingested_data_reader_usecase.gousecases/org_export_usecase.gousecases/org_import_usecase.gousecases/worker_jobs/async_decision_job.go
✅ Files skipped from review due to trivial changes (1)
- repositories/case_repository.go
🚧 Files skipped from review as they are similar to previous changes (15)
- usecases/org_export_usecase.go
- usecases/ast_eval/evaluate/evaluate_entity_annotation_check_test.go
- models/data_model_pivot.go
- usecases/worker_jobs/async_decision_job.go
- usecases/decision_usecase.go
- repositories/dbmodels/db_data_model_pivot.go
- usecases/org_import_usecase.go
- mocks/data_model_repository.go
- usecases/ast_eval/evaluate/evaluate_record_score.go
- usecases/ingested_data_reader_usecase.go
- usecases/data_model_destroy_usecase.go
- usecases/data_model_usecase.go
- usecases/data_model_usecase_test.go
- usecases/ast_eval/evaluate/evaluate_entity_annotation_check.go
- repositories/data_model_repository.go
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Analyze (go)
- GitHub Check: test_backend / Test back-end
- GitHub Check: test_backend / Lint back-end
🧰 Additional context used
📓 Path-based instructions (2)
repositories/migrations/*.sql
📄 CodeRabbit inference engine (CLAUDE.md)
Database migrations must be created using
gooseand placed inrepositories/migrations/with SQL file format
Files:
repositories/migrations/20260611100000_soft_delete_data_model_pivots.sql
repositories/**
⚙️ CodeRabbit configuration file
repositories/**: Always use uuid v7 when creating ressources.
Do not let the database create its own ressources, instead generate a uuid v7 if the usecase layer doesn't already do so.
Files:
repositories/migrations/20260611100000_soft_delete_data_model_pivots.sql
🔇 Additional comments (1)
repositories/migrations/20260611100000_soft_delete_data_model_pivots.sql (1)
1-11: LGTM!
Problem
The new data model link management lets users change a link's type (
belongs_to ⇄ related). Demoting abelongs_tolink must remove its pivot, but pivots are hard-deleted today, anddecisions.pivot_idreferences them with a NO ACTION FK, so deleting any pivot that has produced decisions fails with an FK violation. Hard-deleting also breaks every consumer that resolves a decision's pivot by id (pivot object enrichment on cases, related-cases lookup, scoring).Solution: soft delete
Pivots get a
deleted_atcolumn. Decisions keep referencing their pivot after deletion, so everything reading pivots from historical decisions keeps working. Among the options considered (block deletion forever, soft-delete links too, snapshot pivot metadata), soft delete is the smallest change that preserves all historical data paths.deleted_atondata_model_pivots; the unique index on (organization_id, base_table_id) becomes partial (WHERE deleted_at IS NULL) so a table can get a new pivot after its old one is deleted.pivot_id.Known limitation (deferred by design): links
A soft-deleted pivot's path_link_ids can end up pointing to a hard-deleted link (demote the link, then delete it — nothing references it anymore, so deletion is allowed). The pivot definition then can't be resolved to a table/field, and old decisions lose their entity enrichment.
The problem is deferred, but guarded:
ReadPivotObjectsFromValuesnow (1) detects pivots whose path links no longer resolve and downgrades them to plain-value pivots — skipping ingested-data enrichment instead of querying with an empty table name — and (2) keeps a per-object enrichment failure local: the object is returned without entity data instead of failing the whole batch (previously one broken pivot blanked the entire case view).Summary by CodeRabbit
New Features
Improvements
Chores