Aller au contenu

Inventaire DPIA — flux de données personnelles dans AKKO

Qui est responsable du DPIA ? L'opérateur AKKO (le client) est responsable du traitement et doit déposer le DPIA auprès de son DPO. AKKO en tant qu'éditeur de plateforme fournit cet inventaire pour que le responsable de traitement sache exactement quelles données les composants AKKO touchent — sans avoir à reconstituer l'information à partir des logs.

Déclenchement — RGPD Art. 35(1) impose un DPIA quand « un type de traitement est susceptible d'engendrer un risque élevé pour les droits et libertés des personnes physiques ». Une plateforme comme AKKO qui ingère l'activité d'utilisateurs authentifiés, fédère des requêtes sur plusieurs sources, et exécute des agents LLM sur du contenu fourni par les utilisateurs franchit typiquement ce seuil.

Lecture de l'inventaire

Chaque ligne est un flux de données personnelles distinct. Colonnes :

Colonne Sens
Composant Le service AKKO qui détient la donnée
Catégorie RGPD Art. 4(1) — type de donnée personnelle
Personne concernée À qui la donnée appartient (employé / client / utilisateur final)
Stockage Où elle atterrit physiquement
Conservation Durée par défaut de la plateforme
Base légale Base par défaut quand AKKO est utilisé tel que conçu (le responsable peut surcharger)
Mesure de sécurité Mesure technique/organisationnelle qui mitige le risque

Les valeurs par défaut sont la configuration prête à l'emploi. Le responsable de traitement peut durcir la conservation ou changer la base légale via les runbooks listés en Références en bas.


1 — Authentification & identité

Composant Catégorie Personne Stockage Conservation Base légale Sécurité
Keycloak (akko-keycloak) Email, prénom/nom, appartenance aux groupes, hash mot de passe (bcrypt), secrets OTP Employé, partenaire DB PostgreSQL keycloak Jusqu'à suppression du compte Contrat (Art. 6(1)(b)) — nécessaire pour authentifier Bcrypt, TOTP optionnel, SSO, log d'audit
directory service / 389-DS (akko-directory) Idem Keycloak quand fédéré Employé Backend LDAP Jusqu'à suppression Contrat TLS 1.3, RBAC
Cookie de session oauth2-proxy ID de session chiffré, ID token OIDC (claims : sub, email, groups, exp) Utilisateur authentifié Cookie navigateur + Redis Durée de vie cookie (8h par défaut) Contrat Cookie AES-GCM, Secure, HttpOnly, SameSite=Lax

2 — Activité & logs d'audit

Composant Catégorie Personne Stockage Conservation Base légale Sécurité
Logs de décision OPA ID utilisateur, rôle, ressource demandée, décision, horodatage Utilisateur authentifié Stream decision_logs logs layer 90 jours par défaut Intérêt légitime (Art. 6(1)(f)) — audit sécurité Append-only, accès restreint via cockpit
Événements admin Keycloak ID admin, ID cible, action (create/delete/changement de rôle), horodatage Admin + cible PostgreSQL keycloak.admin_events 90 jours par défaut Obligation légale (Art. 6(1)(c)) — DORA Art. 11 / NIS2 Art. 21 Tamper-evident, accès restreint
Log de requêtes Trino ID utilisateur, texte SQL, IP source, horodatage, octets scannés Utilisateur authentifié OPA → stream trino_queries logs layer 90 jours par défaut Intérêt légitime — audit, capacity planning Le texte SQL peut contenir des données personnelles si l'utilisateur SELECT depuis des colonnes PII ; gating via row-filters OPA
Log d'audit Airflow ID utilisateur lançant le DAG, instance de tâche, horodatage Opérateur PostgreSQL airflow.log 30 jours par défaut Obligation légale UI à accès restreint
Log d'accès cockpit ID utilisateur, page visitée, horodatage Utilisateur authentifié Log nginx → logs layer 30 jours par défaut Intérêt légitime Agrégé pour stats d'usage

3 — Contenu fourni par l'utilisateur

