Архитектура¶
Репозиторий — monorepo: React 19 + Vite + TypeScript SPA и Express API, агрегирующий публичные ленты уязвимостей. SPA никогда не обращается к NVD или OSV напрямую; весь исходящий трафик идёт через сервер, чтобы ключи, кэш и rate limits оставались централизованными.
В этой главе — соответствие папок обязанностям, поток scan и watch через handlers и ссылка на OpenAPI, отдаваемый в runtime.
Топология верхнего уровня¶
flowchart LR
classDef ui fill:#e9edf5,stroke:#00baba,color:#253343
classDef api fill:#f3fcfc,stroke:#008c8c,color:#253343
classDef ext fill:#fff7ed,stroke:#eda232,color:#253343
Browser[Browser SPA]:::ui --> API[Express /api]:::api
API --> NVD[NVD]:::ext
API --> OSV[OSV]:::ext
API --> GH[GitHub]:::ext
API --> CISA[CISA KEV]:::ext
API --> RSS[RSS]:::ext
Разбор диаграммы¶
Браузер сохраняет стек, локаль и переключатели источников в localStorage, затем вызывает POST /api/scan или POST /api/watch. Слой API проверяет JSON-тела, вызывает scanStack в server/services/scan.ts и возвращает объединённые уязвимости. Логика провайдеров — в server/services/; общая дедупликация — в server/lib/merge.ts; обогащение переводом — в server/services/enrich.ts.
Пошаговый путь запроса (полное сканирование)¶
server/routes/scan.tsпринимаетPOST /scan.server/handlers/scanHandlers.tsразбирает тело черезstackValidation.ts.scanStackопределяет включённые встроенные источники и пользовательские RSS.- Параллельные fetch по инструментам завершаются; результаты merge и сортируются.
- Опционально
enrichVulnsWithTranslationsприtranslate: true. - JSON
ScanResponseвозвращается клиенту;persistLastScanвsrc/lib/scanCache.tsзаписываетcve-radar:last-scanс ключом стека.
Слой базы данных (опциональный PostgreSQL)¶
При заданном DATABASE_URL метаданные сканов сохраняются в PostgreSQL через server/db/scanHistory.ts, стеки tenant — через server/db/tenants.ts. SQL-миграции в server/db/migrations/*.sql выполняются автоматически при старте pool.
Type-safe определения схемы для постепенной миграции ORM — в server/db/schema.ts (Drizzle ORM). server/db/drizzle.ts предоставляет getDb() на общем pool pg. Сохранение tenant и scan-history (server/db/tenants.ts, server/db/scanHistory.ts) использует query builder Drizzle; SQL-миграции в server/db/migrations/*.sql по-прежнему выполняются при старте pool.
Сервисы уведомлений¶
Серверные оповещения watch используют server/services/notifications/NotificationService.ts. Адаптеры каналов (Slack, Discord, Telegram, SMTP, generic webhook) читают env из Конфигурации. server/services/alerts.ts делегирует сервису для совместимости с ALERT_WEBHOOK_URL.
Общий слой контрактов¶
Типы и порядок severity находятся в shared/ (shared/api/vulnerability.ts, shared/constants/severityOrder.ts). И src/, и server/ импортируют через @shared/*; server/types.ts re-export для обратной совместимости. npm run build:server компилирует shared/ в dist-server/.
Структура API-слоя¶
| Модуль | Роль |
|---|---|
server/index.ts |
Express app, монтирование роутеров |
server/routes/health.ts |
GET /health |
server/routes/meta.ts |
capabilities, sources, openapi.json |
server/routes/scan.ts |
scan, watch, scan/validate |
server/routes/v1.ts |
Версионированный mount тех же handlers |
server/routes/translateLocale.ts |
POST /translate |
server/handlers/scanHandlers.ts |
Общая логика scan/watch/validate |
server/openapi/spec.json |
Контракт OpenAPI 3.1 |
Legacy-пути остаются под /api/*; интеграции должны предпочитать /api/v1/* (см. Справочник API).
Карта frontend¶
| Область | Путь |
|---|---|
| Shell | src/components/layout/AppShell.tsx, SubNav.tsx, SetupWizard.tsx |
| Вкладки | src/components/tabs/* |
| Кэш scan | src/lib/scanCache.ts |
| API-клиент | src/api/scan.ts, watch.ts, scanPayload.ts |
| i18n | src/i18n/messages/*.ts |
| Hooks | useVulnScan, useWatch, useVulnTranslations, useFontScale |
| Middleware | server/middleware/rateLimit.ts, scanTimeout.ts |
Backend-сервисы (ленты)¶
| Провайдер | Модуль |
|---|---|
| NVD | server/services/nvd.ts |
| OSV | server/services/osv.ts |
| GitHub | server/services/github.ts |
| CISA KEV | server/services/cisa.ts |
| RSS | server/services/rss.ts |
| Перевод | server/services/translate.ts |
Кэширование и лимиты¶
In-memory кэш (server/lib/cache.ts) поддерживает RSS XML и строки перевода. Задержка NVD — из server/lib/rateLimit.ts (upstream pacing). Rate limits запросов для scan/watch применяются в server/middleware/rateLimit.ts (отдельные bucket; validate не ограничивается). Результаты scan на клиенте сохраняются в localStorage через scanCache.ts. Возможности через GET /api/capabilities отражают жёсткие лимиты валидаторов (50 инструментов, 20 пользовательских лент).
Далее: Оповещения