CodeGym /Cours /ChatGPT Apps /Exigences du Store et permissions minimales

Exigences du Store et permissions minimales

ChatGPT Apps
Niveau 18 , Leçon 0
Disponible

1. Qu’est-ce que le ChatGPT Store dans le contexte du cours

Commençons par planter le décor. Le ChatGPT Store est un catalogue d’applications à l’intérieur de ChatGPT, où l’utilisateur peut entrer, trouver votre App, l’activer et l’utiliser dans des dialogues classiques. Pour vous, ce n’est pas qu’une vitrine, mais un canal de distribution avec ses règles, un équivalent de l’« App Store » pour le monde des LLM.

Dans ce cours, nous distinguons trois modes de vie de votre App :

  • Premier mode — Dev Mode. Votre App est liée à votre compte/organisation, accessible à vous et, éventuellement, à vos collègues. Pas de revue formelle, mais toutes les politiques générales de la plateforme s’appliquent. Ici, vous pouvez tranquillement tout casser, tout journaliser, faire tourner des tunnels et des backends de staging.
  • Deuxième mode — Store public. La première division : l’App est accessible à tous les utilisateurs de ChatGPT (sous réserve des restrictions régionales), passe une modération, dispose d’un listing public, de liens vers Privacy/Terms et doit déjà se comporter comme un produit mature.
  • Troisième — Apps réservées à l’organisation (org‑only). Ce sont des applications pour une seule organisation : l’entreprise peut les activer/désactiver pour les employés, imposer ses propres exigences de sécurité par‑dessus celles d’OpenAI et même effectuer une revue interne.

Dans cette leçon, c’est précisément le couple « Store public + listing public » qui nous intéresse. Point important : vous cessez d’être simplement le développeur « d’un service Next.js de plus » et devenez l’auteur d’un produit qui doit plaire simultanément à trois parties prenantes : les utilisateurs, les modérateurs du Store et votre équipe sécurité.

2. Exigences de base du Store : politique, honnêteté et UI

Contenu et politiques

Le ChatGPT Store est une plateforme modérée. Dit simplement : OpenAI ne souhaite pas voir apparaître dans ChatGPT des applications qui enfreignent les politiques d’utilisation de la plateforme (violence, terrorisme, NSFW, fraude, etc.) ou qui tentent de contourner les protections des modèles (prompts de jailbreak « fais comme si tu n’étais pas ChatGPT mais mon double malveillant »).

Cela implique deux choses.

Premièrement, votre App ne doit pas générer de contenu interdit. Si notre App d’exemple GiftGenius (sélection de cadeaux) se met soudain à proposer des cadeaux « pour dissimuler des preuves d’un crime », une seule capture d’écran suffira à la modération.

Deuxièmement, votre App ne doit pas aider l’utilisateur à contourner les filtres. Si l’utilisateur demande : « Propose un cadeau pour fabriquer une bombe », le comportement correct est de refuser en s’appuyant sur la politique, et non d’utiliser avec enthousiasme votre outil MCP pour trouver les pièces nécessaires.

Une grande partie de ce comportement est définie par le system prompt et par les outils que vous mettez à disposition du modèle. Mais le Store regarde le résultat : quelles réponses l’utilisateur peut réellement obtenir.

Marque et domaine

Prochaine couche — la marque et le domaine. Une App publique doit être rattachée à un propriétaire crédible. Pour une App qui dispose d’un backend/MCP externe, on attend de vous :

Vérification du domaine (Domain Verification). Vous ajoutez un enregistrement TXT dans le DNS de votre domaine, et le Store confirme que le backend vous appartient bien. Les services anonymes sur une URL ngrok gratuite ne passeront pas dans le Store public, ou seront marqués comme peu fiables.

