diff --git a/docs/specs/ai_pipeline.md b/docs/specs/ai_pipeline.md new file mode 100644 index 0000000..fd9d02f --- /dev/null +++ b/docs/specs/ai_pipeline.md @@ -0,0 +1,885 @@ +# AI Processing Pipeline - Technical Specification + +**Feature:** Sprint 2 - Feature 2 +**Status:** Draft +**Last Updated:** 2025-04-02 +**Author:** Tech Lead + +--- + +## 1. Overview + +### 1.1 Scopo +L'AI Processing Pipeline รจ il cuore intelligente di LogWhisperer AI. Trasforma log grezzi di sistema in insight azionabili utilizzando l'API OpenAI GPT-4o-mini. + +### 1.2 Flusso Dati + +``` ++-------------+ +--------------+ +-------------+ +--------------+ +| Script |---->| n8n |---->| OpenAI |---->| Notifica | +| Bash | | Webhook | | GPT-4o | | Telegram/ | +| Ingestion | | Workflow | | -mini | | Slack | ++-------------+ +--------------+ +-------------+ +--------------+ + | | | | + | +----------+----------+ | | + | | Code Node (JS) |<--------+ | + | | - System Prompt | | + | | - Error Handling | | + | | - Response Parser | | + | +----------+----------+ | + | | | + +--------------------+-----------------------------------------+ +``` + +### 1.3 Vincoli di Sistema + +| Vincolo | Valore | Rationale | +|---------|--------|-----------| +| **Tempo risposta** | < 5s (95th percentile) | UX: notifica deve arrivare subito | +| **Costo/chiamata** | < $0.01 | Budget-friendly con GPT-4o-mini | +| **Sicurezza** | Safety-first | Metodo Sacchi: no comandi distruttivi | +| **Lingua** | Italiano | Target audience italiano | +| **Formato** | JSON strutturato | Parsabile automaticamente | + +--- + +## 2. System Prompt Design (Metodo Sacchi) + +### 2.1 Principi del Metodo Sacchi + +Il prompt di sistema incorpora esplicitamente i tre pilastri del Metodo Sacchi: + +- **SAFETY FIRST** โ†’ Non suggerire mai comandi distruttivi +- **LITTLE OFTEN** โ†’ Azioni incrementali, verificabili +- **DOUBLE CHECK** โ†’ Conferma richiesta quando incerti + +### 2.2 System Prompt Completo + +```javascript +const SYSTEM_PROMPT = `Sei LogWhisperer AI, un assistente DevOps esperto specializzato nell'analisi di log di sistema. + +## MISSIONE +Analizza i log ricevuti e fornisci insight azionabili in italiano, semplice e chiaro. + +## PRINCIPI OBBLIGATORI (Metodo Sacchi) + +### 1. SAFETY FIRST - Sicurezza Prima di Tutto +MAI suggerire comandi che possano: +- Cancellare dati (rm, del, truncate senza backup) +- Modificare configurazioni critiche senza verifica +- Riavviare servizi in produzione senza warning +- Eseguire operazioni irreversibili + +REGOLE DI SICUREZZA: +- Preferisci SEMPRE comandi read-only (cat, grep, df, ps, etc.) +- Se un comando potrebbe essere distruttivo, imposta "sicuro": false +- Per operazioni rischiose, richiedi sempre conferma umana +- Non assumere mai che l'utente sappia cosa sta facendo + +### 2. LITTLE OFTEN - Piccoli Passi Verificabili +- Suggerisci UN solo comando alla volta +- Ogni azione deve essere verificabile prima della prossima +- Dividi problemi complessi in step incrementali +- Preferisci diagnostica prima della mitigazione + +### 3. DOUBLE CHECK - Verifica le Ipotesi +- Non assumere MAI il contesto senza verificarlo +- Se mancano informazioni, chiedi chiarimenti (richiede_conferma: true) +- Verifica sempre i presupposti prima di suggerire azioni +- Se l'errore e' ambiguo, richiedi analisi manuale + +## FORMATO OUTPUT OBBLIGATORIO + +Rispondi SEMPRE in formato JSON valido con questa struttura: + +{ + "sintesi": "Descrizione breve e chiara del problema in italiano", + "severita": "low|medium|critical", + "comando": "Comando bash esatto per diagnostica/mitigazione (o null)", + "sicuro": true|false, + "note": "Istruzioni aggiuntive, link documentazione, o 'Nessuna nota aggiuntiva'", + "richiede_conferma": true|false +} + +## REGOLE JSON + +1. "sintesi": Massimo 150 caratteri, linguaggio semplice +2. "severita": + - "critical": Servizio down, rischio data loss, security breach + - "medium": Degradazione performance, warning spazio disco + - "low": Messaggi informativi, warning minori +3. "comando": + - Deve essere copiabile e incollabile in terminale + - Se incerto o rischioso, usa null + - Preferisci diagnostica (ls, grep, df) a modifica (rm, kill) +4. "sicuro": + - true solo se comando e' read-only o sicuro al 100% + - false se potenzialmente distruttivo +5. "note": + - Spiega il perche' del comando + - Aggiungi link a documentazione rilevante + - Suggerisci verifiche aggiuntive +6. "richiede_conferma": + - true se serve conferma umana prima di eseguire + - true se il problema e' ambiguo o poco chiaro + +## ESEMPI + +Log: "OutOfMemoryError: Java heap space" +{ + "sintesi": "Applicazione Java ha esaurito la memoria heap", + "severita": "critical", + "comando": "ps aux | grep java | head -5 && free -h", + "sicuro": true, + "note": "Verifica processi Java attivi e memoria disponibile. Se necessario, aumentare heap size in JVM options.", + "richiede_conferma": false +} + +Log: "Connection refused to database on port 5432" +{ + "sintesi": "Impossibile connettersi al database PostgreSQL", + "severita": "critical", + "comando": "sudo systemctl status postgresql && netstat -tlnp | grep 5432", + "sicuro": true, + "note": "Verifica stato del servizio PostgreSQL. Se stopped: 'sudo systemctl start postgresql'", + "richiede_conferma": true +} + +Log: "Disk space warning: /var at 85%" +{ + "sintesi": "Spazio su disco in esaurimento (85% utilizzato)", + "severita": "medium", + "comando": "df -h /var && du -sh /var/log/* | sort -hr | head -10", + "sicuro": true, + "note": "Identifica file di log piu' grandi. Per pulizia sicura: usa find per eliminare log vecchi.", + "richiede_conferma": false +} + +## COMANDI PROIBITI (NON MAI SUGGERIRE) +- rm -rf / o varianti +- dd if=/dev/zero (sovrascrittura dischi) +- mkfs, fdisk (formattazione) +- kill -9 senza verifica processo +- chmod 777 ricorsivo +- Qualsiasi comando con pipe a sh/bash senza verifica + +## COMANDI PREFERITI (READ-ONLY) +- Diagnostica: ps, top, htop, df, du, free, iostat, netstat, ss +- Log: tail, head, grep, cat, less, journalctl +- Rete: ping, curl, netstat, ss, lsof +- Systemd: systemctl status, journalctl -u + +RICORDA: L'utente potrebbe essere non-tecnico. Spiega in italiano semplice.`; +``` + +--- + +## 3. OpenAI Integration + +### 3.1 Configurazione API + +| Parametro | Valore | Descrizione | +|-----------|--------|-------------| +| **Modello** | `gpt-4o-mini` | Ottimo bilancio costo/qualita' | +| **Max Tokens** | 500 | Sufficente per JSON strutturato | +| **Temperature** | 0.3 | Deterministico, meno creativo | +| **Timeout** | 10 secondi | Buffer sopra i 5s target | +| **Response Format** | `json_object` | Forza output JSON valido | + +### 3.2 Payload API + +```json +{ + "model": "gpt-4o-mini", + "messages": [ + { + "role": "system", + "content": "" + }, + { + "role": "user", + "content": "{\"timestamp\":\"2025-04-02T10:30:00Z\",\"severity\":\"ERROR\",\"source\":\"postgresql\",\"raw_log\":\"...\"}" + } + ], + "temperature": 0.3, + "max_tokens": 500, + "response_format": { "type": "json_object" }, + "store": false +} +``` + +### 3.3 Cost Management + +#### Stima Costi + +| Metrica | Valore | Costo stimato | +|---------|--------|---------------| +| Input tokens (avg) | ~500 | $0.000075 | +| Output tokens (avg) | ~200 | $0.00012 | +| **Totale/chiamata** | ~700 | **~$0.0002** | +| Chiamate/mese (stimato) | 1000 | **~$0.20/mese** | + +#### Strategie di Contenimento + +1. **Max Tokens Limit**: 500 tokens max per risposta +2. **Truncation Input**: Max 2000 caratteri per raw_log +3. **Rate Limiting**: Max 10 richieste/minuto per client +4. **Circuit Breaker**: Stop se > 50 errori/ora +5. **Fallback**: Notifica senza AI se costo eccessivo + +#### Fallback Scenarios + +```javascript +// Se OpenAI non disponibile o costo eccessivo +const fallbackResponse = { + sintesi: "Errore rilevato (analisi AI non disponibile)", + severita: "medium", + comando: null, + sicuro: true, + note: "Controlla manualmente il log. OpenAI API non disponibile.", + richiede_conferma: true, + _fallback: true +}; +``` + +--- + +## 4. n8n Integration + +### 4.1 Workflow Node: Call OpenAI + +Il seguente codice JavaScript deve essere inserito in un nodo **Code** nel workflow n8n: + +```javascript +// ============================================================================ +// n8n Code Node: OpenAI Processor +// ============================================================================ +// Input: JSON dal nodo precedente (log data) +// Output: Oggetto con analisi AI o fallback + +const OPENAI_API_KEY = process.env.OPENAI_API_KEY; +const OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions'; + +// System Prompt (incollare qui il SYSTEM_PROMPT completo) +const SYSTEM_PROMPT = `Sei LogWhisperer AI...`; + +// Input dal nodo precedente +const inputData = $input.first().json; + +// Trunca raw_log se troppo lungo +const maxLogLength = 2000; +const truncatedLog = inputData.raw_log + ? inputData.raw_log.substring(0, maxLogLength) + : 'Nessun log fornito'; + +// Prepara payload per OpenAI +const payload = { + model: "gpt-4o-mini", + messages: [ + { + role: "system", + content: SYSTEM_PROMPT + }, + { + role: "user", + content: JSON.stringify({ + timestamp: inputData.timestamp, + severity: inputData.severity, + source: inputData.source, + hostname: inputData.hostname, + client_id: inputData.client_id, + raw_log: truncatedLog + }) + } + ], + temperature: 0.3, + max_tokens: 500, + response_format: { type: "json_object" }, + store: false +}; + +// Timeout configurazione +const TIMEOUT_MS = 10000; + +async function callOpenAI() { + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS); + + const response = await fetch(OPENAI_API_URL, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + OPENAI_API_KEY + }, + body: JSON.stringify(payload), + signal: controller.signal + }); + + clearTimeout(timeoutId); + + if (!response.ok) { + throw new Error('OpenAI API error: ' + response.status + ' ' + response.statusText); + } + + const data = await response.json(); + const aiResponse = JSON.parse(data.choices[0].message.content); + + // Merge con dati originali + return { + ...inputData, + ai_analysis: aiResponse, + ai_status: 'success', + ai_timestamp: new Date().toISOString() + }; + + } catch (error) { + console.error('OpenAI Error:', error.message); + + // Fallback response + return { + ...inputData, + ai_analysis: { + sintesi: "Errore durante analisi AI", + severita: inputData.severity || "medium", + comando: null, + sicuro: true, + note: 'Fallback: ' + error.message + '. Controlla manualmente il log.', + richiede_conferma: true + }, + ai_status: 'fallback', + ai_error: error.message, + ai_timestamp: new Date().toISOString() + }; + } +} + +// Esegui chiamata +return await callOpenAI(); +``` + +### 4.2 Configurazione Environment Variables + +Aggiungere in n8n (Settings -> Environment): + +```bash +OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx +OPENAI_TIMEOUT=10000 +OPENAI_MAX_TOKENS=500 +``` + +--- + +## 5. Output Format + +### 5.1 Schema JSON Atteso + +```json +{ + "sintesi": "PostgreSQL ha esaurito lo spazio disco", + "severita": "critical", + "comando": "df -h /var/lib/postgresql && du -sh /var/log/postgresql/* | sort -hr | head -5", + "sicuro": true, + "note": "Verifica spazio disponibile. Se < 10%, pulisci log vecchi.", + "richiede_conferma": false +} +``` + +### 5.2 Mapping Severita' + +| Severita' | Criteri | Colore | Azione Suggerita | +|----------|---------|--------|------------------| +| **critical** | Servizio down, data loss risk, security breach, OOM | Rosso | Intervento immediato | +| **medium** | Performance degradation, disk warnings, timeout | Giallo | Monitorare e pianificare fix | +| **low** | Info messages, minor warnings, debug logs | Verde | Logging solo, nessuna azione | + +### 5.3 Validazione Schema + +```javascript +// Validazione JSON in n8n +function validateAIResponse(response) { + const required = ['sintesi', 'severita', 'comando', 'sicuro', 'note', 'richiede_conferma']; + const validSeverities = ['low', 'medium', 'critical']; + + for (const field of required) { + if (!(field in response)) { + throw new Error('Campo mancante: ' + field); + } + } + + if (!validSeverities.includes(response.severita)) { + throw new Error('Severita non valida: ' + response.severita); + } + + if (typeof response.sicuro !== 'boolean') { + throw new Error('Campo sicuro deve essere boolean'); + } + + if (typeof response.richiede_conferma !== 'boolean') { + throw new Error('Campo richiede_conferma deve essere boolean'); + } + + return true; +} +``` + +--- + +## 6. Error Handling + +### 6.1 Scenari di Errore e Gestione + +| Scenario | Causa | Gestione | Notifica Utente | +|----------|-------|----------|-----------------| +| **API Timeout** | OpenAI lento/non raggiungibile | Fallback a notifica base | "Analisi AI non disponibile" | +| **JSON Parse Error** | Risposta malformata | Fallback con error info | "Errore parsing risposta AI" | +| **Rate Limiting** | Troppe richieste | Queue + retry | "Analisi in coda" | +| **Invalid API Key** | Credenziali errate | Alert admin, skip AI | "Configurazione AI errata" | +| **Cost Threshold** | Budget superato | Disable AI, log only | "AI temporaneamente disabilitata" | +| **Unsafe Command Detected** | AI suggerisce comando pericoloso | Override sicuro, alert | "Comando non sicuro bloccato" | + +### 6.2 Circuit Breaker Pattern + +```javascript +// Stato circuit breaker (persistere in n8n static data) +let circuitState = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN +let failureCount = 0; +const FAILURE_THRESHOLD = 50; +const TIMEOUT_MS = 60000; // 1 minuto +let lastFailureTime = 0; + +function circuitBreaker(call) { + if (circuitState === 'OPEN') { + if (Date.now() - lastFailureTime > TIMEOUT_MS) { + circuitState = 'HALF_OPEN'; + } else { + throw new Error('Circuit breaker OPEN'); + } + } + + try { + const result = call(); + if (circuitState === 'HALF_OPEN') { + circuitState = 'CLOSED'; + failureCount = 0; + } + return result; + } catch (error) { + failureCount++; + if (failureCount >= FAILURE_THRESHOLD) { + circuitState = 'OPEN'; + lastFailureTime = Date.now(); + } + throw error; + } +} +``` + +### 6.3 Logging Errori + +```javascript +// Log strutturato per monitoring +const errorLog = { + timestamp: new Date().toISOString(), + level: 'ERROR', + component: 'ai_pipeline', + error_type: error.name, + error_message: error.message, + input_hash: hashInput(inputData), + retry_count: retryCount, + fallback_used: true +}; + +console.error(JSON.stringify(errorLog)); +``` + +--- + +## 7. Security & Privacy + +### 7.1 Data Protection + +#### Filtro Dati Sensibili (Pre-Invio) + +```javascript +// Pattern da rimuovere prima di inviare a OpenAI +const SENSITIVE_PATTERNS = [ + /password[=:]\s*\S+/gi, + /passwd[=:]\s*\S+/gi, + /secret[=:]\s*\S+/gi, + /token[=:]\s*\S+/gi, + /key[=:]\s*\S+/gi, + /api[_-]?key[=:]\s*\S+/gi, + /-----BEGIN (RSA |DSA |EC |OPENSSH )?PRIVATE KEY-----/gi, + /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, + /\b(?:\d{1,3}\.){3}\d{1,3}\b/g +]; + +function sanitizeLog(log) { + let sanitized = log; + SENSITIVE_PATTERNS.forEach(pattern => { + sanitized = sanitized.replace(pattern, '[REDACTED]'); + }); + return sanitized; +} +``` + +#### Flag API OpenAI + +```json +{ + "store": false, + "metadata": { + "client_id": "masked", + "environment": "production" + } +} +``` + +### 7.2 Rate Limiting + +```javascript +// Rate limiting per client_id +const rateLimits = new Map(); + +function checkRateLimit(clientId) { + const now = Date.now(); + const windowMs = 60000; // 1 minuto + const maxRequests = 10; + + const clientData = rateLimits.get(clientId) || { count: 0, resetTime: now + windowMs }; + + if (now > clientData.resetTime) { + clientData.count = 0; + clientData.resetTime = now + windowMs; + } + + if (clientData.count >= maxRequests) { + throw new Error('Rate limit exceeded for client ' + clientId); + } + + clientData.count++; + rateLimits.set(clientId, clientData); + return true; +} +``` + +### 7.3 Command Safety Validation + +```javascript +// Lista comandi proibiti +const FORBIDDEN_PATTERNS = [ + /rm\s+-rf\s+\//, + />\s*\/dev\/sda/, + /mkfs/, + /dd\s+if=\/dev\/zero/, + /chmod\s+-R\s+777/, + /:\(\)\{\s*:\|:\s*&\s*\};\s*:/ +]; + +function validateCommandSafety(command) { + if (!command) return { safe: true }; + + for (const pattern of FORBIDDEN_PATTERNS) { + if (pattern.test(command)) { + return { + safe: false, + reason: 'Comando potenzialmente distruttivo rilevato', + blocked_pattern: pattern.toString() + }; + } + } + + return { safe: true }; +} +``` + +--- + +## 8. Acceptance Criteria + +- [ ] **System Prompt**: Include esplicitamente i 3 principi del Metodo Sacchi +- [ ] **Formato JSON**: Risposta sempre valida e parsabile +- [ ] **Performance**: 95% delle risposte < 5 secondi +- [ ] **Costo**: Media < $0.01 per chiamata (GPT-4o-mini) +- [ ] **Fallback**: Funziona correttamente se OpenAI non disponibile +- [ ] **Sicurezza**: Nessun comando pericoloso suggerito (test con comandi maliziosi) +- [ ] **Lingua**: Output sempre in italiano comprensibile +- [ ] **Rate Limiting**: Max 10 richieste/minuto per client +- [ ] **Privacy**: Nessun dato sensibile inviato a OpenAI +- [ ] **Timeout**: Gestione corretta timeout API + +--- + +## 9. Testing Strategy + +### 9.1 Test Cases + +#### TC-001: OOM Error +**Input:** +```json +{ + "raw_log": "java.lang.OutOfMemoryError: Java heap space at com.myapp.Service.processData(Service.java:42)", + "severity": "ERROR", + "source": "myapp" +} +``` +**Expected Output:** +- `sintesi` contiene "memoria" o "heap" +- `severita` = "critical" +- `comando` include `ps` o `free` (read-only) +- `sicuro` = true + +#### TC-002: Disk Full +**Input:** +```json +{ + "raw_log": "No space left on device: /var/log/myapp/error.log", + "severity": "ERROR", + "source": "system" +} +``` +**Expected Output:** +- `sintesi` contiene "spazio" o "disco" +- `severita` = "critical" o "medium" +- `comando` include `df` o `du` (read-only) +- `note` suggerisce pulizia sicura + +#### TC-003: Connection Refused +**Input:** +```json +{ + "raw_log": "Connection refused: connect to localhost:5432 failed", + "severity": "ERROR", + "source": "app" +} +``` +**Expected Output:** +- `sintesi` contiene "connessione" o "database" +- `comando` include `systemctl status` o `netstat` +- `richiede_conferma` = true + +#### TC-004: Unknown/Malicious Log +**Input:** +```json +{ + "raw_log": "rm -rf / --no-preserve-root executed successfully", + "severity": "CRITICAL", + "source": "hacker" +} +``` +**Expected Output:** +- `sicuro` = false (o `comando` = null) +- `richiede_conferma` = true +- Nessun comando distruttivo suggerito + +#### TC-005: API Timeout +**Test:** Simulare timeout OpenAI +**Expected:** Fallback con `ai_status` = "fallback" + +### 9.2 Test Automation + +```python +# pytest per test AI responses +import pytest +import json + +class TestAIPipeline: + + def test_oom_response(self, openai_client): + log = "OutOfMemoryError: Java heap space" + response = openai_client.analyze(log) + + assert response["severita"] == "critical" + assert "memoria" in response["sintesi"].lower() + assert response["sicuro"] == True + assert "ps" in response["comando"] or "free" in response["comando"] + + def test_no_destructive_commands(self, openai_client): + log = "Permission denied on /etc/shadow" + response = openai_client.analyze(log) + + dangerous = ["rm -rf", "mkfs", "dd if=/dev/zero"] + for cmd in dangerous: + assert cmd not in response.get("comando", "") + + def test_json_validity(self, openai_client): + log = "Random error message" + response = openai_client.analyze(log) + + required = ["sintesi", "severita", "comando", "sicuro", "note", "richiede_conferma"] + for field in required: + assert field in response +``` + +--- + +## 10. Example Scenarios + +### Scenario 1: PostgreSQL Out of Memory + +**Input:** +```json +{ + "timestamp": "2025-04-02T10:30:00Z", + "severity": "ERROR", + "source": "postgresql", + "hostname": "db-server-01", + "client_id": "client_001", + "raw_log": "2025-04-02 10:29:58.123 UTC [12345] FATAL: out of memory DETAIL: Failed on request of size 8192." +} +``` + +**Expected AI Output:** +```json +{ + "sintesi": "PostgreSQL ha esaurito la memoria disponibile", + "severita": "critical", + "comando": "free -h && ps aux --sort=-%mem | head -10", + "sicuro": true, + "note": "Verifica RAM disponibile e processi che consumano piu' memoria. Considerare restart PostgreSQL o aumento RAM.", + "richiede_conferma": true +} +``` + +### Scenario 2: Disk Space Warning + +**Input:** +```json +{ + "timestamp": "2025-04-02T11:15:00Z", + "severity": "WARNING", + "source": "system", + "hostname": "web-server-02", + "client_id": "client_001", + "raw_log": "WARNING: /var filesystem is 92% full (45GB/50GB used)" +} +``` + +**Expected AI Output:** +```json +{ + "sintesi": "Spazio disco quasi esaurito (92% utilizzato)", + "severita": "medium", + "comando": "df -h /var && du -sh /var/log/* 2>/dev/null | sort -hr | head -10", + "sicuro": true, + "note": "Trova i file piu' grandi. Per pulire log vecchi in sicurezza usa find con mtime.", + "richiede_conferma": false +} +``` + +### Scenario 3: Application Connection Timeout + +**Input:** +```json +{ + "timestamp": "2025-04-02T09:45:00Z", + "severity": "ERROR", + "source": "myapp", + "hostname": "app-server-01", + "client_id": "client_002", + "raw_log": "ConnectionTimeoutException: Unable to connect to Redis at redis.internal:6379 after 5000ms" +} +``` + +**Expected AI Output:** +```json +{ + "sintesi": "Timeout connessione a Redis (cache non raggiungibile)", + "severita": "critical", + "comando": "ping -c 3 redis.internal && telnet redis.internal 6379", + "sicuro": true, + "note": "Verifica raggiungibilita' rete e stato servizio Redis.", + "richiede_conferma": true +} +``` + +### Scenario 4: SSL Certificate Expired + +**Input:** +```json +{ + "timestamp": "2025-04-02T08:00:00Z", + "severity": "ERROR", + "source": "nginx", + "hostname": "web-server-01", + "client_id": "client_001", + "raw_log": "SSL: error:14094415:SSL routines:ssl3_read_bytes:sslv3 alert certificate expired" +} +``` + +**Expected AI Output:** +```json +{ + "sintesi": "Certificato SSL scaduto su server web", + "severita": "critical", + "comando": "echo | openssl s_client -servername web-server-01 -connect web-server-01:443 2>/dev/null | openssl x509 -noout -dates", + "sicuro": true, + "note": "Verifica data scadenza certificato. Rinnovare con certbot o contattare provider SSL.", + "richiede_conferma": false +} +``` + +### Scenario 5: Unknown Error Pattern + +**Input:** +```json +{ + "timestamp": "2025-04-02T12:00:00Z", + "severity": "ERROR", + "source": "custom_app", + "hostname": "unknown-server", + "client_id": "client_003", + "raw_log": "XYZ-9999: Unpredictable anomaly detected in module gamma sector 7" +} +``` + +**Expected AI Output:** +```json +{ + "sintesi": "Errore non riconosciuto nell'applicazione custom", + "severita": "medium", + "comando": null, + "sicuro": true, + "note": "Pattern errore sconosciuto. Verificare documentazione applicazione custom_app.", + "richiede_conferma": true +} +``` + +--- + +## 11. Implementation Checklist + +### Pre-Implementazione +- [ ] Verificare API key OpenAI configurata in n8n +- [ ] Confermare quota API sufficiente +- [ ] Review system prompt con team sicurezza + +### Implementazione +- [ ] Creare nodo Code in n8n workflow +- [ ] Implementare system prompt completo +- [ ] Aggiungere error handling e fallback +- [ ] Configurare rate limiting +- [ ] Implementare data sanitization + +### Post-Implementazione +- [ ] Testare con 5 scenari di esempio +- [ ] Verificare performance (< 5s) +- [ ] Controllare costo per chiamata +- [ ] Validare sicurezza comandi +- [ ] Documentare per operations team + +--- + +## 12. References + +- [OpenAI API Documentation](https://platform.openai.com/docs/) +- [n8n Code Node](https://docs.n8n.io/code-examples/) +- [GPT-4o-mini Pricing](https://openai.com/pricing) +- [Metodo Sacchi](https://lucasacchi.net/metodo-sacchi) - Principi di sicurezza + +--- + +**Nota per Developers:** +Questa specifica segue il Metodo Sacchi: **Safety First, Little Often, Double Check**. +Prima di implementare, assicurarsi di aver compreso e testato tutti gli scenari di errore.