Network Topology tab
Adds a Topology view to each project that renders a host / credential / access graph derived automatically from the project's free-text facts — turning the prose agents write into a map you can read at a glance.
What it does
- Facts ↔ Topology toggle on the graph canvas; a Cytoscape (dagre) graph whose nodes are hosts colored by the highest confirmed access level (root/SYSTEM, admin, user, scanned-only), with the attacker box and ICS/OT targets called out, and edges typed as visibility / pivot / cred-works.
- On-demand generation, cached in a new
topologytable (auto-migrates viaCREATE TABLE IF NOT EXISTS); a staleness badge appears when new facts arrive. - Selectable extractor model via a gear dropdown — the recommended option is highlighted; unavailable ones are greyed with the reason.
How the extractor finds models
The feature does not hard-code one backend. list_models() merges:
- Workers of the running dispatcher — it locates the live
cairn dispatch --config Xprocess, reads that config, and exposes every worker carrying an API endpoint + key (pi/GLM/Qwen/DeepSeek via OpenAI-compatible or Anthropic HTTP, or container-modeclaudecode). The dispatcher's primary worker becomes the recommended default, so "whatever model you plugged in" just shows up. - Host CLIs on PATH —
claude(sonnet/opus/haiku) andcodex. - A fully custom command via
CAIRN_TOPO_CMD.
Notes:
- API keys are read server-side only and are never included in the
/topology/modelspayload sent to the browser. - For "thinking" models (e.g. GLM) the call sends
thinking: {type: disabled}so they don't spend the whole output budget on reasoning and return empty content; the field is stripped and retried on a 400/422 for strict backends. - Claude Haiku is flagged as discouraged (its cyber safeguards reject offensive-security notes).
New endpoints
GET /topology/modelsGET /projects/{id}/topologyPOST /projects/{id}/topology/refresh?model=<id>
Files
server/topology_extract.py (new), server/routers/topology.py (new),
server/db.py, server/app.py, server/static/index.html.
Verified end-to-end against Claude Sonnet (29 hosts / 51 edges) and a live GLM worker
(~z-ai/glm-flash-latest via an OpenAI-compatible endpoint, 29 hosts / 44 edges) on a
real engagement's 38 facts.
Вкладка «Топология сети» (RU)
Добавляет в каждый проект вкладку Topology — граф хостов / учёток / уровней доступа, который строится автоматически из свободного текста фактов проекта.
Что умеет
- Переключатель Facts ↔ Topology; граф Cytoscape (dagre), где узлы-хосты раскрашены по наивысшему подтверждённому доступу (root/SYSTEM, admin, user, только скан), выделены атакующая машина и цели АСУ ТП, а рёбра размечены как видимость / пивот / рабочие креды.
- Генерация по кнопке, результат кэшируется в новой таблице
topology; при появлении новых фактов показывается плашка «устарело». - Выбор модели-экстрактора через шестерёнку: рекомендованная подсвечена, недоступные серые с причиной.
Как находятся модели
Бэкенд не привязан к одному провайдеру. list_models() объединяет:
- Воркеры запущенного диспетчера — находит живой процесс
cairn dispatch --config X, читает конфиг и показывает каждый воркер с API-эндпоинтом и ключом (pi/GLM/Qwen/DeepSeek через OpenAI- или Anthropic-совместимый HTTP, либоclaudecodeв контейнерном режиме). Основной воркер диспетчера становится рекомендованным по умолчанию — «какую нейронку подключил, та и появляется». - Хостовые CLI на PATH —
claude(sonnet/opus/haiku) иcodex. - Произвольная команда через
CAIRN_TOPO_CMD.
Важное:
- Ключи API читаются только на сервере и никогда не попадают в ответ
/topology/models. - Для «думающих» моделей (например GLM) запрос шлёт
thinking: {type: disabled}, иначе они тратят весь бюджет вывода на рассуждения и возвращают пустой ответ; поле убирается и запрос повторяется при 400/422 на строгих бэкендах. - Claude Haiku помечен как нежелательный (его cyber-фильтры отклоняют офенсив-контент).
Проверено
End-to-end на Claude Sonnet (29 хостов / 51 ребро) и на живом GLM-воркере
(~z-ai/glm-flash-latest, OpenAI-совместимый эндпоинт, 29 хостов / 44 ребра) на 38
фактах реального проекта.
🤖 Generated with Claude Code