TokenHub par FNB Solutions : canonicaliser des catalogues de produits numériques à grande échelle

Comment TokenHub normalise les catalogues fragmentés de fournisseurs régionaux en entités stables et auditables pour les prix, le routage et l'analytique.

Points clés

  • TokenHub est l'infrastructure de commerce numérique que FNB Solutions a construite pour vendre des jetons de jeux numériques via des revendeurs locaux. Elle agrège les catalogues de 12 fournisseurs.
  • La canonicalisation transforme plus de 40 000 références fournisseurs en environ 3 100 produits canoniques stables, si bien que les prix, le routage et l'analytique reposent sur un seul modèle.
  • Le pipeline est déterministe et atomique : des entrées identiques produisent toujours des sorties identiques, et chaque cycle est validé en une seule transaction, sans jamais d'état partiel.
  • L'intégration d'un nouveau fournisseur prend environ 3 jours au lieu de 3 semaines environ, car la curation antérieure et les règles apprises sont reprises automatiquement.

Introduction

TokenHub est l'épine dorsale données et commerce de FNB Solutions pour distribuer et vendre des jetons de jeux numériques au sein d'un écosystème de fournisseurs très fragmenté.
La plateforme opère dans des régions où l'infrastructure de paiement mondiale est inégale et où les revendeurs locaux restent le pilier du commerce numérique. En reliant ces commerçants aux fournisseurs numériques, TokenHub permet aux clients d'acheter des jetons dans des boutiques locales de confiance grâce à des soldes prépayés, tout en garantissant une exécution et un rapprochement cohérents à grande échelle.

Elle agrège des centaines de titres, de PUBG et Free Fire jusqu'à Call of Duty, auprès de plusieurs partenaires régionaux qui publient chacun des catalogues gérés indépendamment. Cette agrégation de catalogues fournisseurs se heurte à des flux très hétérogènes : formats, identifiants, conventions de nommage et sémantique des devises varient d'un fournisseur à l'autre. Certains décrivent les packs par leur valeur (« 70,000 Credits »), d'autres par leur référence (« Pack 70k »), d'autres encore par leur composition (« 60k + 10k Bonus »).
Sans normalisation, TokenHub ne peut ni comparer les prix de façon fiable, ni router les achats, ni produire des analyses exactes.

Pour y remédier, TokenHub met en œuvre un système de canonicalisation déterministe qui rapproche les références propres à chaque fournisseur en entités canoniques stables et auditables, en réduisant la curation manuelle au minimum tout en garantissant la cohérence à grande échelle.


Vue d'ensemble de l'architecture

Le moteur de canonicalisation de TokenHub repose sur une architecture à deux niveaux :

Couche d'instantanés éphémères : ingère, normalise, regroupe et inspecte les données fournisseurs sous forme d'instantanés immuables, un par exécution.
Couche de persistance canonique : stocke les produits, packs, liaisons et règles de curation canoniques validés, utilisés par les services de vitrine et de tarification.

Chaque import fournisseur s'exécute sous la forme d'un CanonJob immuable : un instantané daté et interrogeable, qui peut être rejoué sans risque et sans modifier les données canoniques.

Entités principales

CoucheTable(s)Rôle
ÉphémèreCanonJobReprésente une exécution complète d'ingestion et de regroupement pour un fournisseur (immuable).
ÉphémèreCanonSnapProduct, CanonSnapPackage, CanonSnapSource, CanonSnapSuggestionEnregistrements d'instantané dérivés des flux bruts et des suggestions de similarité.
CanoniqueCanonicalProduct, CanonicalPackageEntités de catalogue normalisées et durables.
CanoniqueOfferingRéférence fournisseur + prix et métadonnées, rattachés à des packs canoniques.
CanoniqueCanonicalBindingCorrespondance : (providerId, externalProductId) → (canonicalId, canonicalPackageKey).
CanoniqueNegativePairEmpêche de suggérer à nouveau des fusions déjà rejetées.
Canonique (règles)SuppressionRule, RenameRule, PackageRenameRuleCuration automatisée : masquer, renommer ou réétiqueter des éléments lors des exécutions suivantes.
Canonique (audit)CanonEditJournalJournal versionné et immuable de toutes les modifications (renommage, fusion, masquage, suppression).

