Skip to main content

Rules & Relations

Rules define how entities in your graph relate to each other. They can automatically infer relationships based on patterns, or explicitly map specific entities together.

Intra-Molecule vs Inter-Molecule Relations

Relationships in SixDegree come from two sources:

Intra-Molecule Relations (Created by Molecules)

Molecules automatically create relationships between entities they discover within their own domain:

  • GitHub molecule: GitHubRepository --owned_by--> GitHubOrganization
  • Kubernetes molecule: K8sDeployment --in_namespace--> K8sNamespace
  • PagerDuty molecule: PagerDutyService --on_escalation_policy--> PagerDutyEscalationPolicy

These relationships are intrinsic to the source system and don't require configuration.

Inter-Molecule Relations (Created by Rules)

Relationships across different systems are established through rules:

  • SnykProject --scans--> GitHubRepository
  • K8sDeployment --deployed_from--> GitHubRepository
  • PagerDutyService --monitors--> K8sDeployment
  • GitHubRepository --owned_by--> OktaGroup

This separation keeps molecules loosely coupled—a Snyk molecule doesn't need to understand GitHub. Instead, you configure rules that match your organization's conventions.

tip

Molecules may suggest inter-molecule rules based on common patterns, but you control which cross-system relationships are created.

What is a Rule?

A rule is a declarative specification that creates relationships between entities. Rules can be:

  • Pattern-based: Automatically link entities when certain conditions match (e.g., "link Jira issues to PRs where the PR title contains the issue key")
  • Explicit: Directly map specific entities together (e.g., "this Jira project manages these 3 repos")

Rule Structure

Rules follow a Kubernetes-style YAML format:

apiVersion: sixdegree.ai/v1
kind: Rule
metadata:
name: jira-pr-linking
namespace: default
labels:
category: cross-tool
spec:
enabled: true
priority: 100
trigger:
on: discovery.completed
source:
kind: JiraIssue
match: all
target:
kind: GitHubPullRequest
match: pattern
query: 'target.spec.title.contains(source.labels["key"])'
relation:
type: IMPLEMENTED_IN
attributes:
inferred: "true"
onDelete: keep

Triggers

Triggers define when a rule is evaluated.

TriggerDescription
discovery.completedAfter a molecule finishes discovery
entity.createdWhen a new entity is added to the graph
entity.updatedWhen an entity's attributes change
entity.deletedWhen an entity is removed
relation.createdWhen a new relation is created
relation.deletedWhen a relation is removed
manualOnly runs when explicitly triggered

Example: Event-based trigger

trigger:
on: entity.created
match:
kind: GitHubPullRequest
labels:
status: open

Example: Manual trigger

trigger:
on: manual

Source Matching

The source section defines which entities the rule starts from.

Match Modes

ModeDescription
allEvery entity of the specified kind
patternEntities matching a CEL expression
specificExplicitly listed entities

Example: All entities of a kind

source:
kind: JiraIssue
match: all

Example: Pattern matching

source:
kind: JiraProject
match: pattern
query: 'source.labels["team"] == "platform"'

Example: Specific entities

source:
kind: JiraProject
match: specific
entities:
- name: PROJ
- name: INFRA

Target Matching

The target section defines which entities to link to.

Example: Pattern-based target

target:
kind: GitHubPullRequest
match: pattern
query: 'target.spec.title.contains(source.labels["key"])'

Example: Specific targets

target:
kind: GitHubRepository
match: specific
entities:
- name: org/repo-a
- name: org/repo-b
- name: org/repo-c

Relations

The relation section defines what relationship to create.

Relation Types

Common relation types include:

TypeDescription
MANAGESOwnership or management relationship
IMPLEMENTED_INCode implements a requirement
DEPENDS_ONDependency relationship
DEPLOYED_TODeployment target
OWNED_BYOwnership

You can define custom relation types based on your domain.

Relation Attributes

Relations can have attributes that provide context:

relation:
type: MANAGES
attributes:
since: "2024-01-15"
priority: high
notes: "Primary project for backend services"

Every relation automatically gets:

  • created_at: When the relation was created
  • created_by: What created it (rule:{name}, user:{id}, or molecule:{name})

Computed Attributes

Attributes can be computed from source or target entities using CEL:

relation:
type: IMPLEMENTED_IN
attributes:
issue_key: '{{ source.labels["key"] }}'
pr_number: '{{ target.spec.number }}'

Lifecycle

onDelete Behavior

When a rule is deleted, what happens to the relations it created?

ValueBehavior
keepRelations persist after rule deletion
cascadeRelations are deleted with the rule
onDelete: cascade

Idempotency

Rules are idempotent by default. Running a rule multiple times won't create duplicate relations.

