Aller au contenu
WebViewGold Du vibe coding à l'App Store
Français
Obtenir WebViewGold

ChatGPT & Codex

Suppression de compte pour les apps Supabase et Firebase, cartographiée et construite avec Codex

Les deux stores refusent les apps qui permettent de s'inscrire mais pas de partir. La fonctionnalité paraît modeste, mais une suppression correcte touche l'authentification, chaque collection ou table, le stockage de fichiers, les abonnements et le token Sign in with Apple : c'est exactement le genre de modification transversale que Codex gère bien dès qu'il dispose d'un inventaire. Voici un workflow en deux passes : Codex cartographie les données dans une session en lecture seule, puis implémente la purge avec des tests.

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

Ce qu'exigent les stores, et ce que l'examinateur touche

Apple (guideline 5.1.1(v)) : si l'app permet de créer un compte, les utilisateurs doivent pouvoir lancer la suppression de leur compte dans l'app, et supprimer signifie supprimer le compte et ses données, pas poser un indicateur de désactivation. Une étape de confirmation est acceptée. Si les utilisateurs peuvent se connecter avec Apple, Apple attend de vous que vous révoquiez leurs tokens via l'API REST de Sign in with Apple lors de la suppression. Google Play : un parcours dans l'app, plus une page web où l'on peut demander la suppression sans réinstaller l'app, dont vous saisissez l'URL dans la section Sécurité des données de la Play Console.

Ce que fait réellement l'examinateur : il s'inscrit ou utilise votre compte de démo, ouvre les réglages, cherche Supprimer le compte et va parfois jusqu'au bout. Sur Google Play, le lien web est ouvert lui aussi ; s'il exige une connexion ou renvoie une 404, c'est un refus (le refus Google Play expliqué).

Pourquoi deux passes avec Codex : la suppression échoue en silence. Une collection ou un dossier de stockage oublié ne déclenche aucune erreur, il reste simplement là. C'est la cartographie des données avant d'écrire du code qui rend le résultat complet. Les exemples utilisent React, Express, Firebase Auth, Firestore et Cloud Storage ; les équivalents Supabase figurent dans le tableau. Le guide sur l'obligation de suppression de compte couvre les mêmes règles pour ceux qui créent sans agent de code, et le helper isNativeApp() provient du modèle AGENTS.md.

Passe 1 : cartographier les données dans une session en lecture seule

Le sandbox read-only permet à Codex de lire des fichiers et d'exécuter des commandes inoffensives comme rg, mais pas de modifier quoi que ce soit. La première passe reste ainsi honnête : elle ne peut que regarder. Le prompt figure en anglais dans les commentaires ; vous pouvez le coller tel quel ou dans votre langue.

bash
# Pass 1: inventory only. Codex can read, search and answer, but not edit.
cd my-app
codex --sandbox read-only --ask-for-approval on-request

# Paste this into the session:
#   Read AGENTS.md. Find every place this codebase stores or sends data about a
#   user: auth providers, Firestore collections and subcollections (and the field
#   that links each document to the user), Cloud Storage paths, server logs,
#   third parties that receive user data (RevenueCat, Stripe, OneSignal, email,
#   analytics, error tracking) and what the web app keeps on the device
#   (cookies, localStorage, IndexedDB, values written with writevalue://).
#   Output one Markdown table: location | link to the user | delete or retain | reason.
#   Mark anything you are unsure about. Do not propose code yet.

# When the table is right, switch to write access inside the session with
# /permissions and ask Codex to save it as docs/user-data-map.md. Commit it.

Ce que couvre une suppression complète

