Skip to main content
Welcome. This site supports keyboard navigation and screen readers. Press ? at any time for keyboard shortcuts. Press [ to focus the sidebar, ] to focus the content. High-contrast themes are available via the toolbar.
serard@dev00:~/cv

23. Le DataHub de Qwant — journalisation serveur, recherches, clics et publicités

← Sommaire | ← Précédent

Nature de l'analyse. Ce chapitre repose sur l'examen en lecture seule du dépôt Git API-API-TAG-PACKAGER, notamment du tag v1.32.1 du 22 décembre 2016 et de l'historique des fichiers concernés. Il décrit ce que le code versionné permettait de faire. Sauf pièce de déploiement supplémentaire, il ne transforme pas cette capacité en preuve de fonctionnement effectif sur tout le trafic ni de conservation durable de chaque événement.

Conclusion principale. Le code établit l'existence, en 2016, d'un système interne centralisé désigné comme DataHub, capable d'associer les recherches, clics et impressions publicitaires à l'adresse IP complète, au User-Agent, au contexte HTTP et, à partir d'août 2016, à un hash stable dérivé de l'IP. La qualification technique de tracking serveur individualisable côté Qwant est étayée. Le dépôt ne démontre toutefois ni un profil publicitaire longitudinal effectivement constitué, ni une transmission du DataHub à Microsoft, ni les durées de conservation ou les accès au système aval.

Analyse vérifiée le 4 août 2026.


A. Dépôt examiné

Le dépôt étudié est le projet PHP/CodeIgniter API-API-TAG-PACKAGER, qui contient le code de l'API front de Qwant. Le même dépôt est analysé plus largement dans le chapitre Analyse forensique détaillée — API-API-TAG-PACKAGER.

Le worktree local est positionné sur un commit develop du 6 juillet 2016. L'historique local contient cependant des tags postérieurs, jusqu'à v1.32.1. Afin de ne pas modifier le worktree, les versions postérieures ont été lues avec des commandes Git sans effet sur les fichiers :

git show v1.32.1^{}:www/application/models/logger.php
git grep -n "logEvent" v1.32.1^{} -- www/application
git blame -L <début>,<fin> v1.32.1^{} -- <fichier>
git show --stat <commit>

Cette méthode permet de contrôler le contenu exact d'un tag et son attribution Git sans checkout, sans switch, sans reset et sans modification de l'index.

B. Version de référence

Le tag principal retenu est v1.32.1, qui se résout vers le commit :

22aa5650889b1a77e1ef9008ea55fef30cc8916f

Il s'agit du dernier tag présent dans le dépôt local. Il contient la forme la plus étendue du DataHub observée dans ce corpus : recherches, clics, impressions publicitaires, appels externes, actions de compte, erreurs et boucle de bannissement.

Un tag prouve qu'un état du code a été identifié comme version de release. Il ne constitue pas, à lui seul, un journal de déploiement. Les artefacts construits, manifestes CI/CD, configurations de serveurs et journaux d'exécution seraient nécessaires pour établir le périmètre effectivement servi.

C. Distinctions indispensables

Trois flux doivent rester séparés :

  1. le DataHub interne Qwant, alimenté par des messages JSON envoyés vers RabbitMQ ;
  2. les appels externes, notamment vers Bing et Bing Ads ;
  3. des stockages Qwant voisins, comme la table search_suggest et l'index Elasticsearch click_url_temp.

Le fait qu'un même parcours de recherche déclenche plusieurs flux ne signifie pas que le contenu du DataHub a été transmis à Microsoft.


A. Une transformation d'un logger préexistant

Le DataHub n'est pas le premier mécanisme de journalisation du projet. L'historique de logger.php remonte à 2013 et comporte notamment des références à un access logger, à MongoDB et à Elasticsearch. En 2016, le DataHub apparaît comme une refonte et une centralisation de cette journalisation préexistante.

L'historique Git attribue l'implémentation principale à Thomas Decaux :

