
Ein Graphen-Toolkit für die Bedrohungsforschung – und andere Dinge.
Dieses Projekt wurde weitgehend per Vibecoding erstellt, daher solltest du entsprechende Vorsichtsmaßnahmen treffen. Der Code wurde von echten Programmierern überprüft, ist aber nicht gegen Schwachstellen gehärtet. Ohne eine gründliche Sicherheitsüberprüfung nicht extern zugänglich machen.
Quantickle ist ein interaktives, browserzentriertes Toolkit zum Erstellen und Untersuchen von Netzwerkgraphen. Das Frontend (Cytoscape.js + eigene UI) übernimmt Rendering, Bearbeitung und Layout-Ausführung, während der schlanke Express-Server die UI ausliefert, Integrationsaufrufe weiterleitet und optional Graphen in Neo4j speichert. Mit anderen Worten: Der Browser besitzt den Graphenzustand und die Visualisierung, während der Server existiert, um bei Bedarf Assets und Integrationen bereitzustellen.
bezier), gerade, gebündelte (unbundled-bezier), Taxi- und abgerundete Taxi-Optionen.haystack- und segments-Kurvenstile.Hier sind einige Beispiele, was Quantickle kann:

Quantickle baut auf einer kleinen Menge gemeinsamer Konzepte auf, die die Dokumentation verbinden:
Koordinatensystem & räumliche Layouts — Quantickles absolute und tiefenbewusste Layouts verwenden einen 0–1000-Würfel für x-, y- und z-Koordinaten. Vollständige räumliche Regeln und Lichtverhalten findest du unter COORDINATE_SYSTEM.md.
Graphdateiverwaltung & Projektdateien — .qut-Dateien sind der kanonische gespeicherte Zustand; sie speichern Knoten, Kanten, Metadaten und die Container-Hierarchie.
Neo4j-Integration — Der Server kann Graphen in Neo4j speichern und daraus abrufen, einschließlich Metadaten-Snapshots. Details zu Konfiguration und Workflow findest du unter NEO4J_INTEGRATION_README.md.
Ein Quantickle-Graph ist eine Menge von Knoten und Kanten mit Metadaten, die Layout, Styling und Gruppierung steuern.
metadata, Knoten-Array, Kanten-Array und optionalem Layout- oder Ansichtszustand.id plus optionalen Attributen wie , , , und Koordinaten. Knoten können auch Markdown-- oder benutzerdefinierte Eigenschaften enthalten, die von Integrationen verwendet werden.labeltypesizecolorinfosource- und target-Knoten-IDs sowie optionalem label, type, weight und Styling-Metadaten.Quantickles internes Graph-JSON ist eine flache Struktur mit nodes- und edges-Arrays. Container-Beziehungen und -Klassen werden als Knotenmetadaten gespeichert.
Quantickle akzeptiert mehrere Importformate über Datei → Daten importieren und über automatisierte Integrationen. Jeder Importeur speist dieselbe Graph-Pipeline, die auch beim Speichern von .qut-Projektdateien verwendet wird. Die folgenden Strukturen stellen daher auch die Exportformen dar.
Der CSV-Importeur erkennt zwei Layouts:
Knoten- und Kantenabschnitte – Exportformat von Quantickle und die sicherste Option bei manueller Datenvorbereitung. Die Datei enthält eine Knotentabelle, gefolgt von einer leeren Zeile und einer Kantentabelle: ```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
Zusätzliche Spalten werden toleriert—der Importeur normalisiert Kopfzeilen wie
Node Label, nodeLabel oder label, bewahrt explizite color/size-Werte
und behält Koordinaten bei, sofern sie angegeben sind.
source- und target-Spalten enthalten. Optionale Spalten wie label, type,
weight, source_type, target_type, source_label oder color werden
in die generierten Knoten und Kanten übernommen, sofern vorhanden: ```csv
source,target,label,source_type,target_type
srv-1,cli-1,allows,server,client
srv-1,sensor-2,monitors,server,sensor
Quantickle parst Header ohne Beachtung der Groß-/Kleinschreibung, akzeptiert sowohl snake_case- als auch durch Leerzeichen getrennte Namen und überspringt leere Zeilen automatisch.
.edges)Einfache, durch Leerzeichen getrennte Kantenpaare werden für schnelle Skelettgraphen unterstützt. Fehlende Knoten werden automatisch erstellt:```text srv-1 cli-1 srv-1 sensor-2
> **Hinweis:** Excel-Arbeitsmappen (`.xlsx`) werden nicht mehr unterstützt. Exportieren oder speichern Sie
> die Daten als CSV, bevor Sie sie in Quantickle importieren.
#### JSON
`Datei → Daten importieren` akzeptiert auch JSON-Exporte von Quantickle oder rohe
Cytoscape-Elementauflistungen. Wenn die Datei `elements` mit verschachtelten
`data`-Einträgen enthält, werden sie in Quantickles interne Struktur normalisiert.
#### Quantickle-Graph (`.qut`)
`.qut`-Dateien sind JSON-Dokumente mit flachen Knoten- und Kantenobjekten. Ein minimaler
Graph sieht folgendermaßen aus:```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-Dateien, die Knoten/Kanten in einem data-Objekt speichern, werden weiterhin akzeptiert — der
Loader flacht sie automatisch ab und bewahrt Koordinaten, Klassen und
Container-Hierarchie-Metadaten.
Beim Austausch von Daten mit der HTTP-API oder der Neo4j-Integration sende dieselbe
abgeflachte Struktur, die für .qut-Dateien verwendet wird:```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" }
]
}
Das optionale Feld `info` unterstützt weiterhin Markdown und wird zusammen mit beliebigen
benutzerdefinierten Eigenschaften gespeichert.
<a id="layouts"></a>
## Layouts
Quantickle gruppiert Layouts in praktische Familien, sodass du für die jeweilige Aufgabe das richtige auswählen kannst:
- **Kraftbasiert** (force, cose, fcose) — gut für die explorative Strukturerkundung und wenn du natürliche Clusterbildung wünschst.
- **Hierarchisch & Fluss** (breadthfirst, dagre) — am besten geeignet für Abhängigkeitsbäume, Aufrufgraphen oder kausale Abläufe.
- **Raster & Kreis** — schnelle, deterministische Layouts für Dashboards, kleine Graphen und Exporte.
- **Zeitbasiert** (timeline, timeline-scatter, temporal-attraction) — verwende dies, wenn zeitliche Ordnung oder Aktualität im Mittelpunkt steht.
- **Räumlich/Absolut** (absolute, depth-aware) — für kartenartige oder diagrammatische Layouts mit bekannten Koordinaten.
- **Cluster/Radial** (radial-recency) — verwende dies, wenn du nach Typ oder Aktualitätsringen gruppieren möchtest.
### Layout-Optionen```javascript
// js/layouts.js
const layoutOptions = {
'force': {
name: 'force',
animate: true,
randomize: false,
infinite: false
},
'grid': {
name: 'grid',
rows: undefined,
cols: undefined
}
// ... more layouts
}
Das benutzerdefinierte timeline-Layout positioniert Knoten entlang einer Zeitachse. Sie können die zentrale Leiste über die Option barStyle anpassen:```javascript
cy.layout({
name: 'timeline',
barStyle: {
color: '#3498db', // bar color
height: 15, // bar height in pixels
className: 'my-timeline-bar' // optional CSS class
}
}).run();
Wenn `className` angegeben wird, erhält die Zeitleistenleiste diese Klasse und ihr Standard-Farb- und Höhen-Styling wird entfernt, sodass du sie über CSS ansprechen kannst.
### Radial-Recency-Layout
Verwende `radial-recency`, um die neuesten Elemente am nächsten zum Zentrum und ältere auf äußeren Ringen zu platzieren. Das Layout ordnet den Winkel einem sekundären Attribut (Typ/Cluster/Gruppe) zu, sodass zusammengehörige Knoten um den Kreis herum ausgerichtet bleiben. Du kannst die Ringe mit einigen Optionen anpassen:```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();
Siehe graphs/radial_time_rings.qut für eine kleine Test-Fixture, die konzentrische Zeitbänder demonstriert, die nach Cluster-/Typ-Metadaten gruppiert sind.
Verwenden Sie das timeline-scatter-Layout, um Zeitstempel direkt auf x-Positionen abzubilden, während Knoten vertikal nach Ähnlichkeit, Kategorie oder Community verteilt werden. Es akzeptiert einstellbare Skalierungen für beide Achsen und optionales Jitter, um Überlappungen zu reduzieren:```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();
Knoten mit numerischen Ähnlichkeitswerten (`similarity`, `similarityScore` oder `similarity_score`) sind um den Mittelwert zentriert, während kategoriale oder Community-Labels gleichmäßig verteilte Bahnen entlang der y-Achse erzeugen.
### Zeitliches Attraktions-Layout
Verwende den Zeitstempel-Abstand, um die Federstärken zu steuern, während die Abstoßung gering gehalten wird:```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();
Wählen Sie Layout → Temporal Attraction - Time Weighted in der Benutzeroberfläche oder übergeben Sie name: 'temporal-attraction' über die CLI/API-Layoutkonfiguration, um es zu aktivieren.
Quantickle kann Daten aus externen Systemen ziehen oder mit ihnen synchronisieren. Integrationen laufen im Allgemeinen über den Server, da sie Anmeldedaten, Proxy-Regeln oder Persistenz erfordern.
http://localhost:3000.Ausführlichere Anleitungen und Screenshots finden Sie im Benutzerhandbuch.
.qut für eine Projekt-Snapshots mit voller Wiedergabetreue (Layout, Metadaten, Container).Quantickle initialisiert sich über das globale window.QuantickleApp, das in js/main.js definiert ist. Die Anwendung ruft automatisch window.QuantickleApp.init() auf, sobald das DOM bereit ist.
// 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
Der Express-Server (`server.js`) stellt das statische Frontend bereit und legt mehrere JSON-Endpunkte offen, die von der Benutzeroberfläche genutzt werden. Alle Routen sind mit `/api` präfixiert:
| Methode & Pfad | Beschreibung |
| --- | --- |
| `GET /api/domain-files` | Listet JSON-Domaindefinitionen auf, die sich in `assets/domains/` befinden. |
| `GET /api/examples` | Gibt Metadaten zu den mitgelieferten Beispiel-`.qut`-Graphen zurück. |
| `GET /api/serpapi` | Proxyt Google-Suchanfragen an SerpApi; erfordert `SERPAPI_API_KEY` in der Query-String oder in der Umgebung. |
| `GET /api/openai/models` | Proxyt OpenAI-Modelllisten-Anfragen an `api.openai.com`; erfordert einen `Authorization: Bearer ...`-Header. |
| `GET /api/proxy?url=…` | Leitet HTTP/HTTPS-Anfragen an erlaubte Hosts mit browserähnlichen Headern weiter. |
| `POST /api/neo4j/graph` | Speichert einen Graphen in Neo4j. Akzeptiert das oben beschriebene, abgeflachte Quantickle-Graph-JSON als Body. |
| `POST /api/neo4j/node-graphs` | Findet gespeicherte Graphen, die Knoten enthalten, welche zum bereitgestellten `labels`-Array passen. |
| `GET /api/neo4j/graphs` | Listet in Neo4j gespeicherte Graphen zusammen mit zusammenfassenden Metadaten auf. |
| `GET /api/neo4j/graph/:name` | Ruft einen gespeicherten Graphen ab und gibt `metadata`, `nodes` und `edges` zurück. |
| `DELETE /api/neo4j/graph/:name` | Entfernt einen gespeicherten Graphen aus Neo4j. |
Alle Neo4j-Endpunkte akzeptieren Zugangsdaten über die Header `X-Neo4j-Url`, `X-Neo4j-Username` und `X-Neo4j-Password` (oder die Umgebungsvariablen `NEO4J_URL`, `NEO4J_USER` und `NEO4J_PASSWORD` auf dem Server). Wenn angegeben, wird das Objekt `metadata` zusammen mit dem Graphen gespeichert und ein Zeitstempel `savedAt` automatisch angehängt.
<a id="api-keys"></a>
### API-Schlüssel
Einige Funktionen erfordern API-Schlüssel. Diese werden über das Integrations-Panel im lokalen Speicher des Browsers gespeichert.
- **SerpAPI** — erforderlich für die Websuche der RAG-Pipeline. Fügen Sie Ihren Schlüssel im Integrationsdialog hinzu, und er wird von der clientseitigen RAG-Pipeline verwendet.
- **VirusTotal** — wird verwendet, um Domain-/IP-/Datei-/URL-Knoten anzureichern und Beziehungsgraphen abzurufen.
- **CIRCL-LU** — optionale Authentifizierungsdaten, falls Ihr MISP-Feed diese erfordert.
Für die Kommandozeilen-Nutzung können Sie alternativ `SERPAPI_API_KEY` in der Umgebung setzen.
<a id="backend-proxy"></a>
### Backend-Proxy
Der Server stellt einen CORS-umgehenden Proxy bereit, der HTTP(S)-Anfragen an Hosts weiterleitet, die in der Proxy-Allowlist aufgeführt sind. Verwenden Sie `/api/proxy` mit einem URL-Parameter:```
curl "http://localhost:3000/api/proxy?url=https%3A%2F%2Fopentip.kaspersky.com%2F"
Die Basis-Allowlist befindet sich in config/proxy-allowlist.json. Sie müssen diese Datei bereitstellen (oder eine durch Kommas getrennte Umgebungsvariable PROXY_ALLOWLIST vor dem Start des Servers setzen); andernfalls protokolliert der Proxy einen fatalen Konfigurationsfehler und lehnt jede Anfrage mit HTTP 403 ab.
Integration-spezifische Hosts (für Backend-Integrationsadapter wie OpenAI und VirusTotal) werden durch config/integration-allowlist.json (oder INTEGRATION_ALLOWLIST) geregelt. Zur Laufzeit werden beide Allowlists zusammengeführt. Jeder Eintrag sollte einen Host oder ein Wildcard-Muster enthalten, das der Proxy erreichen darf. Wildcards mit * sind überall in einem Eintrag unterstützt, sodass *.example.com jede Subdomain von example.com erlaubt und Masken wie news-* wie erwartet funktionieren. Subdomains erben außerdem den Eintrag ihrer übergeordneten Domain, sodass das Hinzufügen von example.com automatisch www.example.com erlaubt.
Eine minimale Allowlist-Datei sieht wie folgt aus:```json { "allowlist": ["otx.alienvault.com", "feeds.example.org"] }
Wenn Sie Umgebungsvariablen bevorzugen, setzen Sie `PROXY_ALLOWLIST="otx.alienvault.com,feeds.example.org"`, bevor Sie den Server starten.
Wenn der Proxy eine Anfrage weiterleitet, sendet er jetzt einen browserähnlichen Headersatz (einschließlich moderner Chrome-`User-Agent`-, `Accept`-, `Accept-Language`- und `Sec-Fetch-*`-Werte), sodass Websites, die ihre Inhalte hinter Anti-Bot-Filtern abschirmen, genauso reagieren, wie sie es bei einem normalen Seitenaufruf tun würden. Jeder dieser Header kann überschrieben werden, indem bei Bedarf `x-proxy-<header>`-Überschreibungen aus der Client-Anfrage bereitgestellt werden.
<a id="storage"></a>
## Speicher
Quantickle behält den Graphzustand während der Arbeit im Browser und persistiert ihn, wenn Sie exportieren oder synchronisieren.
- **Browser-Speicher** — Einstellungen und API-Schlüssel werden lokal im Browser gespeichert.
- **Projektdateien (`.qut`)** — werden in Ihrem Arbeitsbereichsordner gespeichert, um originalgetreue Graph-Snapshots zu erhalten. Siehe [GRAPH_FILE_MANAGEMENT_README.md](https://github.com/rsac-labs/quantickle/blob/main/GRAPH_FILE_MANAGEMENT_README.md) für Arbeitsbereichsregeln und Dateilebenszyklus.
- **Neo4j** — optionale serverseitige Persistenz für Zusammenarbeit und Suche, konfiguriert über die Neo4j-Integration.
<a id="project-structure"></a>
## Projektstruktur```
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
Graph wird nicht gerendert
Schlechte Leistung
Layout-Probleme
Dieses Projekt wird nicht aktiv als kanonischer Store gepflegt. Pull Requests werden wahrscheinlich ignoriert. Feedback, Fehlerberichte und Kommentare sind jedoch willkommen.
Dieses Projekt ist unter der Apache 2.0 License lizenziert – siehe die LICENSE-Datei für Details.