Files
Lumotia/docs/issues/c4-transcript-profile-fk.md
Jake 9b0067b4c0
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
Land release blocker fixes and workspace cleanup
2026-04-23 00:16:09 +01:00

2.7 KiB

RB-03 CRITICAL: transcript provenance can reference deleted profiles

Severity: CRITICAL Path: crates/storage/src/migrations.rs:208-216, crates/storage/src/database.rs:61-89, :697-708 Source: 2026-04-22 code review Labels: release-blocker, critical, data-integrity, storage Status: RESOLVED (2026-04-22)

Resolution

Chose the strict provenance path:

  • Migration v9 rebuilds transcripts with profile_id REFERENCES profiles(id) ON DELETE RESTRICT.
  • Existing orphaned transcript profile_id values are reconciled onto DEFAULT_PROFILE_ID during the copy into the rebuilt table.
  • Because SQLite table renames rewrite dependent references, the migration also rebuilds segments, recreates the transcript FTS virtual table/triggers, and repopulates FTS from the rebuilt transcript rows inside the same transaction.

Application-layer behaviour now matches the schema:

  • insert_transcript rejects unknown profile_id values with a clear storage error before attempting the insert.
  • delete_profile returns a human-readable reassign-first error when transcripts still reference that profile.

Regression tests:

  • migration_v9_reconciles_orphaned_transcript_profiles_and_adds_fk
  • insert_transcript_rejects_unknown_profile_id
  • delete_profile_rejects_when_transcripts_reference_it

Problem

v8 migration adds transcripts.profile_id but without a FOREIGN KEY constraint. insert_transcript accepts any profile_id string without validation. delete_profile doesn't guard against existing transcript references. The combined result: persisted transcripts can keep orphaned profile IDs indefinitely, breaking provenance integrity.

Acceptance

  • A v9 migration adds FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE RESTRICT (or ON DELETE SET NULL if soft-orphaning is preferred — decide during the fix).
  • The migration reconciles existing orphans: either backfill with DEFAULT_PROFILE_ID, or null them, per the chosen FK semantic.
  • insert_transcript passes the FK check — no behaviour change on the happy path.
  • delete_profile returns a meaningful error when transcripts reference the profile being deleted (or cascades to null, matching the FK semantic).
  • Regression tests: (a) delete_profile with transcript references behaves per the chosen semantic; (b) insert_transcript with a non-existent profile_id errors; (c) existing orphans are reconciled on first migration to v9.

Fix scope

Large. FK constraint design decision + migration + reconciliation + database.rs updates + tests.

Dependencies

  • Blocked by: RB-02 (migrations atomicity — the v9 migration must be transactional).