Date Commit Auteur Git Apport documenté
31 mars 2016 48a167106a t.decaux@qwant.com #QAPI-370 Integrate dataHub aka new logger : nouvelle configuration, hook, recherches, clics et refonte de logger.php
5-22 avril 2016 plusieurs commits QAPI-370 Thomas Decaux, merges de Pierre Vignaux structure des événements, métadonnées HTTP, origine client, URL et locale
14 juin 2016 c3c69dff89 Thomas Decaux passage à phpAmqpLib et ajout de plusieurs hôtes RabbitMQ pour la haute disponibilité
21 juillet 2016 86e9620bda Thomas Decaux journalisation des impressions publicitaires
2 août 2016 f286205e82 Thomas Decaux journalisation des réponses instantanées réussies
3 août 2016 7799a5c560 Thomas Decaux ajout de client.hash et du score antispam
31 août 2016 4bdfca906f Thomas Decaux détail des annonces publicitaires enregistrées
7 septembre 2016 c5f1e1d72d Thomas Decaux actions de compte, boards, notes, contacts et suppressions
9 septembre 2016 451981b7ea Thomas Decaux contrôleur dédié aux clics SERP et page d'accueil
13 septembre 2016 23f26e55ba Thomas Decaux événements de flood et d'abus

B. Rôle de Pierre Vignaux et d'autres contributeurs

Pierre Vignaux apparaît comme le principal intégrateur dans les branches prelive et master. L'historique montre notamment :

  • des merges répétés de feature/QAPI-370 dans prelive à partir du 5 avril 2016 ;
  • les merges de versions vers master ;
  • des modifications du score antispam et de logSearch() ;
  • des corrections du hash client et de certains événements de clic ;
  • le commit d6aa1cf0c6 du 5 décembre 2016, intitulé split ban by IP SSI and by IP datahub.

Nghia Duong a notamment contribué à la journalisation des exceptions, des erreurs de connexion et au mécanisme voisin feedSearchSuggest().

Jonathan Cassar apparaît dans certains merges et évolutions périphériques, sans que l'historique contrôlé lui attribue le noyau initial du DataHub.

C. Premières versions taguées

Dans les tags disponibles localement :

  • v1.16.15, daté du 26 mai 2016, contient déjà la nouvelle classe DataHub active ;
  • v1.18.0, daté du 16 juin 2016, porte explicitement le message de tag « DataHub » ;
  • v1.32.1, daté du 22 décembre 2016, contient le périmètre fonctionnel étendu décrit ici.

Les séries de tags suivent parfois des lignées divergentes. Elles doivent donc être lues comme des instantanés versionnés, pas comme une suite parfaitement linéaire.

D. Limite de l'attribution nominative

Git documente un auteur déclaré, un committer, une date et un contenu. Il ne suffit pas à établir :

  • qui a décidé le projet au niveau de la direction ;
  • qui en a défini seul les finalités ;
  • qui avait connaissance de toutes les données collectées ;
  • la responsabilité juridique personnelle d'un contributeur ;
  • l'activation effective du code sur les serveurs de production.

La formulation rigoureuse est donc : « l'historique Git attribue l'implémentation principale à Thomas Decaux et son intégration récurrente à Pierre Vignaux », et non une conclusion sur une faute personnelle.


A. Chaîne générale

Le flux visible dans le dépôt est le suivant :

Requête utilisateur
        ↓
Producteur d'événement : recherche, clic, publicité, compte, erreur…
        ↓
Logger::logEvent()
        ↓
Tampon en mémoire pendant la requête
        ↓
QwantHook::onShutDown()
        ↓
Logger::flushEvents()
        ↓
Message JSON → RabbitMQ interne → consommateurs DataHub absents du dépôt

QwantHook enregistre une fonction de fin de processus. Lorsque le contrôleur et son conteneur existent, il récupère le logger, ajoute éventuellement une erreur PHP fatale puis vide le tampon.

Dans v1.32.1, flushEvents() appelle fastcgi_finish_request() avant l'envoi. L'objectif visible est de terminer la réponse adressée au client avant d'effectuer la transmission analytique.

B. Transport RabbitMQ

Le code :

  • charge une liste d'hôtes via logger_transport_host ;
  • mélange leur ordre ;
  • essaie successivement de s'y connecter ;
  • utilise AMQPStreamConnection sur le port 5672 ;
  • publie dans l'échange direct amq.direct ;
  • utilise la routing key v1 ;
  • sérialise chaque événement en JSON.