EmplacementFirebase (API Express)Supabase
Utilisateur d'authentificationgetAuth().deleteUser(uid) avec firebase-admin, en dernière étapesupabase.auth.admin.deleteUser(id) dans une Edge Function avec la clé service role, en dernière étape
Base de donnéesrecursiveDelete() pour le document utilisateur et ses sous-collections, plus des requêtes sur les champs propriétairesDes clés étrangères vers auth.users avec on delete cascade, ou des suppressions explicites avant l'appel d'authentification
FichiersgetStorage().bucket().deleteFiles({ prefix: "users/UID/" })Listez le dossier de l'utilisateur, puis storage.from(bucket).remove(paths)
Sign in with ApplerevokeAccessToken(auth, token) après que l'utilisateur s'est réauthentifié avec Apple ; Firebase ne stocke aucun token ApplePas automatique. L'endpoint de révocation d'Apple a besoin d'un token issu de la connexion ; demandez à Codex de vérifier ce que votre flux expose et de signaler le manque
Abonnements des storesVous ne pouvez pas les résilier à la place de l'utilisateur. Dites-le dans la boîte de dialogue et proposez cancelinapppurchase:// ; supprimez éventuellement le client RevenueCat côté serveurIdem
Push, e-mail, analyticsSupprimez les lignes des appareils push, retirez le contact de votre outil d'e-mailing, utilisez l'API de suppression de chaque prestataireIdem
L'appareilreset:// fait effacer à WebViewGold les cookies et le cache ; écrasez tout ce qui a été stocké avec writevalue://, qui survit à l'effacement du cacheIdem

WebViewGold nous a permis d'avoir le temps de mise sur le marché le plus court et le plus efficace jamais possible parmi toutes les autres plates-formes d'application que nous avons essayées au cours des 5 dernières années. Je ne sais pas pourquoi je ne vous ai pas découvert plus tôt, mais je suis vraiment, vraiment content de l'avoir fait. Nous approchons actuellement les 6000 téléchargements d'application sur l'App Store iOS et Google Play Store sans aucun problème!

Antonio Davila · CodeCanyon

Passe 2 : le prompt d'implémentation

Lancez une nouvelle session avec codex --sandbox workspace-write --ask-for-approval on-request, afin que ce soit la carte des données, et non la conversation précédente, qui fasse foi. Pour Supabase, remplacez l'étape 3 par une Edge Function qui vérifie le JWT, supprime les objets du stockage, s'appuie sur les clés étrangères en cascade et appelle auth.admin.deleteUser.

À coller dans Codex (workspace-write, approbations à la demande)
Lisez AGENTS.md et docs/user-data-map.md. Implémentez une suppression de compte conforme à la guideline 5.1.1(v) de l'App Store et à la politique de suppression de compte de Google Play. Stack : front-end React, API Express, Firebase Auth, Firestore, Cloud Storage. Cette app web s'exécute aussi dans des apps natives iOS et Android créées avec WebViewGold ; utilisez isNativeApp() pour les comportements propres à l'app.