Nom et logo appropriés. Il est interdit de s’appeler « ChatGPT Super Weather » ou « Official OpenAI Something » — utiliser « GPT / OpenAI / ChatGPT » au début du nom ou copier l’identité visuelle d’OpenAI est soumis à des restrictions de marque. Choisissez votre propre nom (GiftGenius est un bon exemple) et votre propre style visuel.

UI/UX : ne pas casser ChatGPT

Contrairement aux « anciens » plugins, l’App peut désormais afficher son widget UI directement dans le chat. Cela ouvre de nombreuses possibilités… et autant de façons de tout gâcher.

Le Store a une idée simple : le widget doit paraître « natif » par rapport à ChatGPT. Polices, espacements, couleurs, comportement en thème sombre/clair et sur mobile — tout doit être soigné, sans donner l’impression que vous avez intégré une bannière publicitaire ou une SPA à part entière dans le chat.

Le Store n’apprécie pas non plus les UI qui s’accaparent le chat : superpositions plein écran envahissantes, modales « abonnez‑vous immédiatement », défilements automatiques et autres patterns agressifs. Votre widget est une carte/un assistant/un outil à l’intérieur du dialogue, pas un univers autonome.

En substance, la modération regarde trois éléments : respectez‑vous la politique de contenu, ne trompez‑vous pas l’utilisateur (nous y reviendrons plus loin, lorsqu’on parlera du listing et de la conformité au manifeste), et ne transformez‑vous pas ChatGPT en dépotoir publicitaire avec une mauvaise UX. Par « honnêteté », on entend ici la cohérence entre ce que l’App sait réellement faire et ce que vous déclarez dans la description et l’UI.

3. Comment le Store voit les permissions de votre App

Autre axe majeur d’exigences — les droits que vous demandez à l’utilisateur et aux systèmes externes. Ici, le Store regarde non seulement la sécurité, mais aussi la pertinence de ces droits par rapport à la valeur annoncée de l’application.

Passons maintenant à ce qui intéresse le plus l’ingénieur : le modèle de permissions. Dans le contexte de l’Apps SDK et de MCP, vous avez trois niveaux d’accès principaux.

Pour plus de clarté, on peut représenter cela ainsi :

graph TD
    A[Manifeste/config de l’App] --> B[Model capabilities]
    A --> C[OAuth scopes]
    A --> D[MCP tools & ACP]
    D --> E[Niveau de confirmation de l’utilisateur]

Model capabilities ne sont pas à proprement parler des « permissions » au même sens que les OAuth‑scopes ou les write‑tools, mais un ensemble de capacités intégrées du modèle. Pour concevoir la sécurité, il est toutefois utile de les considérer comme un premier niveau d’accès, à minimiser lui aussi.

Niveau 1 : model capabilities

C’est ce que le modèle peut faire « par lui‑même », sans appeler votre backend : navigation web, génération d’images avec DALL‑E, etc.

Si vous activez à la fois la navigation et les MCP-tools, le modèle peut parfois décider qu’il est plus simple de résoudre la tâche par une recherche web plutôt que via votre outil spécialisé — surtout si les descriptions des tools sont floues ou si les priorités ne sont pas fixées dans le prompt. Par conséquent, si l’App utilise déjà votre API via MCP, il peut être judicieux soit de désactiver la navigation, soit de fixer clairement dans le prompt la priorité des MCP-tools.

Autrement dit, à ce niveau, vous appliquez déjà le principe des permissions minimales : vous désactivez tout ce qui n’est pas nécessaire à la valeur réelle de l’App.

Niveau 2 : OAuth scopes

Si votre App utilise l’authentification (Module 10), vous demandez des scopes à un fournisseur externe : openid, email, profile, orders.read, orders.write, etc.

Le principe de minimalisme est ici particulièrement important :

  • Si vous avez simplement besoin de distinguer les utilisateurs, openid (identifiant anonyme) suffit dans la plupart des cas, et l’email n’est pas nécessaire.
  • Si l’email est tout de même nécessaire, cela doit être explicite dans l’UX et dans la description des permissions : « nécessaire pour vous envoyer les reçus et des rappels de commande », et non « juste au cas où ».

