Bot de vente, tableau de bord d’administration et support IA
Boutique de guides vendus par bot de messagerie, back-office web et assistant de support qui cherche dans les guides avant de répondre.

En bref
- Problème
- Vendre mes guides par bot demande de tenir ensemble stock chiffré, paiements venus de plusieurs canaux, livraison et support, sans jamais livrer deux fois ni laisser une question sans réponse.
- Ce que j’ai réalisé
- Trois services TypeScript sur une base SQLite partagée : un bot de vente, un assistant de support adossé aux guides, et un back-office web à rôles, audit et 2FA.
- Résultat
- La réservation de stock et l’anti-rejeu des paiements tiennent dans une requête et un index ; l’assistant indexe les guides en fragments et trace chaque réponse avec son coût en jetons.
- Rôle
- Conception, architecture, orchestration et vérification.
- Équipe
- Projet individuel
- Statut
- Terminé
- Confidentialité
- Certains détails sont volontairement anonymisés.
Le back-office, écran par écran
Captures d’un serveur de démonstration alimenté par des données entièrement factices : aucun client réel, aucune boutique réelle, aucune commande réelle n’y figure.
Accès
, ouvrir la capture complèteConnexion L’accès au back-office passe par un e-mail et un mot de passe, ou par le compte de la plateforme du bot.
Vue d’ensemble
, ouvrir la capture complèteVue d’ensemble — indicateurs des deux bots Indicateurs du bot d’assistance et du bot de vente, courbes des sessions et du revenu sur un mois, répartition des résolutions.
Ventes
, ouvrir la capture complèteCommandes — liste filtrable et temps réel Chaque commande avec son client, son guide, son prix, l’état du paiement et de la livraison ; filtres par paiement, livraison, méthode, origine, guide et fondateur.
, ouvrir la capture complèteFiche commande — paiement, livraison et révélation du guide livré Client, produit, paiement et compte de réception en tête ; chaque exemplaire livré se révèle après vérification, et l’e-mail de paiement rapproché est joint.
, ouvrir la capture complèteStock — disponibilité par guide et variante Pour chaque guide, le disponible, le réservé et le livré, avec une jauge de disponibilité.
, ouvrir la capture complèteVariantes — paliers de prix et contenu produit Prix de base et prix par variante d’un guide, avec paliers dégressifs, stock, source et expiration ; seule l’édition des prix se fait ici.
, ouvrir la capture complèteRevenus — séries temporelles et répartition Revenu du jour, de la semaine, du mois et panier moyen, filtrables par méthode et compte de réception ; courbe cumulée et histogramme par méthode.
, ouvrir la capture complèteStatistiques de vente Conversion, paiements en attente, taux de rapprochement des webhooks ; revenu et commandes par jour, répartition par méthode, par guide et par fournisseur ; derniers e-mails non rapprochés.
Clients et paiements
, ouvrir la capture complèteClients — segmentation et historique Un client par ligne : commandes, revenu total, dernière commande, ancienneté et accès actifs ; filtres par minimum de commandes et de revenu.
, ouvrir la capture complèteFiche client — historique d’achat et fidélité Dépenses et accès actifs en tête, guides accordés avec leur date, puis l’historique complet des commandes du client.
, ouvrir la capture complèteComptes de réception — multi-fournisseurs Les comptes qui reçoivent les paiements, par fournisseur, avec adresse masquée, cible de courrier entrant, état et dernière utilisation ; chaque action est auditée et demande une ré-authentification.
Fondateurs
, ouvrir la capture complèteFondateurs — règlement des parts Règlement entre co-fondateurs : part de chacun, reçu, théorique et écart, historique des règlements, détail par méthode, transferts à effectuer et revenus par fondateur sur trois mois.
, ouvrir la capture complèteFondateurs — statistiques avancées Tableau croisé du revenu confirmé par fondateur et par méthode de paiement depuis le dernier règlement.
, ouvrir la capture complèteFondateurs — surcharges de parts par produit Une part spécifique peut être fixée pour un couple guide / fondateur ; elle s’applique aux commandes futures.
Fidélisation
, ouvrir la capture complèteCodes promo Chaque code avec sa réduction, ses utilisations, le revenu impacté, les économies accordées, son expiration et son statut.
, ouvrir la capture complèteCampagnes automatiques de fidélisation Règles de cadeau automatique : déclencheur, type, statut, dernière exécution et nombre d’attributions.
, ouvrir la capture complèteCampagne — règle de déclenchement et attributions Configuration d’une règle, son JSON brut de condition et d’action, et l’historique des cadeaux attribués, livrés ou échoués.
, ouvrir la capture complèteAvis clients — sollicitation post-livraison Après chaque livraison, le bot invite le client à laisser un avis puis le relance une fois ; salon, délais et message sont réglables.
Telegram
, ouvrir la capture complèteTelegram — support et tickets Système de tickets du bot de vente : activation, supergroupe de support, et catégories avec réponse FAQ, demande de référence et état.
, ouvrir la capture complèteTelegram — parcours d’accueil Génération d’un lien d’invitation signé qui lie un utilisateur à une boutique à la première ouverture ; le registre des liaisons est en lecture seule.
, ouvrir la capture complèteTelegram — annonces Composition d’un message riche (texte, citation, photo, boutons) avec aperçu ré-assaini avant publication.
, ouvrir la capture complèteTelegram — observabilité Indicateurs en lecture seule de la boutique : accès canaux actifs, refus de messages privés, file de notifications en attente ou en échec, incidents de bascule.
, ouvrir la capture complèteTelegram — drops et récompenses Drops promo de canal : les premiers membres qui réclament reçoivent un code à usage unique ; aucun drop n’existe encore.
, ouvrir la capture complèteCommandes de la boutique Telegram La liste des commandes d’une seconde boutique : mêmes filtres, produits et codes promo propres, recherche par référence ou identifiant client.
Assistant IA
, ouvrir la capture complèteAssistant IA — sessions de support Chaque session d’assistance avec son guide, sa catégorie, son état, son mode de résolution, sa durée et la note laissée.
, ouvrir la capture complèteConversation d’assistance — transcription et coût en jetons Guide, état, durée et jetons consommés en tête, retour de l’utilisateur, puis la transcription message par message avec le temps de réponse de l’assistant.
, ouvrir la capture complèteAssistant IA — statistiques Sessions par période, part résolue sans IA, temps moyen, jetons consommés, satisfaction ; sessions par jour et par guide, répartition des résolutions, heures de pointe et évolution de la satisfaction.
, ouvrir la capture complèteAssistant IA — guides indexés Chaque guide indexé avec sa version, sa description, le nombre de fragments, d’arbres de diagnostic, de rôles et d’accès.
, ouvrir la capture complèteGuide — fragments indexés et arbre de diagnostic Les fragments indexés d’un guide, classés par catégorie, avec leur taille ; onglets Diagnostic, Rôles, Prompt et Stats.
, ouvrir la capture complèteBase de connaissance Une entrée par problème connu avec sa solution, son guide, sa catégorie, son nombre d’utilisations, sa note et son statut ; recherche par mot-clé.
, ouvrir la capture complèteIncidents détectés Incidents actifs détectés à partir des signalements, avec description et nombre de reports, puis l’historique avec durée et date de résolution.
, ouvrir la capture complèteRetours utilisateurs Avis laissés après chaque session : part de positifs, de négatifs, avec commentaire ; chaque ligne renvoie à sa session.
Exploitation
, ouvrir la capture complèteAlertes Notifications automatiques classées par gravité : stock bas ou épuisé, commandes en attente, quota anti-fraude, erreurs IA, bot hors ligne.
, ouvrir la capture complèteUtilisateurs — rôles et isolation par boutique Comptes du back-office avec e-mail, rôle, 2FA, statut et dernière connexion ; la plateforme de chaque boutique est épinglée dans le registre.
, ouvrir la capture complèteConfiguration Vue en lecture seule des clés de configuration des deux bots : méthodes de paiement, minimums, grilles de prix par palier, relance d’avis, alertes de stock.
, ouvrir la capture complèteLogs applicatifs Visualisation en temps réel des logs des bots, filtrée par bot, domaine, boutique et niveau, avec défilement automatique.
Audit et sécurité
, ouvrir la capture complèteJournal d’audit Chaque action d’administration horodatée avec son auteur, sa ressource, ses détails et l’adresse d’origine.
, ouvrir la capture complèteAudit de sécurité Surface des événements de sécurité réservée au super-administrateur : filtres par action, utilisateur et période, export CSV.
, ouvrir la capture complèteParamètres du compte et 2FA Profil du compte connecté (nom affiché, e-mail, changement de mot de passe) et onglet de sécurité pour la double authentification.
Sommaire7 sections
Contexte
Projet personnel mené de mai à août 2026 : une boutique de mes propres guides numériques, vendus par bot de messagerie et administrés depuis un back-office web. Dans la boutique, un guide est une famille de produits : il regroupe plusieurs pièces d’un même lot, que l’acheteur choisit parmi ses variantes. Trois services TypeScript partagent un seul fichier SQLite en mode WAL : le bot de vente, l’assistant de support et le dashboard Next.js. La boutique vend par un bot Telegram ; le code est né sur Discord, et la version Telegram tourne comme quatrième service depuis un dépôt frère, sur la même base et le même back-office. Seul sur le projet, j’ai vérifié chaque livraison par le typage et par 307 fichiers de tests. Le projet est terminé depuis fin août : je n’y apporte plus que des correctifs et des vérifications, sans nouvelle fonctionnalité majeure.
Le problème
Pour chaque vente, le bot réserve un lot de stock chiffré, attend un paiement venu de l’un des canaux, puis livre le guide par message privé. Un virement ne porte pas de référence de commande : deux commandes au même prix sont indiscernables. Une ligne de stock peut partir deux fois si la livraison relit le stock par acheteur et non par commande : c’est arrivé une fois. Côté support, une question mal formulée échappe à une recherche par termes exacts.
Architecture et décisions
Dans la base commune, le bot de vente et l’assistant ont des tables disjointes : commandes et stock pour le premier, guides, sessions et connaissance pour le second. Le stock est chiffré en AES-256-GCM, clé dérivée par scrypt, dans un format d’enveloppe commun au bot et au dashboard. Le dashboard lit sur une connexion WAL en lecture seule, sans jamais bloquer sur une écriture du bot.
Un dépôt séparé porte une autre version du même back-office. Une seule table de transitions y décrit les machines à états des commandes et des paiements ; celle des commandes est à sens unique. Les montants y sont des entiers de centimes. Les écritures monétaires y passent par des transactions BEGIN IMMEDIATE, verrouillées en écriture dès l’ouverture. Des triggers SQLite y rendent le journal d’audit immuable. L’anti-rejeu figure parmi les invariants de son schéma. À la différence de la version décrite plus haut, le bot et le dashboard n’y partagent ni format d’enveloppe ni dérivation de clé ; un test de contrat a été écrit pour déchiffrer côté bot ce que chiffre le dashboard.
Stock et paiements
La réservation est un seul UPDATE … RETURNING : il réserve les lignes disponibles du guide et de la variante demandés et renvoie exactement celles qu’il a prises. Une ligne ne peut être livrée qu’après avoir été réservée. Depuis l’incident, la livraison relit les lignes par référence de commande.
Les paiements entrent dans une boîte de réception en base, puis un worker les apparie aux commandes par un score : confirmation automatique à partir de 0,8, revue manuelle à partir de 0,6, refus au-delà de 2 % d’écart de montant. Pour les virements, un sel de −5 à +5 centimes rend chaque total unique parmi les commandes en attente de paiement. La confirmation d’un virement exige un montant exact, un nom d’expéditeur reconnu et un candidat unique. Un index unique sur méthode et référence de paiement interdit de rejouer un paiement sur deux commandes.
Assistant de support, indexation et diagnostic
Une session traverse des états : accueil, diagnostic, qualification, IA active, puis résolu ou escaladé. Le diagnostic est un arbre de questions par guide et par catégorie, à feuilles de réponse ou d’escalade. Sinon, l’IA répond à partir des guides découpés en fragments versionnés et hachés. La recherche est hybride : BM25 sur un index FTS5 pour les termes exacts, cosinus sur des embeddings pour le sens, fusionnés par Reciprocal Rank Fusion ; sans vecteurs, le lexical seul sert.
Chaque message garde ses jetons d’entrée et de sortie et sa latence ; la fiche de session en fait la somme.
Une résolution devient un candidat pour la base de connaissance, dédupliqué par hachage, qu’un humain approuve ou rejette. Un incident s’ouvre quand cinq utilisateurs distincts signalent la même catégorie en quinze minutes, seuils réglables par boutique.
Exploitation, rôles, audit et 2FA
Quatre rôles ordonnés : super-administrateur, administrateur, gestionnaire, lecteur. L’isolation par boutique se tranche côté serveur, dans une table d’attributions. Le cookie de boutique choisit la boutique courante parmi celles attribuées au compte ; un cookie modifié n’ouvre l’accès à aucune autre. La connexion combine mot de passe haché par bcrypt et TOTP ; cinq échecs verrouillent le compte quinze minutes, et un secret 2FA en attente d’activation expire en dix minutes. Les actions sensibles (révéler un lot, supprimer, exporter) exigent une ré-authentification : un jeton de cinq minutes dans un cookie httpOnly, lié à l’utilisateur et à son IP. Chacune écrit dans le journal d’audit l’utilisateur, l’action, la ressource, un détail plafonné à 8 Ko et l’IP.
Le monitoring alerte, sans doublon, sur un stock à cinq lots ou moins, une commande en attente depuis une heure ou un bot silencieux depuis cinq minutes.
Ce que j’ai appris, ce que je referais
La réservation du stock repose sur un UPDATE conditionnel et l’anti-rejeu des paiements sur un index unique : la base de données tient ces deux garanties. L’incident de double livraison venait d’une requête correcte mais mal bornée.
La liaison du jeton de ré-authentification à une action précise est codée mais optionnelle : un jeton vaut cinq minutes pour toutes les actions. L’isolation stricte reste derrière un drapeau, avec un repli « toutes les boutiques » pour un compte sans attribution. Je câblerais la liaison par action et j’activerais l’isolation stricte par défaut. Le module d’achat dépasse 8 000 lignes ; je le découperais avant toute nouvelle fonctionnalité.


