
Инструментарий для построения графов для исследования угроз — и не только
Этот проект в значительной степени создан методом «vibecoding», поэтому соблюдайте соответствующие меры предосторожности. Код был проверен реальными программистами, но не защищён от уязвимостей. Не открывайте внешний доступ без тщательного аудита безопасности.
Quantickle — это интерактивный инструментарий, работающий в первую очередь в браузере, для построения и изучения сетевых графов. Фронтенд (Cytoscape.js + пользовательский интерфейс) отвечает за отрисовку, редактирование и выполнение раскладок, а лёгкий Express-сервер отдаёт интерфейс, проксирует вызовы интеграций и опционально сохраняет графы в Neo4j. Иными словами, браузер управляет состоянием графа и визуализацией, тогда как сервер предоставляет ресурсы и интеграции по мере необходимости.
bezier), прямые, пучковые (unbundled-bezier), такси и округлённые такси.haystack и segments через настраиваемые стили.Вот несколько примеров того, что умеет Quantickle:

Quantickle опирается на небольшой набор общих понятий, связывающих документацию:
Система координат и пространственные раскладки — абсолютные раскладки Quantickle и раскладки с учётом глубины используют куб 0–1000 для координат x, y и z. Полные правила пространственного размещения и освещения см. в COORDINATE_SYSTEM.md.
Управление файлами графов и проектные файлы — файлы .qut представляют собой каноническое сохранённое состояние; они хранят узлы, рёбра, метаданные и иерархию контейнеров.
Интеграция с Neo4j — сервер может сохранять и извлекать графы из Neo4j, включая снимки метаданных. Конфигурацию и описание рабочего процесса см. в NEO4J_INTEGRATION_README.md.
Граф Quantickle — это набор узлов и рёбер с метаданными, которые управляют раскладкой, стилизацией и группировкой.
metadata, массив узлов, массив рёбер и опционально состояние раскладки или вида.id и опциональными атрибутами, такими как , , , и координаты. Узлы также могут содержать информацию в Markdown или пользовательские свойства, используемые интеграциями.labeltypesizecolorinfosource + target, а также опциональными полями label, type, weight и метаданными стилей.Внутренний JSON-формат графа Quantickle — это плоская структура с массивами nodes и edges. Отношения контейнеров и классы сохраняются как метаданные узлов.
Quantickle принимает несколько форматов импорта через Файл → Импорт данных и из автоматических интеграций. Каждый импортёр использует тот же конвейер графов, что и при сохранении проектных файлов .qut, поэтому описанные ниже структуры также представляют собой формы экспорта.
Импортёр CSV распознаёт два формата:
Разделы узлов и рёбер – формат экспорта, используемый Quantickle и самый безопасный вариант при ручной подготовке данных. Файл содержит таблицу узлов, за которой следует пустая строка и таблица рёбер: ```csv node_id,node_label,node_type,node_size,node_color,node_x,node_y srv-1,Gateway,server,40,#2dd4bf,100,250 cli-1,Analyst,client,28,#38bdf8,320,210
source,target,label,weight,type srv-1,cli-1,allows,1,connection
Дополнительные столбцы допускаются — импортер нормализует заголовки, такие как
Node Label, nodeLabel или label, сохраняет любые явные значения color/size,
и сохраняет координаты, если они предоставлены.
source и target. Необязательные столбцы, такие как label, type,
weight, source_type, target_type, source_label или color, объединяются
в сгенерированные узлы и ребра при их наличии: ```csv
source,target,label,source_type,target_type
srv-1,cli-1,allows,server,client
srv-1,sensor-2,monitors,server,sensor
.edges)Поддерживаются пары рёбер, разделенные пробелами, для быстрого построения скелетных графов. Отсутствующие узлы создаются автоматически.```text srv-1 cli-1 srv-1 sensor-2
> **Примечание:** Книги Excel (`.xlsx`) больше не поддерживаются. Перед импортом в Quantickle экспортируйте или сохраните данные в формате CSV.
#### JSON
`File → Import Data` также принимает экспорты JSON, созданные Quantickle, или коллекции элементов Cytoscape. Когда файл содержит `elements` с вложенными записями `data`, они нормализуются во внутреннюю структуру Quantickle.
#### Граф Quantickle (`.qut`)
Файлы `.qut` — это документы JSON с плоскими объектами узлов и рёбер. Минимальный граф выглядит так:```json
{
"metadata": { "name": "My graph" },
"nodes": [
{ "id": "srv-1", "label": "Gateway", "type": "server", "size": 40 }
],
"edges": [
{ "id": "srv-1_cli-1", "source": "srv-1", "target": "cli-1", "label": "allows" }
]
}
Legacy files that store nodes/edges inside a data object are still accepted—the
loader flattens them automatically and preserves coordinates, classes, and
container hierarchy metadata.
When exchanging data with the HTTP API or Neo4j integration, send the same
flattened shape used by .qut files:```json
{
"nodes": [
{ "id": "srv-1", "label": "Gateway", "type": "server", "size": 40 }
],
"edges": [
{ "id": "srv-1_cli-1", "source": "srv-1", "target": "cli-1", "label": "allows" }
]
}
The optional `info` field still supports Markdown and is persisted alongside any
custom properties.
<a id="layouts"></a>
## Макеты
Quantickle группирует макеты в практичные семейства, чтобы вы могли выбрать подходящий для конкретной задачи:
- **Force-directed** (force, cose, fcose) — хороши для изучения структуры и естественной кластеризации.
- **Hierarchical & flow** (breadthfirst, dagre) — идеальны для деревьев зависимостей, графов вызовов или потоков причинно-следственных связей.
- **Grid & circle** — быстрые, детерминированные макеты для панелей мониторинга, небольших графов и экспорта.
- **Time-based** (timeline, timeline-scatter, temporal-attraction) — используйте, когда временной порядок или недавность имеют значение.
- **Spatial/absolute** (absolute, depth-aware) — используйте для картоподобных или диаграммных макетов с известными координатами.
- **Cluster/radial** (radial-recency) — используйте, когда нужна группировка по типу или кольцам недавности.
### Параметры макетов```javascript
// js/layouts.js
const layoutOptions = {
'force': {
name: 'force',
animate: true,
randomize: false,
infinite: false
},
'grid': {
name: 'grid',
rows: undefined,
cols: undefined
}
// ... more layouts
}
Пользовательский макет timeline располагает узлы вдоль временной оси. Вы можете настроить центральную полосу с помощью опции barStyle:```javascript
cy.layout({
name: 'timeline',
barStyle: {
color: '#3498db', // bar color
height: 15, // bar height in pixels
className: 'my-timeline-bar' // optional CSS class
}
}).run();
Когда указан `className`, временная шкала получает этот класс, а его стили цвета и высоты по умолчанию удаляются, чтобы вы могли нацелиться на него через CSS.
### Радиальная компоновка по давности
Используйте `radial-recency`, чтобы разместить самые новые элементы ближе к центру, а более старые — на внешних кольцах. Компоновка сопоставляет угол с дополнительным атрибутом (тип/кластер/группа), поэтому связанные узлы остаются выровненными по кругу. Вы можете настроить кольца с помощью нескольких опций:```javascript
cy.layout({
name: 'radial-recency',
ringThickness: 140, // radial spacing between time rings
minSeparation: 80, // minimum distance between neighbors along a ring
angleJitter: 0.15, // optional jitter (radians) to break perfect symmetry
angleStrategy: 'grouped' // or 'alphabetical' for deterministic ordering
}).run();
Смотрите graphs/radial_time_rings.qut для небольшого примера, который демонстрирует концентрические временные полосы, сгруппированные по метаданным кластера/типа.
Используйте макет timeline-scatter для прямого отображения временных меток на позиции по оси X, распределяя узлы по вертикали по сходству, категории или сообществу. Он принимает настраиваемые шкалы для обеих осей и необязательный разброс (jitter) для уменьшения перекрытия:```javascript
cy.layout({
name: 'timeline-scatter',
xScale: 0.5, // pixels per millisecond (auto-calculated when omitted)
yScale: 60, // spread for similarity/category lanes
jitter: 4, // optional per-node jitter to minimise overlap
barStyle: { // applied when timeline bars already exist
color: '#222',
height: 12,
className: 'scatter-bar'
}
}).run();
Nodes with numeric similarity scores (`similarity`, `similarityScore`, or `similarity_score`) are centred around the mean, while categorical or community labels create evenly spaced lanes along the y-axis.
### Макет временного притяжения
Используйте расстояние по временной метке, чтобы регулировать силы пружин, сохраняя слабое отталкивание:```javascript
cy.layout({
name: 'temporal-attraction',
timeMode: 'gaussian', // or 'bucket'
timeSigma: 60 * 60 * 1000, // Gaussian falloff window (in ms)
bucketSize: 24 * 60 * 60 * 1000, // bucket size when using bucket mode
repulsionStrength: 12 // minimal node repulsion
}).run();
Выберите Layout → Temporal Attraction - Time Weighted в интерфейсе или передайте name: 'temporal-attraction' через конфигурацию макета CLI/API, чтобы включить его.
Quantickle может получать данные из внешних систем или синхронизироваться с ними. Интеграции обычно проходят через сервер, так как требуют учетных данных, правил прокси или постоянного хранения.
http://localhost:3000.Для более подробных инструкций и скриншотов см. Руководство по использованию.
.qut для полноценного снимка проекта (макет, метаданные, контейнеры).Quantickle инициализируется через глобальный объект window.QuantickleApp, определенный в js/main.js. Приложение автоматически вызывает window.QuantickleApp.init(), когда DOM готов.
// js/config.js const config = { performance: { nodeLimit: 1000, // Max nodes to render at once batchSize: 100, // Nodes to add per batch webgl: true, // Enable WebGL rendering hideEdgesOnViewport: false // Hide edges while dragging } }
<a id="api"></a>
## API
### HTTP API
Сервер Express (`server.js`) обслуживает статический фронтенд и предоставляет несколько
JSON-конечных точек, используемых интерфейсом. Все маршруты имеют префикс `/api`:
| Метод и путь | Описание |
| --- | --- |
| `GET /api/domain-files` | Перечисляет JSON-определения доменов, находящиеся в `assets/domains/`. |
| `GET /api/examples` | Возвращает метаданные о встроенных примерах графов `.qut`. |
| `GET /api/serpapi` | Проксирует запросы Google Поиска к SerpApi; требуется `SERPAPI_API_KEY` в строке запроса или в окружении. |
| `GET /api/openai/models` | Проксирует запросы получения списка моделей OpenAI к `api.openai.com`; требуется заголовок `Authorization: Bearer ...`. |
| `GET /api/proxy?url=…` | Пересылает HTTP/HTTPS запросы разрешённым хостам с заголовками, наподобие браузерных. |
| `POST /api/neo4j/graph` | Сохраняет граф в Neo4j. Принимает уплощённое тело JSON графа Quantickle, описанное выше. |
| `POST /api/neo4j/node-graphs` | Находит сохранённые графы, содержащие узлы, соответствующие предоставленному массиву `labels`. |
| `GET /api/neo4j/graphs` | Перечисляет графы, хранящиеся в Neo4j, вместе с сводными метаданными. |
| `GET /api/neo4j/graph/:name` | Извлекает сохранённый граф, возвращая `metadata`, `nodes` и `edges`. |
| `DELETE /api/neo4j/graph/:name` | Удаляет сохранённый граф из Neo4j. |
Все конечные точки Neo4j принимают учётные данные через заголовки `X-Neo4j-Url`, `X-Neo4j-Username`
и `X-Neo4j-Password` (или переменные окружения `NEO4J_URL`, `NEO4J_USER` и
`NEO4J_PASSWORD` на сервере). При их указании объект `metadata` сохраняется вместе с графом, а временная метка `savedAt` добавляется автоматически.
<a id="api-keys"></a>
### Ключи API
Некоторые функции требуют ключей API. Они хранятся в локальном хранилище браузера через панель интеграций.
- **SerpAPI** — требуется для веб-поиска в RAG-конвейере. Добавьте свой ключ в диалоговом окне интеграций, и он будет использоваться клиентским RAG-конвейером.
- **VirusTotal** — используется для обогащения узлов доменов/IP/файлов/URL и извлечения графов связей.
- **CIRCL-LU** — необязательные учётные данные для аутентификации, если ваш MISP-фид их требует.
Для использования из командной строки вы также можете установить `SERPAPI_API_KEY` в окружении.
<a id="backend-proxy"></a>
### Бэкенд-прокси
Сервер предоставляет прокси, обходящий CORS, который пересылает HTTP(S) запросы хостам из белого списка прокси. Используйте `/api/proxy` с параметром URL:```
curl "http://localhost:3000/api/proxy?url=https%3A%2F%2Fopentip.kaspersky.com%2F"
Основной белый список находится в config/proxy-allowlist.json. Вы должны предоставить этот файл (или установить переменную окружения PROXY_ALLOWLIST с разделителем-запятой перед запуском сервера); в противном случае прокси регистрирует фатальную ошибку конфигурации и отклоняет каждый запрос с HTTP 403.
Хосты для конкретных интеграций (для адаптеров интеграции бэкенда, таких как OpenAI и VirusTotal) управляются файлом config/integration-allowlist.json (или INTEGRATION_ALLOWLIST). Во время выполнения оба белых списка объединяются. Каждая запись должна содержать хост или шаблон с подстановочным знаком, который прокси может достичь. Подстановочные знаки с использованием * поддерживаются в любом месте записи, поэтому *.example.com разрешает любой поддомен example.com, а маски типа news-* работают как ожидается. Поддомены также наследуют запись родительского домена, поэтому добавление example.com автоматически разрешает www.example.com.
Минимальный файл белого списка выглядит так:```json { "allowlist": ["otx.alienvault.com", "feeds.example.org"] }
Если вы предпочитаете переменные окружения, установите `PROXY_ALLOWLIST="otx.alienvault.com,feeds.example.org"` перед запуском сервера.
Когда прокси перенаправляет запрос, теперь он отправляет набор заголовков, похожих на браузерные (включая современные значения Chrome `User-Agent`, `Accept`, `Accept-Language` и `Sec-Fetch-*`), так что сайты, которые закрывают контент за антибот-фильтрами, отвечают так же, как на обычную загрузку страницы. Любой из этих заголовков можно переопределить, указав переопределения `x-proxy-<header>` из клиентского запроса при необходимости.
<a id="storage"></a>
## Хранилище
Quantickle сохраняет состояние графа в браузере во время работы, а затем сохраняет его при экспорте или синхронизации.
- **Хранилище браузера** — настройки и ключи API хранятся локально в браузере.
- **Файлы проекта (`.qut`)** — сохраняются в вашу рабочую папку для создания снимков графа с полной точностью. Смотрите [GRAPH_FILE_MANAGEMENT_README.md](https://github.com/rsac-labs/quantickle/blob/HEAD/GRAPH_FILE_MANAGEMENT_README.md) для правил рабочей области и жизненного цикла файлов.
- **Neo4j** — опциональное серверное сохранение для совместной работы и поиска, настраивается через интеграцию с Neo4j.
<a id="project-structure"></a>
## Структура проекта```
quantickle/
├── assets/ # Static assets
│ ├── backgrounds/ # Background graphics
│ ├── icons/ # Mostly empty now; icons are colocated with node types
│ ├── domains/ # Node type definitions
│ ├── help/ # Help pages
│ ├── examples/ # Example graphs
│ └── css/ # Stylesheets referenced by index.html
├── config/ # Proxy allowlist
├── data_retrieval/ # SerpAPI/web search helpers used by the RAG pipeline
├── graphs/ # Workspace folder for bundled and test .qut graphs
├── js/ # Front-end source modules
│ ├── main.js # Application bootstrap
│ ├── ai-input-manager.js # Currently unused
│ ├── api.js # HTTP client for server endpoints
│ ├── graph.js # Graph rendering and management
│ ├── graph-manager.js # High-level graph state orchestration
│ ├── graph-reference-resolver.js # Normalization of graph references
│ ├── layouts.js # Layout registration and options
│ ├── 3d-globe-layout.js # 3D Layout
│ ├── absolute-layout.js # Absolute coordinate layout
│ ├── custom-layouts.js # Other custom layouts
│ ├── aggressive-performance-fix.js # Aggressive Performance Fix for Large Graph Panning
│ ├── non-invasive-performance-fix.js # Non-Invasive Performance Fix for Large Graphs
│ ├── lod-system.js # Level of Detail (LOD) System
│ ├── auto-refresh.js # Auto-refresh functionality when new data arrives
│ ├── config.js # Default settings
│ ├── domain-loader.js # Loading and managing domain-specific node type configurations
│ ├── edge-editor.js # Editing edge styles
│ ├── extensions.js # Loading and registration of Cytoscape extensions
│ ├── integrations.js # Configuration and connection to external services
│ ├── rag-pipeline.js # Handles AI-assisted data ingestion
│ ├── secure-storage.js # Encrypts sensitive values in sessionStorage
│ ├── source-editor.js # Editor for the JSON graph source
│ ├── tables.js # Data table updates, filtering, and display
│ ├── ui.js # User interface interactions and notifications
│ ├── validation.js # Validation of all data inputs
│ ├── workspace-manager.js # Workspace file functionality
│ ├── utils.js # Shared browser utilities
│ ├── integrations/ # Integration-specific helpers (MISP/CIRCL-LU, etc.)
│ └── features/ # Feature modules (node editor, callouts, timeline, ...)
├── tests/ # Automated regression tests covering UI flows, imports, and APIs
├── utils/ # Node helpers (Neo4j client, readability shim, CLI scripts)
├── public/
│ ├── index.html # Static front-end
│ └── favicon.ico # Main app icon
├── package.json # Node dependencies and scripts
└── server.js # Express server exposing the HTTP API
График не отображается
Низкая производительность
Проблемы с макетом
Этот проект активно не поддерживается как каноническое хранилище. Запросы на слияние (PR), скорее всего, будут проигнорированы. Однако приветствуются отзывы, сообщения об ошибках и комментарии.
Этот проект лицензирован под лицензией Apache 2.0 — подробности см. в файле LICENSE.