Callgraph Schema Reference

Audience: Signals Guild, analyzer authors, integrators producing or consuming call graphs.

Scope: The stella.callgraph.v1 document schema — fields, enumerations, determinism rules, and migration from legacy formats.

Stella Ops represents every analyzed program as a call graph: nodes for symbols, edges for calls, and entrypoints for the surfaces that invoke them. The stella.callgraph.v1 schema below is the canonical, deterministic format that reachability analysis and risk scoring consume.

Schema Version

Current Version: stella.callgraph.v1

All call graphs should include the schema field set to stella.callgraph.v1. Legacy call graphs without this field are automatically migrated on ingestion.

Document Structure

A CallgraphDocument contains the following top-level fields:

FieldTypeRequiredDescription
schemastringYesSchema identifier: stella.callgraph.v1
scanKeystringNoScan context identifier
languageCallgraphLanguageNoPrimary language of the call graph
artifactsCallgraphArtifact[]NoArtifacts included in the graph
nodesCallgraphNode[]YesGraph nodes representing symbols
edgesCallgraphEdge[]YesCall edges between nodes
entrypointsCallgraphEntrypoint[]NoDiscovered entrypoints
metadataCallgraphMetadataNoGraph-level metadata
idstringYesUnique graph identifier
componentstringNoComponent name
versionstringNoComponent version
ingestedAtDateTimeOffsetNoIngestion timestamp (ISO 8601)
graphHashstringNoContent hash for deduplication

Legacy Fields

These fields are preserved for backward compatibility:

FieldTypeDescription
languageStringstringLegacy language string
rootsCallgraphRoot[]Legacy root/entrypoint representation
schemaVersionstringLegacy schema version field

Enumerations

CallgraphLanguage

Supported languages for call graph analysis:

