Aller au contenu principal

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>.py avec 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/inspect
  • POST /v1/dlp/redact
  • GET /v1/dlp/rules
  • POST /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), attributs eai.tenant_id, eai.run_id, propagation traceparent.
  • 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=true et PostgreSQL ; les composants externes désactivés utilisent leur repli in-process.

14. Tests d'acceptation​

  1. mode block -> 403 dlp_blocked
  2. mask remplace l'entité
  3. Accès inter-tenant refusé
  4. 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 mode block, la réponse est 422 dlp_blocked avec direction=file et l'adaptateur n'est pas appelé.
  • Les réponses texte des adaptateurs (champs text, transcript, ocr_text, réponses text/*) 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.