Aller au contenu principal

Confidentialité des données et RGPD

Confidentialité des données et RGPD

En tant que développeur européen, vous devez comprendre comment les données transitent via l’API OpenAI et quelles mesures prendre pour respecter le RGPD. Cette leçon couvre les aspects techniques de la conformité.

Comment OpenAI traite vos données

Via l’API (pas ChatGPT)

Quand vous utilisez l’API OpenAI pour votre application :

  • Les données ne sont PAS utilisées pour entraîner les modèles (politique API)
  • Les données sont conservées 30 jours pour détecter les abus, puis supprimées
  • Vous pouvez demander la suppression anticipée (Zero Data Retention)
  • Les données transitent via les serveurs OpenAI (principalement aux États-Unis)
# Vérifier la politique de rétention de votre organisation
# sur platform.openai.com/settings/organization/data-controls

Minimisation des données

Le RGPD impose de ne traiter que les données strictement nécessaires. Appliquez ce principe à vos appels API :

import re

def anonymiser_avant_envoi(texte: str) -> tuple[str, dict]:
    """Anonymise les données personnelles avant l'envoi à l'API."""
    remplacements = {}
    compteur = {"email": 0, "telephone": 0, "nom": 0}

    # Emails
    def remplacer_email(match):
        compteur["email"] += 1
        cle = f"[EMAIL_{compteur['email']}]"
        remplacements[cle] = match.group()
        return cle

    texte = re.sub(
        r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b',
        remplacer_email, texte
    )

    # Téléphones français
    def remplacer_tel(match):
        compteur["telephone"] += 1
        cle = f"[TEL_{compteur['telephone']}]"
        remplacements[cle] = match.group()
        return cle

    texte = re.sub(
        r'\b(?:0|\+33)\s*[1-9](?:[\s.-]*\d{2}){4}\b',
        remplacer_tel, texte
    )

    return texte, remplacements

def restaurer_donnees(texte: str, remplacements: dict) -> str:
    """Restaure les données après traitement par l'API."""
    for cle, valeur in remplacements.items():
        texte = texte.replace(cle, valeur)
    return texte

# Utilisation
from openai import OpenAI
client = OpenAI()

texte_original = "Contactez Jean Dupont a [email protected] ou 06 12 34 56 78"

# Anonymiser
texte_anonyme, mapping = anonymiser_avant_envoi(texte_original)
print(f"Envoyé a l'API : {texte_anonyme}")
# Envoyé a l'API : Contactez Jean Dupont a [EMAIL_1] ou [TEL_1]

# Appel API avec données anonymisées
response = client.responses.create(
    model="gpt-5.3",
    input=f"Résumez ce message : {texte_anonyme}"
)

# Restaurer
resultat = restaurer_donnees(response.output_text, mapping)
print(f"Résultat final : {resultat}")

Pipeline conforme RGPD

from datetime import datetime
import json
import hashlib

class RGPDCompliantPipeline:
    """Pipeline de traitement conforme au RGPD."""

    def __init__(self):
        self.client = OpenAI()
        self.log_traitements = []

    def traiter(self, texte: str, finalite: str,
                base_legale: str, user_id: str) -> str:
        """Traite un texte en respectant le RGPD."""

        # 1. Enregistrer la base légale du traitement
        traitement = {
            "timestamp": datetime.now().isoformat(),
            "user_hash": hashlib.sha256(user_id.encode()).hexdigest()[:12],
            "finalite": finalite,
            "base_legale": base_legale,  # consentement, interet_legitime, contrat
        }

        # 2. Minimiser les données
        texte_anonyme, mapping = anonymiser_avant_envoi(texte)

        # 3. Appel API
        response = self.client.responses.create(
            model="gpt-5.3",
            input=texte_anonyme,
            # Stocker le moins longtemps possible
        )

        traitement["tokens_utilises"] = response.usage.total_tokens
        self.log_traitements.append(traitement)

        # 4. Restaurer et retourner
        return restaurer_donnees(response.output_text, mapping)

    def exporter_registre(self) -> str:
        """Exporte le registre des traitements (Article 30 RGPD)."""
        return json.dumps(self.log_traitements, indent=2, ensure_ascii=False)