Idempotence : des entrées identiques produisent toujours des sorties canoniques identiques. Les relations vérifiées restent stables d'une ingestion à l'autre.


Intégration des fournisseurs et normalisation de catalogue

Chaque intégration définit une configuration JSON qui décrit la structure et les paramètres de l'API du fournisseur :

json
{ "products": { "path": "/products", "method": "GET", "optionalParams": ["page", "offset"] }, "purchase": { "path": "/order", "method": "POST", "requiredParams": ["id", "number", "quantity"] } }

Des modules de traduction (par exemple translateProviderProducts) convertissent les réponses des fournisseurs dans un format interne standardisé :

json
{ "name": "BOLI", "category": "provider-category-299", "packages": [{ "name": "BOLI", "offerings": [{ "externalProductId": "878", "priceCents": 0, "currency": "USD", "metadata": { "minAmount": 10000, "maxAmount": 50000000, "requirements": [{ "name": "player_number", "label": "Player number" }] } }] }] }

La normalisation est déterministe. Tous les identifiants sont passés en minuscules et normalisés en Unicode, les quantités numériques sont analysées avec des unités explicites, et les montants sont stockés en centimes entiers. Les exigences et métadonnées définies par le fournisseur sont conservées intégralement.

L'attribut de région de chaque offre reflète la boutique ou le marché de vente (par exemple iTunes Italie ou iTunes France), et non la localisation physique du joueur. Cette distinction préserve l'exactitude des prix régionaux, de la fiscalité et de la visibilité du catalogue, sans faire d'hypothèse sur la géographie de l'utilisateur final.


Canonicalisation au niveau du fournisseur

Avant tout alignement entre fournisseurs, TokenHub effectue une canonicalisation au niveau du fournisseur. Le catalogue de chaque fournisseur est d'abord unifié en interne, de sorte que les doublons, comme Free Fire, Garena Free Fire et free fire, se fondent en un seul produit canonique propre à ce fournisseur. Chaque flux est ainsi cohérent en lui-même avant la mise en correspondance canonique globale.

Au sein de chaque fournisseur, TokenHub procède aussi à la consolidation des packs : il identifie les packs sémantiquement identiques même lorsqu'ils sont présentés différemment, comme « 70k coins », « 60k + 10k bonus » ou « 70,000 credits ». En calculant une signature sémantique pour chaque pack (quantité normalisée, unité, durée et indicateurs de variante comme bonus ou abonnement), le système fusionne les offres équivalentes tout en conservant les références d'origine pour l'auditabilité.


Pipeline de canonicalisation

Chaque exécution de canonicalisation s'effectue dans une seule transaction de base de données par CanonJob.

Passe 1 : regroupement des produits

La première étape, le regroupement des produits, identifie les produits entrants qui représentent probablement le même jeu ou la même entité numérique. Les produits sont regroupés selon leurs tokens textuels normalisés et leur similarité sémantique, de sorte que des variantes comme « FREE FIRE », « FREE FIRE CODE » et « Garena Free Fire » se retrouvent dans un même groupe candidat.

Ce processus combine une normalisation déterministe avec de la correspondance approximative et des heuristiques d'alias. Il tient compte des noms normalisés, de la fréquence des tokens et des fusions déjà confirmées pour éviter les faux positifs. Lorsqu'elles sont disponibles, des métadonnées comme la catégorie de boutique ou le canal du fournisseur renforcent la confiance du regroupement.

Chaque groupe est enregistré sous la forme d'un CanonSnapProduct, avec un canonicalName calculé, une normKey (la signature de tokens normalisée), une liste de memberIndexes et des liens vers les entrées des flux sources. Ces groupes deviennent les unités élémentaires de revue et de curation lors de la phase suivante.