RuleSets

A RuleSet groups related rules together. This is useful for:

  • Rules that come from a molecule
  • Rules that should be enabled/disabled together
  • Versioned collections of rules
apiVersion: sixdegree.ai/v1
kind: RuleSet
metadata:
name: jira-integration-rules
labels:
source: molecule/jira
version: "1.2.0"
rules:
- name: jira-pr-linking
spec:
trigger:
on: discovery.completed
source:
kind: JiraIssue
match: all
target:
kind: GitHubPullRequest
match: pattern
query: 'target.spec.title.contains(source.labels["key"])'
relation:
type: IMPLEMENTED_IN

- name: jira-component-repos
spec:
trigger:
on: discovery.completed
source:
kind: JiraComponent
match: all
target:
kind: GitHubRepository
match: pattern
query: 'target.metadata.name == source.spec.repository'
relation:
type: TRACKS

Molecule-provided Rules

Molecules can ship default RuleSets. These are installed when the molecule is configured and can be:

  • Enabled or disabled as a group
  • Upgraded when the molecule updates
  • Overridden by user-defined rules

CEL Expressions

Rules use CEL (Common Expression Language) for pattern matching and computed values.

Available Variables

VariableDescription
sourceThe source entity
targetThe target entity (in target queries)
entityThe triggering entity (in conditions)

Entity Fields

// Metadata
entity.metadata.name
entity.metadata.namespace
entity.metadata.createdAt

// Labels
entity.labels["key"]

// Spec (entity-specific fields)
entity.spec.title
entity.spec.url
entity.spec.status

String Functions

// Substring check
target.spec.title.contains("PROJ-123")

// Prefix/suffix
source.metadata.name.startsWith("feature/")
target.spec.branch.endsWith("-hotfix")

// Regex matching (RE2 syntax)
source.labels["key"].matches("^PROJ-[0-9]+$")
target.spec.title.matches(".*PROJ-\\d+.*")

Comparison

// Equality
source.labels["team"] == "platform"

// Numeric comparison
entity.spec.priority > 5

// Boolean logic
source.spec.status == "open" && target.spec.merged == false

Common Patterns

target.spec.title.contains(source.labels["key"])

Match repos by naming convention

target.metadata.name.startsWith(source.spec.prefix + "-")

Match by label

target.labels["team"] == source.labels["team"]

Examples

Pattern-based: Jira to GitHub PR

Link Jira issues to GitHub PRs when the PR title contains the issue key.

apiVersion: sixdegree.ai/v1
kind: Rule
metadata:
name: jira-pr-linking
spec:
enabled: true
trigger:
on: discovery.completed
source:
kind: JiraIssue
match: all
target:
kind: GitHubPullRequest
match: pattern
query: 'target.spec.title.contains(source.labels["key"])'
relation:
type: IMPLEMENTED_IN
attributes:
inferred: "true"
onDelete: keep

Explicit: Project manages repos

A Jira project manages specific repositories.

apiVersion: sixdegree.ai/v1
kind: Rule
metadata:
name: proj-manages-repos
spec:
trigger:
on: manual
source:
kind: JiraProject
match: specific
entities:
- name: PROJ
target:
kind: GitHubRepository
match: specific
entities:
- name: myorg/api-service
- name: myorg/web-frontend
- name: myorg/shared-lib
relation:
type: MANAGES
attributes:
notes: "Core platform repositories"
onDelete: cascade

A single repo is managed by a specific project.

apiVersion: sixdegree.ai/v1
kind: Rule
metadata:
name: api-managed-by-platform
spec:
trigger:
on: manual
source:
kind: GitHubRepository
match: specific
entities:
- name: myorg/api-service
target:
kind: JiraProject
match: specific
entities:
- name: PLATFORM
relation:
type: MANAGED_BY
onDelete: cascade

CLI Usage

# Apply rules from a file
sixdegree apply -f rules.yaml

# List all rules
sixdegree get rules

# Get a specific rule
sixdegree get rule jira-pr-linking

# Delete a rule
sixdegree delete rule jira-pr-linking

# Run a manual rule
sixdegree run rule proj-manages-repos

# List rulesets
sixdegree get rulesets

# Disable a ruleset
sixdegree disable ruleset jira-integration-rules

Best Practices

  1. Use descriptive names: Rule names should explain what relationship they create
  2. Prefer pattern matching: Automated rules scale better than explicit mappings
  3. Use RuleSets for related rules: Group rules that belong together
  4. Set appropriate onDelete: Use cascade for explicit mappings, keep for inferred relations
  5. Test with dry-run: Use sixdegree apply --dry-run to preview what relations would be created
  6. Document complex CEL: Add comments in your YAML for complex expressions