--- name: "account-deletion-flow-android" description: "Implement Google Play required account deletion: in-app AND on website. Use when the user says 'account deletion android', 'delete account play', 'play account deletion requirement'." --- # Account Deletion Flow (Play Required) Mandatory since Dec 2023. Both in-app + on website. ## Implementation context The snippets describe the consuming mobile app and its own authenticated backend. The bearer value is that app user’s session token obtained through its established authentication flow; it is not a token read from the plugin installer’s environment. Deletion requests and AI consent settings are independent app features. Do not execute these snippets as plugin startup or account-management actions. ## In-app Settings → Account → Delete Account → confirmation → delete. ```tsx // Settings screen Delete account // Confirmation Title: "Delete account?" Body: "This permanently deletes your account and all data. Cannot be undone." Buttons: [Cancel, Delete] // On Delete: async function deleteAccount() { await fetch('/api/delete-account', { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }); await SecureStore.deleteItemAsync('auth_token'); router.replace('/sign-in'); } ``` ## Backend delete endpoint ```ts // /api/delete-account app.delete('/api/delete-account', async (c) => { const userId = c.get('jwtPayload').sub; // 1. Soft delete: mark deleted_at, hide from queries await db.update(users).set({ deletedAt: new Date() }).where(eq(users.id, userId)); // 2. Schedule hard delete (30 day grace) await scheduleJob('hardDeleteUser', { userId, runAt: addDays(new Date(), 30) }); // 3. Cancel any active subscriptions await revenueCat.subscriber.delete(userId); // 4. Log for audit await auditLog.create({ event: 'account_deletion_requested', userId }); return c.json({ ok: true }); }); ``` ## Website (also required) Public URL where users can request deletion WITHOUT installing app. `/account-deletion`: ```html
``` Backend verifies via email link, then deletes. ## Play Console declaration Setup → Data deletion → "Provide URL" → enter your `/account-deletion` URL. ## What MUST be deleted - User account - All user-generated content - Linked records (purchases, settings, etc.) - Backups (within retention window) ## What you can keep - Aggregate stats (anonymized) - Legal hold data (if required by law) - Audit logs (for fraud / safety) ## Grace period 30 days is industry standard. User can cancel within grace by signing back in. ## Common gotchas - Forgetting to delete in third-party services (RevenueCat, Sentry user, PostHog person) - "Account deletion" link goes to email instead of in-app → rejection - 24-hr delete vs 30-day grace → either works, document clearly - Hard delete from backup retention (Postgres point-in-time recovery has 30-day default) ## Pair with - `generate-privacy-policy-android` (link from policy) - `data-safety-form` (declare deletion mechanism)