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--> GitHubRepositoryK8sDeployment --deployed_from--> GitHubRepositoryPagerDutyService --monitors--> K8sDeploymentGitHubRepository --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.
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.
| Trigger | Description |
|---|---|
discovery.completed | After a molecule finishes discovery |
entity.created | When a new entity is added to the graph |
entity.updated | When an entity's attributes change |
entity.deleted | When an entity is removed |
relation.created | When a new relation is created |
relation.deleted | When a relation is removed |
manual | Only 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
| Mode | Description |
|---|---|
all | Every entity of the specified kind |
pattern | Entities matching a CEL expression |
specific | Explicitly 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:
| Type | Description |
|---|---|
MANAGES | Ownership or management relationship |
IMPLEMENTED_IN | Code implements a requirement |
DEPENDS_ON | Dependency relationship |
DEPLOYED_TO | Deployment target |
OWNED_BY | Ownership |
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 createdcreated_by: What created it (rule:{name},user:{id}, ormolecule:{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?
| Value | Behavior |
|---|---|
keep | Relations persist after rule deletion |
cascade | Relations 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
| Variable | Description |
|---|---|
source | The source entity |
target | The target entity (in target queries) |
entity | The 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
Link issues to PRs by key in title
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
Single relation: Direct link
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
- Use descriptive names: Rule names should explain what relationship they create
- Prefer pattern matching: Automated rules scale better than explicit mappings
- Use RuleSets for related rules: Group rules that belong together
- Set appropriate onDelete: Use
cascadefor explicit mappings,keepfor inferred relations - Test with dry-run: Use
sixdegree apply --dry-runto preview what relations would be created - Document complex CEL: Add comments in your YAML for complex expressions