Au-delà de la réduction des doublons, le regroupement apporte une compression sémantique : des milliers de noms vaguement apparentés deviennent quelques centaines de groupes cohérents. Les traitements suivants sont plus rapides, la génération de suggestions devient prévisible et la revue manuelle peut passer à l'échelle.

Passe 2 : consolidation des packs

Au sein de chaque groupe de produits, TokenHub effectue la consolidation des packs, qui normalise et fusionne les packs redondants ou équivalents sous une signature sémantique unifiée.

Une signature de pack est calculée à partir d'attributs normalisés clés : nom du pack, quantité, unité (crédits, diamants, etc.), plage de valeurs, paramètres requis (comme les identifiants de joueur) et indicateurs de type (bonus, abonnement, durée limitée, etc.). En représentant les packs par des signatures plutôt que par leur nom affiché, le système détecte de façon fiable que « 70k Credits », « 60k + 10k Bonus » et « 70,000 » sont des offres équivalentes.

Les packs dont les signatures concordent fusionnent en un seul enregistrement CanonSnapPackage, qui devient le représentant canonique de cette configuration. Les offres restent distinctes afin de conserver les écarts de prix et de devise, et le prix actif valide le plus bas de chaque groupe est marqué isPrimary pour les traitements en aval.

La consolidation des packs réduit considérablement le bruit dans le catalogue et évite la sur-segmentation. Elle améliore aussi la justesse des comparaisons entre fournisseurs, en garantissant que des propositions de valeur équivalentes sont reconnues comme telles, quelles que soient les différences locales de nommage ou de présentation.

Passe 3 : graphe de suggestions

Après la consolidation des packs, TokenHub construit un graphe de suggestions, un réseau d'équivalences et de relations potentielles entre candidats canoniques de différents groupes. Chaque arête de ce graphe représente un indice de similarité généré automatiquement : par exemple, que « Free Fire Diamonds 70k » chez un fournisseur correspond peut-être à « 70,000 FF Credits » chez un autre.

Le graphe est calculé en combinant le recouvrement de tokens normalisés, des mesures de distance sémantique, l'équivalence numérique et des schémas appris à partir des fusions déjà acceptées. Ces scores de similarité sont persistés sous forme d'enregistrements CanonSnapSuggestion, chacun annoté avec les identifiants des groupes sources, des valeurs de confiance et des métadonnées d'audit qui renvoient à leur origine.

Sur le plan opérationnel, le graphe de suggestions est la colonne vertébrale du processus de revue et de curation de TokenHub. Il permet aux curateurs d'agir vite et en confiance : les candidats à la fusion les plus probables sont présentés en premier, tandis que les comparaisons redondantes ou déjà rejetées sont écartées. Quand un administrateur accepte ou rejette une suggestion, ce retour est immédiatement intégré aux calculs suivants du graphe, ce qui permet au système d'« apprendre » des décisions humaines et d'améliorer continuellement sa précision.

Pour les imports volumineux, qui comptent souvent des dizaines de milliers de variantes de produits, le graphe transforme ce qui serait un exercice de comparaison manuelle en une revue efficace et ciblée. Au lieu de passer en revue toutes les références, les administrateurs se concentrent uniquement sur les candidats à la fusion pertinents, ce qui réduit le délai de décision et évite les erreurs dues à la fatigue.

Le graphe de suggestions joue également un rôle clé dans l'auditabilité et la reproductibilité. Chaque arête est horodatée, versionnée et rattachée à une exécution d'ingestion précise, afin que les administrateurs et les auditeurs puissent comprendre pourquoi deux enregistrements ont été présentés comme similaires, même des mois plus tard.

En résumé, le graphe de suggestions est la carte cognitive de TokenHub : il relie les nœuds sémantiquement proches, guide les relecteurs humains par le chemin le plus court vers la convergence canonique, et garantit que chaque nouvelle exécution est plus rapide, plus propre et plus précise que la précédente.