La configuration de production contient deux adresses IP privées, tandis que la configuration générale vise un hostname interne comportant queue.analytics.qwant.plive. Ces éléments établissent une configuration destinée aux environnements internes Qwant.

Ils ne prouvent pas que les serveurs étaient accessibles ou que chaque message a été reçu. Le code :

  • ignore les exceptions de connexion ;
  • ne montre pas d'accusé de réception du broker ;
  • ne persiste pas localement les événements qui n'ont pas pu partir ;
  • ne contient pas le consommateur de la queue.

C. Structure commune d'un événement

Chaque appel à logEvent() crée une enveloppe comportant :

Bloc Champs principaux
Événement date Unix, identifiant, nom, version du schéma
Produit module, version applicative, environnement, type d'API, application et origine
Client IP complète, origine réseau, locale, User-Agent, hash client
Requête méthode HTTP, host, URI complète, serveur, score antispam, référent complet et décomposé
Données métier bloc dynamique nommé selon le produit et le type d'événement

Le bloc métier prend par exemple le nom :

api_search_search_data
api_search_click_serp_data
api_search_ads_print_data
api_account_login_error_data

La présence de l'URI complète et du référent signifie qu'un événement peut contenir des paramètres supplémentaires au-delà des champs explicitement ajoutés par son producteur.


A. Adresse IP complète

Pour chaque événement, getLogItemClient() appelle ip_address() et place directement le résultat dans le champ :

'ip' => $ip

Le DataHub interne ne reçoit donc pas seulement une IPv4 tronquée. Il reçoit l'adresse IP que l'API considère comme celle du client, en clair, ainsi que le User-Agent.

Cette distinction corrige une confusion possible :

  • côté DataHub Qwant : IP complète dans l'enveloppe commune ;
  • côté Bing Ads : tentative de troncature du dernier octet pour les IPv4 dans le header X-Search-ClientIP.

B. Hash client stable

À partir du commit 7799a5c560 du 3 août 2016, une adresse publique reçoit aussi un hash calculé ainsi :

SHA-256(IP + sel serveur)

Le sel est une constante serveur commune au code observé. À sel inchangé, une même IP publique produit donc le même hash d'un événement à l'autre et d'un jour à l'autre.

Cela permet techniquement de regrouper les événements liés à une même IP dans la durée, si les messages sont reçus et conservés. Ce hash n'identifie pas nécessairement une personne :

  • plusieurs utilisateurs peuvent partager une même IP ;
  • une IP dynamique peut changer ;
  • un VPN ou un proxy peut agréger de nombreux utilisateurs ;
  • le dépôt ne montre pas une table reliant ce hash à une identité civile.

Pour les adresses internes, le code génère des valeurs de type lan_<adresse> ; pour les appels locaux, il utilise des libellés spéciaux.

C. Identifiant de chaque événement

L'identifiant d'événement incorpore :

  • le mois, le jour et l'heure ;
  • le produit et le type d'événement ;
  • les huit premiers caractères d'un MD5 de IP + User-Agent ;
  • une partie aléatoire.

Le hash client stable reste cependant le mécanisme de rapprochement le plus direct visible dans v1.32.1.

D. Absence d'opposition visible

Dans les fichiers producteurs contrôlés, aucun mécanisme lié à DNT, à un consentement ou à une opposition utilisateur n'est testé avant logEvent().

isLoggable() exclut les événements non nommés error pour deux User-Agents techniques exacts :

  • qwant-monitor ;
  • qwant-stresstest.

Cette condition vise les outils de supervision, pas un choix de l'utilisateur. Le commentaire parle d'événements info|debug, mais la condition réelle écarte tous les événements non nommés error pour ces deux User-Agents.


Dans v1.32.1, Logger::logSearch() construit un événement comportant :

  • la requête complète dans query ;
  • la locale ;
  • le domaine de recherche : Web, images, actualités, social, shopping, etc. ;
  • l'offset et le nombre demandé ;
  • le nombre de résultats ;
  • l'indication d'un résultat issu du cache ;
  • l'onglet de l'interface ;
  • la durée de traitement ;
  • l'indication d'une tendance ;
  • les filtres utilisés ;
  • un score antispam ;
  • le statut HTTP.

