### **8. Sécurité, Authentification et RGPD**

#### **8.1. Frontières de confiance**

| Frontière | Ce qui est validé | Où |
| --- | --- | --- |
| Page hôte vers SDK | Rien n'est supposé : ni la présence d'un élément, ni l'intégrité des API du navigateur | SDK, en permanence |
| SDK vers backend | Clé publique, origine, forme et volume des lots d'événements | Backend, avant écriture |
| Extension vers backend | Session, appartenance à l'organisation, contrat de parcours, contenu riche | Backend, avant écriture |
| Content script vers service worker | Type et forme de chaque message | Service worker, à la réception |
| Backend vers PostgreSQL | Contraintes de clés, d'unicité et de domaine | Moteur de base de données |

Aucune de ces validations n'est déléguée à la couche précédente. La validation côté extension existe pour la qualité du retour à l'administrateur ; celle du backend est la seule qui fasse autorité.

#### **8.2. Clé publique du SDK**

La clé publique est visible dans le code source de chaque page cliente. Elle est traitée comme une donnée publique, jamais comme un secret.

**Ce qu'elle autorise :** lire le manifeste et les versions publiées du projet, et déposer des événements de télémétrie depuis une origine autorisée.

**Ce qu'elle n'autorise pas :** lire un brouillon, lister les projets, accéder à des statistiques, écrire ou publier quoi que ce soit. Aucune opération d'administration n'accepte ce type de clé, quelle que soit la route empruntée.

La conséquence est assumée : un tiers peut lire les parcours publiés d'un client à partir de sa clé. Ces documents contiennent des libellés d'interface et des sélecteurs, c'est-à-dire des informations déjà visibles par tout visiteur du site. Les clients en sont informés, plutôt que rassurés par une protection que la restriction d'origine ne fournit pas réellement (section 7.3).

#### **8.3. Authentification des administrateurs**

**Méthode V1 : OAuth 2.0 / OpenID Connect** auprès de Google, Microsoft et GitHub (ADR-05). Aucun mot de passe n'est stocké par Circuy, ce qui supprime d'emblée toute une catégorie d'incidents.

Le protocole n'est pas réimplémenté : il repose sur une bibliothèque OAuth/OIDC éprouvée et étroitement ciblée, dont le choix précis est arrêté au démarrage de l'implémentation. Écrire soi-même une validation de jeton d'identité ou une vérification de paramètre anti-rejeu est exactement le genre de code dont les failles ne se voient qu'après exploitation.

**Sessions par identifiant opaque, non par jeton auto-porteur.** La session est un identifiant aléatoire stocké en base et transporté par un cookie `HttpOnly`, `Secure`, `SameSite=Lax`, valable trente jours de façon glissante.

Ce choix s'écarte du couple jeton court et jeton de renouvellement décrit dans les documents de travail. Un jeton auto-porteur ne se révoque pas : sa seule qualité est de dispenser d'une lecture en base, or nous disposons d'une base à un millième de milliseconde du serveur applicatif, et d'une instance unique (ADR-10). Nous paierions donc en révocabilité une performance dont nous n'avons pas besoin. Déconnecter un appareil, exclure un collaborateur ou réagir à un vol de session doit être immédiat et fiable.

#### **8.4. Authentification de l'extension**

1. L'utilisateur lance la connexion depuis la popup, qui ouvre le flux d'authentification web du navigateur vers `app.circuy.net/auth/extension`.
2. Le dashboard authentifie l'utilisateur par les moyens de la section 8.3.
3. Le backend émet un **jeton d'extension** : valeur aléatoire opaque, enregistrée en base, rattachée à l'utilisateur et à l'installation, révocable individuellement.
4. La page redirige vers l'URL de rappel de l'extension, porteuse du jeton.
5. Le service worker le capte et le range dans `chrome.storage.local`.

**Le stockage local du navigateur est proscrit** pour ce jeton : il est accessible depuis les content scripts et donc exposé aux pages hôtes.

**Pas de rotation par jeton de renouvellement.** Le jeton d'extension est de longue durée et vérifié en base à chaque appel, exactement comme une session. Ajouter un cycle de renouvellement doublerait les chemins d'échec, dans un contexte où le jeton ne quitte jamais le service worker et où la révocation est déjà immédiate.

La liste des extensions connectées est visible dans le dashboard, avec révocation unitaire.

#### **8.5. Contenu injecté**