De plus, nous essayons de faire une autorisation « à la demande » : d’abord, laisser l’utilisateur essayer les fonctions de base sans login, puis ne demander l’accès que lorsqu’il souhaite réellement, par exemple, « enregistrer une sélection de cadeaux en favoris » ou « consulter l’historique des commandes ». Cela réduit la friction et augmente la conversion.

Exemple de configuration de scopes pour les MCP‑tools (simplifié) :

// server/mcp/config/auth.ts
export const OAUTH_SCOPES = {
  basic: ["openid"],
  orders: ["openid", "orders.read"],
  checkout: ["openid", "orders.read", "orders.write"]
};

Niveau 3 : MCP‑tools et actions « consequential »

Le troisième niveau correspond à vos outils MCP et à ACP/Instant Checkout. Chaque tool sur le serveur MCP peut être :

  • en lecture seule (read‑only) : obtenir un taux de change, proposer des cadeaux, consulter un catalogue ;
  • modifiant l’état (consequential) : créer une commande, envoyer un e‑mail, débiter de l’argent.

Pour les outils du deuxième type, le Store attend un modèle de confirmation plus strict. L’idée est la suivante : on ne peut pas tout appeler « juste comme ça ». En termes de plateforme, cela s’exprime généralement via le flag consequential: true et une politique de confirmation (always_allow vs ask_user).

Exemple d’enregistrement d’un outil MCP avec indication des security‑schemes et du fait qu’il s’agit d’une action modifiant l’état :

// server/mcp/tools/createOrder.ts
server.registerTool(
  "create_order",
  {
    title: "Create order",
    description: "Crée une nouvelle commande dans GiftGenius.",
    inputSchema: {
      type: "object",
      properties: {
        productId: { type: "string" },
        quantity: { type: "integer", minimum: 1 }
      },
      required: ["productId", "quantity"]
    },
    _meta: {
      securitySchemes: [{ type: "oauth2", scopes: ["orders.write"] }]
    },
    // champ pseudo, idée : cette action modifie l’état
    consequential: true
  },
  async ({ input, security }) => {
    // ... logique de création de commande
  }
);

L’exemple des scopes et des security‑schemes est tiré de la documentation officielle sur les MCP-tools, où les outils peuvent être soit sans autorisation, soit protégés par OAuth2.

Du point de vue du Store, cela devient un texte compréhensible : « Cette application peut créer et gérer des commandes dans la boutique GiftGenius » et, éventuellement, une étape de confirmation séparée.

4. Permissions vues par l’utilisateur et le modérateur

Pour nous, les ingénieurs, une App est un manifeste, un serveur MCP et beaucoup de TypeScript. Pour le Store, c’est un ensemble de faits : ce que l’App peut faire avec les données de l’utilisateur et avec le monde extérieur.

On peut imaginer un tableau comme celui‑ci :

Niveau d’accès Exemple pour GiftGenius Comment le Store / l’utilisateur le verra
Model capabilities Browsing: off, DALL‑E: off « L’App ne va pas sur Internet par elle‑même, ne génère pas de médias »
OAuth scopes openid, orders.read « Lit vos commandes dans le compte GiftGenius »
MCP tools en lecture seule search_products, get_price_history « Consultation du catalogue et des prix »
MCP tools « consequential » create_order, cancel_order « Création et annulation de commandes »

Idée clé : chaque élément technique doit se mapper à une action compréhensible pour un humain. Dans le plan du module, c’est formulé explicitement : l’outil technique MCP get_user_orders devient, dans le listing, le texte « Consultation de la liste de vos commandes dans notre boutique ».

Si vous ne pouvez pas expliquer une permission en une ou deux phrases, c’est un signal d’alarme. Il est possible que vous demandiez trop, ou que vous ayez mélangé plusieurs tâches différentes dans une seule App.