Ces données métier sont ajoutées à l'enveloppe commune contenant l'IP complète, le hash IP, le User-Agent, l'URI et le référent.

B. Recherches non cachées et recherches servies depuis le cache

search_service.php appelle logSearch() :

  • après une recherche exécutée par un modèle de recherche ;
  • lorsqu'un résultat est resservi depuis le cache ;
  • pour certains motifs bloqués comme abusifs, avec statut HTTP 402.

Le cache n'empêche donc pas la journalisation de la recherche utilisateur. Il change seulement la valeur du champ cached et évite éventuellement un nouvel appel au fournisseur externe.

Le code ne garantit pas l'enregistrement de toute tentative : une validation de domaine ou de limite peut retourner avant l'appel au logger, tandis qu'une exception peut générer un événement d'erreur au lieu d'un événement search complet.

C. Score antispam

Le code attribue des scores particuliers à certains motifs, notamment :

  • les opérateurs site: et intitle: ;
  • certaines recherches de CV en anglais comportant une expression entre guillemets ;
  • des suites de plusieurs points d'interrogation.

Le score est déplacé dans le bloc commun request. Il ne s'agit donc pas seulement d'une statistique de performance : le DataHub reçoit aussi une qualification automatisée de certains comportements.


VI. feedSearchSuggest() : un stockage distinct du DataHub

Avant les principales validations de recherche, search_service.php appelle aussi feedSearchSuggest().

Pour les recherches Web, cette fonction :

  1. normalise la requête ;
  2. récupère une adresse IP depuis les headers ou variables serveur ;
  3. calcule un SHA-1 incorporant la date, l'IP, la locale et la requête ;
  4. utilise ce hash pour éviter plusieurs insertions identiques dans la journée ;
  5. écrit la requête normalisée et la locale dans la table SQL search_suggest.

Le commentaire indique explicitement :

This data will be used for suggest optimization

Il s'agit d'un traitement Qwant lié aux recherches, mais pas du transport RabbitMQ DataHub.

L'IP n'est pas stockée en clair dans les trois colonnes visibles de la requête SQL. Elle entre toutefois dans le hash de déduplication. Ce hash inclut aussi la requête et la date : contrairement à client.hash, il n'est pas un identifiant stable commun à des recherches différentes.

Le TTL d'une heure visible dans cette fonction concerne le cache utilisé pour éviter les insertions répétées. Il ne documente pas la durée de conservation des lignes dans la base SQL.


A. Clic sur un résultat de recherche

Le contrôleur LoggerClickAPIController expose la route :

api/click/(:any)

Lorsque son endpoint url() est appelé avec des données valides, il enregistre :

  • la requête ;
  • l'URL cible complète ;
  • le host, le schéma et le domaine cible ;
  • la position du résultat ;
  • le domaine de recherche ;
  • le type de lien, notamment résultat normal ou publicité ;
  • la locale, l'appareil et l'onglet.

Un hash journalier incorpore la requête, l'URL, l'IP, la locale et la date. Comme pour les recherches, l'enveloppe DataHub ajoute par ailleurs l'IP complète, le hash client stable et le User-Agent.

Le dépôt API prouve que l'endpoint journalise les clics qui lui sont soumis. Il ne suffit pas à démontrer que toutes les interfaces Qwant appelaient cet endpoint pour chaque clic : ce point nécessiterait le code front correspondant ou des traces réseau.

B. Second enregistrement Elasticsearch

Après l'événement DataHub, le même contrôleur appelle url_model->saveUrl(). Ce modèle écrit dans l'index Elasticsearch click_url_temp :

  • le hash journalier ;
  • l'URL ;
  • la requête ;
  • la locale ;
  • la position ;
  • la date et l'heure.

Il existe donc deux chemins distincts pour un clic reçu :

  1. message DataHub ;
  2. document Elasticsearch.

Le nom click_url_temp suggère un usage temporaire, mais aucune durée d'effacement n'est démontrée dans le fichier.

C. Page d'accueil et Cinetick

Le contrôleur enregistre également :

  • les clics de page d'accueil, avec type et position ;
  • les clics Cinetick, avec requête, film, cinéma, ville et séance.