C'est le risque le plus sérieux du produit : Circuy transporte du contenu rédigé chez un client jusqu'aux navigateurs de ses utilisateurs. Une faille ici ferait de Circuy un vecteur d'attaque contre les sites qu'il équipe.

**Assainissement à la publication, côté serveur.** Le corps des étapes est nettoyé par une bibliothèque d'assainissement HTML éprouvée, jamais par des expressions régulières écrites pour l'occasion. Seul le résultat assaini est enregistré : la donnée stockée est déjà sûre, et le SDK n'a pas à refaire ce travail chez chaque visiteur.

**Liste blanche stricte :** emphase, gras, liens, listes et sauts de ligne. Sont retirés sans exception les balises de script et de style, tous les attributs d'événement, et tout lien dont le protocole n'est ni `http`, ni `https`, ni `mailto`. Les liens sortants reçoivent `rel="noopener noreferrer"`.

**Compatibilité avec une politique de sécurité de contenu stricte.** Le SDK n'insère aucune balise de style dans le document hôte : sa feuille de style est adoptée par la racine fantôme sous forme d'objet construit (section 3.2). Il n'évalue jamais de chaîne comme du code. Un client appliquant une politique de sécurité de contenu restrictive peut donc intégrer Circuy sans l'assouplir, ce qui est un argument commercial autant qu'une exigence technique.

#### **8.6. RGPD**

**Ce qui est réellement collecté sur les utilisateurs finaux :**

| Donnée | Nature |
| --- | --- |
| Identifiants de projet, de parcours, de version, d'étape | Technique |
| Identifiant de session | Aléatoire, renouvelé à chaque session, jamais relié à une personne |
| Type d'événement et horodatage | Technique |
| Option choisie lors d'une question | Réponse à un choix proposé par le client |

**Ce qui n'est pas collecté :** adresse IP, agent utilisateur, cookie, identifiant persistant, contenu des champs de formulaire, URL complète, et les attributs transmis à `identify`, qui ne servent qu'au ciblage local (section 5.4).

L'absence d'identifiant persistant côté serveur est une décision de conception, pas une omission : elle est ce qui permet d'affirmer que la télémétrie de Circuy ne permet pas de reconstituer le parcours d'une personne, et elle explique pourquoi le plafonnement de fréquence est tenu localement (section 3.5).

**Stockage sur le terminal.** Le SDK écrit dans le stockage local du navigateur pour reprendre un parcours interrompu et ne pas rejouer un parcours déjà vu. Cet usage relève du fonctionnement même du service demandé par l'éditeur du site. La qualification définitive au regard des règles sur le consentement appartient toutefois au client, qui est responsable de traitement ; Circuy lui fournit la description exacte des clés écrites, de leur contenu et de leur durée, afin qu'il puisse l'intégrer à sa propre documentation. Il n'appartient pas à Circuy de trancher à sa place.

**Rôles.** Le client est responsable de traitement, Circuy est sous-traitant. Un contrat de sous-traitance est fourni, énumérant les traitements, les durées et l'unique hébergeur.

**Localisation.** Toutes les données, y compris les sauvegardes et les journaux, résident **aux Pays-Bas**, chez l'hébergeur Greenshift (section 7.4). La communication commerciale annonce donc un hébergement européen, jamais français : une affirmation inexacte sur ce point serait la plus coûteuse de toutes pour un produit vendu sur la souveraineté.

Le centre de données est exploité en colocation par Iron Mountain, société de droit américain, qui fournit le bâtiment, l'énergie et la sécurité physique sans accès logique aux données. Ce point figure au contrat de sous-traitance en toute transparence, avec la description exacte du rôle de chaque intervenant.

Aucun traitement, aucun transfert et aucun sous-traitant ne sortent de l'Union européenne. C'est la substance du différenciateur de souveraineté et cela doit le rester : toute dépendance future à un service extra-européen, y compris un fournisseur de modèle de langage (section 10.1), le contredirait frontalement et exige un ADR explicite.

**Durées.** Les événements sont supprimés au-delà de treize mois (section 5.6). La suppression d'un projet efface en cascade ses parcours, ses versions et ses événements.

**Droits des personnes.** Ne détenant aucun identifiant de personne, Circuy ne peut pas isoler les données d'un utilisateur final : il n'y a pas de données personnelles à extraire ou à rectifier. Les demandes portant sur les comptes administrateurs, qui sont eux nominatifs, sont traitées depuis le dashboard.
