refactor(data): remove unpublished legacy cleanup migrations

This commit is contained in:
elky
2026-09-04 11:26:59 +08:00
parent 579f2c7cc1
commit bac6d6866a
34 changed files with 79 additions and 3323 deletions
@@ -1,16 +0,0 @@
UPDATE request_candidates
SET
username = NULL,
api_key_name = NULL,
extra_data = NULL,
required_capabilities = NULL,
error_message = NULL,
error_type = NULL,
skip_reason = NULL
WHERE username IS NOT NULL
OR api_key_name IS NOT NULL
OR extra_data IS NOT NULL
OR required_capabilities IS NOT NULL
OR error_message IS NOT NULL
OR error_type IS NOT NULL
OR skip_reason IS NOT NULL;
@@ -1,124 +0,0 @@
-- Historical HTTP captures predate the deny-by-default persistence policy and
-- may contain credentials or request content. Keep the usage and projected
-- billing facts, but remove every legacy copy of the raw exchange.
UPDATE `usage` AS usage_rows
LEFT JOIN usage_cost_reservations AS reservation
ON reservation.state = 'reserved'
AND REGEXP_LIKE(
reservation.reservation_token,
'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',
'c'
)
AND reservation.request_id = usage_rows.request_id
AND reservation.subject_id = usage_rows.user_id
AND reservation.reservation_token = JSON_UNQUOTE(JSON_EXTRACT(
CASE
WHEN JSON_VALID(usage_rows.request_metadata) = 1
THEN usage_rows.request_metadata
ELSE JSON_OBJECT()
END,
'$.plan_usage_reservation_token'
))
SET usage_rows.error_message = NULL,
usage_rows.error_category = CASE
WHEN usage_rows.error_category IS NULL
OR TRIM(usage_rows.error_category) = '' THEN NULL
WHEN LOWER(TRIM(usage_rows.error_category)) IN (
'auth', 'cancelled', 'client_error', 'http_error',
'non_success_status', 'provider_error', 'rate_limit', 'redirect',
'server_error', 'stream_missing_terminal_event',
'stream_terminal_error', 'upstream_error'
) THEN LOWER(TRIM(usage_rows.error_category))
ELSE 'other_error'
END,
usage_rows.request_headers = NULL,
usage_rows.request_body = NULL,
usage_rows.provider_request_headers = NULL,
usage_rows.provider_request_body = NULL,
usage_rows.response_headers = NULL,
usage_rows.response_body = NULL,
usage_rows.client_response_headers = NULL,
usage_rows.client_response_body = NULL,
usage_rows.request_body_compressed = NULL,
usage_rows.provider_request_body_compressed = NULL,
usage_rows.response_body_compressed = NULL,
usage_rows.client_response_body_compressed = NULL,
usage_rows.request_metadata = CASE
WHEN reservation.reservation_token IS NULL THEN NULL
WHEN JSON_TYPE(JSON_EXTRACT(
CASE
WHEN JSON_VALID(usage_rows.request_metadata) = 1
THEN usage_rows.request_metadata
ELSE JSON_OBJECT()
END,
'$.plan_usage_reservation_deferred'
)) = 'BOOLEAN'
AND JSON_UNQUOTE(JSON_EXTRACT(
CASE
WHEN JSON_VALID(usage_rows.request_metadata) = 1
THEN usage_rows.request_metadata
ELSE JSON_OBJECT()
END,
'$.plan_usage_reservation_deferred'
)) = 'true'
THEN JSON_SET(
JSON_OBJECT(
'plan_usage_reservation_token', reservation.reservation_token
),
'$.plan_usage_reservation_deferred',
JSON_EXTRACT('true', '$')
)
ELSE JSON_OBJECT(
'plan_usage_reservation_token', reservation.reservation_token
)
END
WHERE usage_rows.error_message IS NOT NULL
OR usage_rows.error_category IS NOT NULL
OR usage_rows.request_headers IS NOT NULL
OR usage_rows.request_body IS NOT NULL
OR usage_rows.provider_request_headers IS NOT NULL
OR usage_rows.provider_request_body IS NOT NULL
OR usage_rows.response_headers IS NOT NULL
OR usage_rows.response_body IS NOT NULL
OR usage_rows.client_response_headers IS NOT NULL
OR usage_rows.client_response_body IS NOT NULL
OR usage_rows.request_body_compressed IS NOT NULL
OR usage_rows.provider_request_body_compressed IS NOT NULL
OR usage_rows.response_body_compressed IS NOT NULL
OR usage_rows.client_response_body_compressed IS NOT NULL
OR usage_rows.request_metadata IS NOT NULL;
DELETE FROM usage_http_audits;
DELETE FROM usage_body_blobs;
-- All fields needed by billing reads are projected into typed columns on this
-- table. The historical JSON documents include rule expressions, catalog
-- snapshots, and arbitrary dimensions, so they are not retained.
UPDATE usage_settlement_snapshots
SET settlement_snapshot = NULL,
billing_dimensions = NULL
WHERE settlement_snapshot IS NOT NULL
OR billing_dimensions IS NOT NULL;
UPDATE video_tasks
SET original_request_body = NULL,
converted_request_body = NULL,
progress_message = NULL,
error_message = NULL,
request_metadata = NULL,
video_url = NULL,
video_urls = NULL,
thumbnail_url = NULL,
stored_video_path = NULL,
webhook_url = NULL
WHERE original_request_body IS NOT NULL
OR converted_request_body IS NOT NULL
OR progress_message IS NOT NULL
OR error_message IS NOT NULL
OR request_metadata IS NOT NULL
OR video_url IS NOT NULL
OR video_urls IS NOT NULL
OR thumbnail_url IS NOT NULL
OR stored_video_path IS NOT NULL
OR webhook_url IS NOT NULL;
@@ -1,43 +0,0 @@
UPDATE background_task_runs
SET owner_instance = NULL,
created_by = CASE
WHEN LOWER(TRIM(created_by)) IN ('admin', 'scheduler', 'system')
THEN LOWER(TRIM(created_by))
ELSE NULL
END,
progress_message = NULL,
payload_json = NULL,
result_json = NULL,
error_message = CASE
WHEN status = 'failed' THEN 'background_task_failed'
ELSE NULL
END
WHERE owner_instance IS NOT NULL
OR created_by IS NOT NULL
OR progress_message IS NOT NULL
OR payload_json IS NOT NULL
OR result_json IS NOT NULL
OR error_message IS NOT NULL;
UPDATE background_task_events
SET event_type = CASE
WHEN event_type IN (
'cancel_requested', 'failed', 'queued', 'running',
'skipped', 'succeeded', 'worker_boot'
) THEN event_type
ELSE 'unclassified_event'
END,
message = CASE
WHEN event_type IN (
'cancel_requested', 'failed', 'queued', 'running',
'skipped', 'succeeded', 'worker_boot'
) THEN event_type
ELSE 'unclassified_event'
END,
payload_json = NULL
WHERE message <> event_type
OR payload_json IS NOT NULL
OR event_type NOT IN (
'cancel_requested', 'failed', 'queued', 'running',
'skipped', 'succeeded', 'worker_boot'
);
@@ -1,13 +0,0 @@
-- Stripe PaymentIntent client secrets are payment capabilities. New writes
-- store only encrypted values; legacy plaintext cannot be migrated safely
-- without the application encryption key, so remove it fail-closed.
UPDATE payment_orders
SET status = CASE
WHEN LOWER(TRIM(payment_method)) = 'stripe' AND status = 'pending'
THEN 'expired'
ELSE status
END,
gateway_response = JSON_REMOVE(gateway_response, '$.client_secret')
WHERE gateway_response IS NOT NULL
AND JSON_VALID(gateway_response) = 1
AND JSON_CONTAINS_PATH(gateway_response, 'one', '$.client_secret') = 1;
@@ -1,6 +0,0 @@
-- Callback idempotency uses payload_hash and does not require the raw body.
-- Older versions stored provider-controlled payloads that may contain payment
-- capabilities or customer PII, so remove those legacy copies fail-closed.
UPDATE payment_callbacks
SET payload = NULL
WHERE payload IS NOT NULL;
@@ -1,5 +0,0 @@
-- Video prompts are user content and are not required for polling or billing.
-- Remove historical copies now that new writes discard them before persistence.
UPDATE video_tasks
SET prompt = NULL
WHERE prompt IS NOT NULL;
@@ -1,6 +0,0 @@
-- Identity claims required by the application are stored in dedicated columns.
-- Remove legacy provider-controlled userinfo JSON, which may contain unrelated
-- PII or credentials and is not needed for authentication or account binding.
UPDATE user_oauth_links
SET extra_data = NULL
WHERE extra_data IS NOT NULL;
@@ -88,290 +88,6 @@ PREPARE aether_drop_fact_user_fk_stmt FROM @aether_drop_fact_user_fk_sql;
EXECUTE aether_drop_fact_user_fk_stmt;
DEALLOCATE PREPARE aether_drop_fact_user_fk_stmt;
UPDATE request_candidates
SET username = NULL, api_key_name = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = request_candidates.user_id
)
AND (username IS NOT NULL OR api_key_name IS NOT NULL);
UPDATE request_candidates
SET api_key_name = NULL
WHERE api_key_name IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM api_keys WHERE api_keys.id = request_candidates.api_key_id
);
UPDATE video_tasks
SET username = NULL, api_key_name = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = video_tasks.user_id
)
AND (username IS NOT NULL OR api_key_name IS NOT NULL);
UPDATE video_tasks
SET api_key_name = NULL
WHERE api_key_name IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM api_keys WHERE api_keys.id = video_tasks.api_key_id
);
UPDATE `usage`
SET username = NULL, api_key_name = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = `usage`.user_id
)
AND (username IS NOT NULL OR api_key_name IS NOT NULL);
UPDATE `usage`
SET api_key_name = NULL
WHERE api_key_name IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM api_keys WHERE api_keys.id = `usage`.api_key_id
);
UPDATE stats_user_daily
SET username = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = stats_user_daily.user_id
)
AND username IS NOT NULL;
UPDATE stats_user_summary
SET username = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = stats_user_summary.user_id
)
AND username IS NOT NULL;
UPDATE stats_user_daily_model
SET username = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = stats_user_daily_model.user_id
)
AND username IS NOT NULL;
UPDATE stats_user_daily_provider
SET username = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = stats_user_daily_provider.user_id
)
AND username IS NOT NULL;
UPDATE stats_user_daily_api_format
SET username = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = stats_user_daily_api_format.user_id
)
AND username IS NOT NULL;
UPDATE stats_user_daily_model_provider
SET username = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = stats_user_daily_model_provider.user_id
)
AND username IS NOT NULL;
UPDATE stats_user_daily_cost_savings
SET username = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = stats_user_daily_cost_savings.user_id
)
AND username IS NOT NULL;
UPDATE stats_user_daily_cost_savings_provider
SET username = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = stats_user_daily_cost_savings_provider.user_id
)
AND username IS NOT NULL;
UPDATE stats_user_daily_cost_savings_model
SET username = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = stats_user_daily_cost_savings_model.user_id
)
AND username IS NOT NULL;
UPDATE stats_user_daily_cost_savings_model_provider
SET username = NULL
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = stats_user_daily_cost_savings_model_provider.user_id
)
AND username IS NOT NULL;
UPDATE stats_daily_api_key
SET api_key_name = NULL
WHERE NOT EXISTS (
SELECT 1 FROM api_keys WHERE api_keys.id = stats_daily_api_key.api_key_id
)
AND api_key_name IS NOT NULL;
UPDATE user_plan_entitlements AS entitlement
SET status = CASE WHEN status = 'active' THEN 'revoked' ELSE status END,
expires_at = LEAST(expires_at, UNIX_TIMESTAMP()),
updated_at = UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = entitlement.user_id
);
UPDATE wallets AS wallet
SET status = 'disabled', updated_at = UNIX_TIMESTAMP()
WHERE (wallet.user_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = wallet.user_id
))
OR (wallet.api_key_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM api_keys WHERE api_keys.id = wallet.api_key_id
));
UPDATE user_referrals AS referral
SET invite_code_snapshot = 'deleted-user',
source_json = NULL,
updated_at = UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = referral.inviter_user_id
)
OR NOT EXISTS (
SELECT 1 FROM users WHERE users.id = referral.invitee_user_id
);
UPDATE referral_rewards AS reward
SET status = CASE
WHEN status IN ('pending', 'failed', 'applying') THEN 'voided'
ELSE status
END,
failure_reason = NULL,
admin_note = NULL,
updated_at = UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = reward.inviter_user_id
)
OR NOT EXISTS (
SELECT 1 FROM users WHERE users.id = reward.invitee_user_id
);
UPDATE audit_logs AS history
SET description = 'deleted user event',
ip_address = NULL,
user_agent = NULL,
event_metadata = NULL,
error_message = NULL
WHERE (history.user_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = history.user_id
))
OR (history.api_key_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM api_keys WHERE api_keys.id = history.api_key_id
));
UPDATE wallet_transactions AS history
SET description = NULL
WHERE EXISTS (
SELECT 1
FROM wallets AS wallet
WHERE wallet.id = history.wallet_id
AND (
(wallet.user_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = wallet.user_id
))
OR (wallet.api_key_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM api_keys WHERE api_keys.id = wallet.api_key_id
))
)
);
UPDATE wallet_transactions AS history
SET description = NULL
WHERE history.operator_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = history.operator_id
);
UPDATE payment_orders AS history
SET gateway_response = NULL
WHERE (history.user_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = history.user_id
))
OR EXISTS (
SELECT 1
FROM wallets AS wallet
WHERE wallet.id = history.wallet_id
AND (
(wallet.user_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = wallet.user_id
))
OR (wallet.api_key_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM api_keys WHERE api_keys.id = wallet.api_key_id
))
)
);
UPDATE payment_callbacks AS history
SET payload = NULL,
error_message = NULL
WHERE EXISTS (
SELECT 1
FROM payment_orders AS payment_order
LEFT JOIN wallets AS wallet ON wallet.id = payment_order.wallet_id
WHERE (
payment_order.id = history.payment_order_id
OR (history.order_no IS NOT NULL AND payment_order.order_no = history.order_no)
)
AND (
(payment_order.user_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = payment_order.user_id
))
OR (wallet.user_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = wallet.user_id
))
OR (wallet.api_key_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM api_keys WHERE api_keys.id = wallet.api_key_id
))
)
);
UPDATE refund_requests AS history
SET reason = NULL,
payout_reference = NULL,
payout_proof = NULL,
failure_reason = NULL
WHERE (history.user_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = history.user_id
))
OR EXISTS (
SELECT 1
FROM wallets AS wallet
WHERE wallet.id = history.wallet_id
AND (
(wallet.user_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = wallet.user_id
))
OR (wallet.api_key_id IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM api_keys WHERE api_keys.id = wallet.api_key_id
))
)
)
OR (history.requested_by IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = history.requested_by
))
OR (history.approved_by IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = history.approved_by
))
OR (history.processed_by IS NOT NULL AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = history.processed_by
));
UPDATE referral_rewards AS reward
SET failure_reason = NULL,
admin_note = NULL,
updated_at = UNIX_TIMESTAMP()
WHERE reward.admin_operator_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = reward.admin_operator_id
);
UPDATE redeem_code_batches AS history
SET description = NULL
WHERE history.created_by IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users WHERE users.id = history.created_by
);
-- Keep existing historical row values unchanged. Runtime deletion paths enforce
-- the current anonymization policy for newly deleted users.
SELECT 1;
@@ -1,451 +0,0 @@
-- Keep nullable/system-owned history rows intact while clearing values tied to
-- deleted users or API keys. Raw payment callback payloads are always removed
-- because they are not required for idempotency and may contain PII.
UPDATE request_candidates
SET username = NULL, api_key_name = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = request_candidates.user_id AND users.is_deleted = 0
)
AND (username IS NOT NULL OR api_key_name IS NOT NULL);
UPDATE request_candidates
SET api_key_name = NULL
WHERE api_key_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM api_keys
JOIN users AS api_key_owner
ON api_key_owner.id = api_keys.user_id AND api_key_owner.is_deleted = 0
WHERE api_keys.id = request_candidates.api_key_id
)
AND api_key_name IS NOT NULL;
UPDATE video_tasks
SET username = NULL, api_key_name = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = video_tasks.user_id AND users.is_deleted = 0
)
AND (username IS NOT NULL OR api_key_name IS NOT NULL);
UPDATE video_tasks
SET api_key_name = NULL
WHERE api_key_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM api_keys
JOIN users AS api_key_owner
ON api_key_owner.id = api_keys.user_id AND api_key_owner.is_deleted = 0
WHERE api_keys.id = video_tasks.api_key_id
)
AND api_key_name IS NOT NULL;
UPDATE `usage`
SET username = NULL, api_key_name = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = `usage`.user_id AND users.is_deleted = 0
)
AND (username IS NOT NULL OR api_key_name IS NOT NULL);
UPDATE `usage`
SET api_key_name = NULL
WHERE api_key_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM api_keys
JOIN users AS api_key_owner
ON api_key_owner.id = api_keys.user_id AND api_key_owner.is_deleted = 0
WHERE api_keys.id = `usage`.api_key_id
)
AND api_key_name IS NOT NULL;
UPDATE stats_user_daily
SET username = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = stats_user_daily.user_id AND users.is_deleted = 0
)
AND username IS NOT NULL;
UPDATE stats_user_summary
SET username = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = stats_user_summary.user_id AND users.is_deleted = 0
)
AND username IS NOT NULL;
UPDATE stats_user_daily_model
SET username = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = stats_user_daily_model.user_id AND users.is_deleted = 0
)
AND username IS NOT NULL;
UPDATE stats_user_daily_provider
SET username = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = stats_user_daily_provider.user_id AND users.is_deleted = 0
)
AND username IS NOT NULL;
UPDATE stats_user_daily_api_format
SET username = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = stats_user_daily_api_format.user_id AND users.is_deleted = 0
)
AND username IS NOT NULL;
UPDATE stats_user_daily_model_provider
SET username = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = stats_user_daily_model_provider.user_id AND users.is_deleted = 0
)
AND username IS NOT NULL;
UPDATE stats_user_daily_cost_savings
SET username = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = stats_user_daily_cost_savings.user_id AND users.is_deleted = 0
)
AND username IS NOT NULL;
UPDATE stats_user_daily_cost_savings_provider
SET username = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = stats_user_daily_cost_savings_provider.user_id
AND users.is_deleted = 0
)
AND username IS NOT NULL;
UPDATE stats_user_daily_cost_savings_model
SET username = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = stats_user_daily_cost_savings_model.user_id
AND users.is_deleted = 0
)
AND username IS NOT NULL;
UPDATE stats_user_daily_cost_savings_model_provider
SET username = NULL
WHERE user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM users
WHERE users.id = stats_user_daily_cost_savings_model_provider.user_id
AND users.is_deleted = 0
)
AND username IS NOT NULL;
UPDATE stats_daily_api_key
SET api_key_name = NULL
WHERE api_key_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM api_keys
JOIN users AS api_key_owner
ON api_key_owner.id = api_keys.user_id AND api_key_owner.is_deleted = 0
WHERE api_keys.id = stats_daily_api_key.api_key_id
)
AND api_key_name IS NOT NULL;
UPDATE user_plan_entitlements AS entitlement
SET status = CASE WHEN status = 'active' THEN 'revoked' ELSE status END,
expires_at = LEAST(expires_at, UNIX_TIMESTAMP()),
updated_at = UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = entitlement.user_id AND users.is_deleted = 0
);
UPDATE user_referrals AS referral
SET invite_code_snapshot = 'deleted-user',
source_json = NULL,
updated_at = UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = referral.inviter_user_id AND users.is_deleted = 0
)
OR NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = referral.invitee_user_id AND users.is_deleted = 0
);
UPDATE referral_rewards AS reward
SET status = CASE
WHEN status IN ('pending', 'failed', 'applying') THEN 'voided'
ELSE status
END,
failure_reason = NULL,
admin_note = NULL,
updated_at = UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = reward.inviter_user_id AND users.is_deleted = 0
)
OR NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = reward.invitee_user_id AND users.is_deleted = 0
);
UPDATE referral_rewards AS reward
SET failure_reason = NULL,
admin_note = NULL,
updated_at = UNIX_TIMESTAMP()
WHERE reward.admin_operator_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = reward.admin_operator_id AND users.is_deleted = 0
);
UPDATE wallets AS wallet
SET status = 'disabled', updated_at = UNIX_TIMESTAMP()
WHERE (wallet.user_id IS NULL AND wallet.api_key_id IS NULL)
OR (wallet.user_id IS NOT NULL AND wallet.api_key_id IS NOT NULL)
OR (wallet.user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = wallet.user_id AND users.is_deleted = 0
))
OR (wallet.api_key_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM api_keys
JOIN users AS api_key_owner
ON api_key_owner.id = api_keys.user_id AND api_key_owner.is_deleted = 0
WHERE api_keys.id = wallet.api_key_id
));
UPDATE audit_logs AS history
SET description = 'deleted user event',
ip_address = NULL,
user_agent = NULL,
event_metadata = NULL,
error_message = NULL
WHERE (history.user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = history.user_id AND users.is_deleted = 0
))
OR (history.api_key_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM api_keys
JOIN users AS api_key_owner
ON api_key_owner.id = api_keys.user_id AND api_key_owner.is_deleted = 0
WHERE api_keys.id = history.api_key_id
));
UPDATE wallet_transactions AS history
SET description = NULL
WHERE EXISTS (
SELECT 1
FROM wallets AS wallet
WHERE wallet.id = history.wallet_id
AND ((wallet.user_id IS NULL AND wallet.api_key_id IS NULL)
OR (wallet.user_id IS NOT NULL AND wallet.api_key_id IS NOT NULL)
OR (wallet.user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = wallet.user_id AND users.is_deleted = 0
))
OR (wallet.api_key_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM api_keys
JOIN users AS api_key_owner
ON api_key_owner.id = api_keys.user_id
AND api_key_owner.is_deleted = 0
WHERE api_keys.id = wallet.api_key_id
)))
)
OR NOT EXISTS (
SELECT 1 FROM wallets AS wallet WHERE wallet.id = history.wallet_id
)
OR (history.operator_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = history.operator_id AND users.is_deleted = 0
));
UPDATE payment_orders AS history
SET gateway_response = NULL
WHERE (history.user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = history.user_id AND users.is_deleted = 0
))
OR EXISTS (
SELECT 1
FROM wallets AS wallet
WHERE wallet.id = history.wallet_id
AND ((wallet.user_id IS NULL AND wallet.api_key_id IS NULL)
OR (wallet.user_id IS NOT NULL AND wallet.api_key_id IS NOT NULL)
OR (wallet.user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = wallet.user_id AND users.is_deleted = 0
))
OR (wallet.api_key_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM api_keys
JOIN users AS api_key_owner
ON api_key_owner.id = api_keys.user_id
AND api_key_owner.is_deleted = 0
WHERE api_keys.id = wallet.api_key_id
)))
)
OR NOT EXISTS (
SELECT 1 FROM wallets AS wallet WHERE wallet.id = history.wallet_id
);
-- Raw provider payloads are never needed for idempotency and must be purged
-- even when an old callback cannot be linked back to an order.
UPDATE payment_callbacks
SET payload = NULL
WHERE payload IS NOT NULL;
UPDATE payment_callbacks AS history
SET error_message = NULL
WHERE history.error_message IS NOT NULL
AND (
NOT EXISTS (
SELECT 1
FROM payment_orders AS payment_order
WHERE payment_order.id = history.payment_order_id
OR (history.order_no IS NOT NULL AND payment_order.order_no = history.order_no)
)
OR EXISTS (
SELECT 1
FROM payment_orders AS payment_order
LEFT JOIN wallets AS wallet ON wallet.id = payment_order.wallet_id
WHERE (payment_order.id = history.payment_order_id
OR (history.order_no IS NOT NULL AND payment_order.order_no = history.order_no))
AND ((payment_order.user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = payment_order.user_id AND users.is_deleted = 0
))
OR wallet.id IS NULL
OR (wallet.user_id IS NULL AND wallet.api_key_id IS NULL)
OR (wallet.user_id IS NOT NULL AND wallet.api_key_id IS NOT NULL)
OR (wallet.user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = wallet.user_id AND users.is_deleted = 0
))
OR (wallet.api_key_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM api_keys
JOIN users AS api_key_owner
ON api_key_owner.id = api_keys.user_id
AND api_key_owner.is_deleted = 0
WHERE api_keys.id = wallet.api_key_id
)))
)
);
UPDATE refund_requests AS history
SET reason = NULL,
payout_reference = NULL,
payout_proof = NULL,
failure_reason = NULL
WHERE (history.user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = history.user_id AND users.is_deleted = 0
))
OR EXISTS (
SELECT 1
FROM wallets AS wallet
WHERE wallet.id = history.wallet_id
AND ((wallet.user_id IS NULL AND wallet.api_key_id IS NULL)
OR (wallet.user_id IS NOT NULL AND wallet.api_key_id IS NOT NULL)
OR (wallet.user_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = wallet.user_id AND users.is_deleted = 0
))
OR (wallet.api_key_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM api_keys
JOIN users AS api_key_owner
ON api_key_owner.id = api_keys.user_id
AND api_key_owner.is_deleted = 0
WHERE api_keys.id = wallet.api_key_id
)))
)
OR NOT EXISTS (
SELECT 1 FROM wallets AS wallet WHERE wallet.id = history.wallet_id
)
OR (history.requested_by IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = history.requested_by AND users.is_deleted = 0
))
OR (history.approved_by IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = history.approved_by AND users.is_deleted = 0
))
OR (history.processed_by IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = history.processed_by AND users.is_deleted = 0
));
UPDATE redeem_code_batches AS history
SET description = NULL
WHERE history.created_by IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = history.created_by AND users.is_deleted = 0
);
UPDATE refund_requests
SET requested_by = NULL
WHERE requested_by IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = refund_requests.requested_by AND users.is_deleted = 0
);
UPDATE refund_requests
SET approved_by = NULL
WHERE approved_by IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = refund_requests.approved_by AND users.is_deleted = 0
);
UPDATE refund_requests
SET processed_by = NULL
WHERE processed_by IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM users
WHERE users.id = refund_requests.processed_by AND users.is_deleted = 0
);
@@ -1,8 +0,0 @@
-- Older gateway releases marked every OAuth email as verified without
-- retaining verification provenance. Reset those claims conservatively; a
-- later trusted OAuth assertion for the same normalized email can upgrade it.
UPDATE users
SET email_verified = 0,
updated_at = UNIX_TIMESTAMP()
WHERE LOWER(TRIM(auth_source)) = 'oauth'
AND email_verified = 1;