E-02 Passerelle DLP
Brique E: Données, RAG, contexte, mémoire. Version anglaise: E-02-dlp-gateway
1. Rôle et responsabilités
Inspecte et transforme les flux (prompts, sorties d'outils, messages, documents) : detect, mask, tokenize, block.
- Appliquer les règles eai.dlp_rules
- Choisir le mode selon la politique et la destination
- Tokeniser via E-03 en mode tokenize
2. Position dans l'architecture et interactions
- Appelants: Gateway modèles, Tool Gateway, Channel Gateway, A2A.
- Chemin d'exécution: Synchrone, en ligne.
- Toute interaction passe par l'API Control Plane v1 (
/v1) derrière la passerelle API (D-14).
3. Composant open source et partie développée
- Open source: Presidio (anonymizer)
- Développé: Passerelle, règles, modes.
- Intégration externe via un adaptateur
eai/integrations/<system>.pyavec repli in-process lorsque l'URL n'est pas configurée.
4. Modèle de données
Tables (schéma eai, RLS tenant_id):
eai.dlp_rules
Colonnes communes : id uuid, tenant_id uuid NOT NULL, created_at, updated_at ; politique RLS current_setting('app.tenant_id', true)::uuid.
5. Contrat
- Contrat appliqué: policy-contract (obligations dlp)
- Schéma JSON:
contracts/v1/policy-contract.schema.json - Champs clés:
obligations[].type=dlp, mode - Validation :
POST /v1/contracts/{name}/validate; application d'un manifeste :POST /v1/manifests/apply.
6. Endpoints API
POST /v1/dlp/inspectPOST /v1/dlp/redactGET /v1/dlp/rulesPOST /v1/dlp/rules
Requête POST /v1/dlp/redact:
{
"text": "Appelez-moi au 06 12 34 56 78",
"mode": "mask"
}
Réponse:
{
"text": "Appelez-moi au <PHONE_NUMBER>",
"findings": [
{
"type": "PHONE_NUMBER"
}
],
"action": "masked"
}
7. Exemples SDK
Python:
from enterprise_ai import EnterpriseAI
client = EnterpriseAI(base_url="<control-plane-url>", api_key="eai_xxx_secret")
out = client.dlp.redact(text="...", mode="mask")
TypeScript:
import { EnterpriseAI } from "@enterprise-ai/sdk";
const client = new EnterpriseAI({ baseUrl: "<control-plane-url>", apiKey: process.env.EAI_API_KEY });
const out = await client.dlp.redact({ text: "...", mode: "mask" });
Java:
EnterpriseAIClient client = EnterpriseAIClient.builder()
.baseUrl("<control-plane-url>")
.apiKey(System.getenv("EAI_API_KEY"))
.build();
JsonNode out = client.dlp().redact(Map.of("text", "Call me at +33 6 12 34 56 78", "mode", "mask"));
Go:
c, _ := eai.NewClient(eai.WithBaseURL("<control-plane-url>"), eai.WithAPIKey(os.Getenv("EAI_API_KEY")))
out, _ := c.DLP.Redact(ctx, map[string]any{"text": "...", "mode": "mask"})
8. Configuration
- Variables d'environnement:
EAI_DATABASE_URL - Clés Helm:
controlPlane.config,controlPlane.secrets
9. Contrôles de sécurité
- Mode block pour secret vers fournisseur externe
- Règles modifiables par security_officer
- Toutes les requêtes portent le tenant issu du credential ; RLS PostgreSQL
- Chaque mutation et décision de politique écrit un événement d'audit chaîné
10. Observabilité
- Métriques Prometheus:
eai_dlp_findings_total{type,mode} - Traces: spans OpenTelemetry avec conventions sémantiques GenAI (
gen_ai.operation.name,gen_ai.agent.id,gen_ai.tool.name), attributseai.tenant_id,eai.run_id, propagationtraceparent. - Actions d'audit:
dlp.redact,dlp.inspect
11. Unités FinOps
- Caractères inspectés.
- Émis comme Usage Event (
POST /v1/finops/usage) avec tenant, projet, agent et run.
12. Modes de défaillance et résilience
- Refus par défaut (fail closed) sur données restricted
- Erreurs normalisées (enveloppe error, message_i18n en/fr)
13. Adoption autonome (client d'un client)
- enterprise_ai.dlp + Control Plane.
- SDK:
enterprise_ai.privacy / dlp / knowledge_bases / memory / retention / lineage - Déploiement minimal : chart Helm avec
controlPlane.enabled=trueet PostgreSQL ; les composants externes désactivés utilisent leur repli in-process.
14. Tests d'acceptation
- mode block -> 403 dlp_blocked
- mask remplace l'entité
- Accès inter-tenant refusé
- Erreur renvoyée en fr avec Accept-Language: fr
Fichiers des adaptateurs et DLP de sortie en flux
- Un fichier envoyé à un adaptateur spécialisé (par exemple
/v1/gateway/audio/transcriptions) passe par la DLP multimodale F11 avant l'appel : texte extrait selon le type (document, OCR d'image, transcription audio) et métadonnées (nom du fichier). En modeblock, la réponse est 422dlp_blockedavecdirection=fileet l'adaptateur n'est pas appelé. - Les réponses texte des adaptateurs (champs
text,transcript,ocr_text, réponsestext/*) passent par la DLP de réponse avec le mode du tenant. - En flux, un tampon glissant est toujours actif dès que la DLP n'est pas à
off: la fin du texte (EAI_STREAM_DLP_HOLDBACK_CHARS, 128 caractères par défaut) est retenue, et une entité détectée à cheval sur la coupure est gardée entière pour le morceau suivant. Une donnée coupée entre deux morceaux est donc détectée et masquée.
RAG gouverné (kit L4)
Presidio (presidio-analyzer et presidio-anonymizer, modèle spaCy en_core_web_sm) est testé pour de vrai sur des exemples bancaires fictifs (IBAN FR, carte avec Luhn, téléphone français, e-mail, nom) dans tests/test_data_presidio_real.py ; les reconnaisseurs intégrés restent le repli.