diff --git a/internal/upgrade/version.go b/internal/upgrade/version.go index 6b3efe02..be8b246b 100644 --- a/internal/upgrade/version.go +++ b/internal/upgrade/version.go @@ -2,4 +2,4 @@ package upgrade // RequiredSchemaVersion is the schema migration version this binary requires. // Bump this whenever adding a new SQL migration file. -const RequiredSchemaVersion uint = 85 +const RequiredSchemaVersion uint = 86 diff --git a/migrations/000086_fix_channel_contacts_merged_fk.down.sql b/migrations/000086_fix_channel_contacts_merged_fk.down.sql new file mode 100644 index 00000000..dd7b9d17 --- /dev/null +++ b/migrations/000086_fix_channel_contacts_merged_fk.down.sql @@ -0,0 +1,8 @@ +-- Roll back only the corrective FK. +-- Do not recreate the old self-reference FK because it is incompatible with valid data. +BEGIN; + +ALTER TABLE channel_contacts +DROP CONSTRAINT IF EXISTS fk_channel_contacts_merged_id; + +COMMIT; diff --git a/migrations/000086_fix_channel_contacts_merged_fk.up.sql b/migrations/000086_fix_channel_contacts_merged_fk.up.sql new file mode 100644 index 00000000..877fc615 --- /dev/null +++ b/migrations/000086_fix_channel_contacts_merged_fk.up.sql @@ -0,0 +1,14 @@ +-- Fix channel_contacts.merged_id FK. +-- merged_id stores tenant_users.id, not channel_contacts.id. +BEGIN; + +ALTER TABLE channel_contacts +DROP CONSTRAINT IF EXISTS fk_channel_contacts_merged_id; + +ALTER TABLE channel_contacts +ADD CONSTRAINT fk_channel_contacts_merged_id +FOREIGN KEY (merged_id) +REFERENCES tenant_users(id) +ON DELETE SET NULL; + +COMMIT; diff --git a/migrations/audit_fk_integrity.sql b/migrations/audit_fk_integrity.sql index be7f0219..2a50efc2 100644 --- a/migrations/audit_fk_integrity.sql +++ b/migrations/audit_fk_integrity.sql @@ -66,11 +66,18 @@ FROM webhooks w LEFT JOIN channel_instances ci ON ci.id = w.channel_id WHERE w.channel_id IS NOT NULL AND ci.id IS NULL; --- channel_contacts: merged_id self-ref orphans -SELECT 'channel_contacts.merged_id orphans' AS check_name, COUNT(*) AS violations +-- channel_contacts: merged_id tenant_users orphans +SELECT 'channel_contacts.merged_id tenant_users orphans' AS check_name, COUNT(*) AS violations FROM channel_contacts cc -LEFT JOIN channel_contacts cc2 ON cc2.id = cc.merged_id -WHERE cc.merged_id IS NOT NULL AND cc2.id IS NULL; +LEFT JOIN tenant_users tu ON tu.id = cc.merged_id +WHERE cc.merged_id IS NOT NULL AND tu.id IS NULL; + +-- channel_contacts: merged_id tenant drift +SELECT 'channel_contacts.merged_id tenant drift' AS check_name, COUNT(*) AS violations +FROM channel_contacts cc +JOIN tenant_users tu ON tu.id = cc.merged_id +WHERE cc.merged_id IS NOT NULL + AND cc.tenant_id <> tu.tenant_id; -- traces: parent_trace_id self-ref orphans SELECT 'traces.parent_trace_id orphans' AS check_name, COUNT(*) AS violations