Convex : internal vs public — ne pas exposer ce qu'on n'a pas à exposer

1 min read29 avril 2026#convex#sécurité#backend#typescript

Convex : internal vs public — ne pas exposer ce qu'on n'a pas à exposer

Par défaut, toute fonction Convex exportée avec export const est accessible depuis le frontend.

export const confirmPayment = mutation({ ... })
// → n'importe qui peut appeler api.payments.confirmPayment depuis le navigateur

Pour une fonction de confirmation de paiement, c'est un problème. Tu ne veux pas qu'un utilisateur puisse appeler ça directement depuis la console de son navigateur.


La distinction est simple :

// Accessible depuis le frontend — pour les vraies interactions utilisateur
export const getMyOrders = query({ ... });
 
// Accessible uniquement depuis le backend Convex — jamais depuis le client
export const confirmPayment = internalMutation({ ... });
export const sendNotification = internalAction({ ... });

La règle : tout ce qui modifie des données financières, des statuts critiques, ou des accès utilisateur → internal.

L'appel depuis le backend :

await ctx.runMutation(internal.payments.confirmPayment, { orderId });
// internal. au lieu de api.

api. → frontend peut appeler. internal. → backend seulement.

Si tu hésites entre les deux : demande-toi si tu serais à l'aise qu'un utilisateur curieux l'appelle depuis sa console. Si non — c'est internal.