feat: workflow n8n d'alerte + doc, fin Phase 3 (v0.18.0)

Export JSON workflows-n8n/chlova-alerts.v1.0.0.json (webhook → mail,
formate par type d'alerte) + doc d'asset (palier privileged, rollback).
ALERT_WEBHOOK_URL dans .env.example + compose (vide = log-only).
need-review.md : alertes implémentées. Compose revalidé, 53 tests, 0 vuln.

Palier de risque : privilégié (workflow envoie des mails) — désactivable
via ALERT_WEBHOOK_URL vide ; non exécuté depuis le dépôt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kantin-Petit
2026-06-23 01:54:46 +02:00
parent db96c4a25e
commit b617487d0d
7 changed files with 121 additions and 3 deletions
View File
+53
View File
@@ -0,0 +1,53 @@
{
"name": "CHLOVA Alerts v1.0.0",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "chlova-alert",
"responseMode": "onReceived",
"options": {}
},
"id": "11111111-1111-4111-8111-111111111111",
"name": "Webhook CHLOVA",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [240, 300],
"webhookId": "chlova-alert"
},
{
"parameters": {
"language": "javaScript",
"jsCode": "// Construit sujet + corps du mail selon le type d'alerte CHLOVA.\nconst a = $json;\nlet subject, lines = [];\nswitch (a.kind) {\n case 'blocked_attempt':\n subject = `[CHLOVA] Tentative BLOQUÉE : ${a.tool}`;\n lines = [`Asset: ${a.assetId}`, `Outil: ${a.tool}`, `Statut: ${a.status}`, 'Action: review requise (/approve ou /refuse).'];\n break;\n case 'first_provisional_exec':\n subject = `[CHLOVA] 1ère exécution (provisoire) : ${a.tool}`;\n lines = [`Asset: ${a.assetId}`, `Outil: ${a.tool}`, 'Sursis de 7 jours en cours.'];\n break;\n case 'countdown_j1':\n subject = `[CHLOVA] Rappel J-1 : ${a.items.length} asset(s) expirent bientôt`;\n lines = a.items.map(i => `${i.id} [${i.riskTier}] expire ${new Date(i.expiresAt).toISOString().slice(0,10)}`);\n break;\n case 'daily_digest':\n subject = `[CHLOVA] Digest : ${a.blocked} bloqué(s), ${a.provisional} provisoire(s)`;\n lines = a.items.map(i => `${i.id} [${i.riskTier}/${i.status}]`);\n break;\n default:\n subject = `[CHLOVA] Alerte: ${a.kind}`;\n lines = [JSON.stringify(a)];\n}\nreturn [{ json: { subject, text: lines.join('\\n') } }];"
},
"id": "22222222-2222-4222-8222-222222222222",
"name": "Format mail",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [480, 300]
},
{
"parameters": {
"fromEmail": "chlova@example.com",
"toEmail": "REMPLACER_PAR_DESTINATAIRE",
"subject": "={{ $json.subject }}",
"text": "={{ $json.text }}",
"options": {}
},
"id": "33333333-3333-4333-8333-333333333333",
"name": "Envoi mail",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2.1,
"position": [720, 300],
"credentials": {
"smtp": { "id": "REMPLACER", "name": "SMTP CHLOVA" }
}
}
],
"connections": {
"Webhook CHLOVA": { "main": [[{ "node": "Format mail", "type": "main", "index": 0 }]] },
"Format mail": { "main": [[{ "node": "Envoi mail", "type": "main", "index": 0 }]] }
},
"settings": { "executionOrder": "v1" },
"meta": { "chlova": { "asset": "workflow-chlova-alerts", "version": "1.0.0", "riskTier": "privileged" } }
}