1. Réglages > Compte > Supprimer le compte. Une feuille de confirmation explique ce qui est supprimé, ce que nous conservons et pendant combien de temps (d'après la carte), et que les abonnements des stores restent facturés par Apple ou Google jusqu'à leur résiliation. Si l'utilisateur a un abonnement store actif et que isNativeApp() est true, affichez un bouton Gérer l'abonnement qui navigue vers cancelinapppurchase://.
2. Connexion récente : si le serveur répond recent-login-required, réauthentifiez l'utilisateur. Pour les utilisateurs avec le fournisseur apple.com, réauthentifiez-les toujours avec OAuthProvider("apple.com"), lisez l'access token avec OAuthProvider.credentialFromResult et appelez revokeAccessToken(auth, token) avant l'appel au serveur.
3. DELETE /api/account dans Express : vérifiez l'ID token avec checkRevoked, exigez un auth_time datant de moins de 5 minutes, puis supprimez dans cet ordre : les fichiers Storage sous users/{uid}/, chaque emplacement Firestore de la carte (recursiveDelete pour les sous-collections, y compris pushDevices), le client Stripe et, si la carte l'indique, le client RevenueCat (derrière un feature flag, secret lu dans l'environnement), et enfin l'utilisateur Auth. Chaque étape doit pouvoir être relancée sans risque si la requête échoue à mi-chemin.
4. Après la réussite : déconnectez l'utilisateur et, quand isNativeApp() est true, naviguez vers reset:// pour que WebViewGold efface les cookies et le cache ; dans les navigateurs, videz le localStorage. Affichez ensuite un écran d'au revoir.
5. Une page publique /delete-account qui fonctionne sans connexion : elle explique les étapes dans l'app et propose un formulaire de demande (adresse e-mail) pour ceux qui n'ont plus l'app. Les demandes vont dans une collection deletionRequests et déclenchent un e-mail à [adresse du support].
6. Ajoutez à /privacy une courte section sur la suppression et la conservation des données.
7. Tests : utilisez les émulateurs Firebase si le projet les utilise déjà, sinon des mocks. La suppression retire chaque emplacement de la carte, un second appel ne fait rien, et un token périmé est refusé.
Indiquez les fichiers modifiés, l'URL à saisir dans la Play Console et ce que je dois configurer.

Le code à chercher dans le diff

Deux fichiers portent la logique. L'ordre côté serveur compte : les données d'abord, l'utilisateur d'authentification en dernier, pour qu'une requête qui échoue puisse simplement être relancée. Le client gère la révocation Apple, car Firebase ne conserve pas les tokens Apple et l'utilisateur doit de toute façon se réauthentifier.

javascript
// server/routes/account.js (Express + firebase-admin)
import express from "express";
import { getAuth } from "firebase-admin/auth";
import { getFirestore } from "firebase-admin/firestore";
import { getStorage } from "firebase-admin/storage";

export const accountRouter = express.Router();
const OWNED = [["projects", "ownerId"], ["comments", "authorId"], ["pushDevices", "uid"]]; // from docs/user-data-map.md

accountRouter.delete("/api/account", async (req, res) => {
  const idToken = (req.get("Authorization") || "").replace(/^Bearer /, "");
  let user;
  try {
    user = await getAuth().verifyIdToken(idToken, true); // true = reject revoked tokens
  } catch {
    return res.status(401).json({ error: "unauthenticated" });
  }
  if (Date.now() / 1000 - user.auth_time > 300) {
    return res.status(403).json({ error: "recent-login-required" });
  }
  const uid = user.uid;
  const db = getFirestore();

  await getStorage().bucket().deleteFiles({ prefix: "users/" + uid + "/" });
  for (const [name, field] of OWNED) {
    const owned = await db.collection(name).where(field, "==", uid).get();
    for (const doc of owned.docs) await db.recursiveDelete(doc.ref);
  }
  await db.recursiveDelete(db.collection("users").doc(uid));
  await getAuth().deleteUser(uid); // last: everything above is safe to re-run
  res.status(204).end();
});

// src/lib/deleteAccount.js (client, Firebase JS SDK)
import { OAuthProvider, reauthenticateWithPopup, revokeAccessToken } from "firebase/auth";
import { isNativeApp } from "./platform";

export async function deleteAccount(auth) {
  const user = auth.currentUser;
  if (user.providerData.some((p) => p.providerId === "apple.com")) {
    const result = await reauthenticateWithPopup(user, new OAuthProvider("apple.com"));
    const credential = OAuthProvider.credentialFromResult(result);
    await revokeAccessToken(auth, credential.accessToken); // Apple 5.1.1(v)
  }
  const res = await fetch("/api/account", {
    method: "DELETE",
    headers: { Authorization: "Bearer " + (await user.getIdToken(true)) }
  });
  if (res.status === 403) throw new Error("recent-login-required");
  if (!res.ok) throw new Error("delete-failed");
  await auth.signOut();
  if (isNativeApp()) window.location.href = "reset://"; // WebViewGold clears cookies and cache
}

Le workflow de bout en bout

  1. Cartographier

    Exécutez la passe 1 dans le sandbox en lecture seule, corrigez vous-même le tableau (Codex ne peut pas savoir quelles données vous devez conserver pour des raisons fiscales ou légales), puis commitez docs/user-data-map.md.

  2. Construire

    Exécutez la passe 2 dans une nouvelle session. Demandez un /review avant d'accepter les modifications et comparez la route serveur à la carte, ligne par ligne.

  3. Configurer

    Saisissez l'URL publique /delete-account dans la section Sécurité des données de la Play Console. Mentionnez la suppression et la conservation des données dans votre politique de confidentialité (ce que doit contenir la politique).

  4. Vérifier

    Déroulez la checklist ci-dessous avec un compte jetable sur un build TestFlight et sur un build de test interne.

  5. Protéger le compte de démo

    Les examinateurs peuvent le supprimer. Recréez-le avant chaque soumission, et précisez dans les notes pour l'examen qu'ils peuvent tout à fait créer un nouveau compte pour tester la suppression. Plus d'informations sur le parcours de publication dans le guide du workflow Codex.

Vérifiez comme le ferait un examinateur

  • Un compte de test avec des données dans chaque emplacement de la carte (un projet, un commentaire, un fichier importé, un appareil push).
  • Suppression dans l'app : l'utilisateur disparaît de Firebase Authentication, et il ne reste aucun document Firestore ni fichier Storage lui appartenant.
  • Après la suppression, un utilisateur de test Sign in with Apple ne voit plus votre app parmi les apps Sign in with Apple dans les réglages de son compte Apple.
  • L'app revient à un état déconnecté propre ; la rouvrir ne restaure pas l'ancienne session.
  • La page /delete-account s'ouvre sans connexion dans une fenêtre de navigation privée, et la demande envoyée par le formulaire arrive bien.
  • Appeler la route de suppression deux fois, ou après un échec simulé à mi-chemin, aboutit au même état propre.

Pièges

  • Désactiver au lieu de supprimer. Un indicateur deleted: true n'est pas une suppression au sens de la 5.1.1(v).
  • Les suppressions côté client via les règles de sécurité. Elles sont partielles par nature (pas de droits d'administrateur, pas d'utilisateur d'authentification, pas de références chez les autres utilisateurs) ; faites-le sur le serveur.
  • Supprimer d'abord l'utilisateur d'authentification. Si la requête échoue ensuite, les données se retrouvent orphelines et plus personne ne peut s'authentifier pour terminer le travail.
  • Les popups dans l'app. Si reauthenticateWithPopup se comporte mal dans la WebView, utilisez reauthenticateWithRedirect et lisez le résultat avec getRedirectResult.
  • Oublier les abonnements. Supprimer le compte n'arrête pas la facturation de l'App Store ou de Google Play ; prévenez l'utilisateur avant qu'il ne confirme.
  • Une page /delete-account derrière une connexion, ou une clé service role dans le code client sur Supabase. Les deux sont signalées très vite.

Questions fréquentes

Un délai de grâce est-il autorisé ?

Oui. Vous pouvez programmer la suppression définitive un peu plus tard (par exemple 14 jours) si vous l'indiquez dans la confirmation et dans la politique de confidentialité, et laisser l'utilisateur annuler en se reconnectant. La suppression elle-même doit tout de même avoir lieu.

Puis-je plutôt utiliser l'extension Firebase Delete User Data ?

C'est une bonne base : elle supprime les chemins Firestore et les fichiers Storage configurés quand l'utilisateur d'authentification est supprimé. Il vous faut quand même le bouton dans l'app, la révocation du token Apple, la page de demande publique et une vérification que sa configuration correspond à votre carte des données.

La page de demande web doit-elle supprimer automatiquement ?

Non. Google Play demande un moyen de solliciter la suppression en dehors de l'app. Un formulaire qui crée une demande que vous traitez ensuite est acceptable, à condition de la traiter réellement dans le délai que vous annoncez.

Dois-je aussi supprimer les données dans RevenueCat et Stripe ?

Supprimez ou anonymisez ce que vous n'avez pas besoin de conserver. Les données de paiement peuvent être soumises à des durées de conservation légales ; indiquez ce que vous conservez et pourquoi dans la politique de confidentialité. La résiliation des abonnements des stores reste une action de l'utilisateur.

Faut-il donner à Codex l'accès à ma base de données de production pour cela ?

Non. Codex écrit le code et les tests sur des émulateurs ou des mocks ; c'est vous qui exécutez la suppression en production via la route déployée. Gardez les identifiants de production hors des sessions d'agents et des environnements cloud.

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.

Voir les offres sur la page principale

Full Service

$698 par plateforme $798

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.

Détails du Full Service Propulsé par WeSetupYourWebViewApp

Prix Soldes d'hiver valables jusqu'au 31 décembre 2026.

Prêt à publier votre app ?

Garantie d'approbation App Store & Google Play – ou remboursement sous 14 jours

Vous préférez déléguer ? Full Service : nous configurons, compilons et livrons sous 72 heures, dès $698 par plateforme. Des questions ? Chattez avec nous 24/7.

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.