fix: аудит — 19 фиксов безопасности, надёжности, UI и 16 новых тестов

- S4: bump jinja2>=3.1.4, python-multipart>=0.0.18, httpx>=0.28.0
- S5: _detect_ecosystem — DEFAULT_ECOSYSTEM для неизвестных форматов
- S6: harvester — log.exception() вместо log.error()
- S8: _scan_component — urlencode параметров
- P1: scanner — proc.kill() при таймауте
- P3: api_packages — selectinload(Scan.findings), убран N+1
- P4+P5: утечка _url_locks и _llm_locks при early return
- P6: DB reaper — сброс {'status':'analyzing'} при старте
- UI: htmx-пагинация, фильтры не теряют flagged, 404 с layout
- UI: мобильные таблицы overflow-x, полная стата на дашборде
- UI: i18n статусов в _status_badge, urlencode package_name
- 16 новых тестов: analyze endpoint (6), scanner errors (4),
  webhook signature (2), llm client (4)
This commit is contained in:
Marker689
2026-05-10 10:45:44 +03:00
parent d483a8b21d
commit 1341404568
31 changed files with 575 additions and 152 deletions

View File

@@ -63,6 +63,7 @@ After startup:
| `TEMP_DIR` | `/tmp/guarddog-nexus` | Temporary download directory |
| `MAX_CONCURRENT_SCANS` | `4` | Maximum simultaneous GuardDog processes |
| `LLM_ENABLED` | `0` | Set to `1` to enable LLM analysis |
| `LLM_AUTO_ANALYZE` | `0` | Set to `1` to auto-analyze after scan; `0` = manual mode via UI button |
| `LLM_API_KEY` | _(empty)_ | API key (OpenAI / Groq / Ollama / etc.) |
| `LLM_API_BASE` | `https://api.openai.com/v1` | OpenAI-compatible base URL |
| `LLM_MODEL` | `gpt-4o-mini` | Model name |
@@ -128,15 +129,54 @@ GuardDog Nexus accepts `UPDATED` webhook events from Nexus.
## LLM Analysis
GuardDog Nexus can automatically analyze each finding through an LLM. When enabled (`LLM_ENABLED=1`), every flagged scan gets an AI breakdown: threat assessment, code analysis, and recommendations.
GuardDog Nexus can analyze findings through an LLM. When enabled (`LLM_ENABLED=1`), flagged findings receive an AI breakdown: threat assessment, code analysis, and recommendations.
**Auto mode:** after a flagged scan completes, each finding is sent to the LLM. Reports are saved to the database and included in JSON log output.
### Operating Modes
**Manual mode:** the web UI has an "Analyze with LLM" button next to each finding — click to get an inline verdict.
The `LLM_AUTO_ANALYZE` variable controls the analysis mode:
Supported providers: any OpenAI-compatible API (OpenAI, Groq, Ollama, vLLM, etc.).
- **`LLM_AUTO_ANALYZE=1` (automatic):** each finding is automatically sent to the LLM after a scan completes. Reports are saved to the database and included in JSON log output. No "Analyze" button is shown in the UI.
- **`LLM_AUTO_ANALYZE=0` (manual, default):** an "Analyze with LLM" button is shown next to each finding in the web UI. The user clicks to trigger analysis and see the inline verdict.
LLM response format (JSON):
### finding.report State Machine
The `finding.report` field transitions through these states:
| Value | UI |
|-------|----|
| `None` | "Analyze with LLM" button (manual mode only) |
| `{"status": "analyzing"}` | Spinner |
| `{verdict:, summary:, ...}` | Report + "Retry" link |
### Supported Providers
Any OpenAI-compatible API. Configuration examples:
```bash
# OpenAI (manual mode)
LLM_ENABLED=1
LLM_AUTO_ANALYZE=0
LLM_API_KEY=sk-...
LLM_API_BASE=https://api.openai.com/v1
LLM_MODEL=gpt-4o-mini
# Groq with auto-analysis (faster, free tier)
LLM_ENABLED=1
LLM_AUTO_ANALYZE=1
LLM_API_KEY=gsk_...
LLM_API_BASE=https://api.groq.com/openai/v1
LLM_MODEL=llama-3.3-70b-versatile
# Local Ollama
LLM_ENABLED=1
LLM_API_KEY=ollama
LLM_API_BASE=http://host.docker.internal:11434/v1
LLM_MODEL=llama3.2
```
### Response Format
LLM returns JSON with fields:
- `verdict``safe` / `suspicious` / `malicious`
- `summary` — one-line verdict
- `analysis` — detailed breakdown (23 paragraphs)
@@ -156,7 +196,7 @@ guarddog-nexus/
│ ├── i18n.py # RU/EN translations
│ ├── logging_setup.py # JSON structured logging
│ └── main.py # FastAPI app entry point
├── tests/ # pytest tests (50+)
├── tests/ # pytest tests (85 tests)
├── scripts/ # Setup scripts
├── docker-compose.yml
├── Dockerfile