# Utilisation
pipeline = RGPDCompliantPipeline()

resultat = pipeline.traiter(
    texte="Le client Pierre Martin souhaite résilier son abonnement.",
    finalite="Traitement de demande de résiliation",
    base_legale="contrat",
    user_id="user-456"
)
print(resultat)
print(pipeline.exporter_registre())

Gestion du consentement

class ConsentManager:
    """Gestion du consentement utilisateur pour le traitement IA."""

    def __init__(self):
        self.consentements: dict[str, dict] = {}

    def enregistrer_consentement(self, user_id: str, finalites: list[str]):
        """Enregistre le consentement d'un utilisateur."""
        self.consentements[user_id] = {
            "finalites": finalites,
            "date": datetime.now().isoformat(),
            "version": "v1.0"
        }

    def verifier_consentement(self, user_id: str, finalite: str) -> bool:
        """Vérifie si l'utilisateur a consenti a une finalité."""
        consent = self.consentements.get(user_id)
        if not consent:
            return False
        return finalite in consent["finalites"]

    def retirer_consentement(self, user_id: str):
        """Retire le consentement (droit de retrait)."""
        if user_id in self.consentements:
            del self.consentements[user_id]
            # Ici : supprimer aussi les données associées

# Utilisation
consent = ConsentManager()

# L'utilisateur consent au traitement IA
consent.enregistrer_consentement("user-123", ["assistance_ia", "analyse_texte"])

# Vérifier avant chaque traitement
if consent.verifier_consentement("user-123", "assistance_ia"):
    # Procéder au traitement
    response = client.responses.create(
        model="gpt-5.3",
        input="Question de l'utilisateur"
    )
else:
    print("Consentement requis pour ce traitement")

Droit à l’effacement (Article 17)

def exercer_droit_effacement(user_id: str):
    """Implémente le droit a l'effacement RGPD."""

    # 1. Supprimer les données locales
    # supprimer_donnees_utilisateur(user_id)

    # 2. Les données envoyées a l'API OpenAI sont supprimées
    # automatiquement après 30 jours (ou immédiatement
    # avec Zero Data Retention activé)

    # 3. Supprimer les logs qui contiennent des données personnelles
    # supprimer_logs_utilisateur(user_id)

    # 4. Documenter la suppression
    log = {
        "action": "droit_effacement",
        "user_hash": hashlib.sha256(user_id.encode()).hexdigest()[:12],
        "date": datetime.now().isoformat(),
        "donnees_supprimees": [
            "historique_conversations",
            "profil_utilisateur",
            "logs_activite"
        ]
    }
    print(json.dumps(log, indent=2, ensure_ascii=False))

exercer_droit_effacement("user-123")

Checklist RGPD pour les développeurs

  • Identifier la base légale de chaque traitement (consentement, contrat, etc.)
  • Minimiser les données envoyées à l’API (anonymisation)
  • Tenir un registre des traitements (Article 30)
  • Implémenter le droit d’accès et le droit à l’effacement
  • Documenter les transferts hors UE (OpenAI = serveurs US)
  • Activer Zero Data Retention si possible
  • Ne jamais loguer de données personnelles en clair

Points clés à retenir

  • L’API OpenAI ne réentraîne PAS ses modèles avec vos données
  • Anonymisez les données personnelles avant chaque appel API
  • Tenez un registre des traitements conforme à l’Article 30
  • Implémentez les droits RGPD : accès, rectification, effacement, portabilité
  • Le transfert de données hors UE nécessite des garanties (clauses contractuelles)
  • Documentez chaque décision relative à la protection des données