# Les 6 choses que je vérifie avant de mettre une app construite avec l'IA en production

<p class="meta-line">Mik Bry · 2026-07-22 · lecture ~10 min · IA · Sécurité</p>

<div class="article-hero">

![Une main plane au-dessus d'un bouton de mise en production ; six signaux d'alerte restent discrets à l'arrière-plan.](/assets/2026-07-22-six-red-flags-hero.png)

</div>

Votre app tourne. Les pages s'affichent, l'inscription fonctionne, le paiement apparaît et la démo est convaincante.

C'est déjà beaucoup. Mais ce n'est pas la même chose qu'être prêt pour la production.

Dès qu'il y a de vrais utilisateurs, de l'argent et des données réelles, les questions changent. Je ne regarde plus seulement si le parcours prévu fonctionne. Je regarde ce qui se passe quand on change un numéro dans une URL, quand un paiement échoue à moitié, quand un script crée des centaines de comptes, quand une clé privée devient visible pour les visiteurs ou quand l'interface affiche « succès » alors qu'en réalité rien ne s'est passé derrière.

L'IA n'a pas inventé ces problèmes. J'ai fait certaines des mêmes erreurs bien avant qu'elle écrive du code pour moi. Ce qu'elle change, c'est la vitesse : on arrive beaucoup plus vite à un produit crédible, y compris dans des zones que personne n'a encore vraiment mises à l'épreuve.

Voici les six choses que je regarde en premier.

<div class="article-toc">
<div class="article-toc-label">Les six vérifications</div>

1. [Le paiement marche… sur le chemin prévu](#s1)
2. [Le serveur fait trop confiance au navigateur](#s2)
3. [Rien ne freine les abus](#s3)
4. [Des secrets se retrouvent là où ils ne devraient pas](#s4)
5. [La base de données ne protège pas forcément un client d'un autre](#s5)
6. [Un échec ressemble à un succès](#s6)

</div>

<h2 id="s1"><span class="section-no">01 —</span> Le paiement marche… sur le chemin prévu</h2>

Un écran de paiement peut donner l'impression que tout est terminé alors que le système ne l'est pas.

Les vérifications évidentes restent indispensables : êtes-vous en mode test ou en production ? La confirmation du prestataire de paiement revient-elle bien vers votre app ? L'application enregistre-t-elle correctement le résultat final ?

Mais je ne m'arrête pas à l'écran Stripe.

Je cherche aussi toutes les autres façons dont l'app peut considérer un compte comme payé, créer ou modifier un abonnement, ouvrir un accès ou changer son statut de facturation. Une intégration Stripe propre ne sert pas à grand-chose si un autre chemin caché dans l'app peut produire le même résultat sans les mêmes contrôles.

<div class="check-callout">
<div class="check-callout-label">Premier test · sans risque</div>

Ouvrez le tableau de bord de votre prestataire de paiement et vérifiez l'environnement utilisé. En mode test, utilisez ses cartes de test et vérifiez que l'application traite correctement les paiements réussis **et** les échecs. Si vous êtes déjà en production, planifiez un petit paiement remboursable plutôt que d'improviser avec une vraie transaction client.

Passer ce test ne prouve pas que le système de paiement est sûr. Il confirme simplement que le chemin le plus évident est correctement branché.

</div>

<p class="refs"><strong>Référence :</strong> <a href="https://docs.stripe.com/get-started/checklist/go-live?locale=en-GB">Stripe — checklist de mise en production</a> couvre notamment le passage test/production, les webhooks de production, les événements retardés ou dupliqués, les clés API et les cas limites.</p>

<h2 id="s2"><span class="section-no">02 —</span> Le serveur fait trop confiance au navigateur</h2>

L'interface sait quelle facture, quel projet ou quel compte vous regardez. Ça ne veut pas dire que le serveur a vérifié que vous aviez le droit d'y accéder.

Le cas classique est simple : vous ouvrez `/facture/42`, vous remplacez `42` par `41`, et l'application vous renvoie la facture de quelqu'un d'autre.

L'app ne doit jamais considérer qu'une information est fiable simplement parce qu'elle vient du navigateur du visiteur. Ce que le navigateur envoie peut être modifié.

<div class="check-callout">
<div class="check-callout-label">Premier test · sans risque</div>

Créez deux comptes de test que vous contrôlez. Connectez-vous avec le premier et essayez d'ouvrir une donnée appartenant au second en changeant le numéro ou le code visible dans l'URL. Une application correctement protégée refuse. Si elle renvoie les données de l'autre compte, arrêtez-vous là : vous avez déjà trouvé le problème.

</div>

<p class="refs"><strong>Référence :</strong> <a href="https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html">OWASP — Insecure Direct Object Reference Prevention</a> recommande précisément ce type de test : utiliser deux comptes et vérifier que l'un ne peut pas accéder aux objets de l'autre en modifiant une référence.</p>

<h2 id="s3"><span class="section-no">03 —</span> Rien ne freine les abus</h2>

Un formulaire qui fonctionne une fois peut parfois être appelé dix mille fois.

L'inscription est le cas évident, mais le même problème existe pour la récupération de mot de passe, les invitations, l'envoi de fichiers, les e-mails, les codes de connexion à usage unique et les fonctions reliées à un fournisseur d'IA.

Ce dernier cas mérite une attention particulière. Si votre app envoie des requêtes à OpenAI, Anthropic, Mistral ou un autre service en utilisant votre compte, un attaquant peut parfois se servir de votre app comme relais et déclencher des requêtes payantes à vos frais. Une fonction IA mal protégée peut donc transformer un abus en vraie facture.

Sans protection qui ralentit ou bloque les usages répétitifs et suspects, une fonctionnalité anodine en démo peut devenir très coûteuse.

<div class="check-callout">
<div class="check-callout-label">Premier test · sans risque</div>

Utilisez uniquement des comptes et adresses que vous contrôlez et répétez plusieurs fois la même action. Est-ce qu'une limite apparaît ? Une confirmation ? Un délai ? Un refus face à une répétition évidente ? Si rien ne freine jamais, ça mérite une vraie revue — surtout pour une fonction qui vous coûte de l'argent à chaque utilisation.

</div>

<p class="refs"><strong>Référence :</strong> <a href="https://owasp.org/API-Security/editions/2023/en/0xa4-unrestricted-resource-consumption/">OWASP API Security — Unrestricted Resource Consumption</a> recommande de limiter la fréquence des appels et de configurer des limites de dépense chez les fournisseurs, car des appels répétés peuvent consommer des ressources payantes et avoir un impact business.</p>

<h2 id="s4"><span class="section-no">04 —</span> Des secrets se retrouvent là où ils ne devraient pas</h2>

Une clé privée copiée par erreur dans des fichiers partagés avec le code. Un mot de passe de base de données qui apparaît dans des journaux techniques. Une clé de paiement de production envoyée au navigateur de chaque visiteur.

Ce sont des erreurs simples à créer et presque invisibles tant que l'app fonctionne.

Les outils d'IA peuvent connecter des services très vite. Ça ne garantit pas qu'ils rangent toujours les clés privées au bon endroit.

<div class="check-callout">
<div class="check-callout-label">Premier test · sans risque</div>

Demandez où sont stockées les clés utilisées pour les paiements, la base de données, l'e-mail ou les services d'IA, et si certaines sont envoyées au navigateur d'un visiteur ou incluses dans des fichiers accessibles à d'autres personnes.

Vous pouvez aussi regarder ce que reçoit votre navigateur, ou demander à quelqu'un de technique de le faire. Ne rien trouver ne prouve pas que tout est sûr : ce test sert seulement à repérer les erreurs les plus évidentes.

</div>

<p class="refs"><strong>Références :</strong> <a href="https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html">OWASP — Secrets Management</a> explique pourquoi les clés API et identifiants de base de données ne doivent pas être écrits en clair dans le code ou dispersés dans des fichiers de configuration. <a href="https://docs.github.com/en/code-security/concepts/secret-security/secret-scanning">GitHub — Secret scanning</a> documente les risques liés aux clés, mots de passe et jetons exposés dans un dépôt.</p>

<h2 id="s5"><span class="section-no">05 —</span> La base de données ne protège pas forcément un client d'un autre</h2>

Une interface propre peut cacher un problème sérieux : l'écran ne montre que vos données, mais le système derrière peut malgré tout laisser passer celles de quelqu'un d'autre.

Des services comme Supabase permettent d'imposer directement une règle du type : « ce client ne peut lire que ses propres données ». D'autres systèmes appliquent la même protection ailleurs.

La technologie utilisée n'est pas le plus important. Ce qui compte, c'est que cette protection existe à un endroit que le visiteur ne peut pas contourner.

<div class="check-callout">
<div class="check-callout-label">Premier test · sans risque</div>

Ouvrez la partie sécurité de votre base de données ou de votre hébergeur et regardez s'il signale des problèmes d'accès aux données clients. Si vous utilisez Supabase, son Security Advisor et les règles de sécurité au niveau des lignes sont de bons points de départ. Ensuite, faites un test avec deux comptes que vous contrôlez : l'un ne doit jamais pouvoir lire les données de l'autre.

</div>

> **Mon conseil :** des outils comme Supabase sont très pratiques pour construire vite. Ils regroupent la base de données, la connexion des utilisateurs, le stockage de fichiers et d'autres services au même endroit.
>
> Pour un produit qui a vocation à durer et à grossir, je préfère généralement garder la base de données plus indépendante du reste. Concrètement, cela peut vouloir dire utiliser un service PostgreSQL managé comme Neon ou AWS, et laisser l'application y accéder via son propre serveur.
>
> Pourquoi ? Parce que si le produit fonctionne, vous voudrez peut-être changer la gestion des comptes, déplacer une partie de l'application, ajouter d'autres services ou simplement mieux maîtriser le coût de la base. Garder cette brique indépendante donne plus de liberté pour la suite.
>
> Cela ne veut **pas** dire que Supabase est un mauvais choix ou qu'il sera toujours plus cher. C'est souvent un excellent outil pour construire un MVP. Mon point est simplement que la simplicité du départ peut devenir une dépendance plus tard, donc je préfère faire ce choix en connaissance de cause.

<p class="refs"><strong>Références :</strong> <a href="https://supabase.com/docs/guides/database/postgres/row-level-security">Supabase — Row Level Security</a> indique que la RLS est activée par défaut pour les tables créées avec le Table Editor du Dashboard, mais qu'elle doit être activée explicitement pour les tables créées en SQL ou via le SQL Editor. Supabase recommande aussi d'activer la RLS sur les tables des schémas exposés. Sa <a href="https://supabase.com/docs/guides/deployment/going-into-prod">checklist de production</a> recommande de vérifier le Security Advisor et les politiques RLS avant la mise en production.</p>

<h2 id="s6"><span class="section-no">06 —</span> Un échec ressemble à un succès</h2>

C'est un problème facile à rater parce que l'interface peut être parfaite.

Le paiement affiche « succès », mais rien n'a été enregistré. Le formulaire devient vert, mais le message n'est jamais parti. L'upload se termine, mais le fichier n'existe pas. L'animation est finie, alors que l'opération réelle derrière a échoué.

Dans les apps construites avec l'IA que je relis, les échecs sont souvent beaucoup moins testés que le parcours normal qui fonctionne.

<div class="check-callout">
<div class="check-callout-label">Premier test · sans risque</div>

Utilisez des valeurs invalides mais sans conséquence et des situations prévues pour échouer. Envoyez un fichier vide. Saisissez une valeur négative là où elle n'a aucun sens. Faites un paiement de test prévu pour être refusé. L'app doit refuser clairement, sans laisser derrière elle des données à moitié enregistrées.

Un message vert n'est pas une preuve que l'opération a réussi.

</div>

<p class="refs"><strong>Références :</strong> <a href="https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html">OWASP — Input Validation</a> recommande de vérifier à la fois la forme des données et leur cohérence métier. <a href="https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html">OWASP — Error Handling</a> recommande de traiter explicitement les cas d'échec afin de ne pas laisser l'application dans un état imprévisible.</p>

<aside class="lr-callout">
  <div class="lr-callout-icon" aria-hidden="true"></div>
  <div class="lr-callout-body">
    <p class="lr-callout-eyebrow">Première lecture automatique</p>
    <p class="lr-callout-text">Avant de demander une revue CTO, vous pouvez commencer par le <a href="https://mikbry.com/pret-a-lancer/">Launch Readiness Scan</a>. Il donne une première lecture automatique, mais ne voit ni votre environnement de production ni le contexte métier.</p>
  </div>
</aside>

## Avant de mettre en production

Posez-vous six questions simples :

- **Paiements :** l'état réel du paiement a-t-il été vérifié, y compris les échecs et les chemins adjacents qui peuvent ouvrir un accès payant ?
- **Accès :** un compte de test peut-il ouvrir les données d'un autre ?
- **Abus :** qu'est-ce qui empêche un script de répéter une opération sensible ou coûteuse — notamment une fonction qui appelle un service d'IA que vous payez ?
- **Secrets :** savez-vous où sont stockées vos clés de production et qui peut les lire ?
- **Données :** existe-t-il une règle, hors du contrôle du visiteur, qui sépare réellement les données de chaque client ?
- **Échecs :** quand une opération échoue, le produit échoue-t-il vraiment proprement au lieu de seulement changer l'interface ?

Si une réponse est « je ne sais pas », vous avez trouvé quelque chose à vérifier. Pas forcément une catastrophe.

La nuance est importante.

<section class="cta-offers">
  <div class="cta-offers-head">
    <span class="eyebrow">Si vous voulez aller plus loin</span>
    <p class="cta-offers-lead">Je relis des applications construites avec l'IA ou en vibe coding avant leur mise en production.</p>
  </div>

  <div class="price-card price-card--featured price-card--solo">
    <span class="price-pill">Commencer ici</span>
    <div class="price-card-body">
      <div class="price-name-row">
        <span class="price-icon" aria-hidden="true"></span>
        <span class="price-name">Trust Report</span>
      </div>
      <p class="price-desc">Une revue automatisée de votre app et de son code, réalisée avec mes outils d'analyse. Vous obtenez les principaux risques, ce qui mérite l'attention avant le lancement et ce qui peut attendre. Si vous souhaitez parcourir les résultats ensemble, une revue avec moi est disponible en option.</p>
    </div>
    <div class="price-card-right">
      <div class="price-row">
        <span class="price-amt">349 €</span>
        <span class="price-note">une fois</span>
      </div>
      <a class="cta-btn cta-btn-accent" href="/pret-a-lancer/">Obtenir le vôtre</a>
    </div>
  </div>

  <div class="audit-strip">
    <div class="audit-icon-tile" aria-hidden="true"></div>
    <div class="audit-text">
      <div class="audit-label">Audit — besoin d'une revue plus approfondie ?</div>
      <p class="audit-desc">Architecture, paiements, accès, données clients, garde des clés de déploiement, logiciels tiers, et une recommandation de mise en production documentée par un CTO humain.</p>
    </div>
    <span class="audit-price">à partir de 1 200 €</span>
    <a class="cta-btn cta-btn-outline" href="mailto:hello@mikbry.com">Contacter Mik</a>
  </div>
</section>

Les six vérifications ci-dessus constituent un bon premier filtre. Elles peuvent faire ressortir des problèmes évidents, mais elles ne peuvent pas vous montrer ce que vous ne savez pas encore qu'il faut tester.

Si l'app s'apprête à gérer de vrais utilisateurs, de l'argent ou des données sensibles, c'est précisément là qu'un regard technique expérimenté devient utile.