Ces événements reçoivent eux aussi l'enveloppe client et HTTP commune.


A. Appel adressé à Bing Ads

Lorsque les conditions d'affichage publicitaire sont réunies, search_ads.php construit une requête vers bingapis.com. Le code transmet notamment :

  • le mot-clé de recherche dans l'URL ;
  • le User-Agent ;
  • le référent ;
  • un header X-Search-ClientIP.

Pour une IPv4, anonymizeIp() remplace le dernier octet par zéro :

82.65.234.124 → 82.65.234.0

La fonction cherche exclusivement le dernier point. Si l'adresse ne contient pas de point, elle la renvoie inchangée. Une IPv6 peut donc être transmise sans troncature dans ce chemin, sous réserve du format réellement fourni en production.

Le volet Microsoft et la qualification publique des données transmises sont analysés séparément dans Validation par la CNIL. Les affirmations attribuées à Qwant dans les procédures sont rapprochées des pièces dans Accusations et réalité documentaire.

B. Événement interne ads_print

Après l'appel publicitaire, Qwant construit un événement DataHub comprenant :

  • le mot-clé ;
  • l'appareil ;
  • la locale ;
  • l'onglet ;
  • le domaine ;
  • le nombre d'annonces ;
  • le titre et l'URL source de chaque annonce retournée.

Le logger ajoute à cet événement l'IP complète, le hash IP stable, le User-Agent et le contexte HTTP.

La formulation exacte est donc :

Qwant disposait d'un événement interne permettant de rapprocher une requête publicitaire, les annonces affichées et des identifiants techniques côté Qwant.

Il serait inexact d'écrire que le DataHub ne recevait que l'IPv4 tronquée : cette valeur concerne le header adressé à Bing Ads. Il serait également excessif d'affirmer, à partir de ce seul fichier, que Qwant avait effectivement constitué un profil publicitaire longitudinal de chaque utilisateur.

C. Appels externes journalisés dans le DataHub

httpgateway.php crée aussi des événements external_api pour une liste de fournisseurs comprenant notamment Bing/Azure, Flickr, Dailymotion, Google APIs, Twitter et plusieurs services shopping.

Les champs comprennent :

  • l'URL externe complète, susceptible de contenir la requête et d'autres paramètres ;
  • le host et le domaine fonctionnel ;
  • le code HTTP ;
  • la durée ;
  • le volume téléchargé.

Comme toujours, ces informations sur l'appel sortant sont associées, dans le message DataHub, aux métadonnées de la requête entrante.


IX. Autres catégories d'événements

Dans v1.32.1, le DataHub dépasse largement la seule publicité.

Produit Événements visibles Données métier principales
Recherche search, click_serp, click_homepage, ads_print, external_api, unban, flood requête, URL, rang, annonces, fournisseur, motif de blocage
IA ia_query, ia_cinetick_click requête, module, template, film, cinéma, ville, séance
Compte registration, login_error, removal_wanted, removal_success, flood identifiant utilisateur, pays, type, référent, erreur, parfois username ou email lors d'un flood
Boards board_creation, note_creation, flood identifiants, identifiant utilisateur et titre du board
Core contact type, sujet, statut, région ou URL selon le formulaire
API 404, error, legacy logger message, fichier, ligne, type, token et trace partielle

Les erreurs PHP ou exceptions peuvent contenir jusqu'à 1 024 caractères de trace. Leur contenu exact dépend du message produit par le code appelé ; le dépôt ne permet pas d'exclure qu'une erreur transporte occasionnellement une valeur issue de la requête.

Les événements de compte ou de board peuvent inclure un identifiant numérique de compte. En revanche, l'événement standard de recherche ne contient pas directement cet identifiant. Un rapprochement entre recherche et compte serait techniquement envisageable par IP, User-Agent, temps ou autres données, mais aucune jointure de ce type n'est implémentée dans le dépôt étudié.


X. Le DataHub comme mécanisme de décision

Le DataHub ne sert pas uniquement à produire des statistiques.

Dans user_model.php, la fonction isBannedByDataHub() :

  1. calcule une clé Couchbase à partir du hash salé de l'IP ;
  2. consulte un cache équilibré ;
  3. considère l'adresse comme bannie si la clé existe.