Modifications des administrateurs, règles et priorités

Toutes les modifications administratives s'effectuent sur la couche d'instantanés et restent entièrement réversibles. Lorsqu'un administrateur renomme un produit, fusionne des groupes ou masque des entrées indésirables, le système enregistre chaque action sous la forme d'un objet de modification structuré :

json
{ "type": "rename", "target": "canonSnapProduct:42", "value": "FREE FIRE" }

Pendant l'édition, TokenHub conserve un tampon local, canon:job:<id>:edits, qui permet d'annuler, de rétablir et de reprendre après un plantage. Lorsque l'action Apply est exécutée, TokenHub crée ou met à jour les enregistrements canoniques concernés (CanonicalProduct, CanonicalPackage et Offering), établit les liens entre fournisseur et entité canonique dans CanonicalBinding, et persiste toute la logique de curation sous forme de règles déterministes.

Les règles de renommage corrigent les libellés des produits, les règles de renommage de packs ajustent le nom des packs, et les règles de masquage retirent des éléments de la vitrine ou de l'index de recherche. Les paires négatives enregistrent les fusions explicitement rejetées pour éviter de futures suggestions redondantes. Chaque modification appliquée est consignée dans le CanonEditJournal immuable, ce qui garantit une traçabilité complète.

Les règles s'appliquent dans un ordre prévisible : les règles de masquage l'emportent sur tout le reste, suivies des règles de renommage de produits et de packs, les noms canoniques bruts servant de solution de repli. Lors des imports suivants, ces règles et liaisons sont appliquées automatiquement avant la génération de nouvelles suggestions, ce qui réduit le travail manuel et garantit un nommage cohérent et stable d'une ingestion à l'autre.

La curation avec intervention humaine est un élément essentiel de ce processus. Chaque correction vérifiée améliore la capacité de la machine à proposer des suggestions automatiques justes lors des exécutions suivantes, ce qui permet à la qualité de l'automatisation de progresser naturellement sans renoncer au contrôle.


Exemple : de l'instantané à la persistance

Instantané en entrée

json
{ "canonicalName": "FREE FIRE", "packages": [{ "key": "110|free|fire", "offerings": [ {"providerId": "provider", "externalProductId": "878", "priceCents": 10000}, {"providerId": "provider", "externalProductId": "879", "priceCents": 12000} ] }] }

Écritures résultantes en base de données

TableExemple
CanonicalProduct{ "id": 1, "name": "FREE FIRE", "slug": "free-fire" }
CanonicalPackage{ "id": 10, "canonicalId": 1, "key": "110" }
Offering{ "id": 100, "packageId": 10, "providerId": "provider", "externalProductId": "878", "priceCents": 10000, "currency": "USD", "isPrimary": true }
Offering{ "id": 101, "packageId": 10, "providerId": "provider", "externalProductId": "879", "priceCents": 12000, "currency": "USD", "isPrimary": false }
CanonicalBinding{ "providerId": "provider", "externalProductId": "878", "canonicalId": 1, "canonicalPackageKey": "110" }
RenameRule{ "canonicalId": 1, "from": "FREE FIRE CODE", "to": "FREE FIRE" }
PackageRenameRule{ "canonicalId": 1, "key": "110|free|fire", "to": "110 FREE FIRE" }
SuppressionRule{ "providerId": "provider", "externalProductId": "test-sku-zzz", "reason": "deprecated" }
NegativePair{ "leftCanonicalId": 1, "rightCanonicalId": 99 }

Actualisation, architecture et versionnage

Les imports fournisseurs sont sûrs, idempotents et rejouables. Les liaisons existantes rattachent automatiquement les références, en mettant à jour les prix et la disponibilité sur place. Les nouvelles références apparaissent comme de nouvelles lignes d'instantané, tandis que les entrées obsolètes sont masquées ou désactivées par des règles de masquage. Le catalogue évolue ainsi en continu, sans destruction de données ni reprise manuelle.

