This document lists the functions that the protobom CEL library registers in
the CEL environment. The authoritative definitions live in
pkg/library/api.go.
All functions use CEL member call syntax, that is, they are invoked on a receiver element:
sboms[0].get_packages().to_document()The receiver columns in the tables below show which element types each function can be invoked on.
Programs evaluated with the bundled runner have two predefined variables in scope:
| Variable | Type | Description |
|---|---|---|
sboms |
list of Document | The SBOMs loaded into the environment, in the order they were passed to runner.BuildVariables(). |
protobom |
Protobom | Global object hosting the functions not bound to a document element, such as load_sbom(). |
Both variable names can be customized when configuring the library with
library.WithDocsVarName() and library.WithProtobomVarName().
| Function | Arguments | Returns | Description | Document | NodeList | Node |
|---|---|---|---|---|---|---|
get_files() |
— | NodeList | Returns the nodes describing files | ✔️ | ✔️ | ✔️ |
get_packages() |
— | NodeList | Returns the nodes describing packages | ✔️ | ✔️ | ✔️ |
get_node_by_id(id) |
string | Node | Returns the node with the matching identifier | ✔️ | ✔️ | — |
get_nodes_by_name(name) |
string | list of Node | Returns all nodes whose name matches | — | ✔️ | — |
get_nodes_by_purl_type(type) |
string | NodeList | Returns all nodes whose package URL is of the given type | ✔️ | ✔️ | — |
get_nodes_by_identifier(type, value) |
string, string | list of Node | Returns the nodes carrying an identifier of the named type ("purl", "cpe23", ...) with the given value |
— | ✔️ | — |
get_matching_node(node) |
Node | Node | Returns the node describing the same software as the provided node, matching by hashes and package URL. Evaluates to null when nothing matches and errors when more than one node does |
— | ✔️ | — |
get_node_descendants(id, depth) |
string, int | NodeList | Returns the graph fragment starting at a node, down to the given depth | — | ✔️ | — |
get_node_ancestors(id, depth) |
string, int | NodeList | Returns the graph fragment with the elements pointing to a node, up to the given depth | — | ✔️ | — |
get_node_graph(id) |
string | NodeList | Returns the full graph of the node with the given identifier | — | ✔️ | — |
get_node_siblings(id) |
string | NodeList | Returns the fragment with the immediate siblings of the node with the given identifier | — | ✔️ | — |
get_edges_from(id) |
string | list of Edge | Returns the edges originating at the node with the given identifier | — | ✔️ | — |
get_edges_to(id) |
string | list of Edge | Returns the edges pointing to the node with the given identifier | — | ✔️ | — |
get_root_nodes() |
— | list of Node | Returns the root nodes of the graph | ✔️ | ✔️ | — |
| Function | Arguments | Returns | Description | Document | NodeList | Node | Metadata |
|---|---|---|---|---|---|---|---|
get_node_list() |
— | NodeList | Returns the document's node list | ✔️ | — | — | — |
get_metadata() |
— | Metadata | Returns the document's metadata | ✔️ | — | — | — |
get_nodes() |
— | list of Node | Returns the nodes of the node list | — | ✔️ | — | — |
get_edges() |
— | list of Edge | Returns the edges of the node list | — | ✔️ | — | — |
get_authors() |
— | list of Person | Returns the document authors | ✔️ | — | — | ✔️ |
get_suppliers() |
— | list of Person | Returns the persons acting as suppliers of a node | — | — | ✔️ | — |
get_originators() |
— | list of Person | Returns the persons acting as originators of a node | — | — | ✔️ | — |
get_purl() |
— | string | Returns the package URL of a node. Nodes without one, files among them, evaluate to an empty string | — | — | ✔️ | — |
In addition to these functions, the wrapped protobom elements expose their fields directly to CEL programs using the protobuf field names, for example:
sboms[0].metadata.name
sboms[0].node_list.get_root_nodes()[0].name| Function | Arguments | Returns | Description | Document | NodeList | Node |
|---|---|---|---|---|---|---|
to_node_list() |
— | NodeList | Wraps the element into a NodeList | ✔️ | ✔️ | ✔️ |
to_document() |
— | Document | Wraps the element into a new Document | ✔️ | ✔️ | |
add(nodelist) |
NodeList | NodeList | Returns the union of both node lists | — | ✔️ | — |
intersect(nodelist) |
NodeList | NodeList | Returns the nodes and relationships common to both node lists | — | ✔️ | — |
relate_node_list_at_id(nodelist, id, type) |
NodeList, string, string | same as receiver | Relates the nodes of a NodeList to the node with the given identifier through a relationship of the named type | ✔️ | ✔️ | — |
absorb(other) |
same as receiver | same as receiver | Completes the receiver with what the argument knows: fields it lacks are filled and collections (hashes, identifiers, licenses, references, properties; for documents also tools, authors and document types) are merged entry by entry. Nothing the receiver states is overridden. Node lists match nodes by id | ✔️ | ✔️ | ✔️ |
dedupe() |
— | same as receiver | Collapses the nodes describing the same component (see same_component) into one each. The first in list order survives and absorbs the rest; every relationship and root reference is rewired to it |
✔️ | ✔️ | — |
graft(id, nodelist, root_id, type) |
string, NodeList, string, string | same as receiver | Copies the graph reachable from root_id in the given NodeList, with fresh identifiers, and relates its root to the node id of the receiver through a relationship of the named type. Only outgoing relationships are followed |
✔️ | ✔️ | — |
graft_into(id, nodelist, root_id) |
string, NodeList, string | same as receiver | Like graft, but the node root_id is absorbed into the node id instead of being related to it: its graph hangs below id and the relationships that left or reached it now leave or reach id |
✔️ | ✔️ | — |
unrelate_nodes(from, to, type) |
string, string, string | NodeList | Removes the relationship of the named type between two nodes. Other destinations of the same relation are preserved | — | ✔️ | — |
remove_edges_from(id, type) |
string, string | NodeList | Removes all the relationships of the named type originating at a node | — | ✔️ | — |
Relationship types are named by their protobom identifiers, such as
"dependsOn" or "contains". The match ignores case and underscores, so
SPDX-style spellings like "DEPENDS_ON" name the same type; a name that
matches no type is an evaluation error. All of these functions keep CEL
value semantics: the element they are invoked on is never modified, the
result is a new element with the change applied.
to_document() is registered
but currently fails at evaluation time.
| Function | Arguments | Returns | Description | Document | NodeList | Node |
|---|---|---|---|---|---|---|
same_component(node) |
Node | bool | Whether both nodes describe the same component: the same kind of node, agreeing on every hash algorithm they share, or, when they share none, carrying the same purl. A disagreeing hash is final | — | — | ✔️ |
hashes_conflict(node) |
Node | bool | Whether the nodes state different values for a hash algorithm they both carry | — | — | ✔️ |
dedupe() collapses exactly the nodes same_component() would pair, with
one safeguard: a node never joins a group when its hashes conflict with
any member, so a node without hashes cannot bridge two whose hashes differ.
| Function | Arguments | Returns | Description | Document | NodeList | Node |
|---|---|---|---|---|---|---|
diff(other) |
same type as receiver | map | Compares two elements and returns a map describing the changes that transform the receiver into the argument | ✔️ | ✔️ | ✔️ |
diff(other, with_ids) |
same type, bool | map | Same, counting identifier changes as changes when the flag is true | ✔️ | ✔️ | ✔️ |
Following the protobom diff semantics, identifiers are used to pair the nodes of the two elements but their changes do not count as changes unless the flag is passed.
Every report carries a count entry totaling the changes, so two
equivalent elements produce {"count": 0} and expressions can gate on the
count without null checks:
sboms[0].diff(sboms[1]).count == 0A nodelist report also carries added, removed and modified (the
modified entries are maps with before, after, added, removed and
count), the edges_added and edges_removed deltas, and
root_elements_added and root_elements_removed. A document report nests
a metadata and a nodelist report, present only when they carry changes.
A node report carries added and removed nodes populated with the fields
that changed.
Functions that read from the host filesystem are not registered by default.
To enable them, configure the library with the EnableIO option:
library.NewProtobom(library.WithEnableIO(true))| Function | Arguments | Returns | Description | Receiver |
|---|---|---|---|---|
load_sbom(path) |
string | Document | Parses an SBOM file (SPDX or CycloneDX) and returns it as a Document | protobom |