ValueDescription
UnknownLanguage not determined
DotNet.NET (C#, F#, VB.NET)
JavaJava and JVM languages
NodeNode.js / JavaScript / TypeScript
PythonPython
GoGo
RustRust
RubyRuby
PhpPHP
BinaryNative binary (ELF, PE)
SwiftSwift
KotlinKotlin

SymbolVisibility

Access visibility levels for symbols:

ValueDescription
UnknownVisibility not determined
PublicPublicly accessible
InternalInternal to assembly/module
ProtectedProtected (subclass accessible)
PrivatePrivate to containing type

EdgeKind

Edge classification based on analysis confidence:

ValueDescriptionConfidence
StaticStatically determined callHigh
HeuristicHeuristically inferredMedium
RuntimeRuntime-observed edgeHighest

EdgeReason

Reason codes explaining why an edge exists (critical for explainability):

ValueDescriptionTypical Kind
DirectCallDirect method/function callStatic
VirtualCallVirtual/interface dispatchStatic
ReflectionStringReflection-based invocationHeuristic
DiBindingDependency injection bindingHeuristic
DynamicImportDynamic import/requireHeuristic
NewObjConstructor/object instantiationStatic
DelegateCreateDelegate/function pointer creationStatic
AsyncContinuationAsync/await continuationStatic
EventHandlerEvent handler subscriptionHeuristic
GenericInstantiationGeneric type instantiationStatic
NativeInteropNative interop (P/Invoke, JNI, FFI)Static
RuntimeMintedRuntime-minted edge from executionRuntime
UnknownReason could not be determined-

EntrypointKind

Types of entrypoints:

ValueDescription
UnknownType not determined
HttpHTTP endpoint
GrpcgRPC endpoint
CliCLI command handler
JobBackground job
EventEvent handler
MessageQueueMessage queue consumer
TimerTimer/scheduled task
TestTest method
MainMain entry point
ModuleInitModule initializer
StaticConstructorStatic constructor

EntrypointFramework

Frameworks that expose entrypoints:

ValueDescriptionLanguage
UnknownFramework not determined-
AspNetCoreASP.NET CoreDotNet
MinimalApiASP.NET Core Minimal APIsDotNet
SpringSpring FrameworkJava
SpringBootSpring BootJava
ExpressExpress.jsNode
FastifyFastifyNode
NestJsNestJSNode
FastApiFastAPIPython
FlaskFlaskPython
DjangoDjangoPython
RailsRuby on RailsRuby
GinGinGo
EchoEchoGo
ActixActix WebRust
RocketRocketRust
AzureFunctionsAzure FunctionsMulti
AwsLambdaAWS LambdaMulti
CloudFunctionsGoogle Cloud FunctionsMulti

EntrypointPhase

Execution phase for entrypoints:

ValueDescription
ModuleInitModule/assembly initialization
AppStartApplication startup (Main)
RuntimeRuntime request handling
ShutdownShutdown/cleanup handlers

Node Structure

A CallgraphNode represents a symbol (method, function, type) in the call graph:

{
  "id": "n001",
  "nodeId": "n001",
  "name": "GetWeatherForecast",
  "kind": "method",
  "namespace": "SampleApi.Controllers",
  "file": "WeatherForecastController.cs",
  "line": 15,
  "symbolKey": "SampleApi.Controllers.WeatherForecastController::GetWeatherForecast()",
  "artifactKey": "SampleApi.dll",
  "visibility": "Public",
  "isEntrypointCandidate": true,
  "attributes": {
    "returnType": "IEnumerable<WeatherForecast>",
    "httpMethod": "GET",
    "route": "/weatherforecast"
  },
  "flags": 3
}

Node Fields

FieldTypeRequiredDescription
idstringYesUnique identifier within the graph
nodeIdstringNoAlias for id (v1 schema convention)
namestringYesHuman-readable symbol name
kindstringYesSymbol kind (method, function, class)
namespacestringNoNamespace or module path
filestringNoSource file path
lineintNoSource line number
symbolKeystringNoCanonical symbol key (v1)
artifactKeystringNoReference to containing artifact
visibilitySymbolVisibilityNoAccess visibility
isEntrypointCandidateboolNoWhether node is an entrypoint candidate
purlstringNoPackage URL for external packages
symbolDigeststringNoContent-addressed symbol digest
attributesobjectNoAdditional attributes
flagsintNoBitmask for efficient filtering

Symbol Key Format

The symbolKey follows a canonical format:

{Namespace}.{Type}[`Arity][+Nested]::{Method}[`Arity]({ParamTypes})

Examples:

Edge Structure

A CallgraphEdge represents a call relationship between two symbols:

{
  "sourceId": "n001",
  "targetId": "n002",
  "from": "n001",
  "to": "n002",
  "type": "call",
  "kind": "Static",
  "reason": "DirectCall",
  "weight": 1.0,
  "offset": 42,
  "isResolved": true,
  "provenance": "static-analysis"
}

Edge Fields

FieldTypeRequiredDescription
sourceIdstringYesSource node ID (caller)
targetIdstringYesTarget node ID (callee)
fromstringNoAlias for sourceId (v1)
tostringNoAlias for targetId (v1)
typestringNoLegacy edge type
kindEdgeKindNoEdge classification
reasonEdgeReasonNoReason for edge existence
weightdoubleNoConfidence weight (0.0-1.0)
offsetintNoIL/bytecode offset
isResolvedboolNoWhether target was fully resolved
provenancestringNoProvenance information
candidatesstring[]NoVirtual dispatch candidates

Entrypoint Structure

A CallgraphEntrypoint represents a discovered entrypoint:

{
  "nodeId": "n001",
  "kind": "Http",
  "route": "/api/users/{id}",
  "httpMethod": "GET",
  "framework": "AspNetCore",
  "source": "attribute",
  "phase": "Runtime",
  "order": 0
}

Entrypoint Fields

FieldTypeRequiredDescription
nodeIdstringYesReference to the node
kindEntrypointKindYesType of entrypoint
routestringNoHTTP route pattern
httpMethodstringNoHTTP method (GET, POST, etc.)
frameworkEntrypointFrameworkNoFramework exposing the entrypoint
sourcestringNoDiscovery source
phaseEntrypointPhaseNoExecution phase
orderintNoDeterministic ordering

Determinism Requirements

For reproducible analysis, call graphs must be deterministic:

  1. Stable Ordering

    • Nodes must be sorted by id (ordinal string comparison)
    • Edges must be sorted by sourceId, then targetId
    • Entrypoints must be sorted by order
  2. Enum Serialization

    • All enums serialize as camelCase strings
    • Example: EdgeReason.DirectCall"directCall"
  3. Timestamps

    • All timestamps must be UTC ISO 8601 format
    • Example: 2025-01-15T10:00:00Z
  4. Content Hashing

    • The graphHash field should contain a stable content hash
    • Hash algorithm: SHA-256
    • Format: sha256:{hex-digest}

Schema Migration

Legacy call graphs without the schema field are automatically migrated:

  1. Schema Field: Set to stella.callgraph.v1
  2. Language Parsing: String language converted to CallgraphLanguage enum
  3. Visibility Inference: Inferred from symbol key patterns:
    • Contains .Internal.Internal
    • Contains ._ or <Private
    • Default → Public
  4. Edge Reason Inference: Based on legacy type field:
    • call, directDirectCall
    • virtual, callvirtVirtualCall
    • newobjNewObj
    • etc.
  5. Entrypoint Inference: Built from legacy roots and candidate nodes
  6. Symbol Key Generation: Built from namespace and name if missing

Validation Rules

Call graphs are validated against these rules:

  1. All node id values must be unique
  2. All edge sourceId and targetId must reference existing nodes
  3. All entrypoint nodeId must reference existing nodes
  4. Edge weight must be between 0.0 and 1.0
  5. Artifacts referenced by nodes must exist in the artifacts list

Golden Fixtures

Reference fixtures for testing are located at: tests/reachability/fixtures/callgraph-schema-v1/

FixtureDescription
dotnet-aspnetcore-minimal.jsonASP.NET Core application
java-spring-boot.jsonSpring Boot application
node-express-api.jsonExpress.js API
go-gin-api.jsonGo Gin API
legacy-no-schema.jsonLegacy format for migration testing
all-edge-reasons.jsonAll 13 edge reason codes
all-visibility-levels.jsonAll 5 visibility levels