Le modèle de persistance de TokenHub repose sur PostgreSQL et Prisma ORM, avec un schéma transparent et explicite. Chaque cycle d'ingestion ou de modification est journalisé et versionné pour permettre la reproduction et le retour arrière. Des dictionnaires d'alias conservent les états de nommage propres à chaque fournisseur et globaux, tandis que les paires négatives enregistrent des contraintes explicites « ne pas fusionner » qui protègent la précision canonique. Toutes les opérations sont transactionnelles et vérifiables, ce qui garantit un lignage de données reproductible et auditable, des flux bruts jusqu'aux entités canoniques.


Auditabilité, provenance et sécurité

TokenHub conserve le lignage complet, des données brutes du fournisseur jusqu'aux entités et offres canoniques finales, en passant par les enregistrements d'instantané. Chaque modification est encapsulée dans une transaction atomique unique et consignée dans CanonEditJournal, ce qui permet aux administrateurs de retrouver l'origine et la justification de chaque enregistrement. Des empreintes cryptographiques garantissent l'intégrité, et le rejeu déterministe permet de reconstruire et de vérifier précisément n'importe quel état historique.

En production, TokenHub applique un contrôle d'accès strict fondé sur les rôles, isole les identifiants des fournisseurs de la logique applicative et ne collecte aucune donnée personnelle des utilisateurs. Des indicateurs opérationnels, comme le taux de réussite des ingestions, la couverture des alias, le taux de doublons et le débit de curation, sont surveillés en continu pour maintenir la qualité et la fiabilité du catalogue.


Caractéristiques opérationnelles

Le système fonctionne avec une cohérence transactionnelle stricte : chaque cycle de canonicalisation est validé comme une unité atomique, sans aucun état partiel. Des règles de correspondance déterministes garantissent que des entrées identiques produisent toujours des sorties identiques, et des instantanés immuables préservent des vues datées et reproductibles des données. Les règles apprises et les paires négatives éliminent le bruit des correspondances redondantes ou peu fiables, ce qui garde le graphe de suggestions précis et exploitable. Les règles de masquage protègent la vitrine : les éléments obsolètes ou exclus restent invisibles sur toutes les surfaces.


Résultat

Le cadre de canonicalisation de TokenHub fournit une base vérifiable et reproductible pour gérer des écosystèmes de produits numériques complexes. En transformant des flux fournisseurs incohérents en une couche canonique unifiée, il permet à chaque système en aval (tarification, vitrine, analytique et rapprochement) de s'appuyer sur une source de vérité unique et structurée.

Le résultat est un catalogue qui évolue en toute sécurité : la curation antérieure persiste automatiquement, les règles déterministes empêchent les régressions, et chaque transformation reste auditable, de la donnée source jusqu'à l'enregistrement canonique. Les opérateurs gagnent des cycles d'import prévisibles et des différentiels propres ; les ingénieurs, une architecture à la fois traçable et reproductible ; les équipes de gouvernance des données, l'assurance que des entrées identiques produisent toujours des résultats identiques et vérifiables.

Plutôt qu'un simple exercice de correspondance figé, TokenHub fonctionne comme un moteur de normalisation continue : il s'améliore à chaque cycle de revue, intègre de nouveaux fournisseurs sans refonte et fait de la cohérence une propriété du système lui-même.

Le projet lui-même, avec l'équipe, le calendrier et les résultats, est présenté dans l'étude de cas sur l'infrastructure de commerce numérique. Ce type d'intégration compte parmi les principaux facteurs de coût de tout développement (voir ce qui détermine le coût d'une application web sur mesure) ; les concevoir est au cœur de notre travail en architecture logicielle et en développement d'applications web sur mesure.

Pour aller plus loin

  • Documentation PostgreSQL, Transactions (en anglais), le fondement du cycle de canonicalisation atomique
  • Référence de l'API Stripe, Requêtes idempotentes (en anglais), un modèle largement utilisé pour relancer des requêtes sans risque auprès de fournisseurs externes