Skip to content

Graph Schema

Every cloud resource is a CRN-keyed node. Every relationship is a typed edge. Here is the full schema.


Node Schema

Every cloud resource is a Node in the graph. The canonical in-memory representation:

Field Type Description
crn string Cloud Resource Name: stable unique identifier
type string Resource type (e.g., ec2:instance, gke:cluster)
provider string Cloud provider (aws, gcp, azure, k8s, linode)
region string Cloud region (e.g., us-east-1, eu-west-1)
state string Provider-reported lifecycle state (running, stopped, etc.)
cost_usd_mo float32 Estimated monthly cost in USD
tags map[string]string Resource tags / labels
properties map[string]any All provider-specific attributes
creation_timestamp uint64 Unix epoch of resource creation
valid_to uint64 Logical deletion timestamp (0 = active)
is_waste bool Heuristics engine verdict
waste_reason string Human-readable waste explanation
risk_score float64 Oracle formal verification score (0–100)
reachability string reachable / unreachable / unknown
phase string Remediation pipeline phase
verdict string Engine-computed classification

Edge Types

Edges are typed directed relationships between nodes. The EdgeRelationship enum:

Relationship Direction Meaning
AttachedTo A → B A is physically attached to B (volume → instance)
SecuredBy A → B A's network access is controlled by B (instance → security group)
Contains A → B A is the logical parent of B (VPC → subnet)
Runs A → B A executes on B (pod → node)
FlowsTo A → B Traffic flows from A to B (subnet → internet gateway)
Grants A → B A grants permissions to B (IAM role → resource)
Uses A → B A depends on B at the API level (Lambda → RDS)

Example Subgraph

ec2:instance (i-0abc123)
    ├── SecuredBy → ec2:security-group (sg-0aaa)
    ├── AttachedTo → ebs:volume (vol-0bbb)
    └── Uses → rds:instance (db-prod)
               └── SecuredBy → ec2:security-group (sg-rds)

The Ghost Linker discovers cross-provider edges that no individual plugin can see. For example, a K8s pod's CIDR range overlapping an AWS VPC peering route.


FlatBuffers Specification

The graph is serialized using FlatBuffers for zero-copy inter-process transport between the daemon and plugins:

// pkg/graph/graph.fbs
namespace CloudSlash.Graph;

enum EdgeRelationship : byte {
    AttachedTo = 0,
    SecuredBy  = 1,
    Contains   = 2,
    Runs       = 3,
    FlowsTo    = 4,
    Grants     = 5,
    Uses       = 6
}

table Property {
    key:   string;
    value: string;
}

table Node {
    crn:                string (required, key);
    type:               string (required);
    state:              string;
    cost_usd_mo:        float32;
    properties:         [Property];
    creation_timestamp: uint64;
    valid_to:           uint64;   // 0 = active; >0 = logically deleted
}

table Edge {
    source_crn:   string (required);
    target_crn:   string (required);
    relationship: EdgeRelationship;
    properties:   [Property];
    valid_to:     uint64;         // s.a.u isolation boundary
}

table Graph {
    nodes:        [Node];
    edges:        [Edge];
    version:      uint32;
    last_updated: uint64;
}

root_type Graph;

CRN Format

The CloudSlash Resource Name (CRN) provides a stable, globally unique identifier for every resource. It is the graph node key, audit ledger key, and history API key.

crn:devi:<provider>:<region>:<service>:<type>:<account_id>:<physical_id>

Examples

Provider CRN
AWS EC2 crn:devi:aws:us-east-1:ec2:instance:123456789012:i-0abc123def456789
GCP VM crn:devi:gcp:us-central1:compute:instance:data-lake-prod:vm-worker-01
Azure VM crn:devi:azure:eastus:compute:vm:sub-abc123:my-analytics-vm
K8s Pod crn:devi:k8s:us-east-1:core:pod:kube-system:coredns-7db6d8ff4-xk9z2
Linode crn:devi:linode:us-east:compute:instance:12345678:my-linode

CRNs are deterministic. The same physical resource always produces the same CRN across scans. This stability is essential for time-travel queries and audit trail correlation.


Temporal Air-Gapping

s.a.u does not delete nodes from the graph when resources are removed. It uses logical deletion via the valid_to timestamp:

// When a resource is deleted or purged:
node.valid_to = time.Now().UnixMicro()

All graph traversals filter using:

node.valid_to == 0 || node.valid_to > time.Now().UnixMicro()

Logically deleted nodes remain in the BadgerDB temporal store. This enables time-travel queries (cs diff) and forensic attribution long after the physical resource is gone.


Concurrency Model

The graph uses a double-sharded, lock-striped design for high-throughput concurrent writes:

  • Node shards: 256 shards keyed by CRN hash. Each shard has its own sync.RWMutex.
  • Edge shards: 128 shards keyed by (source_crn + relationship) hash.
  • Writer pool: The Swarm AIMD orchestrator sizes the plugin RPC worker pool to runtime.NumCPU().
  • Boundary resolution pool: Ghost Linker uses a separate pool of NumCPU workers with an 8192-capacity channel for cross-provider edge discovery.

This design eliminates global lock contention. It allows ingestion of tens of thousands of nodes per second from concurrent plugin streams.


Querying the Graph

DEVI AI

Natural Language

> Which EC2 instances in us-east-1 have been idle for over 90 days?
> Show all resources with risk_score > 80
> What would break if I deleted the NAT gateway?

Via REST API

# List all nodes (paginated)
GET http://localhost:8080/api/v1/graph/nodes?limit=100&provider=aws

# Get a specific node by CRN
GET http://localhost:8080/api/v1/graph/nodes/crn:devi:aws:us-east-1:ec2:instance:123:i-0abc123

# Get a node's edges (neighbors)
GET http://localhost:8080/api/v1/graph/nodes/crn:devi:aws:us-east-1:ec2:instance:123:i-0abc123/edges

# Graph statistics
GET http://localhost:8080/api/v1/graph/stats

Example Stats Response

{
  "total_nodes": 10420,
  "active_nodes": 10398,
  "logically_deleted": 22,
  "total_edges": 34102,
  "waste_nodes": 847,
  "total_cost_usd_mo": 142300.0,
  "projected_savings_usd_mo": 14230.0,
  "providers": {
    "aws": 7840,
    "k8s": 1920,
    "gcp": 658
  }
}