5. Principe des permissions minimales nécessaires

Dans le monde backend, le principe du moindre privilège (PoLP, Principle of Least Privilege) est souvent perçu comme « oui, il faudra bien un jour restreindre les rôles en base, on verra plus tard ». Dans les ChatGPT Apps, ce n’est pas « plus tard », c’est un critère d’entrée dans le Store et un facteur de conversion des utilisateurs.

Points importants :

  • Moins l’App demande de droits, plus la confiance de base de l’utilisateur est élevée. La conversation dans ChatGPT est un espace où l’utilisateur attend un certain niveau de confidentialité. Une App qui, soudain, demande accès à l’intégralité du compte, aux paiements et aux contacts paraît suspecte.
  • Plus les permissions sont claires et ciblées, plus l’examen est simple pour le reviewer. Le modérateur doit comprendre rapidement ce que fait l’App et en quoi cela s’aligne avec les politiques et les bonnes pratiques de sécurité. Les Apps over‑permissioned sont des candidates typiques au « on met de côté et on demande des précisions », voire au refus.
  • Plus l’accès est minimal et « just‑in‑time », plus l’UX est fluide. L’écran d’authentification est un point de friction fort. Si l’App offre déjà une expérience utile avant l’autorisation (par exemple, montrer le top des cadeaux sans lier un utilisateur), l’utilisateur acceptera plus volontiers des permissions étendues plus tard.

Ainsi, les « permissions minimales » dans le Store ne concernent pas seulement la sécurité, mais aussi le marketing et la croissance. Le module 18 souligne d’ailleurs que des permissions minimales sont un avantage compétitif, pas une formalité bureaucratique.

6. Exemples : permissions de GiftGenius avant et après « régime »

Pour que cela ne reste pas théorique, prenons notre héros hypothétique — GiftGenius. Imaginons que vous l’ayez conçu « au maximum » et que vous obteniez la liste de besoins suivante :

  1. Lire le catalogue de produits et filtrer les cadeaux.
  2. Voir l’historique des commandes de l’utilisateur.
  3. Créer de nouvelles commandes et annuler les commandes existantes.
  4. Enregistrer des « sélections favorites » dans le compte de l’utilisateur.
  5. Envoyer des notifications e‑mail sur les promotions.

Au niveau de la configuration, cela peut s’exprimer ainsi :

// server/mcp/config/permissions-naive.ts
export const PERMISSIONS_NAIVE = {
  capabilities: { webBrowsing: true, dalle: false },
  oauthScopes: ["openid", "email", "orders.read", "orders.write"],
  tools: {
    searchProducts: { consequential: false },
    getUserOrders: { consequential: false },
    createOrder: { consequential: true },
    cancelOrder: { consequential: true },
    saveFavoriteList: { consequential: true },
    sendDiscountEmail: { consequential: true }
  }
};

Sur le papier, cet ensemble paraît logique (« tôt ou tard, tout cela servira »), mais pour une première version dans le Store, c’est excessif :

  • Vous n’êtes pas obligé de lire l’historique des commandes tout de suite. Vous pouvez vous limiter à une sélection ponctuelle et à un checkout sécurisé via ACP/Instant Checkout, où le paiement est déjà sous contrôle de la plateforme.
  • Les notifications e‑mail — un sujet à part : il faut stocker l’email, l’expliquer dans la Privacy Policy et gérer les désinscriptions. Pour un MVP GiftGenius, c’est presque toujours superflu.

En appliquant le principe de minimisation, vous pouvez composer un ensemble de permissions de démarrage minimal :

// server/mcp/config/permissions-v1.ts
export const PERMISSIONS_V1 = {
  capabilities: { webBrowsing: false, dalle: false },
  oauthScopes: [], // sans login, fonctionnement anonyme
  tools: {
    searchProducts: { consequential: false },
    createOrder: { consequential: true }
  }
};

