From 3679e2f3695a64c9a230c9b89fcc79d9e64d1a2c Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Sat, 31 Jan 2026 21:15:53 +0100 Subject: [PATCH] Reset KYC level for users with expired AML and no reactivation (#3095) * Reset KYC level for users with expired AML and no reactivation Users with KycLevel >= 30 who have amlListExpiredDate set but no amlListReactivatedDate should not have elevated KYC levels, as their AML verification has expired and was never renewed. This migration sets their KycLevel back to 20 (basic level). Affected users: 359 * Exclude users with DfxApproval after expiry from KYC reset Users who have a completed DfxApproval after their amlListExpiredDate have legitimately re-verified - they should keep their KycLevel. The amlListReactivatedDate not being set is a separate bug to fix. Updated counts: - Total with expired AML, no reactivation date: 361 - Excluded (have DfxApproval after expiry): 43 - Affected by this migration: 318 --- .../1769200000000-ResetExpiredAmlKycLevel.js | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 migration/1769200000000-ResetExpiredAmlKycLevel.js diff --git a/migration/1769200000000-ResetExpiredAmlKycLevel.js b/migration/1769200000000-ResetExpiredAmlKycLevel.js new file mode 100644 index 0000000000..d170ad3c43 --- /dev/null +++ b/migration/1769200000000-ResetExpiredAmlKycLevel.js @@ -0,0 +1,91 @@ +/** + * @typedef {import('typeorm').MigrationInterface} MigrationInterface + * @typedef {import('typeorm').QueryRunner} QueryRunner + */ + +/** + * Reset KYC level for users with expired AML and no reactivation. + * + * Users with KycLevel >= 30 who have amlListExpiredDate set but no + * amlListReactivatedDate should not have elevated KYC levels, as their + * AML verification has expired and was never renewed. + * + * This migration sets their KycLevel back to 20 (basic level). + * + * IMPORTANT: Excludes 43 users who have a completed DfxApproval after their + * amlListExpiredDate - these users legitimately re-verified but the + * amlListReactivatedDate was not set (separate bug to fix). + * + * Affected users: 318 (as of 2026-01-31) + * Excluded users: 43 (have DfxApproval after expiry) + * + * @class + * @implements {MigrationInterface} + */ +module.exports = class ResetExpiredAmlKycLevel1769200000000 { + name = 'ResetExpiredAmlKycLevel1769200000000'; + + /** + * @param {QueryRunner} queryRunner + */ + async up(queryRunner) { + // First, log the count of affected users for verification + const result = await queryRunner.query(` + SELECT COUNT(*) as count + FROM "dbo"."user_data" + WHERE "kycLevel" >= 30 + AND "amlListExpiredDate" IS NOT NULL + AND "amlListReactivatedDate" IS NULL + AND NOT EXISTS ( + SELECT 1 FROM "dbo"."kyc_step" + WHERE "userDataId" = "user_data"."id" + AND "name" = 'DfxApproval' + AND "status" = 'Completed' + AND "created" > "user_data"."amlListExpiredDate" + ) + `); + console.log(`Resetting KYC level for ${result[0].count} users with expired AML and no reactivation`); + + // Update KycLevel to 20 for affected users (excluding those with DfxApproval after expiry) + await queryRunner.query(` + UPDATE "dbo"."user_data" + SET "kycLevel" = 20 + WHERE "kycLevel" >= 30 + AND "amlListExpiredDate" IS NOT NULL + AND "amlListReactivatedDate" IS NULL + AND NOT EXISTS ( + SELECT 1 FROM "dbo"."kyc_step" + WHERE "userDataId" = "user_data"."id" + AND "name" = 'DfxApproval' + AND "status" = 'Completed' + AND "created" > "user_data"."amlListExpiredDate" + ) + `); + } + + /** + * @param {QueryRunner} queryRunner + */ + async down(queryRunner) { + // Note: This down migration cannot fully restore the original state + // as we don't know the original KycLevel values. This sets them to 50 + // as a reasonable default for users who had completed KYC. + console.log('Warning: Down migration sets KycLevel to 50, original values are not preserved'); + + await queryRunner.query(` + UPDATE "dbo"."user_data" + SET "kycLevel" = 50 + WHERE "kycLevel" = 20 + AND "amlListExpiredDate" IS NOT NULL + AND "amlListReactivatedDate" IS NULL + AND "kycStatus" = 'Completed' + AND NOT EXISTS ( + SELECT 1 FROM "dbo"."kyc_step" + WHERE "userDataId" = "user_data"."id" + AND "name" = 'DfxApproval' + AND "status" = 'Completed' + AND "created" > "user_data"."amlListExpiredDate" + ) + `); + } +};