Skip to main content

sbom_tools/
lib.rs

1//! **A powerful library for working with Software Bills of Materials (SBOMs).**
2//!
3//! `sbom-tools` provides a comprehensive suite of tools for parsing, analyzing, diffing,
4//! and enriching software bills of materials. It is designed to be a foundational library for
5//! supply chain security, compliance, and dependency management workflows.
6//!
7//! The library supports common SBOM formats like **CycloneDX** and **SPDX** and normalizes them
8//! into a unified, easy-to-use data model. It powers both a command-line interface (CLI)
9//! for direct use and a Rust library for programmatic integration into your own applications.
10//!
11//! ## Key Features
12//!
13//! - **Multi-Format Parsing**: Ingests CycloneDX (JSON) and SPDX (JSON, Tag-Value) files,
14//!   with automatic format detection.
15//! - **Intelligent Diffing**: Performs semantic diffs between two SBOMs to identify changes
16//!   in components, dependencies, licenses, and vulnerabilities.
17//! - **Data Enrichment**: Augments SBOMs with external data, including:
18//!   - **Vulnerability Information**: Fetches vulnerability data from the OSV (Open Source Vulnerability) database.
19//!   - **End-of-Life (EOL) Status**: Checks components against the `endoflife.date` API to identify unsupported software.
20//!   - More enrichers for staleness, KEV, etc.
21//! - **Quality & Compliance Scoring**: Checks SBOMs for compliance against established standards
22//!   like NTIA Minimum Elements and the EU Cyber Resilience Act (CRA).
23//! - **Flexible Reporting**: Generates analysis reports in multiple formats, including JSON,
24//!   Markdown, SARIF, and a full-featured interactive Terminal UI (TUI).
25//!
26//! ## Core Concepts & Modules
27//!
28//! The library is organized into several key modules:
29//!
30//! - **[`model`]**: Defines the central data structure, [`NormalizedSbom`]. Regardless of the input
31//!   format (CycloneDX or SPDX), the library parses it into this unified model. This allows you to work with
32//!   a consistent and predictable API for all your SBOM analysis tasks.
33//! - **[`pipeline`]**: Contains the primary functions for processing SBOMs. You can use the functions
34//!   in this module to construct a pipeline to parse, enrich, and generate reports in a single,
35//!   streamlined operation.
36//! - **[`diff`]**: Home of the [`DiffEngine`], which performs a semantic comparison of two `NormalizedSbom` objects.
37//! - **[`enrichment`]**: Provides `Enricher` traits and implementations for augmenting SBOMs with external data.
38//!   Requires the `enrichment` feature flag.
39//! - **[`quality`]**: Contains the [`ComplianceChecker`] for validating SBOMs against standards and the
40//!   [`QualityScorer`] for grading overall quality.
41//! - **[`reports`]**: Includes generators for creating output reports in various formats.
42//!
43//! ## Getting Started: Parsing an SBOM
44//!
45//! The most common entry point is to parse an existing SBOM file using the [`pipeline`] module.
46//! The library will automatically detect the format and return a [`NormalizedSbom`].
47//!
48//! ```no_run
49//! use std::path::Path;
50//! use sbom_tools::parse_sbom;
51//!
52//! fn main() -> Result<(), Box<dyn std::error::Error>> {
53//!     let sbom = parse_sbom(Path::new("path/to/your/sbom.json"))?;
54//!
55//!     println!(
56//!         "Successfully parsed SBOM for '{}' with {} components.",
57//!         sbom.document.name.unwrap_or_else(|| "Unknown".to_string()),
58//!         sbom.components.len()
59//!     );
60//!
61//!     Ok(())
62//! }
63//! ```
64//!
65//! ## Examples
66//!
67//! Below are examples for other common use cases.
68//!
69//! ### Diffing Two SBOMs
70//!
71//! The [`DiffEngine`] identifies what has been added, removed, or modified between an "old"
72//! and a "new" SBOM.
73//!
74//! ```no_run
75//! use std::path::Path;
76//! use sbom_tools::{parse_sbom, DiffEngine};
77//!
78//! fn main() -> Result<(), Box<dyn std::error::Error>> {
79//!     let old_sbom = parse_sbom(Path::new("path/to/old-sbom.json"))?;
80//!     let new_sbom = parse_sbom(Path::new("path/to/new-sbom.json"))?;
81//!
82//!     let engine = DiffEngine::new();
83//!     let diff = engine.diff(&old_sbom, &new_sbom)?;
84//!
85//!     println!("Components Added: {}", diff.components.added.len());
86//!     println!("Components Removed: {}", diff.components.removed.len());
87//!
88//!     for added in &diff.components.added {
89//!         println!("  + {} {}", added.name,
90//!             added.new_version.as_deref().unwrap_or(""));
91//!     }
92//!
93//!     Ok(())
94//! }
95//! ```
96//!
97//! ### Enriching with Vulnerability and End-of-Life (EOL) Data
98//!
99//! You can configure the processing pipeline to run enrichment stages. The following example
100//! enables both OSV vulnerability scanning and EOL status checking.
101//!
102//! *Note: This requires the `enrichment` feature flag to be enabled.*
103//!
104//! ```ignore
105//! use sbom_tools::parse_sbom;
106//! use sbom_tools::model::EolStatus;
107//!
108//! fn main() -> Result<(), Box<dyn std::error::Error>> {
109//!     let mut sbom = parse_sbom("path/to/your/sbom.json")?;
110//!
111//!     // Enrich with OSV vulnerability data (requires `enrichment` feature)
112//!     #[cfg(feature = "enrichment")]
113//!     {
114//!         use sbom_tools::{OsvEnricher, OsvEnricherConfig, VulnerabilityEnricher};
115//!         let enricher = OsvEnricher::new(OsvEnricherConfig::default());
116//!         enricher.enrich(&mut sbom)?;
117//!     }
118//!
119//!     println!("--- Vulnerability and EOL Report ---");
120//!     for component in sbom.components.values() {
121//!         if !component.vulnerabilities.is_empty() {
122//!             println!("\n[!] Component '{}' has {} vulnerabilities:",
123//!                 component.name, component.vulnerabilities.len());
124//!             for vuln in &component.vulnerabilities {
125//!                 println!("    - {}: {}", vuln.id,
126//!                     vuln.summary.as_deref().unwrap_or("No summary"));
127//!             }
128//!         }
129//!
130//!         if let Some(eol_info) = &component.eol {
131//!             if eol_info.status == EolStatus::EndOfLife {
132//!                 println!("\n[!] Component '{}' has reached End-of-Life!",
133//!                     component.name);
134//!                 println!("    - Product: {}", eol_info.product);
135//!                 if let Some(eol_date) = eol_info.eol_date {
136//!                     println!("    - EOL Date: {}", eol_date);
137//!                 }
138//!             }
139//!         }
140//!     }
141//!
142//!     Ok(())
143//! }
144//! ```
145//!
146//! ### Checking for Compliance
147//!
148//! The [`ComplianceChecker`] validates an SBOM against a specific standard, such as the
149//! EU Cyber Resilience Act (CRA).
150//!
151//! ```no_run
152//! use std::path::Path;
153//! use sbom_tools::parse_sbom;
154//! use sbom_tools::quality::{ComplianceChecker, ComplianceLevel};
155//!
156//! fn main() -> Result<(), Box<dyn std::error::Error>> {
157//!     let sbom = parse_sbom(Path::new("path/to/your/sbom.json"))?;
158//!
159//!     // Check against the EU CRA Phase 2 requirements
160//!     let checker = ComplianceChecker::new(ComplianceLevel::CraPhase2);
161//!     let result = checker.check(&sbom);
162//!
163//!     if result.is_compliant {
164//!         println!("SBOM is compliant with {}.", result.level.name());
165//!     } else {
166//!         println!("SBOM is NOT compliant with {}. Found {} errors and {} warnings.",
167//!             result.level.name(),
168//!             result.error_count,
169//!             result.warning_count
170//!         );
171//!
172//!         for violation in result.violations {
173//!             println!("[{:?}] {}: {}",
174//!                 violation.severity, violation.category.name(), violation.message);
175//!         }
176//!     }
177//!
178//!     Ok(())
179//! }
180//! ```
181//!
182//! ## Feature Flags
183//!
184//! `sbom-tools` uses feature flags to manage optional functionality and dependencies.
185//! - `enrichment`: Enables all data enrichment modules, such as OSV and EOL lookups.
186//!   This adds network dependencies like `reqwest`.
187//!
188//! ## Command-Line Interface (CLI)
189//!
190//! This documentation is for the `sbom-tools` library crate. If you are looking for the
191//! command-line tool, please refer to the project's README or install it via `cargo install sbom-tools`.
192
193// Lint to discourage unwrap() in production code - prefer explicit error handling
194#![warn(clippy::unwrap_used)]
195// Pedantic lints: allow categories that are design choices for this codebase
196#![allow(
197    // Cast safety: usize↔f64/f32/u16/i32 casts are pervasive in TUI layout math
198    // and statistical calculations — all values are bounded in practice
199    clippy::cast_precision_loss,
200    clippy::cast_possible_truncation,
201    clippy::cast_sign_loss,
202    clippy::cast_possible_wrap,
203    // Doc completeness: # Errors / # Panics sections are aspirational for 78+15 fns
204    clippy::missing_errors_doc,
205    clippy::missing_panics_doc,
206    // TUI render functions are inherently long — splitting hurts readability
207    clippy::too_many_lines,
208    // State structs legitimately use many bools for toggle flags
209    clippy::struct_excessive_bools,
210    clippy::fn_params_excessive_bools,
211    // self is kept for API consistency / future use across trait-like impls
212    clippy::unused_self,
213    // Variable names like `min`/`mid` or `old`/`new` are clear in context
214    clippy::similar_names
215)]
216
217pub mod cli;
218pub mod config;
219pub mod diff;
220#[cfg(feature = "enrichment")]
221pub mod enrichment;
222pub mod error;
223pub mod matching;
224pub mod model;
225pub mod parsers;
226pub mod pipeline;
227pub mod quality;
228pub mod reports;
229pub mod tui;
230pub mod utils;
231pub mod watch;
232
233// Re-export main types for convenience
234pub use config::{AppConfig, AppConfigBuilder, ConfigPreset, EnrichmentConfig, TuiConfig};
235pub use config::{
236    BehaviorConfig, FilterConfig, GraphAwareDiffConfig, MatchingConfig, MatchingRulesPathConfig,
237    OutputConfig,
238};
239pub use config::{ConfigError, Validatable};
240pub use config::{
241    DiffConfig, MatrixConfig, MultiDiffConfig, QueryConfig, TimelineConfig, ViewConfig,
242};
243pub use diff::{DiffEngine, DiffResult, GraphDiffConfig};
244#[cfg(feature = "enrichment")]
245pub use enrichment::{
246    EnricherConfig, EnrichmentStats, NoOpEnricher, OsvEnricher, OsvEnricherConfig,
247    VulnerabilityEnricher,
248};
249pub use error::{ErrorContext, OptionContext, Result, SbomDiffError};
250pub use matching::{
251    ComponentMatcher, FuzzyMatchConfig, FuzzyMatcher, MatchResult, MatchTier, MatchingRulesConfig,
252    RuleEngine,
253};
254pub use model::{
255    CanonicalId, Component, ComponentSortKey, NormalizedSbom, NormalizedSbomIndex, SbomIndexBuilder,
256};
257pub use parsers::{SbomParser, parse_sbom, parse_sbom_str};
258pub use quality::{QualityGrade, QualityReport, QualityScorer, ScoringProfile};
259#[allow(deprecated)]
260pub use reports::{ReportFormat, ReportGenerator, StreamingReporter, WriterReporter};
261
262// TUI shared ViewModel exports for building custom TUI components
263pub use tui::{
264    CycleFilter, FilterState, ListNavigation, ListState, OverlayState, SearchState,
265    SearchStateCore, StatusMessage, ViewModelOverlayKind,
266};