SportIQ — Plateforme SaaS pour fédérations sportives
Plusieurs applications autour d’un référentiel unique : licences, compétitions, communication et trésorerie d’une fédération sportive, avec une isolation stricte entre fédérations.
Le défi
Une fédération n’est pas un club, et ce n’est pas une entreprise
Une fédération sportive administre un écosystème, pas une organisation : des clubs qui ont leurs propres gestionnaires, des licenciés qui changent de club, des compétitions qui engagent les deux, et une comptabilité qui doit suivre tout cela. Les outils du marché traitent le club. Très peu traitent l’échelon fédéral, et ceux qui le font sont conçus pour une seule fédération à la fois.
Quatre contraintes structurelles rendaient un produit générique inutilisable :
- Plusieurs fédérations sur une seule plateforme. Chacune a ses règles, ses rôles, ses catégories d’âge et ses barèmes — mais aucune ne doit jamais voir les données d’une autre. Ce n’est pas une préférence de configuration : c’est une exigence de sécurité.
- Des identifiants publics lisibles. Un numéro de licence est imprimé, communiqué par téléphone, recopié sur un formulaire papier. Il doit être court et séquentiel — et il ne peut pas l’être si c’est la clé technique d’une base partagée entre plusieurs fédérations.
- Des droits qui ne se résument pas à « admin » et « utilisateur ». Un gestionnaire de club voit son club ; un service fédéral voit tous les clubs mais ne valide pas les licences ; un trésorier voit les montants mais pas les dossiers médicaux. Et la répartition exacte change d’une fédération à l’autre.
- Des métiers qui n’avancent pas au même rythme. La gestion des licences, l’organisation des compétitions et le site public n’ont ni les mêmes utilisateurs, ni les mêmes cycles de livraison, ni les mêmes contraintes de disponibilité.
La solution
Plusieurs applications, un seul référentiel
La plateforme n’est pas une application unique, et ce n’est pas non plus une architecture microservices. C’est un ensemble d’applications autonomes — chacune avec son backend Node.js/Express et son interface Angular, son déploiement et sa propre authentification — construites autour d’une base de données partagée qui sert de point d’intégration.
- Backoffice fédéral — licences, transferts, clubs, personnes, documents.
- Compétitions — engagements, calendriers, matchs, résultats.
- CMS public — le site de la fédération, administré par la fédération elle-même.
- Actualités — une déclinaison réduite du CMS pour les fédérations qui n’ont besoin que de publier.
Le choix est assumé : aucun appel HTTP d’un backend vers un autre. Chaque interface ne parle qu’à son propre backend, et la cohérence vient du modèle de données, pas d’un maillage de services. On évite ainsi la latence en cascade, les transactions distribuées et les pannes en chaîne — au prix d’un couplage au schéma, que trois règles compensent : une seule chaîne de migrations pour tout l’ensemble, des conventions de requêtage identiques dans chaque projet, et aucune clé étrangère (l’intégrité référentielle est tenue par le code, ce qui laisse chaque application maîtresse de ses écritures).
Isolation des données : le point de départ, pas une option
Chaque fédération accède à la plateforme par son propre sous-domaine. La fédération courante est ensuite déduite du jeton d’authentification uniquement — jamais d’un paramètre d’URL, d’un corps de requête ou d’un champ de formulaire, qui sont tous falsifiables. Chaque lecture et chaque écriture est filtrée sur cette fédération, aucune requête ne joint deux fédérations, et un identifiant appartenant à une autre fédération répond 404 et non « accès refusé » : la seconde réponse confirmerait que la donnée existe.
Deux identifiants par enregistrement
Chaque objet métier porte deux clés : une clé interne, utilisée uniquement pour les jointures et jamais exposée, et un identifiant séquentiel propre à la fédération, attribué automatiquement par déclencheur à partir d’un compteur dédié. C’est ce second identifiant que voient les utilisateurs, les URLs et l’API — donc le licencié n° 1 042 de chaque fédération existe indépendamment, avec des numéros courts et sans trou, alors que la base reste unique. La règle est tenue partout : l’identifiant public n’apparaît qu’en sortie, jamais dans un filtre ni dans une jointure.
Des droits calculés, pas codés en dur
Cinq rôles fédéraux sont prédéfinis — administration générale, administration fédérale, lecture fédérale, gestion de club, lecture de club — mais les permissions attachées à chaque rôle sont paramétrables par fédération, et chaque utilisateur peut recevoir des autorisations ou des interdictions individuelles qui s’ajoutent à son rôle. L’ensemble est calculé à la connexion, embarqué dans le jeton, puis vérifié côté serveur sur chaque route et côté interface pour n’afficher que les actions réellement permises.
Le seul service partagé : les fichiers
Licences signées, pièces justificatives, photos, logos : tous les documents sont centralisés dans un service de fichiers unique, et c’est la seule dépendance qu’une application ait envers une autre. Il fonctionne à deux niveaux d’accès :
- les backends l’appellent avec des requêtes signées en HMAC ; le service n’a ni session ni compte utilisateur et ne fait confiance qu’à la signature ;
- les navigateurs accèdent aux documents privés par des URL signées à durée limitée, sans jeton d’authentification et sans jamais voir un chemin de stockage réel.
Trois détails qui font la différence à l’usage : le type MIME est validé d’après le contenu du fichier et non d’après l’en-tête déclaré ; le chemin de stockage contient obligatoirement la fédération, si bien qu’une erreur de code ne peut pas écrire dans le dossier d’une autre ; et l’envoi se fait en deux temps — dépôt temporaire puis confirmation — avec une tâche de nettoyage pour les fichiers jamais confirmés.
Six modules, activés au rythme de la fédération
Gestion de la fédération, licences et transferts, compétitions et matchs, formations/stages et diplômes, marketing et site web, finance et trésorerie. Les six partagent le même référentiel : un licencié saisi une fois est le même dans une feuille de match, dans une session de formation et dans une écriture comptable. Une fédération peut n’en activer que deux et ajouter les autres ensuite, sans reprise de données.
Les résultats
Ce que l’architecture permet
- Une nouvelle fédération s’ajoute sans nouvelle instance — pas de duplication de code, de base ou de serveur, donc pas de dérive entre clients.
- Un métier peut évoluer sans bloquer les autres : les compétitions se livrent sans redéployer le backoffice des licences.
- Un référentiel unique : la même personne n’est plus saisie dans trois fichiers, et licences, engagements et paiements se réconcilient sans export intermédiaire.
- Des numéros de licence courts et séquentiels, utilisables sur un document papier, sans exposer la structure de la base.
- Une répartition des droits qui suit l’organisation réelle, ajustable par la fédération elle-même plutôt que par un développeur.
- Un seul point d’accès aux documents, signé et daté, ce qui rend un contrôle vérifiable.
La plateforme est en production et exploitée sous la marque sportiq.ma, où les six modules sont décrits publiquement. Le développement se poursuit : de nouveaux modules sont en cours, et l’architecture a précisément été choisie pour qu’ils s’ajoutent sans remettre en cause ce qui tourne.
Pourquoi ce projet compte au-delà du sport
Isolation stricte entre organisations, rôles paramétrables, identifiants publics séparés des clés techniques, appels inter-applications signés, documents servis par URL temporaires : ce sont les mêmes contraintes qu’une mutuelle, un groupe de cliniques ou un gestionnaire immobilier multi-sites. C’est le même socle que nous mettons en œuvre sur nos plateformes métier.