Le commentaire indique explicitement :

Checks in couchbase generated by DataHub if an IP is banned

Dans MY_Controller.php, ce résultat peut provoquer une réponse :

429 Too Many Requests

Le code distingue :

  • le bannissement par le DataHub ;
  • une blacklist IP classique ;
  • une blacklist fondée sur IP + User-Agent ;
  • les User-Agents absents ou jugés trop anciens.

Cette chaîne établit une boucle opérationnelle :

Événements et hash client
        ↓
Traitement DataHub absent du dépôt
        ↓
Clé de blacklist dans Couchbase
        ↓
Décision de refuser l'accès à l'API

Le dépôt ne contient pas l'algorithme aval qui décide de créer cette clé. Les seuils, critères, personnes habilitées et durées de bannissement ne peuvent donc pas être reconstitués ici.


Le DataHub permet de réunir dans un même événement :

  • une action : requête, clic, publicité, création, erreur ;
  • son contenu : mots-clés, URL, annonce ou action de compte ;
  • une date ;
  • une IP complète ;
  • un User-Agent ;
  • un hash stable de l'IP ;
  • le contexte de navigation et le référent.

Cette association répétée constitue techniquement une journalisation comportementale individualisable côté serveur. Elle ne nécessite pas de déposer un cookie dans le navigateur.

Le logger étudié :

  • ne dépose pas lui-même de cookie ;
  • ne charge pas de pixel ;
  • n'exécute pas de script de fingerprinting dans le navigateur ;
  • exploite des informations déjà présentes dans la requête HTTP et les paramètres transmis à l'API.

Il convient donc de ne pas confondre :

  • traceur client : cookie, pixel ou script exécuté dans le navigateur ;
  • tracking serveur : rapprochement des requêtes et comportements à partir des données reçues par le serveur.

Le bundle v1.32.1 contient des CGU françaises indiquées « À jour du 2 juin 2016 ». Leur section « Cookies et autres traceurs » affirme :

« L'utilisateur est informé qu'aucun cookie ou autre traceur publicitaire (pixel, fingerprinting) n'est utilisé par Qwant lors de sa navigation sur le Site. »

Cette phrase est plus étroite qu'une affirmation générale d'absence de toute journalisation : elle vise explicitement les cookies, pixels et techniques de fingerprinting publicitaire côté navigation.

Le code DataHub crée néanmoins une tension documentaire importante, car il associe requêtes, clics et publicités à des identifiants techniques côté serveur. Pour qualifier cette tension de fausse déclaration, de manquement ou de dissimulation, il faudrait encore établir :

  • la notice effectivement publiée à la date pertinente ;
  • le périmètre exact donné à l'expression « traceur publicitaire » ;
  • le déploiement effectif du DataHub ;
  • les finalités et durées du traitement ;
  • le régime juridique applicable à la date des faits ;
  • l'information réellement fournie aux utilisateurs.

Le code ne permet pas, à lui seul, d'attribuer une intention mensongère.


A. Faits établis par le dépôt

Le dépôt permet de soutenir que :

  1. le nom DataHub est explicitement utilisé dans les commentaires, commits et un tag ;
  2. une architecture d'envoi JSON vers une queue analytics interne est implémentée ;
  3. l'enveloppe commune contient l'IP complète, le User-Agent, la locale, l'URI et le référent ;
  4. un hash stable de l'IP est ajouté à partir d'août 2016 ;
  5. les recherches normales et celles servies depuis le cache peuvent être journalisées ;
  6. les clics SERP, les clics de page d'accueil et les impressions publicitaires disposent d'événements dédiés ;
  7. les annonces affichées peuvent être enregistrées avec la requête correspondante ;
  8. des actions de compte, de boards, de contact et des erreurs alimentent aussi le DataHub ;
  9. une blacklist produite en aval par le DataHub peut conduire l'API à refuser une requête ;
  10. des versions taguées contiennent ce code et une configuration nommée production vise deux serveurs internes.

B. Inférences techniquement raisonnables mais conditionnelles

