-- Apply AFTER soft_delete and BEFORE re-extraction application code. Idempotent additive migration. -- Keep additive schema on rollback. Drain queued revisions before restoring pre-revision workers. -- History snapshots share the original task expiry, never a renewed retention period. SET @fa_db = DATABASE(); SET @fa_sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@fa_db AND TABLE_NAME='zyt_followup_audio_task' AND COLUMN_NAME='extraction_revision')=0, 'ALTER TABLE zyt_followup_audio_task ADD COLUMN extraction_revision INT UNSIGNED NOT NULL DEFAULT 0, ADD COLUMN extraction_role_override VARCHAR(20) NOT NULL DEFAULT \'\', ADD COLUMN extraction_source_version INT UNSIGNED NOT NULL DEFAULT 0, ADD COLUMN extraction_confirmed_by BIGINT UNSIGNED NOT NULL DEFAULT 0, ADD COLUMN extraction_confirmed_at BIGINT UNSIGNED NOT NULL DEFAULT 0', 'SELECT 1'); PREPARE fa_stmt FROM @fa_sql; EXECUTE fa_stmt; DEALLOCATE PREPARE fa_stmt; CREATE TABLE IF NOT EXISTS zyt_followup_audio_extraction_history ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, task_id BIGINT UNSIGNED NOT NULL, source_version INT UNSIGNED NOT NULL, source_revision INT UNSIGNED NOT NULL, target_revision INT UNSIGNED NOT NULL, channel_roles VARCHAR(20) NOT NULL, actor_id BIGINT UNSIGNED NOT NULL, snapshot_cipher LONGTEXT NULL, created_at BIGINT UNSIGNED NOT NULL, expires_at BIGINT UNSIGNED NOT NULL, purged_at BIGINT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY(id), UNIQUE KEY uk_task_source(task_id,source_version), UNIQUE KEY uk_task_revision(task_id,target_revision), KEY idx_expiry(expires_at,purged_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;