From ac3418cabed96ea37bcc30e65297b2fac63bac21 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 8 May 2026 15:52:24 -0400 Subject: [PATCH 1/5] chore: update "PNID deleted" email to mention the 7 day grace period and how to restore --- src/models/pnid.ts | 28 ++++++++++++++++++- .../grpc/account/v2/delete-account.ts | 2 +- src/services/grpc/api/v2/delete-account.ts | 2 +- src/services/nnas/routes/people.ts | 2 +- src/util.ts | 13 +++++++-- 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/models/pnid.ts b/src/models/pnid.ts index bca37bb..e12a802 100644 --- a/src/models/pnid.ts +++ b/src/models/pnid.ts @@ -235,9 +235,35 @@ PNIDSchema.method('generateMiiImages', async function generateMiiImages(): Promi await uploadCDNAsset(config.s3.bucket, `${userMiiKey}/body.png`, miiStudioBodyImageData, 'public-read'); }); -PNIDSchema.method('markForDeletion', function markForDeletion() { +PNIDSchema.method('markForDeletion', async function markForDeletion() { this.marked_for_deletion = true; this.hard_delete_time = new Date(Date.now() + (7 * 24 * 3600 * 1000)); // * 7 day grace period + + if (this.connections?.stripe?.subscription_id) { + const subscriptionID = this.connections.stripe.subscription_id; + + try { + if (stripe) { + // * If a user has an active subscription when they mark themselves for deletion, then they + // * may get charged again in those 7 days while not having access to their account. To prevent + // * that, just update the subscription to cancel at the end of the period. That way the charge + // * doesn't happen, and the user likely won't be restoring their account anyway. If they do + // * restore the account and do want their subscription back then they can create a new one + // * after this one expires which is effectively the same as the old subscription renewing. + // * Pausing collection is another option however it requires much more effort on our end to + // * properly resume the paused charges and recitify any missed ones to prevent invoices + // * from being skipped. This method is just way easier for us to deal with right now, at the + // * expense of making the user do a tad more work on their end + await stripe.subscriptions.update(subscriptionID, { + cancel_at_period_end: true + }); + } else { + LOG_WARN(`UPDATING SUBSCRIPTION FOR USER ${this.username}. HAS STRIPE DATA UDER ID ${this.connections.stripe.customer_id}, BUT STRIPE CLIENT NOT ENABLED.`); + } + } catch (error) { + LOG_ERROR(`ERROR UPDATING SUBSCRIPTION FOR USER ${this.username} (${subscriptionID}). ${error}`); + } + } }); PNIDSchema.method('scrub', async function scrub() { diff --git a/src/services/grpc/account/v2/delete-account.ts b/src/services/grpc/account/v2/delete-account.ts index 631dbef..c4fa924 100644 --- a/src/services/grpc/account/v2/delete-account.ts +++ b/src/services/grpc/account/v2/delete-account.ts @@ -21,7 +21,7 @@ export async function deleteAccount(request: DeleteAccountRequest): Promise { + const deletionDate = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toLocaleString('en-US', { + timeZone: 'UTC', + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric' + }); const email = new CreateEmail() .addHeader('Dear {{pnid}},', { pnid: username }) - .addParagraph('your PNID has successfully been deleted.') - .addParagraph('If you had a tier subscription, a separate cancellation email will be sent. If you do not receive this cancellation email, or you are still being charged for your subscription, please contact @jonbarrow on our [Discord server](https://discord.pretendo.network/).'); + .addParagraph('your PNID has been scheduled for deletion.') + .addParagraph(`Your account and related data will be permanently deleted in 7 days (${deletionDate}). Note that this will not free the username associated with the account for use in future accounts. In case of accidental deletion, you may restore your account prior to the deletion date. To restore your account, send an email to \`support@pretendo.network\` from the email address used to register the deleted account, with the subject "Requesting account restore", making sure to include the username of the account being restored. Account restoration requests MUST be sent prior to the account deletion date, ideally more than 24 hours prior, or else account data may already be unrecoverable. For any additional support, please create a support thread on our [forum](https://forum.pretendo.network/). If you have an active tier subscription, or had one in the past, your Stripe account and all data/invoices/subscriptions/etc. will be deleted on the date of account deletion, and cannot be restored. If you have an active subscription which would normally renew on a day prior to the account deletion date, the subscription will be cancelled on the day it would normally rewnew and no new charges will be created. If your account is restored with an active subscription, a new subscription may need to be created after restoration due to the automatic cancelling. If you are still being charged for your subscription within the grace period, please contact @jonbarrow on our [Discord server](https://discord.pretendo.network/) prior to the account deletion date.`); const options = { to: emailAddress, - subject: '[Pretendo Network] PNID Deleted', + subject: '[Pretendo Network] PNID Deletion', email }; From 9ae3b5322acd61b9298cea08c216158f80dc2069 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 8 May 2026 17:21:21 -0400 Subject: [PATCH 2/5] chore: split up and reword account deletion email to be a bit shorter --- src/util.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/util.ts b/src/util.ts index c286e9e..ddfbcc0 100644 --- a/src/util.ts +++ b/src/util.ts @@ -289,9 +289,11 @@ export async function sendPNIDDeletedEmail(emailAddress: string, username: strin day: 'numeric' }); const email = new CreateEmail() - .addHeader('Dear {{pnid}},', { pnid: username }) - .addParagraph('your PNID has been scheduled for deletion.') - .addParagraph(`Your account and related data will be permanently deleted in 7 days (${deletionDate}). Note that this will not free the username associated with the account for use in future accounts. In case of accidental deletion, you may restore your account prior to the deletion date. To restore your account, send an email to \`support@pretendo.network\` from the email address used to register the deleted account, with the subject "Requesting account restore", making sure to include the username of the account being restored. Account restoration requests MUST be sent prior to the account deletion date, ideally more than 24 hours prior, or else account data may already be unrecoverable. For any additional support, please create a support thread on our [forum](https://forum.pretendo.network/). If you have an active tier subscription, or had one in the past, your Stripe account and all data/invoices/subscriptions/etc. will be deleted on the date of account deletion, and cannot be restored. If you have an active subscription which would normally renew on a day prior to the account deletion date, the subscription will be cancelled on the day it would normally rewnew and no new charges will be created. If your account is restored with an active subscription, a new subscription may need to be created after restoration due to the automatic cancelling. If you are still being charged for your subscription within the grace period, please contact @jonbarrow on our [Discord server](https://discord.pretendo.network/) prior to the account deletion date.`); + .addHeader('Dear {{pnid}}.', { pnid: username }) + .addParagraph('Your PNID has been scheduled for deletion.') + .addParagraph(`Your account and related data will be permanently deleted in 7 days (${deletionDate}). Note that this will not free the username associated with the account for use in future accounts.`) + .addParagraph('In case of accidental deletion, you may restore your account prior to the deletion date. To restore your account, send an email to [restore-account@pretendo.network](mailto:restore-account@pretendo.network?subject=Requesting%20account%20restore&body=Please%20restore%20my%20account) from the email address used to register the deleted account, with the subject "Requesting account restore", making sure to include the username of the account being restored. Account restoration requests MUST be sent prior to the account deletion date, ideally more than 24 hours prior, or else account data may already be unrecoverable. For any additional support, please create a support thread on our [forum](https://forum.pretendo.network/), or create a support thread on our [Discord server](https://discord.pretendo.network/) if you are unable to access our forum.') + .addParagraph('If you have an active tier subscription, or had one in the past, your Stripe account (including PII/invoices/etc.) will be deleted on the date of account deletion, and cannot be restored. If you have an active subscription which would normally renew on a day within the grace period, no new charges will be created. If your account is restored with an active subscription, a new subscription may need to be created after restoration. If you are still being charged for your subscription within the grace period, please create a support thread on our [forum](https://forum.pretendo.network/), or create a support thread on our [Discord server](https://discord.pretendo.network/) if you are unable to access our forum, prior to the account deletion date.'); const options = { to: emailAddress, From cfabe01f30079179214cfdb77cdffda440e6bb09 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 8 May 2026 17:36:27 -0400 Subject: [PATCH 3/5] chore: make "PNID deleted" email even less wordy Co-authored-by: William Oldham --- src/util.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/util.ts b/src/util.ts index ddfbcc0..34cadf5 100644 --- a/src/util.ts +++ b/src/util.ts @@ -292,8 +292,9 @@ export async function sendPNIDDeletedEmail(emailAddress: string, username: strin .addHeader('Dear {{pnid}}.', { pnid: username }) .addParagraph('Your PNID has been scheduled for deletion.') .addParagraph(`Your account and related data will be permanently deleted in 7 days (${deletionDate}). Note that this will not free the username associated with the account for use in future accounts.`) - .addParagraph('In case of accidental deletion, you may restore your account prior to the deletion date. To restore your account, send an email to [restore-account@pretendo.network](mailto:restore-account@pretendo.network?subject=Requesting%20account%20restore&body=Please%20restore%20my%20account) from the email address used to register the deleted account, with the subject "Requesting account restore", making sure to include the username of the account being restored. Account restoration requests MUST be sent prior to the account deletion date, ideally more than 24 hours prior, or else account data may already be unrecoverable. For any additional support, please create a support thread on our [forum](https://forum.pretendo.network/), or create a support thread on our [Discord server](https://discord.pretendo.network/) if you are unable to access our forum.') - .addParagraph('If you have an active tier subscription, or had one in the past, your Stripe account (including PII/invoices/etc.) will be deleted on the date of account deletion, and cannot be restored. If you have an active subscription which would normally renew on a day within the grace period, no new charges will be created. If your account is restored with an active subscription, a new subscription may need to be created after restoration. If you are still being charged for your subscription within the grace period, please create a support thread on our [forum](https://forum.pretendo.network/), or create a support thread on our [Discord server](https://discord.pretendo.network/) if you are unable to access our forum, prior to the account deletion date.'); + .addParagraph('You may restore your account at any time before the deletion date. To do so, email [restore-account@pretendo.network](mailto:restore-account@pretendo.network?subject=Requesting%20account%20restore&body=Please%20restore%20my%20account) from the email address used to register, with the subject "Requesting account restore" and your PNID username in the body. Requests must be submitted more than 24 hours before the deletion date, as after this point your data may be unrecoverable. For additional help, visit our [forum](https://forum.pretendo.network/) or [Discord server](https://discord.pretendo.network/).') + .addParagraph('If you have or have had an active tier subscription, your associated Stripe data (including payment info and invoices) will be permanently deleted on the deletion date and cannot be restored.') + .addParagraph('No new charges will be made during the grace period, even if a renewal would normally occur. If your account is restored with an active subscription, you may need to resubscribe. If you notice unexpected charges during the grace period, please contact us via our [forum](https://forum.pretendo.network/) or [Discord server](https://discord.pretendo.network/) before the deletion date.') const options = { to: emailAddress, From 722d08e4bcae285311dc3925916e6295db4ca7a6 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Fri, 8 May 2026 17:40:14 -0400 Subject: [PATCH 4/5] fix: correct linting in `sendPNIDDeletedEmail` Co-authored-by: William Oldham --- src/util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.ts b/src/util.ts index 34cadf5..4597ace 100644 --- a/src/util.ts +++ b/src/util.ts @@ -294,7 +294,7 @@ export async function sendPNIDDeletedEmail(emailAddress: string, username: strin .addParagraph(`Your account and related data will be permanently deleted in 7 days (${deletionDate}). Note that this will not free the username associated with the account for use in future accounts.`) .addParagraph('You may restore your account at any time before the deletion date. To do so, email [restore-account@pretendo.network](mailto:restore-account@pretendo.network?subject=Requesting%20account%20restore&body=Please%20restore%20my%20account) from the email address used to register, with the subject "Requesting account restore" and your PNID username in the body. Requests must be submitted more than 24 hours before the deletion date, as after this point your data may be unrecoverable. For additional help, visit our [forum](https://forum.pretendo.network/) or [Discord server](https://discord.pretendo.network/).') .addParagraph('If you have or have had an active tier subscription, your associated Stripe data (including payment info and invoices) will be permanently deleted on the deletion date and cannot be restored.') - .addParagraph('No new charges will be made during the grace period, even if a renewal would normally occur. If your account is restored with an active subscription, you may need to resubscribe. If you notice unexpected charges during the grace period, please contact us via our [forum](https://forum.pretendo.network/) or [Discord server](https://discord.pretendo.network/) before the deletion date.') + .addParagraph('No new charges will be made during the grace period, even if a renewal would normally occur. If your account is restored with an active subscription, you may need to resubscribe. If you notice unexpected charges during the grace period, please contact us via our [forum](https://forum.pretendo.network/) or [Discord server](https://discord.pretendo.network/) before the deletion date.'); const options = { to: emailAddress, From d47f2faa58c8db4ec1d56936284ad9858073e112 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Mon, 11 May 2026 19:45:05 -0400 Subject: [PATCH 5/5] chore: update capitalization in "PNID deleted" email --- src/util.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util.ts b/src/util.ts index 4597ace..7390920 100644 --- a/src/util.ts +++ b/src/util.ts @@ -292,9 +292,9 @@ export async function sendPNIDDeletedEmail(emailAddress: string, username: strin .addHeader('Dear {{pnid}}.', { pnid: username }) .addParagraph('Your PNID has been scheduled for deletion.') .addParagraph(`Your account and related data will be permanently deleted in 7 days (${deletionDate}). Note that this will not free the username associated with the account for use in future accounts.`) - .addParagraph('You may restore your account at any time before the deletion date. To do so, email [restore-account@pretendo.network](mailto:restore-account@pretendo.network?subject=Requesting%20account%20restore&body=Please%20restore%20my%20account) from the email address used to register, with the subject "Requesting account restore" and your PNID username in the body. Requests must be submitted more than 24 hours before the deletion date, as after this point your data may be unrecoverable. For additional help, visit our [forum](https://forum.pretendo.network/) or [Discord server](https://discord.pretendo.network/).') + .addParagraph('You may restore your account at any time before the deletion date. To do so, email [restore-account@pretendo.network](mailto:restore-account@pretendo.network?subject=Requesting%20account%20restore&body=Please%20restore%20my%20account) from the email address used to register, with the subject "Requesting account restore" and your PNID username in the body. Requests must be submitted more than 24 hours before the deletion date, as after this point your data may be unrecoverable. For additional help, visit our [Forum](https://forum.pretendo.network/) or [Discord server](https://discord.pretendo.network/).') .addParagraph('If you have or have had an active tier subscription, your associated Stripe data (including payment info and invoices) will be permanently deleted on the deletion date and cannot be restored.') - .addParagraph('No new charges will be made during the grace period, even if a renewal would normally occur. If your account is restored with an active subscription, you may need to resubscribe. If you notice unexpected charges during the grace period, please contact us via our [forum](https://forum.pretendo.network/) or [Discord server](https://discord.pretendo.network/) before the deletion date.'); + .addParagraph('No new charges will be made during the grace period, even if a renewal would normally occur. If your account is restored with an active subscription, you may need to resubscribe. If you notice unexpected charges during the grace period, please contact us via our [Forum](https://forum.pretendo.network/) or [Discord server](https://discord.pretendo.network/) before the deletion date.'); const options = { to: emailAddress,