The database audit found 3 foreign-key delete-rule mismatches that need to be reconciled between the code and the database.
ai_conversations.permission_profile_id → permission_profiles declares ON DELETE no action in the code, but the database is set to set null.Fix: apply an ALTER TABLE ... DROP CONSTRAINT / ADD CONSTRAINT migration that brings the live database to ON DELETE no action so the code's declared intent is enforced at the DB layer.
Sanity-check first: before shipping, verify the code's no action is actually right for this parent→child relationship. CASCADE on a value-carrying child silently loses data on parent delete. The decision tree:
• child is ephemeral state (logs, acks, in-flight handshakes, derived counters) → CASCADE is safe
• child is value-carrying (refs the parent but should outlive it) → SET NULL is safer than CASCADE
• child carries audit/compliance value (SOC2, GDPR record-keeping) → keep RESTRICT and SET NULL the FK on deletion paths
If the code's declared no action is wrong, fix the code first, then ship the aligning migration.
batch_jobs.org_id → organizations declares ON DELETE no action in the code, but the database is set to cascade.Fix: apply an ALTER TABLE ... DROP CONSTRAINT / ADD CONSTRAINT migration that brings the live database to ON DELETE no action so the code's declared intent is enforced at the DB layer.
Sanity-check first: before shipping, verify the code's no action is actually right for this parent→child relationship. CASCADE on a value-carrying child silently loses data on parent delete. The decision tree:
• child is ephemeral state (logs, acks, in-flight handshakes, derived counters) → CASCADE is safe
• child is value-carrying (refs the parent but should outlive it) → SET NULL is safer than CASCADE
• child carries audit/compliance value (SOC2, GDPR record-keeping) → keep RESTRICT and SET NULL the FK on deletion paths
If the code's declared no action is wrong, fix the code first, then ship the aligning migration.
pending_payments.org_id → organizations declares ON DELETE no action in the code, but the database is set to cascade.Fix: apply an ALTER TABLE ... DROP CONSTRAINT / ADD CONSTRAINT migration that brings the live database to ON DELETE no action so the code's declared intent is enforced at the DB layer.
Sanity-check first: before shipping, verify the code's no action is actually right for this parent→child relationship. CASCADE on a value-carrying child silently loses data on parent delete. The decision tree:
• child is ephemeral state (logs, acks, in-flight handshakes, derived counters) → CASCADE is safe
• child is value-carrying (refs the parent but should outlive it) → SET NULL is safer than CASCADE
• child carries audit/compliance value (SOC2, GDPR record-keeping) → keep RESTRICT and SET NULL the FK on deletion paths
If the code's declared no action is wrong, fix the code first, then ship the aligning migration.