CREATE TABLE IF NOT EXISTS contact_merge_history ( id BIGSERIAL PRIMARY KEY, target_contact_id INTEGER NOT NULL REFERENCES contacts(id) ON DELETE RESTRICT, source_contact_id INTEGER NOT NULL, source_snapshot JSONB NOT NULL, moved_relations JSONB NOT NULL DEFAULT '{}'::jsonb, merged_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_contact_merge_history_target ON contact_merge_history(target_contact_id, merged_at DESC); COMMENT ON TABLE contact_merge_history IS 'Audit trail for destructive contact merges. Source contact snapshots and moved relation counts are retained.';