Endpoints RGPD¶
AKKO v2026.04 livre deux endpoints admin RGPD pour répondre
programmatiquement aux demandes d'accès (DSAR). Les deux sont gated sur
le rôle realm akko-admin et produisent une trace d'audit immutable.
Voir compliance-matrix.fr.md pour la cartographie complète des régulations.
Architecture¶
Les endpoints vivent sur le Deployment akko-catalog-manager (partage
son app FastAPI pour l'auth JWKS Keycloak + audit structuré +
compteurs Prometheus). Ils sont exposés via le proxy nginx cockpit :
Cockpit / CLI
│ Authorization: Bearer <admin-JWT>
▼
cockpit nginx → /api/cockpit/catalog-manager/api/admin/users/...
▼
akko-catalog-manager (routes_gdpr.py)
├─ Keycloak admin-cli (DELETE /users/{id})
├─ Trino (DELETE / SELECT sur tables PII)
└─ Audit JSON → logs layer (S3 WORM 365 j)
Configuration¶
Deux variables d'env sur le Deployment pilotent le comportement :
| Variable | Rôle | Défaut |
|---|---|---|
AKKO_KC_ADMIN_USER |
admin master realm Keycloak | requis |
AKKO_KC_ADMIN_PASSWORD |
mot de passe correspondant (Secret) | requis |
AKKO_GDPR_PII_TABLES |
Liste séparée par virgule iceberg.<schema>.<table> |
auto-découverte iceberg.*.users |
Pour figer un ensemble précis de tables :
akko-catalog-manager:
extraEnv:
- name: AKKO_GDPR_PII_TABLES
value: "iceberg.banking.customers,iceberg.healthcare.patients,iceberg.retail.customers"
POST /api/admin/users/{user_id}/erasure¶
RGPD Art. 17 — Droit à l'effacement (« droit à l'oubli »).
curl -X POST https://cockpit.client.example/api/cockpit/catalog-manager/api/admin/users/42/erasure \
-H "Authorization: Bearer $ADMIN_TOKEN"
Réponse 202 Accepted :
{
"user_id": "42",
"keycloak_deleted": true,
"tables_processed": [
"iceberg.banking.customers",
"iceberg.healthcare.patients"
],
"tables_failed": [],
"timestamp": 1713542400.0,
"actor": "alice"
}
Effets :
- L'utilisateur est supprimé de Keycloak, toutes ses sessions actives sont révoquées.
- Les lignes correspondant à
user_id = <id>sont supprimées de chaque table de la liste PII. - Un événement d'audit immutable
USER_ERASEDest écrit dans logs layer et mirroré vers le bucket S3 WORM (Object Lock COMPLIANCE 365 j).
Les échecs partiels sont consignés dans tables_failed[] sans
interrompre l'effacement global — le reçu fait foi pour ce qui a été
effacé.
GET /api/admin/users/{user_id}/export¶
RGPD Art. 20 — Droit à la portabilité des données.
curl -X GET https://cockpit.client.example/api/cockpit/catalog-manager/api/admin/users/42/export \
-H "Authorization: Bearer $ADMIN_TOKEN" \
--output akko-gdpr-export-42.zip
Réponse : application/zip avec
iceberg_banking_customers.csviceberg_healthcare_patients.csviceberg_retail_customers.csvMANIFEST.json(user_id, exported_at, exported_by, schema_version, format)
Observabilité¶
Compteurs Prometheus exposés par akko-catalog-manager :
akko_gdpr_operations_total{operation="erasure|export", result="success|partial|failure"}
Logs d'audit (LogsQL logs layer) :
Cibles de temps de réponse¶
| Endpoint | Cible p95 | Données test |
|---|---|---|
| erasure (50 tables PII) | < 5 s | 100 k lignes / table |
| export (50 tables PII) | < 20 s | 100 k lignes / table |
Au-delà, l'endpoint renvoie 202 et le travail complet tourne en asynchrone — endpoint de polling sur la roadmap Sprint 44.
Runbook opérationnel¶
| Symptôme | Cause probable | Correctif |
|---|---|---|
| 401 Unauthorized | JWT admin absent / expiré | Re-auth via login cockpit |
| 500 "Keycloak admin credentials not configured" | AKKO_KC_ADMIN_USER/PASSWORD non set | Créer le Secret + redémarrer le déploiement |
tables_failed[].error = "NOT NULL constraint" |
Table PII a des FK avec cascade off | Splitter en plusieurs sous-suppressions documentées |
| Audit absent de logs layer | Logs des pods non scrapés | kubectl -n akko logs deploy/akko-akko-catalog-manager --tail=20 |
Notes juridiques¶
- Le reçu JSON est signé (HMAC-SHA256) avec la clé d'audit du cluster — preuve d'effacement pour le DPO sans avoir à requêter le log store.
- Le « droit à l'oubli » ne prévaut pas sur les obligations de rétention légales (DORA, exigences d'audit AMF). Consulter votre DPO avant d'activer l'endpoint en production.