Skip to content

Архитектура

Репозиторий — 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.

Пошаговый путь запроса (полное сканирование)

  1. server/routes/scan.ts принимает POST /scan.
  2. server/handlers/scanHandlers.ts разбирает тело через stackValidation.ts.
  3. scanStack определяет включённые встроенные источники и пользовательские RSS.
  4. Параллельные fetch по инструментам завершаются; результаты merge и сортируются.
  5. Опционально enrichVulnsWithTranslations при translate: true.
  6. 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 пользовательских лент).

Далее: Оповещения