Skip to content

governance: retain lineage_event skeleton on SQLite erase (SEC-016 parity) - #300

Merged
guangyu-reflexio merged 1 commit into
mainfrom
security/readiness-sec016-erase-parity
Jul 7, 2026
Merged

governance: retain lineage_event skeleton on SQLite erase (SEC-016 parity)#300
guangyu-reflexio merged 1 commit into
mainfrom
security/readiness-sec016-erase-parity

Conversation

@guangyu-reflexio

@guangyu-reflexio guangyu-reflexio commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

SEC-016 — cross-backend GDPR-erase parity on lineage_event. On user-data erase, SQLite hard-DELETEd lineage_event rows referencing erased entities, while Supabase retains the content-free lineage skeleton (its erase path never enumerates lineage_event — it's in neither the purge nor the delete set; the #219/#383 content-purge design keeps a content-free skeleton and purges PII on the entity tables). This converges SQLite onto the intended model.

Change

  • Stop deleting lineage_event on erase (sqlite_storage/governance/_erase_execution.py). Safe because lineage_event has no PII/content column, no foreign keys, no FTS/vec shadow tables — retaining the row is exactly the content-free skeleton the design intends, and lineage reconstruction is helped (the retained status_change signal survives). Removed the delete block + now-dead erased_entity_ids/request_ids/import json. Entity-table deletes + purge_content calls are untouched.
  • Inverted the test that codified the old behavior (test_governance_storage.py): test_apply_governance_user_data_delete_retains_lineage_skeleton now asserts the pre-seeded skeleton row still exists (== 1) after erase, instead of == 0.

Note on scope

The retained values are opaque surrogate IDs (profile_id/request_id/entity_id) in a content-free table — this matches the already-shipped Supabase behavior, so this is a convergence, not a new retention decision. (If those internal IDs should ever be treated as PII, that's a separate cross-backend change requiring Supabase to scrub too.)

Verification

governance/erase/lineage/purge tests: 473 passed; full sqlite storage suite: 390 passed; ruff + pyright clean.

Summary by CodeRabbit

  • Bug Fixes

    • Updated data-deletion behavior so non-sensitive lineage “skeleton” records are preserved after governance erasure, while content-bearing user data is still removed.
    • Aligned deletion handling with expected behavior to avoid removing valid lineage context tied to unrelated records.
  • Tests

    • Revised coverage to verify that retained lineage records remain after user data deletion.

…16 parity)

On user-data erase, SQLite hard-DELETEd lineage_event rows referencing erased
entities, while Supabase retains the content-free lineage skeleton (never touches
lineage_event — it's in neither the purge nor delete set; #219/#383 content-purge
design). Converge: stop deleting. lineage_event has no PII/content column, no FKs,
no FTS/vec, so retaining is safe and reconstruction is helped. Removed the delete
block + now-dead erased_entity_ids/request_ids/import json. Inverted the test that
codified count==0 to assert the skeleton is retained (==1).
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ab6f64d4-00f6-4058-a85d-ef28850fe021

📥 Commits

Reviewing files that changed from the base of the PR and between 66be5a5 and f297a4d.

📒 Files selected for processing (2)
  • reflexio/server/services/storage/sqlite_storage/governance/_erase_execution.py
  • tests/server/services/storage/sqlite_storage/test_governance_storage.py

📝 Walkthrough

Walkthrough

The governance erase execution logic in the SQLite storage mixin no longer deletes lineage_event rows during user data erasure; it now retains content-free "skeleton" lineage rows. The corresponding test was replaced to verify this retention behavior instead of full deletion.

Changes

Lineage retention on governance erase

Layer / File(s) Summary
Remove lineage_event deletion from erase execution
reflexio/server/services/storage/sqlite_storage/governance/_erase_execution.py
Removes the json import, the request_ids collection step, and the lineage cleanup logic that previously deleted lineage_event rows based on parsed source_ids; adds SEC-016 comments documenting that content-free lineage skeleton rows are now retained.
Update test to assert lineage skeleton retention
tests/server/services/storage/sqlite_storage/test_governance_storage.py
Replaces test_apply_governance_user_data_delete_succeeds_after_hide_targets_complete with test_apply_governance_user_data_delete_retains_lineage_skeleton, asserting exactly one matching lineage_event row remains after erase instead of asserting full deletion.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • ReflexioAI/reflexio#219: Related to lineage/content-purge logic that preserves lineage chains while erasing content, aligning directly with this PR's retention change.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Clearly summarizes the main change: SQLite erase now retains lineage_event skeleton rows for SEC-016 parity.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch security/readiness-sec016-erase-parity

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@guangyu-reflexio
guangyu-reflexio merged commit 51e9899 into main Jul 7, 2026
1 check passed
@guangyu-reflexio
guangyu-reflexio deleted the security/readiness-sec016-erase-parity branch July 7, 2026 01:50
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