overmind-mcp
Version:
Orchestrateur universel agents IA multi-modeles via MCP. Inclut le protocole 'Custom-Nickname' pour identifier vos agents avec des surnoms originaux (The Chaos Prophet, Shadow Sniper, etc.), l'isolation mémoire (Private Memory Context) et le support pour
467 lines (381 loc) • 22 kB
Markdown
# Plan d'intégration Loi 25 — Overmind-MCP
> **Version** : 1.1 (décisions périmètre validées)
> **Date** : 21 juillet 2026
> **Statut** : ✅ Périmètre validé — prêt à coder
> **Cible** : overmind-mcp v3.9.0
>
> **Décisions validées** :
> - **Périmètre RP** : Mixte — consentement explicite (tiers externes) + intérêt légitime (usage interne)
> - **Transferts hors QC** : Documentation seule, aucun blocage de providers
> - **Rétention** : 30 jours par défaut pour tout, option de backup/archivage 5 ans
> - **Activation** : Flag `OVERMIND_AUDIT_ENABLED=true` dans `.env` (désactivé = pas de garde)
---
## 1. Contexte
L'Overmind est un **responsable de traitement** au sens de la Loi 25 (Loi moderneisant
des dispositions législatives en matière de protection des renseignements personnels).
Il collecte, stocke et transfère des renseignements personnels (RP) via :
- **Mémoire PostgreSQL/pgvector** : `agent_runs` (prompts/résultats), `knowledge_chunks` (texte + embeddings)
- **8 runners LLM externes** : Claude, Gemini, Kilo, QwenCLI, OpenClaw, Cline, OpenCode, Hermes
- **Bridge Discord** : messages utilisateurs → LLM
- **Profils Hermes** : `.env` (credentials), `SOUL.md` (personas), `state.db` (SQLite local)
La conformité Loi 25 n'est pas optionnelle : la CAI a publié son cadre d'application
des SAP en septembre 2023, et une vague d'application est imminente (2026-2027).
## 2. Articles Loi 25 applicables (matrice de conformité)
| Article | Obligation | État Overmind | Priorité |
|---|---|---|---|
| **3-3.1** | RPRP désigné + reddition de comptes | ❌ Aucun | P0 |
| **3.5-3.8** | Notification d'incident (CAI + personnes) | ❌ Aucun | P0 |
| **4** | Finalité légitime + collecte pertinente | ⚠️ Implicite | P1 |
| **8.1-8.2** | Consentement (libre, éclairé, spécifique) | ❌ Aucun | P0 |
| **12.1** | Évaluation de l'atteinte (échelle de gravité) | ❌ Aucun | P1 |
| **14-17.3** | Droits : accès, rectification, opposition, notification | ❌ Aucun | P0 |
| **18.1** | EFVP (évaluation facteurs vie privée) pour nouveaux projets | ❌ Aucun | P1 |
| **21-22** | Transferts hors Québec (documentation + garanties) | ❌ Aucun | P0 |
| **23.1** | Anonymisation (technique, non-réidentification) | ❌ Aucun | P1 |
| **26** | Droit d'accès (confirmation + communication) | ❌ Aucun | P0 |
| **27** | Droit de rectification | ❌ Aucun | P1 |
| **35.2-35.3** | Conservation et destruction des RP | ❌ Aucune rétention | P0 |
| **35.18** | Registre des traitements / politique de confidentialité | ❌ Aucun | P0 |
## 3. Architecture cible — Privacy by Design
```
┌─────────────────────────────────────────┐
│ Overmind MCP (FastMCP, 16 outils) │
│ │
Requête ──────────▶ │ ┌────────────────────────────────────┐ │
(prompt + │ │ 🛡️ LOI25 GUARD (middleware) │ │
data_subject_id + │ │ • Capture legal_basis │ │
legal_basis) │ │ • Valide consentement │ │
│ │ • Hash/anonymise si requis │ │
│ │ • Log transfert hors QC │ │
│ │ • Check rétention │ │
│ └─────────────┬──────────────────────┘ │
│ │ │
│ ┌───────────┼───────────┐ │
│ ▼ ▼ ▼ │
│ Runner Memory A2A Hub │
│ (8 LLM) (PG/vec) (bridges) │
└────┬──────────┬──────────┬───────────────┘
│ │ │
┌────────▼──────────▼──────────▼──────────────┐
│ 📋 LOI25 DATA LAYER (nouveau) │
│ • consent_records │
│ • data_subjects (registre) │
│ • processing_registry │
│ • incident_log │
│ • access_log │
│ • retention_policies │
│ • transfer_log (hors QC) │
└─────────────────────────────────────────────┘
```
## 4. Plan d'intégration — 8 axes, 4 phases
### Phase 1 — Fondations (P0, fondement légal)
**Objectif** : rendre l'Overmind capable de répondre aux droits d'accès, d'effacement
et de reddition de comptes.
#### 1.1 Schema DB — Gouvernance des RP
**Modifier** `src/memory/PostgresMemoryProvider.ts` (initialisation des tables) :
```sql
-- Extensions de agent_runs
ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS
data_subject_id TEXT, -- identifiant pseudonymisé de la personne
legal_basis TEXT, -- 'consent' | 'contract' | 'legitimate_interest' | 'legal_obligation'
consent_ref TEXT, -- FK vers consent_records.id
retention_expires_at BIGINT, -- timestamp d'expiration (art. 35.2)
anonymized INTEGER DEFAULT 0, -- 1 si anonymisé (art. 23.1)
created_for TEXT; -- finalité (art. 4)
-- Extensions de knowledge_chunks
ALTER TABLE knowledge_chunks ADD COLUMN IF NOT EXISTS
data_subject_id TEXT,
legal_basis TEXT,
consent_ref TEXT,
retention_expires_at BIGINT,
anonymized INTEGER DEFAULT 0;
```
**Nouvelles tables** (migration `scripts/audit_migration.mjs`) :
```sql
CREATE TABLE IF NOT EXISTS data_subjects (
id TEXT PRIMARY KEY, -- UUID pseudonymisé (jamais l'identité brute)
display_name TEXT, -- étiquette optionnelle (ex: "user_discord_123")
source TEXT, -- 'discord' | 'api' | 'manual'
created_at BIGINT,
metadata JSONB -- infos non-RP (compteur de requêtes, etc.)
);
CREATE TABLE IF NOT EXISTS consent_records (
id TEXT PRIMARY KEY,
data_subject_id TEXT NOT NULL,
purpose TEXT NOT NULL, -- 'agent_execution' | 'memory_storage' | 'embedding'
legal_basis TEXT NOT NULL,
granted_at BIGINT,
expires_at BIGINT, -- consentement peut expirer
withdrawn_at BIGINT, -- null si actif
evidence TEXT, -- hash du message/source de consentement
FOREIGN KEY (data_subject_id) REFERENCES data_subjects(id)
);
CREATE TABLE IF NOT EXISTS processing_registry (
id TEXT PRIMARY KEY,
name TEXT NOT NULL, -- 'agent_run_storage' | 'embedding_generation'
purpose TEXT NOT NULL,
legal_basis TEXT NOT NULL,
data_categories TEXT, -- 'prompts' | 'embeddings' | 'discord_messages'
recipients TEXT, -- providers LLM, vector DB
retention_days INTEGER,
created_at BIGINT,
updated_at BIGINT
);
CREATE TABLE IF NOT EXISTS incident_log (
id TEXT PRIMARY KEY,
detected_at BIGINT NOT NULL,
severity TEXT NOT NULL, -- 'low' | 'moderate' | 'high'
category TEXT, -- 'data_leak' | 'unauthorized_access' | 'breach'
description TEXT,
data_subjects_affected INTEGER,
cai_notified INTEGER DEFAULT 0,
subjects_notified INTEGER DEFAULT 0,
resolved_at BIGINT
);
CREATE TABLE IF NOT EXISTS access_log (
id TEXT PRIMARY KEY,
data_subject_id TEXT,
accessed_by TEXT, -- agent_name ou 'system'
action TEXT, -- 'read' | 'write' | 'delete' | 'transfer'
resource_type TEXT, -- 'agent_run' | 'knowledge_chunk'
resource_id TEXT,
purpose TEXT,
timestamp BIGINT
);
CREATE TABLE IF NOT EXISTS retention_policies (
id TEXT PRIMARY KEY,
category TEXT NOT NULL, -- 'agent_runs' | 'knowledge_chunks' | 'discord_messages'
retention_days INTEGER NOT NULL,
legal_basis TEXT,
anonymize_after_days INTEGER, -- anonymiser avant suppression (art. 23.1)
active INTEGER DEFAULT 1
);
CREATE TABLE IF NOT EXISTS transfer_log (
id TEXT PRIMARY KEY,
data_subject_id TEXT,
destination TEXT NOT NULL, -- 'anthropic' | 'google' | 'openai' | etc.
destination_region TEXT, -- 'US' | 'EU' | 'QC'
legal_mechanism TEXT, -- 'standard_contractual_clauses' | 'adequacy' | 'explicit_consent'
data_type TEXT,
timestamp BIGINT
);
```
#### 1.2 Nouveaux outils MCP (7 outils Loi 25)
Créer dans `src/tools/` :
| Outil | Article | Rôle |
|---|---|---|
| `audit_access_request` | 26 | Extrait tous les RP liés à un `data_subject_id` (export JSON) |
| `audit_rectification` | 27 | Modifie un RP sur demande du sujet |
| `audit_erasure` | 27 / 35.3 | Efface/anonymise les RP d'un sujet (droit à l'oubli) |
| `audit_consent` | 8.1-8.2 | Enregistre/vérifie/révoque un consentement |
| `audit_processing_registry` | 3-3.1 / 35.18 | Consulte le registre des traitements |
| `audit_report_incident` | 3.5-3.8 | Signale un incident + génère notification CAI |
| `audit_efvp` | 18.1 | Lance/consulte une évaluation des facteurs vie privée |
Chaque outil suit le pattern existant : `audit_<nom>.ts` exporte `loi25<Nom>Schema`
+ `loi25<Nom>Function`, enregistré dans `server.ts`.
#### 1.3 Migration de données existantes
Script `scripts/audit_backfill.mjs` :
- Scanne les `agent_runs` / `knowledge_chunks` existants
- Pour chaque enregistrement sans `data_subject_id` : tente de détecter un identifiant
dans le prompt (regex email/Discord ID) ou marque `data_subject_id = 'legacy_unknown'`
- Applique une politique de rétention rétroactive (ex: 90 jours)
- Anonymise les enregistrements expirés
---
### Phase 2 — Privacy Guard (P0, exécution)
**Objectif** : intercepter chaque flux de RP pour appliquer les contrôles Loi 25.
#### 2.1 Middleware AuditGuard
Créer `src/lib/audit/guard.ts` — wrapper appliqué à chaque outil manipulant des RP :
```typescript
export interface AuditContext {
dataSubjectId?: string; // obligatoire si RP détectés
legalBasis: LegalBasis; // 'consent' | 'contract' | 'legitimate_interest'
consentRef?: string; // requis si legalBasis = 'consent'
purpose: string; // finalité (art. 4)
anonymize?: boolean; // anonymiser avant stockage
}
```
**Mode mixte validé** — détection automatique de la base légale :
- **Tiers externes** (clients, citoyens via Discord/API) → `consent` obligatoire
- Détection : `dataSubjectId` absent du registre interne → flag `external = true`
- Le guard rejecte si pas de consentement valide
- **Usage interne** (toi + équipe) → `legitimate_interest` suffisant
- Détection : `dataSubjectId` dans allowlist `OVERMIND_AUDIT_INTERNAL_SUBJECTS`
- Pas de blocage, mais log quand même dans `access_log`
- **Fallback** : si `OVERMIND_AUDIT_ENABLED=false` → guard inactif, comportement v3.8
Le guard :
1. **Si `OVERMIND_AUDIT_ENABLED=false`** → pass-through (zero overhead)
2. **Détection de la base légale** selon l'origine du sujet (interne vs tiers)
3. **Valide le consentement** si tiers → reject si expiré/révoqué
4. **Détecte les RP** dans le prompt (regex PII : email, téléphone, NAS, carte crédit)
5. **Hash/anonymise** si `anonymize = true` (SHA-256 de l'identifiant avant stockage)
6. **Log le transfert** si un runner LLM externe est appelé (art. 21) — documentation seule, pas de blocage
7. **Calcule la rétention** selon `retention_policies` et pose `retention_expires_at`
#### 2.2 Capture au niveau du Bridge
Modifier `src/bridge/OverBridgeService.ts` :
- Chaque message Discord entrant génère un `data_subject_id` (hash du Discord user ID)
- Le consentement est capturé : 1er message = capture implicite `legitimate_interest`,
ou explicit si commande `!consent` / `!revoke`
- Le `AuditContext` est propagé jusqu'à `storeRun()`
#### 2.3 Hooks runners
Modifier chaque `*Runner.ts` (8 fichiers) :
- Avant l'appel LLM : log dans `transfer_log` (provider, région, mécanisme légal)
- **Pas de blocage** (décision validée) — tous les providers restent accessibles
- Config flag optionnel `OVERMIND_PII_FILTER=true` : filtre les RP du prompt avant envoi
- La cartographie des transferts est consultable via l'outil `audit_processing_registry`
---
### Phase 3 — Lifecycle & Anonymisation (P1)
#### 3.1 Cron de rétention + archivage 5 ans
Créer `scripts/audit_retention_cron.mjs` (exécutable via systemd / Hermes cron) :
- **Rétention active** : 30 jours pour `agent_runs` ET `knowledge_chunks` (défaut validé)
- **Avant suppression** : archive vers table `archived_runs` / `archived_chunks` (cold storage)
- **Archivage 5 ans** : les archives sont conservées 5 ans puis purgées définitivement
- Suit `retention_policies` table : configurable par catégorie
- Anonymise d'abord (art. 23.1), archive, puis supprime de la table active
**Double table** (hot → cold → delete) :
```sql
-- Archive cold storage (5 ans)
CREATE TABLE IF NOT EXISTS archived_runs (LIKE agent_runs INCLUDING ALL);
ALTER TABLE archived_runs ADD COLUMN archived_at BIGINT;
ALTER TABLE archived_runs ADD COLUMN archive_expires_at BIGINT; -- +5 ans
CREATE TABLE IF NOT EXISTS archived_chunks (LIKE knowledge_chunks INCLUDING ALL);
ALTER TABLE archived_chunks ADD COLUMN archived_at BIGINT;
ALTER TABLE archived_chunks ADD COLUMN archive_expires_at BIGINT;
```
**Workflow cron (chaque 24h)** :
1. `SELECT * FROM agent_runs WHERE retention_expires_at < now()` → anonymise → insert dans `archived_runs` (avec `archive_expires_at = now + 5 ans`) → delete de `agent_runs`
2. Idem pour `knowledge_chunks` → `archived_chunks`
3. `DELETE FROM archived_* WHERE archive_expires_at < now()` (purge définitive >5 ans)
#### 3.1.1 Feature flag `.env`
```bash
# .env — Loi 25 feature flag
OVERMIND_AUDIT_ENABLED=true # master switch (false = pas de guard, comportement v3.8)
OVERMIND_AUDIT_RETENTION_DAYS=30 # rétention active (défaut 30j)
OVERMIND_AUDIT_ARCHIVE_YEARS=5 # archivage cold storage (défaut 5 ans)
OVERMIND_AUDIT_DEFAULT_BASIS=legitimate_interest # base légale par défaut
OVERMIND_AUDIT_AUTO_ANONYMIZE=true # anonymisation à l'expiration
```
#### 3.2 Anonymisation technique
Créer `src/lib/audit/anonymize.ts` :
- Pseudonymisation : remplace identifiants directs par hash SHA-256 + salt
- K-anonymité sur embeddings : bruit gaussien pour réduire la ré-identification
- Généralisation : tronque timestamps à la journée, géoloc à la région
#### 3.3 Détection d'incident
Étendre le système d'alerte existant (`triggerMemoryAlert`) :
- Alertes → `incident_log` au lieu de log seul
- Détection d'anomalies : accès inhabituel, volume anormal, erreur DB répétée
- Workflow de notification (art. 3.5) : template CAI + template sujet
---
### Phase 4 — Transparence & Documentation (P1)
#### 4.1 Politique de confidentialité machine-readable
Créer `docs/PRIVACY_POLICY.json` (structuré, consommable par `audit_processing_registry`) :
- Finalités par traitement
- Bases légales
- Destinataires (providers LLM + leurs régions)
- Durées de conservation
- Droits des personnes + modalités d'exercice
#### 4.2 Cartographie des transferts
Créer `src/lib/audit/transfer_map.ts` — référentiel des 8 providers :
```typescript
export const PROVIDER_REGISTRY = {
anthropic: { region: 'US', mechanism: 'standard_contractual_clauses', documented: true },
google: { region: 'US', mechanism: 'standard_contractual_clauses', documented: true },
openai: { region: 'US', mechanism: 'standard_contractual_clauses', documented: true },
minimax: { region: 'CN', mechanism: 'explicit_consent', documented: false },
zai: { region: 'CN', mechanism: 'explicit_consent', documented: false },
kimi: { region: 'CN', mechanism: 'explicit_consent', documented: false },
// ...
};
```
#### 4.3 Documentation EFVP
Créer `docs/EFVP_OVERMIND.md` (évaluation des facteurs relatifs à la vie privée) :
- Template structuré selon grille CAI
- Analyse des 8 axes Loi 25
- Mesures d'atténuation
#### 4.4 Dashboard conformité
Étendre `get_metrics` tool (existant) :
- Ajoute une section `loi25` : consentements actifs, incidents ouverts, rétention à venir,
transferts des dernières 24h
---
## 5. Nouveaux fichiers à créer
```
src/
├── lib/
│ └── loi25/
│ ├── guard.ts # Middleware Privacy Guard
│ ├── anonymize.ts # Fonctions d'anonymisation
│ ├── transfer_map.ts # Registre des providers/transferts
│ ├── retention.ts # Moteur de rétention
│ └── types.ts # Types AuditContext, etc.
├── tools/
│ ├── audit_access_request.ts
│ ├── audit_rectification.ts
│ ├── audit_erasure.ts
│ ├── audit_consent.ts
│ ├── audit_processing_registry.ts
│ ├── audit_report_incident.ts
│ └── audit_efvp.ts
scripts/
├── audit_migration.mjs # Schema migration
├── audit_backfill.mjs # Migration des données legacy
└── audit_retention_cron.mjs # Cron de purge/anonymisation
docs/
├── PRIVACY_POLICY.json # Politique machine-readable
├── EFVP_OVERMIND.md # Évaluation facteurs vie privée
└── PLAN_AUDIT_INTEGRATION.md # Ce document
```
## 6. Fichiers à modifier
| Fichier | Modification |
|---|---|
| `src/memory/PostgresMemoryProvider.ts` | + colonnes governance, + 7 nouvelles tables |
| `src/memory/types.ts` | + types Audit (ConsentRecord, IncidentLog, etc.) |
| `src/server.ts` | + enregistrement 7 nouveaux outils Loi 25 |
| `src/bridge/OverBridgeService.ts` | + capture consentement + data_subject_id |
| `src/services/*Runner.ts` (8 fichiers) | + hook transfer_log |
| `src/tools/get_metrics.ts` | + section conformité Loi 25 |
| `package.json` | bump 3.9.0 + bin `overmind-loi25-migrate` |
| `.env.example` | + flags `OVERMIND_DATA_RESIDENCY`, `OVERMIND_PII_FILTER` |
## 7. Estimation effort
| Phase | Fichiers | LOC estimé | Tests |
|---|---|---|---|
| 1 — Fondations | 12 | ~1500 | 10 tests |
| 2 — Privacy Guard | 12 | ~1200 | 8 tests |
| 3 — Lifecycle | 4 | ~600 | 5 tests |
| 4 — Transparence | 5 | ~400 | 3 tests |
| **Total** | **33** | **~3700** | **26 tests** |
## 8. Risques
1. **Rétrocompatibilité** : les colonnes ajoutées sont nullable → pas de cassure
2. **Performance** : le guard ajoute ~5ms par requête (regex PII + log) — négligeable
3. **Providers CN** (zai/kimi/minimax-cn) : transferts Chine = mécanisme `explicit_consent`
obligatoire → bloquant si pas de consentement explicite
4. **Embeddings legacy** : les `knowledge_chunks` existants n'ont pas de `data_subject_id`
→ backfill best-effort + anonymisation conservative
## 9. Tests de conformité (critères d'acceptation)
- ✅ `audit_access_request(data_subject_id)` retourne tous les RP en <2s
- ✅ `audit_erasure(data_subject_id)` supprime/hash tous les RP + embeddings
- ✅ Chaque `agent_run` stocké a un `legal_basis` + `retention_expires_at`
- ✅ Chaque appel runner LLM génère une entrée `transfer_log`
- ✅ Cron de rétention purge les enregistrements expirés sans erreur
- ✅ `get_metrics` affiche le taux de conformité (consentements actifs / incidents)
- ✅ Anonymisation : un RP effacé ne peut pas être ré-identifié via embeddings
## 10. Décisions de périmètre (validées 21 juillet 2026)
| Question | Décision | Impact |
|---|---|---|
| **Périmètre RP** | Mixte — consentement explicite (tiers) + intérêt légitime (interne) | Guard détecte l'origine automatiquement, allowlist `.env` |
| **Transferts hors QC** | Documentation seule, aucun blocage | `transfer_log` + cartographie, mais tous les providers restent accessibles |
| **Rétention** | 30 jours active + 5 ans archivage cold storage | Double table `archived_*`, cron anonymise → archive → purge |
| **Activation** | Feature flag `OVERMIND_AUDIT_ENABLED=true` | Désactivé = comportement v3.8 inchangé (rétrocompatible) |
---
## 11. Ordre d'exécution recommandé
```
Étape 1 → scripts/audit_migration.mjs (schema)
Étape 2 → src/lib/audit/types.ts + guard.ts + transfer_map.ts
Étape 3 → src/tools/audit_*.ts (7 outils)
Étape 4 → src/server.ts (enregistrement outils)
Étape 5 → Hooks runners (8 fichiers)
Étape 6 → Bridge capture consentement
Étape 7 → scripts/audit_retention_cron.mjs
Étape 8 → scripts/audit_backfill.mjs (migration legacy)
Étape 9 → Tests + docs
Étape 10 → Bump version 3.9.0 + changeset
```
**Prêt à coder quand tu dis go.**