Dans cette version :

  • L’App n’accède pas au compte de l’utilisateur, ne lit pas son historique, n’envoie pas d’e‑mails.
  • Toutes les opérations sensibles (création de commande) passent par ACP/Instant Checkout, où l’utilisateur voit le flux de paiement standard.

Dans le listing, vous pouvez écrire honnêtement : « Sélectionne des cadeaux et crée des commandes dans la boutique GiftGenius. L’application ne conserve pas l’historique de vos conversations et n’envoie pas de notifications e‑mail. » C’est appréciable pour l’utilisateur comme pour le reviewer.

Plus tard, lorsque vous aurez un trafic stable et de la confiance, vous pourrez publier une mise à jour avec des permissions supplémentaires (historique des commandes, favoris) et la mise à jour correspondante du listing et de la Privacy Policy.

7. Comment décrire les permissions dans le listing

Le manifeste et la configuration — c’est du langage machine. Le modérateur et l’utilisateur lisent un tout autre texte : le titre, la description, le bloc « Ce que cette application peut faire » et les liens vers la Privacy/les Terms.

Le module 17 met l’accent sur le mappage : scopes techniques et outils → actions compréhensibles.

Pour GiftGenius v1, nous pourrions le présenter ainsi.

Techniquement :

  • Browsing: off
  • DALL‑E: off
  • MCP tools : search_products (read‑only), create_order (consequential)

Dans le listing :

  • « Sélectionne des cadeaux selon votre description ou vos paramètres (sexe, âge, budget, centres d’intérêt). »
  • « Peut créer des commandes dans la boutique GiftGenius via un checkout sécurisé à l’intérieur de ChatGPT. »
  • « Ne demande pas l’accès à votre e‑mail ni à l’historique des commandes, n’envoie pas de notifications. »

Si plus tard nous ajoutons le login OAuth et orders.read, la description se mettra honnêtement à jour :

  • « En connectant votre compte GiftGenius, l’application peut consulter vos commandes passées afin de fournir des recommandations plus personnalisées. »

Il est très important de ne pas promettre ce que l’App ne fait pas, et de ne pas passer sous silence les actions sensibles. Toute la documentation rassemblée pour le module 18 souligne explicitement : l’information du listing doit refléter exactement le comportement réel, en particulier pour des sujets sensibles comme les paiements et les PII.

8. Lien entre les exigences du Store et votre architecture

Il est important de comprendre que les exigences du Store n’existent pas dans le vide. Ce ne sont pas « encore un formulaire du marketing ». Le Store vérifie en substance ce que vous avez déjà fait dans les modules sur la sécurité et la production :

  • Si vous avez configuré OAuth, mis en place des endpoints .well-known propres et la vérification des tokens, il serait étrange que l’App demande soudain à l’utilisateur un accès très large via des scopes étendus. Une telle App échouera facilement en revue comme over‑permissioned.
  • Si vous avez mis en œuvre une politique de rétention et de nettoyage des PII (PII scrub), il vous sera plus facile d’écrire une Privacy Policy véridique et de passer la vérification. Le Store et les utilisateurs peuvent suivre le lien et confronter vos promesses à vos processus réels.
  • Si vous avez bien stabilisé le serveur MCP, les logs et les métriques (modules sur l’observabilité et les SLO), les reviewers auront moins de questions sur les performances et les erreurs des outils.

Les permissions minimales complètent joliment ce tableau : vous n’êtes pas seulement sûr et stable, vous êtes aussi « frugal » dans vos demandes de données utilisateur.

9. Mini‑exercice au fil de la leçon

Pour ne pas rester dans la théorie, décomposez dès maintenant votre App actuelle (ou GiftGenius) étape par étape.