Composant Catégorie Personne Stockage Conservation Base légale Sécurité
Documents akko-rag uploadés Texte du document + embeddings (pgvector) ; nom de fichier, ID utilisateur uploader Clients/contrats de l'uploader (potentiellement) PostgreSQL akko_rag.documents + SeaweedFS akko-rag/originals/ Pas de suppression automatique — pilotée par l'opérateur Consentement (Art. 6(1)(a)) si l'utilisateur final upload via UI ; sinon contrat TLS en transit, chiffrement colonne pgcrypto disponible, gate OPA sur /query
Questions ADEN en langage naturel Texte de la question, ID utilisateur, horodatage Utilisateur authentifié PostgreSQL aden.questions 30 jours par défaut Intérêt légitime — amélioration du modèle L'opérateur peut désactiver via aden.persistQuestions=false
Dashboards ADEN JSON dashboard (peut contenir texte SQL + ID utilisateur) Utilisateur authentifié SeaweedFS aden/dashboards/ Jusqu'à suppression utilisateur Intérêt légitime Gating OPA, URLs signées
Sorties de notebooks Texte/images de cellules (peuvent inclure des données personnelles imprimées) Propriétaire du notebook PVC JupyterHub Pilotée par l'opérateur Consentement PVC par utilisateur, pas de lecture cross-user
Expériences MLflow Auteur, paramètres de run, métriques, URI d'artefacts Utilisateur authentifié PostgreSQL mlflow + SeaweedFS mlflow/ Pilotée par l'opérateur Contrat Accès restreint via Keycloak

4 — Traitement médié par LLM

Composant Catégorie Personne Stockage Conservation Base légale Sécurité
Gateway LiteLLM Prompts + complétions routés Utilisateur authentifié En mémoire seulement par défaut ; log optionnel vers logs layer 0 (pas de persistance) par défaut Contrat TLS vers Ollama upstream ; aucun appel API externe par défaut — souverain
Ollama (akko-llm) Idem Idem En mémoire seulement 0 Contrat Air-gapped — modèle tourne sur GPU/CPU local
Trace de raisonnement ADEN Entrées/sorties d'étapes pipeline, contexte récupéré, SQL généré Utilisateur authentifié PostgreSQL aden.reasoning 30 jours par défaut Intérêt légitime — explicabilité (Sprint 41) Conservation pilotée par l'opérateur ; l'utilisateur peut purger sa trace

5 — Lac de données & entrepôt

Composant Catégorie Personne Stockage Conservation Base légale Sécurité
Stockage objet SeaweedFS Tout ce que le client ingère (peut inclure des PII) Personnes concernées du client Volumes SeaweedFS Pilotée par l'opérateur Définie par le client Chiffrement volume optionnel (-volume.encrypted=true — Sprint 52 P1)
PostgreSQL akko_data Idem Idem DB PostgreSQL data Pilotée par l'opérateur Définie par le client Chiffrement colonne pgcrypto disponible
Tables Iceberg (Polaris) Idem Idem SeaweedFS iceberg/ Pilotée par l'opérateur Définie par le client Politiques OPA row/column via Trino
Catalogue OpenMetadata Tags + descriptions de datasets (pas de données ligne) PostgreSQL openmetadata + OpenSearch Pilotée par l'opérateur Métadonnées seulement, pas de corps PII

Comment traiter une demande d'accès (RGPD Art. 15)

Lancer depuis le namespace akko-aden où le bot du responsable a un accès lecture sur tous les sous-systèmes. L'helper dsr.sh est livré à scripts/dsr.sh et produit un bundle JSON unique pour l'utilisateur.

# Identifier l'utilisateur (userId Keycloak, pas l'email — les emails changent)
USER_ID=$(curl -s -H "Authorization: Bearer $ADMIN_TOKEN" \
  "https://identity.akko-ai.com/admin/realms/akko/users?email=user@exemple.com" \
  | jq -r '.[0].id')

# Bundle de tous les flux pour cet utilisateur
bash scripts/dsr.sh "$USER_ID" > dsr-$USER_ID.json

Le bundle couvre identité Keycloak + décisions OPA + requêtes Trino + runs Airflow + questions ADEN + expériences MLflow + listing PVC notebook + documents RAG uploadés. À remettre au demandeur dans le délai légal d'un mois.

Comment traiter un droit à l'effacement (RGPD Art. 17)

