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,121 +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"
SET error_message = NULL,
error_category = CASE
WHEN error_category IS NULL OR TRIM(error_category) = '' THEN NULL
WHEN LOWER(TRIM(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(error_category))
ELSE 'other_error'
END,
request_headers = NULL,
request_body = NULL,
provider_request_headers = NULL,
provider_request_body = NULL,
response_headers = NULL,
response_body = NULL,
client_response_headers = NULL,
client_response_body = NULL,
request_body_compressed = NULL,
provider_request_body_compressed = NULL,
response_body_compressed = NULL,
client_response_body_compressed = NULL,
request_metadata = (
SELECT CASE
WHEN JSON_TYPE(
CASE
WHEN JSON_VALID("usage".request_metadata)
THEN "usage".request_metadata
ELSE '{}'
END,
'$.plan_usage_reservation_deferred'
) = 'true'
THEN JSON_SET(
JSON_OBJECT(
'plan_usage_reservation_token', reservation.reservation_token
),
'$.plan_usage_reservation_deferred',
JSON('true')
)
ELSE JSON_OBJECT(
'plan_usage_reservation_token', reservation.reservation_token
)
END
FROM usage_cost_reservations AS reservation
WHERE reservation.state = 'reserved'
AND LENGTH(reservation.reservation_token) = 36
AND reservation.reservation_token = LOWER(reservation.reservation_token)
AND SUBSTR(reservation.reservation_token, 9, 1) = '-'
AND SUBSTR(reservation.reservation_token, 14, 1) = '-'
AND SUBSTR(reservation.reservation_token, 19, 1) = '-'
AND SUBSTR(reservation.reservation_token, 24, 1) = '-'
AND LENGTH(REPLACE(reservation.reservation_token, '-', '')) = 32
AND REPLACE(reservation.reservation_token, '-', '')
NOT GLOB '*[^0-9a-f]*'
AND reservation.request_id = "usage".request_id
AND reservation.subject_id = "usage".user_id
AND reservation.reservation_token = JSON_EXTRACT(
CASE
WHEN JSON_VALID("usage".request_metadata)
THEN "usage".request_metadata
ELSE '{}'
END,
'$.plan_usage_reservation_token'
)
LIMIT 1
)
WHERE error_message IS NOT NULL
OR error_category IS NOT NULL
OR request_headers IS NOT NULL
OR request_body IS NOT NULL
OR provider_request_headers IS NOT NULL
OR provider_request_body IS NOT NULL
OR response_headers IS NOT NULL
OR response_body IS NOT NULL
OR client_response_headers IS NOT NULL
OR client_response_body IS NOT NULL
OR request_body_compressed IS NOT NULL
OR provider_request_body_compressed IS NOT NULL
OR response_body_compressed IS NOT NULL
OR client_response_body_compressed IS NOT NULL
OR 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)
AND JSON_TYPE(gateway_response, '$.client_secret') IS NOT NULL;
@@ -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;
@@ -1,292 +1,5 @@
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 = MIN(expires_at, CAST(strftime('%s', 'now') AS INTEGER)),
updated_at = CAST(strftime('%s', 'now') AS INTEGER)
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE users.id = entitlement.user_id
);
UPDATE wallets AS wallet
SET status = 'disabled',
updated_at = CAST(strftime('%s', 'now') AS INTEGER)
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 = CAST(strftime('%s', 'now') AS INTEGER)
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 = CAST(strftime('%s', 'now') AS INTEGER)
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 = CAST(strftime('%s', 'now') AS INTEGER)
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
);
-- Retain legacy row contents. This migration only removes user foreign keys
-- required by the current account-deletion flow.
ALTER TABLE user_plan_entitlements RENAME TO _aether_user_plan_entitlements_with_user_fk;
DROP INDEX IF EXISTS idx_user_plan_entitlements_user_active;
DROP INDEX IF EXISTS idx_user_plan_entitlements_order;
@@ -1,449 +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 = MIN(expires_at, CAST(strftime('%s', 'now') AS INTEGER)),
updated_at = CAST(strftime('%s', 'now') AS INTEGER)
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 = CAST(strftime('%s', 'now') AS INTEGER)
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 = CAST(strftime('%s', 'now') AS INTEGER)
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 = CAST(strftime('%s', 'now') AS INTEGER)
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 = CAST(strftime('%s', 'now') AS INTEGER)
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 = CAST(strftime('%s', 'now') AS INTEGER)
WHERE LOWER(TRIM(auth_source)) = 'oauth'
AND email_verified = 1;