Suppression de compte et export des données avec Claude Code : passer la guideline Apple 5.1.1(v) et Google Play
Si les utilisateurs peuvent créer un compte dans votre app, Apple comme Google exigent qu'ils puissent le supprimer depuis l'app, et Google veut en plus une page web pour les demandes de suppression. Claude Code peut construire la fonctionnalité en un après-midi, mais seulement une fois qu'il sait où se trouve chaque donnée utilisateur. Ce guide commence par cette carte des données, puis construit la suppression, un export Télécharger mes données et le nettoyage dans l'app WebViewGold.
Dès $109 en paiement unique par plateforme, ou notre équipe s'occupe de tout dès $698.
Garantie d'approbation – ou remboursement sous 14 jours
Aucun codage requis
Paiement unique, mises à jour gratuites
Support humain 24/7
Conçu en Allemagne depuis 2014 · ISO 27001
9:41
Votre app
Votre appDésormais dans votre poche
App Store · Google Play Approuvée
Ce que les stores exigent réellement
Apple, guideline 5.1.1(v) : si votre app permet de créer un compte, les utilisateurs doivent pouvoir lancer la suppression de leur compte depuis l'app. Les recommandations d'Apple demandent la suppression de l'enregistrement du compte et des données personnelles associées, pas un simple interrupteur de désactivation ; vous pouvez conserver les données que la loi vous oblige à garder, et il convient d'indiquer aux utilisateurs combien de temps prend la suppression. Si vous proposez Sign in with Apple, révoquez les jetons de l'utilisateur via l'API REST d'Apple lors de la suppression du compte. Les abonnements achetés via Apple ne sont pas résiliés par la suppression du compte : expliquez donc aux utilisateurs comment les résilier.
Google Play : les apps qui permettent de créer un compte doivent proposer la suppression dans l'app et un lien web où les utilisateurs peuvent demander la suppression sans réinstaller l'app. Vous indiquez ce lien dans le formulaire Data safety, et la suppression doit couvrir les données associées au compte, hormis celles que vous déclarez conserver. Le guide Google Play sur la suppression de compte couvre le côté console.
Export des données : aucun des deux stores ne l'exige, mais des lois sur la vie privée comme le RGPD donnent aux utilisateurs un droit d'accès et de portabilité, et un bouton Télécharger mes données répond à ces demandes sans ticket au support. C'est aussi un bon test de votre carte des données : si l'agent ne peut pas exporter une donnée, il ne peut probablement pas non plus la supprimer.
Ce que fait Claude Code et ce que vous faites
Domaine
Claude Code
Vous
Carte des données
Explore en mode plan le code, les migrations, les imports de SDK et les webhooks, et rédige un brouillon de DATA_MAP.md
Ajouter ce que le code ne montre pas (tableurs, boîte mail du support, exports manuels) et confirmer les durées de conservation
Code
Interface des réglages, routes d'export et de suppression, helpers de nettoyage, migrations, tests, page /delete-account
Relire, définir les variables d'environnement chez l'hébergeur, déployer
Consoles des stores
Rédige les modifications de la politique de confidentialité et les réponses Data safety
Saisir l'URL de suppression dans la Play Console, mettre à jour App Privacy dans App Store Connect
WebViewGold
Rien d'obligatoire ; peut régler les options du téléchargeur si les projets sont dans le dépôt
Un nouveau build si vous modifiez les réglages du téléchargeur
Prompt 1 : la carte des données, en mode plan
Le mode plan permet à Claude Code de lire et de fouiller le dépôt sans rien modifier. Enregistrez le résultat sous DATA_MAP.md et corrigez-le avant de continuer : c'est ce fichier qui rend la suppression complète.
À coller dans Claude Code en mode plan (Shift+Tab)
Mode plan uniquement, ne modifiez aucun fichier. Nous avons besoin d'une suppression de compte dans l'app (guideline Apple 5.1.1(v) et politique de Google Play sur la suppression de compte) et d'un export Télécharger mes données. Commencez par établir une carte complète des données.
Fouillez la base de code, les migrations, les noms des variables d'environnement, les imports de SDK, les tâches cron et les gestionnaires de webhooks, et listez chaque endroit où se trouvent des données sur un utilisateur : enregistrements d'authentification, chaque table avec une colonne user_id, owner_id ou email et la façon dont elle référence l'utilisateur, buckets de stockage et chemins de fichiers, clients et abonnements Stripe, clients RevenueCat, ID d'abonnement OneSignal, jetons Sign in with Apple, analytics et suivi des erreurs, outils d'e-mail et de newsletter, logs et sauvegardes.
Pour chaque entrée, indiquez : où elle se trouve, quel identifiant la relie à l'utilisateur, comment la supprimer (cascade par clé étrangère, appel d'API, ou conservation avec une justification) et si elle doit figurer dans l'export. Signalez tout ce dont vous n'êtes pas sûr. Présentez le résultat sous forme de tableau markdown que je peux enregistrer sous DATA_MAP.md.
Je suis très content d'avoir acheté cette application ! Extrêmement facile et excellente documentation. J'ai été en contact avec le service client, ils ont répondu très rapidement et très amicalement. Ils ont résolu ma question en un jour. 10/10 recommanderaient.
Une carte des données typique pour une app Supabase
Donnée
Comment elle est supprimée
Dans l'export ?
Utilisateur d'authentification
auth.admin.deleteUser, en dernier
ID, e-mail, date de création
Tables de profil et de contenu
Clés étrangères vers l'utilisateur avec ON DELETE CASCADE
Oui
Fichiers envoyés
API Storage, par dossier utilisateur (le listing n'est pas récursif)
Liens ou fichiers
Client et abonnements Stripe
Résilier les abonnements ; conserver les factures comme la loi l'exige et l'indiquer dans /privacy
Formule et liste des factures
Abonnement App Store / Google Play
Vous ne pouvez pas le résilier ; affichez cancelinapppurchase:// dans l'app
Nom de la formule
Client RevenueCat
Suppression du client via l'API REST de RevenueCat
Non
ID d'abonnement OneSignal
Supprimer vos lignes enregistrées ; éventuellement l'utilisateur OneSignal via leur API
Non
Sign in with Apple
Révoquer le jeton via l'endpoint de révocation d'Apple
Non
Analytics, suivi des erreurs, outils d'e-mail
API de suppression du fournisseur ou conservation documentée
En général non
Prompt 2 : construire la suppression et l'export
Revenez au mode d'autorisation par défaut pour relire chaque modification, ou passez en mode accept-edits si vous préférez relire le diff complet à la fin.
À coller dans Claude Code une fois DATA_MAP.md corrigé
Implémentez la suppression de compte et l'export des données à partir de DATA_MAP.md. Notre app tourne aussi dans des apps natives iOS et Android construites avec WebViewGold (le user agent contient WebViewGoldApp).
1. Réglages > Compte : un bouton Télécharger mes données et un bouton Supprimer le compte.
2. Export : GET /api/account/export renvoie, pour l'utilisateur connecté, un fichier JSON unique avec chaque entrée exportable de la carte, envoyé avec Content-Type application/json et Content-Disposition attachment; filename=my-data.json. Déclenchez-le avec un lien normal vers cette URL, pas avec un téléchargement par Blob ou createObjectURL : dans l'app, le téléchargeur de WebViewGold réagit aux extensions de fichier et aux en-têtes Content-Disposition. Si un export peut être volumineux, générez-le dans une tâche en arrière-plan et envoyez par e-mail un lien signé qui expire après 24 heures.
3. Suppression : un écran de confirmation qui explique ce qui est supprimé, ce que nous conservons pour des raisons légales (factures) et que les abonnements App Store ou Google Play ne sont pas résiliés automatiquement. Dans l'app, affichez un lien Gérer l'abonnement qui navigue vers cancelinapppurchase:// quand l'utilisateur a un abonnement via le store. Exigez que l'utilisateur tape DELETE.
4. POST /api/account/delete : authentifiez, puis, dans cet ordre, résiliez les abonnements Stripe, supprimez le client RevenueCat, révoquez les jetons Sign in with Apple si nous en avons (API REST d'Apple, /auth/revoke), supprimez les fichiers du stockage, supprimez les lignes (privilégiez ON DELETE CASCADE ; ajoutez une migration là où elle manque) et supprimez l'utilisateur d'authentification en dernier avec le client admin. Côté serveur uniquement ; la clé service-role ne doit jamais atteindre le bundle client. Rendez la route idempotente, pour qu'une nouvelle tentative après un échec partiel termine le travail.
5. Après le succès : déconnectez l'utilisateur et affichez /account-deleted. Dans l'app, son bouton Terminé navigue vers reset:// pour effacer les cookies et le cache que conserve le wrapper.
6. Une page publique /delete-account pour les personnes qui n'ont plus l'app : elle explique le chemin dans l'app et propose un formulaire de demande ou une adresse e-mail, fonctionne sans connexion et sur un écran de 320 px.
7. Mettez à jour /privacy avec les durées de conservation et l'URL /delete-account.
8. Tests pour la route de suppression : un utilisateur qui a des données dans chaque table finit avec zéro ligne, et un second appel de la route réussit toujours.
Indiquez les fichiers modifiés, les migrations et chaque étape manuelle que je dois effectuer.
La route de suppression, dans l'ordre qui ne perd aucun ID
D'abord les tiers, tant que vous connaissez encore les ID clients ; l'utilisateur d'authentification en dernier, car la plupart des clés étrangères en dépendent. Les helpers de account-cleanup encapsulent les appels Stripe, RevenueCat et Apple de votre carte des données.
typescript
// app/api/account/delete/route.ts (serveur uniquement)
import { NextResponse } from "next/server";
import { createClient as createAdmin } from "@supabase/supabase-js";
import { createClient } from "@/lib/supabase/server";
import { cancelStripeSubscriptions, deleteRevenueCatCustomer, revokeAppleTokens } from "@/lib/account-cleanup";
export async function POST(req: Request) {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) return NextResponse.json({ error: "unauthorized" }, { status: 401 });
const { confirm } = await req.json();
if (confirm !== "DELETE") return NextResponse.json({ error: "confirmation missing" }, { status: 400 });
const admin = createAdmin(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!);
// 1. Les tiers, tant que les ID existent encore (chaque helper ne fait rien s'il n'y a rien à faire)
await cancelStripeSubscriptions(user.id);
await deleteRevenueCatCustomer(user.id);
await revokeAppleTokens(user.id);
// 2. Fichiers : list() n'est pas récursif, les sous-dossiers demandent leur propre passage
const { data: files } = await admin.storage.from("uploads").list(user.id);
if (files && files.length > 0) {
await admin.storage.from("uploads").remove(files.map((f) => user.id + "/" + f.name));
}
// 3. Les lignes partent avec l'utilisateur via ON DELETE CASCADE (voir DATA_MAP.md)
// 4. L'utilisateur d'authentification, en dernier
const { error } = await admin.auth.admin.deleteUser(user.id);
if (error) return NextResponse.json({ error: "delete failed, safe to retry" }, { status: 500 });
return NextResponse.json({ ok: true });
}
Faire aboutir le téléchargement de l'export dans l'app
Deux petits réglages décident si le fichier arrive sur le téléphone.
Servez une vraie URL de fichier
La route ci-dessus renvoie du JSON avec un en-tête Content-Disposition attachment. Pointez-y un simple lien ; les téléchargements de Blob générés en JavaScript ne sont pas couverts par la documentation du téléchargeur WebViewGold.
iOS
Activez autodownloader dans Config.swift (téléchargement d'après les en-têtes Content-Disposition), ou servez le fichier sous une URL qui se termine par .json et ajoutez ".json" à extentionARY. Voir la documentation du téléchargeur de fichiers iOS.
Android
Activez AUTO_DOWNLOAD_FILES dans Config.java ou ajoutez l'extension à downloadableExtension ; requireStorage doit rester sur true si vous utilisez les téléchargements. Voir la documentation du téléchargeur de fichiers Android.
Recompilez une fois
Ce sont des réglages natifs : ils demandent un nouveau build. Tout le reste de ce guide part avec votre prochain déploiement web. Le Cloud Builder peut produire ce build sans installation locale de Xcode ou d'Android Studio.
Checklist de vérification
Dans les builds TestFlight et de test interne, créez un compte neuf, ajoutez du contenu, envoyez un fichier et, si vous vendez des abonnements, achetez-en un en sandbox.
Touchez Télécharger mes données : le fichier arrive sur le téléphone et contient votre contenu, pas un objet vide.
Touchez Supprimer le compte : la confirmation explique les conséquences et contient la remarque sur l'abonnement, le lien Gérer l'abonnement ouvre l'écran du store, la saisie de DELETE termine le flux et l'app affiche la confirmation.
Touchez Terminé sur la confirmation : reset:// efface les cookies et le cache du wrapper. Notez ce que votre build affiche ensuite et vérifiez qu'il s'agit d'un démarrage propre, pas d'une erreur.
Essayez de vous reconnecter : le compte n'existe plus. Une requête sur l'ID utilisateur renvoie zéro ligne dans chaque table de DATA_MAP.md, et le dossier de stockage est vide.
Pour un utilisateur de test Sign in with Apple, l'app disparaît de la liste Sign in with Apple dans les réglages de ce compte Apple après la suppression : la preuve que le jeton a été révoqué.
Ouvrez /delete-account dans une fenêtre de navigation privée sur un téléphone : la page fonctionne sans connexion, et la même URL figure dans le formulaire Data safety de la Play Console.
Pièges
Une suppression logique seulement. Un indicateur deleted_at, c'est une désactivation. Les reviewers et Google attendent que les données aient disparu, hormis la conservation déclarée.
Supprimer d'abord l'utilisateur d'authentification. Sans cascades, des lignes restent ; avec des cascades, vous perdez les ID dont vous aviez besoin pour Stripe et RevenueCat. Les tiers d'abord, l'authentification en dernier.
Le stockage oublié. Les avatars et les fichiers envoyés survivent à la suppression des lignes. La carte des données existe précisément pour attraper ce cas.
Supprimer le compte de démo du reviewer. Les reviewers peuvent tester la suppression sur le compte que vous leur avez donné. Indiquez dans les notes pour la validation qu'ils peuvent créer un nouveau compte, et recréez le compte de démo après chaque validation.
Caché derrière le support. « Écrivez-nous pour supprimer votre compte » comme seul chemin ne satisfait pas la 5.1.1(v) pour la plupart des apps. Le bouton dans l'app doit lancer la suppression.
Questions fréquentes
Désactiver le compte suffit-il ?
Non. Apple demande la suppression du compte et des données personnelles associées, et Google Play exige que les données soient supprimées, pas seulement masquées. La désactivation peut être une option supplémentaire, pas la seule.
Puis-je conserver certaines données après la suppression ?
Oui, lorsque vous avez une obligation légale ou un motif légitime, comme les factures pour le droit fiscal. Indiquez-le dans votre politique de confidentialité et dans le formulaire Data safety.
La suppression peut-elle prendre quelques jours ?
Un court délai de grâce est courant. Lancez la suppression dans l'app, dites précisément à l'utilisateur quand les données auront disparu, et consultez les recommandations actuelles d'Apple sur la suppression de compte pour la formulation qu'attendent les reviewers.
Que deviennent les abonnements achetés dans l'app ?
Vous ne pouvez pas résilier les abonnements App Store ou Google Play à la place de l'utilisateur. Affichez un lien Gérer l'abonnement (cancelinapppurchase:// dans l'app) et dites clairement que la facturation continue tant qu'il ne résilie pas.
Quel format utiliser pour l'export ?
Un format structuré et lisible par une machine, comme JSON ou CSV. Un fichier JSON par compte est le plus simple à générer, à tester et à expliquer.
Trois façons de mettre votre app dans les stores
Même résultat, charge de travail différente de votre côté. Les trois formules incluent la garantie d'approbation et le support humain 24/7.
Faites-le vous-même
$109 par plateforme, paiement unique
La licence WebViewGold : un projet Xcode ou Android Studio prêt à l'emploi. Collez votre URL, définissez le nom et l'icône, activez les fonctionnalités, compilez et soumettez. Mises à jour gratuites à vie.
Ni Mac, ni Xcode, ni Android Studio : configurez dans le navigateur, nous compilons les deux apps dans le cloud et les transmettons à App Store Connect et à la Play Console.
Envoyez-nous votre URL et votre icône. Notre équipe configure, compile et livre votre app sous 72 heures, en marque blanche, projets sources inclus. Les deux plateformes pour $1,158.
Les remboursements sont accordés aux conditions indiquées dans notre FAQ : un refus non lié au contenu par Apple et/ou Google, demandé dans les 14 jours suivant l'achat.