Sous réserve de réception et de conservation des événements :

  • le hash stable permet de regrouper les événements provenant d'une même IP ;
  • l'association IP + User-Agent + date + contenu peut rendre un parcours individualisable ;
  • le système peut servir à l'analytics produit, à la mesure publicitaire et à l'antiflood ;
  • l'enregistrement conjoint de requêtes et de clics peut permettre des analyses comportementales.

Ces capacités ne prouvent pas que chacune de ces analyses a été effectivement exécutée.

C. Éléments non établis par ce dépôt

Le dépôt ne prouve pas :

  • que tous les tags ont été déployés en production ;
  • que tous les fronts appelaient les endpoints de clic ;
  • que chaque message a atteint RabbitMQ ;
  • le schéma de stockage aval du DataHub ;
  • les durées de conservation ;
  • les habilitations d'accès ;
  • l'existence d'un dashboard ou d'un profil publicitaire par personne ;
  • une correspondance entre un hash et une identité civile ;
  • une transmission du DataHub interne à Microsoft ;
  • l'utilisation du DataHub pour surveiller une personne déterminée ;
  • une faute pénale, civile ou réglementaire ;
  • l'intention personnelle d'un développeur ou d'un dirigeant.

XIII. Formulation probatoire de synthèse

La synthèse la plus solide est la suivante :

Dès 2016, Qwant avait développé et versionné un dispositif interne de journalisation serveur désigné comme DataHub. Dans le tag v1.32.1, ce dispositif était capable d'enregistrer les requêtes de recherche, les clics et les impressions publicitaires avec l'adresse IP complète, le User-Agent, le contexte HTTP et un hash stable dérivé de l'IP. Il permettait ainsi un tracking serveur individualisable côté Qwant et alimentait aussi une fonction de lutte contre les abus. Le code établit cette capacité technique et son intégration dans des versions de release ; il ne suffit pas à démontrer son déploiement sur tout le trafic, ses durées de conservation, la constitution effective d'un profil publicitaire longitudinal ou une transmission du DataHub à Microsoft.

Cette formulation articule le code à sa portée réelle sans réduire le DataHub à une simple statistique publicitaire, ni transformer une capacité technique en résultat opérationnel ou en qualification juridique non démontrée.


Fichiers du tag v1.32.1

  • www/application/models/logger.php — structure des événements, métadonnées client et HTTP, hash, transport RabbitMQ ;
  • www/application/hooks/QwantHook.php — déclenchement du flush en fin de requête ;
  • www/application/config/logger.php — hostname analytics de l'environnement général ;
  • www/application/config/production/logger.php — hôtes internes de production ;
  • www/application/libraries/search_service.php — événements de recherche et feedSearchSuggest() ;
  • www/application/controllers/LoggerClickAPIController.php — clics SERP, page d'accueil et Cinetick ;
  • www/application/models/url_model.php — stockage Elasticsearch distinct des clics ;
  • www/application/models/search/search_ads.php — Bing Ads et événements ads_print ;
  • www/application/models/httpgateway.php — appels aux fournisseurs externes ;
  • www/application/models/user_model.php — lecture de la blacklist générée par le DataHub ;
  • www/application/core/MY_Controller.php — refus d'accès lié au bannissement DataHub.

Commits structurants

  • 48a167106a2bf14b7521767d92242bf41bda6966 — intégration initiale du DataHub ;
  • c3c69dff89c5f06b1ed76070e099830592d50f14 — transport phpAmqpLib et multi-hôtes ;
  • 86e9620bda9ea76653cb5d40cbaf3c74a95c819b — impressions publicitaires ;
  • 7799a5c5607b6c36439d6f6afda040d40b873204 — hash client stable et score antispam ;
  • 4bdfca906f4a0aebefb10c82293ec8b2cd72d9ce — détail des annonces ;
  • 451981b7ea92264f2c3ffd8561cf748d23b8e8f9 — contrôleur de clics ;
  • c5f1e1d72dbca51d22115e2d3c43e2210b88396d — actions de compte et de contenu ;
  • d6aa1cf0c610d5b7eaad19085db4b71bae4c961f — bannissement produit par le DataHub.

Articulation avec le reste du dossier

← Retour au sommaire du dossier Qwant

⬇ Download