Même périmètre que le bundle, mais la suppression nécessite l'accord de l'opérateur car certains enregistrements sont soumis à conservation légale (ex : DORA Art. 11 impose la conservation des logs d'audit même après effacement par la personne concernée). Le script émet un plan de suppression ; l'opérateur valide ; le script exécute par composant, avec une tombstone écrite dans le log d'audit.

bash scripts/erasure.sh "$USER_ID" --dry-run    # plan seulement
bash scripts/erasure.sh "$USER_ID" --execute    # après validation

Transferts hors UE

AKKO est souverain par construction — aucun service ne fait d'appel HTTPS sortant en déploiement par défaut. Le responsable peut le vérifier en inspectant les NetworkPolicies (kubectl get netpol -n akko) — seul le trafic ingress Traefik et intra-namespace est autorisé ; l'egress vers Internet public est bloqué sauf activation explicite (ex : forwarding SIEM, documenté dans SIEM forwarder).

Si l'opérateur active une cible SIEM externe (Splunk Cloud, Sentinel, Elastic Cloud), l'activation est elle-même un transfert et l'opérateur doit l'ajouter à ses addenda DPIA avec la base légale choisie (CCT / adéquation).

Addendum Sprint 59 — flows ADEN ADR-041/042/043

Le refactor ADEN du Sprint 59 introduit trois nouveaux flows internes. Aucun ne touche aux PII de l'utilisateur — ils raisonnent uniquement sur les métadonnées de tables + le rôle de l'appelant — mais le DPO du contrôleur doit savoir qu'ils existent et où vivent les données.

Flow Composant Catégorie de données Stockage Rétention Base légale
ADR-041 OPA scope-first batch OPA + ADEN routes_query.py Rôle Keycloak de l'appelant + liste de FQN candidats catalogue.schéma.table (aucune donnée de ligne) Mémoire process uniquement Per-requête, jamais persisté Intérêt légitime (Art. 6(1)(f)) — enforcement d'accès
ADR-042 cache sémantique Tier 2 ADEN cache_layers.py (LRU in-process) Texte de question → embedding 768-d + clé cache 32-char. Même partition rôle/modèle. Mémoire process uniquement (pas de PVC, pas de Postgres) TTL 1 h, max 512 entrées par rôle/modèle Intérêt légitime — optimisation perf. Bypass via body.force=true ou pod restart.
ADR-043 catalogue sémantique Milvus akko-milvus (off par défaut) Descriptions de tables + noms de colonnes + embeddings 768-d — aucune donnée de ligne PVC StatefulSet, in-cluster uniquement Jusqu'au prochain run du CronJob aden-catalog-indexer (par défaut horaire) Intérêt légitime — recherche catalogue sémantique

Notes pour le contrôleur :

  • Le contenu du cache ADR-042 peut inclure des questions utilisateur (le prompt lui-même). Quand les questions contiennent des données personnelles ("affiche les transactions du client X"), l'embedding n'est réversible qu'avec le même modèle nomic-embed-text-v2 — mais le texte de la question est aussi conservé assez longtemps pour construire la clé cache. À traiter comme données personnelles. Le RTBF est honoré par le TTL et par kubectl rollout restart deploy/akko-akko-aden.
  • ADR-043 Milvus stocke des métadonnées de schéma, pas de lignes. Lister les noms de tables et de colonnes d'une banque n'est pas en soi une donnée personnelle, mais le contrôleur peut tout de même vouloir évaluer la sensibilité (par ex. une table nommée cessations_clients_2026 est révélatrice par elle-même).
  • Les trois flows respectent allowed_tables ADR-041 — un cache hit d'un viewer ne peut jamais être servi à un admin et inversement (bucketing par (rôle, modèle)). Le write path applique aussi remember_semantic avec le rôle de l'appelant — prouvé par tests/test_cache_layers.py::test_semantic_cache_role_partition.

Références

  • Matrice de conformité — mapping DORA / NIS2 / RGPD
  • Audit playbook — extraction du trail d'audit
  • Audit trail — forme des logs et contrôles de rétention
  • SIEM forwarder — intégration SIEM tiers
  • Chiffrement au repos — pgcrypto + chiffrement volume SeaweedFS
  • DR playbook — procédures de récupération (DORA Art. 11)
  • RGPD Art. 35 — déclenchement DPIA
  • Manuel ENISA « Sécurité du traitement des données personnelles » — guidance technique