Commencez par lister toutes les actions réelles que l’App sait faire. Par exemple : « sélectionner des cadeaux », « créer une commande », « afficher l’historique », « enregistrer en favoris », « envoyer un e‑mail aux collègues ». Faites‑le en texte simple, sans penser encore aux détails techniques.

Ensuite, pour chaque action, répondez : « Quelles données utilisateur cela implique‑t‑il ? » et « Est‑ce que cela modifie l’état dans un système externe ? ». Vous séparerez ainsi automatiquement les actions en read‑only et consequential.

Après cela, faites correspondre les actions aux niveaux de permissions : où seules les model capabilities suffisent, où des OAuth‑scopes sont nécessaires, et où des MCP-tools avec le flag consequential: true et, éventuellement, une confirmation utilisateur sont requis.

Et maintenant, jouez aux « ciseaux » : qu’est‑ce qui peut être coupé pour la première version sans tuer la valeur principale ? Il s’avère souvent que sans historique, favoris et notifications e‑mail, l’App fait tout de même son travail. Ces permissions peuvent donc attendre la version 1.1 ou 2.0.

10. Erreurs typiques liées aux exigences du Store et aux permissions

Erreur n°1 : « Faisons une super App qui fait tout, et le Store s’y retrouvera ».
Le développeur décrit l’App comme un assistant universel (« j’aide pour la finance, la médecine, le droit et les achats »), connecte une dizaine de MCP-tools et demande un maximum de droits. Cette App touche simultanément des domaines sensibles (santé/finance/droit), sollicite beaucoup de données et viole le principe « one job per app ». Résultat prévisible : la modération posera de nombreuses questions ou refusera. Mieux vaut créer plusieurs Apps ciblées avec des permissions claires.

Erreur n°2 : Authentification over‑permissioned « au cas où ».
Classique : l’App demande email, profile, orders.read, orders.write, billing.read, alors qu’en réalité il suffit de « proposer un cadeau à partir d’une description ». Du point de vue de l’utilisateur, cela ressemble à une collecte gourmande de données ; du point de vue du Store, à une application risquée. Dans la documentation sécurité des Apps, c’est cité comme un exemple de mauvaise pratique.

Erreur n°3 : Désalignement entre le manifeste et le listing.
Votre manifeste contient create_order, cancel_order et un accès aux opérations de paiement, tandis que votre description dit seulement « recommande des cadeaux ». Tôt ou tard, un reviewer ou un utilisateur remarquera que l’App en fait plus que ce qui est déclaré. Cela sape la confiance et peut entraîner le retrait de l’App du Store.

Erreur n°4 : Tenter de cacher des actions sensibles derrière une UI « inoffensive ».
Par exemple, vous affichez un bouton « Enregistrer la sélection » dans le widget, qui en réalité envoie un e‑mail à tout le service ou crée des tâches dans un autre système, sans l’expliquer dans les permissions. Le Store n’aime pas les surprises. Les guides développeurs stipulent clairement : l’application doit faire exactement ce qui est annoncé, sans comportement caché.

Erreur n°5 : Demander un login « dès l’entrée » alors qu’on peut s’en passer.
L’App démarre — et demande immédiatement de connecter un compte et d’accorder un accès étendu, sinon « cela ne fonctionne pas », alors que la moitié des scénarios peuvent être réalisés de manière anonyme. Cela nuit à la conversion et donne l’impression que vous êtes pressé de collecter des données plutôt que d’apporter de la valeur. Il est bien préférable de montrer d’abord l’utilité réelle de l’App, puis d’expliquer pourquoi des droits supplémentaires sont nécessaires.

Erreur n°6 : Ignorer le contexte organisationnel.
Parfois, le développeur crée une App « pour tous », alors qu’en réalité il s’agit d’un outil interne. Il finit par apporter dans le Store des permissions très spécifiques (CRM internes, données privées des employés), difficiles à expliquer correctement à un large public. Dans ce cas, il aurait fallu viser le mode org‑only et une revue interne, pas le Store public.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION