Graph format
Reference for the GraphNode and GraphEdge types used to represent entities and relationships in the Flowsint graph. Understanding these structures is essential for working with the frontend visualization and the graph database layer.
Overview
Flowsint's graph visualization is built on two core data structures: GraphNode (representing entities) and GraphEdge (representing relationships between entities). These types are defined in flowsint-app/src/types/graph.ts and are used throughout the frontend for rendering, interaction, and data management.
Understanding these structures is important when:
- Building enrichers that create nodes and relationships
- Working on the frontend visualization
- Debugging graph rendering issues
- Extending the graph with new visual features
GraphNode
A GraphNode represents a single entity in the graph (e.g., a domain, an IP address, a person). Every node created by an enricher's create_node() method ends up as a GraphNode in the frontend.
type GraphNode = {
id: string
nodeType: string
nodeLabel: string
nodeProperties: NodeProperties
nodeSize: number
nodeColor: string | null
nodeIcon: keyof typeof LucideIcons | null
nodeImage: string | null
nodeFlag: flagColor | null
nodeShape: NodeShape | null
nodeMetadata: NodeMetadata
x: number
y: number
val?: number
neighbors?: any[]
links?: any[]
}Field reference
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the node. Derived from the type's primary field value. |
nodeType | string | The entity type (e.g., "Domain", "Ip", "Email"). Maps to the Pydantic type class name. |
nodeLabel | string | Human-readable label displayed on the node. Set by the type's compute_label() method. |
nodeProperties | NodeProperties | All properties of the entity as key-value pairs. Contains the serialized fields from the Pydantic type. |
nodeSize | number | Visual size of the node in the graph. |
nodeColor | string | null | Custom color override for the node (CSS color string), or null for default. |
nodeIcon | keyof LucideIcons | null | Icon to display on the node, from the Lucide icon set, or null for default. |
nodeImage | string | null | URL to an image to display on the node (e.g., a profile picture), or null. |
nodeFlag | flagColor | null | Color flag for visual tagging (see Flag colors below), or null. |
nodeShape | NodeShape | null | Shape of the node (see Node shapes below), or null for default circle. |
nodeMetadata | NodeMetadata | Additional metadata as key-value pairs. Used for internal tracking and extended features. |
x | number | X coordinate position in the graph canvas. |
y | number | Y coordinate position in the graph canvas. |
val | number (optional) | Value used by the force-graph engine for sizing calculations. |
neighbors | any[] (optional) | Adjacent nodes, populated by the graph engine at runtime. |
links | any[] (optional) | Connected edges, populated by the graph engine at runtime. |
NodeProperties
type NodeProperties = {
[key: string]: any
}A flexible key-value object containing all the entity's properties. When a Pydantic type is serialized into a node, its fields become entries in nodeProperties. For example, a Domain node would have nodeProperties.domain, nodeProperties.root, etc.
NodeMetadata
type NodeMetadata = {
[key: string]: any
}Similar to nodeProperties but used for system-level metadata rather than entity data. This can include information like creation timestamps, source enricher, or other tracking data.
Node shapes
Nodes can be rendered in four shapes:
type NodeShape = 'circle' | 'square' | 'hexagon' | 'triangle'| Shape | Use case |
|---|---|
circle | Default shape for most entity types |
square | Often used for infrastructure entities |
hexagon | Used for grouped or aggregate entities |
triangle | Used for alert or warning-related entities |
Flag colors
Flags provide a visual tagging system for nodes. Users can flag nodes to highlight them during an investigation.
type flagColor = 'red' | 'orange' | 'blue' | 'green' | 'yellow'Each flag color maps to specific Tailwind CSS classes for consistent styling:
| Flag | Style |
|---|---|
red | text-red-400 fill-red-200 |
orange | text-orange-400 fill-orange-200 |
blue | text-blue-400 fill-blue-200 |
green | text-green-400 fill-green-200 |
yellow | text-yellow-400 fill-yellow-200 |
GraphEdge
A GraphEdge represents a relationship between two nodes (e.g., "RESOLVES_TO", "HAS_SUBDOMAIN", "FOUND_IN_BREACH"). Every relationship created by an enricher's create_relationship() method ends up as a GraphEdge in the frontend.
type GraphEdge = {
source: GraphNode['id']
target: GraphNode['id']
date?: string
id: string
label: string
caption?: string
type?: string
weight?: number
confidence_level?: number | string
}Field reference
| Field | Type | Description |
|---|---|---|
source | string | ID of the source node (the "from" node in the relationship). |
target | string | ID of the target node (the "to" node in the relationship). |
id | string | Unique identifier for this edge. |
label | string | Display label for the edge (e.g., "RESOLVES_TO", "HAS_EMAIL"). This is the relationship type string passed to create_relationship(). |
date | string (optional) | Timestamp associated with the relationship (ISO 8601 format). |
caption | string (optional) | Additional descriptive text displayed on or near the edge. |
type | string (optional) | Relationship classification type for filtering or styling. |
weight | number (optional) | Numerical weight of the relationship, can be used for visual thickness or importance ranking. |
confidence_level | number | string (optional) | Confidence score for the relationship, indicating how reliable the connection is. |
How enrichers map to the graph
When you write an enricher and call graph methods in postprocess(), here's how the data flows:
Creating nodes
# In your enricher's postprocess method
self.create_node(domain) # domain is a Pydantic Domain objectThe graph service automatically:
- Extracts the type name from the Pydantic class (e.g.,
"Domain") ->nodeType - Reads the primary field value (e.g.,
domain.domain) -> used forid - Reads the nodeLabel field (set by
compute_label()) ->nodeLabel - Serializes all fields into
nodeProperties - Sets defaults for visual properties (
nodeSize,nodeColor, etc.)
Creating relationships
# In your enricher's postprocess method
self.create_relationship(domain, ip, "RESOLVES_TO")The graph service automatically:
- Identifies the source node from
domain's type and primary field ->source - Identifies the target node from
ip's type and primary field ->target - Uses the relationship label
"RESOLVES_TO"->label - Generates a unique
idfor the edge
Relationship naming conventions
Relationship labels follow these conventions:
- Use UPPER_SNAKE_CASE (e.g.,
"RESOLVES_TO","HAS_SUBDOMAIN") - Use verb phrases that describe the relationship direction (source -> target)
- The default relationship label is
"IS_RELATED_TO"if none is specified - Common patterns:
HAS_*for ownership/containment (e.g.,"HAS_EMAIL","HAS_SUBDOMAIN")RESOLVES_TOfor DNS-type lookupsFOUND_IN_*for breach/leak associationsREGISTERED_BYfor WHOIS data
Graph settings
The graph visualization is configurable through settings types:
ForceGraphSetting
Controls the physics simulation of the force-directed graph layout:
type ForceGraphSetting = {
value: any
min?: number
max?: number
step?: number
type?: string
description?: string
}ExtendedSetting
General-purpose settings with richer type information:
type ExtendedSetting = {
value: any
type: string
min?: number
max?: number
step?: number
options?: { value: string; label: string }[]
description?: string
}These settings allow users to customize graph behavior like node repulsion, link distance, simulation speed, and visual preferences.
Reserved properties
When creating nodes, certain property names are reserved by the system and should not be used as field names in your custom types:
id- Node identifierx,y- Position coordinatesnodeLabel- Display label (set bycompute_label())label- Legacy label fieldnodeType,type- Entity type identifiersnodeImage,nodeIcon,nodeColor,nodeSize- Visual propertiescreated_at- Creation timestampsketch_id- Investigation sketch association