Skip to content

Commit 082461b

Browse files
committed
Merge docs/polish into main (mdBook + examples + README refresh)
2 parents 30d2d4f + c1f51ce commit 082461b

40 files changed

Lines changed: 2925 additions & 20 deletions

.github/workflows/docs.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: docs
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'docs/**'
8+
- '.github/workflows/docs.yml'
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
pages: write
14+
id-token: write
15+
16+
# Allow only one concurrent deployment, skipping in-flight runs but always
17+
# letting the most recent push reach production. Manually-dispatched runs
18+
# fall outside the cancel-in-progress to support targeted re-deploys.
19+
concurrency:
20+
group: docs-pages
21+
cancel-in-progress: true
22+
23+
jobs:
24+
build:
25+
runs-on: ubuntu-latest
26+
steps:
27+
- uses: actions/checkout@v4
28+
29+
- name: Install Rust toolchain
30+
uses: dtolnay/rust-toolchain@stable
31+
32+
- uses: Swatinem/rust-cache@v2
33+
with:
34+
key: docs-mdbook
35+
shared-key: docs
36+
37+
- name: Install mdBook
38+
shell: bash
39+
run: |
40+
# Pin to a specific minor version for build reproducibility.
41+
# Bump deliberately (and review the rendered diff) when upstream
42+
# ships a meaningful new feature.
43+
cargo install --locked --version 0.5.2 mdbook
44+
45+
- name: Build the book
46+
shell: bash
47+
run: mdbook build docs
48+
49+
- name: Upload Pages artifact
50+
uses: actions/upload-pages-artifact@v3
51+
with:
52+
path: docs/book
53+
54+
deploy:
55+
needs: build
56+
runs-on: ubuntu-latest
57+
environment:
58+
name: github-pages
59+
url: ${{ steps.deployment.outputs.page_url }}
60+
steps:
61+
- name: Deploy to GitHub Pages
62+
id: deployment
63+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@
66
.DS_Store
77
.vscode/
88
.idea/
9+
10+
# mdBook output (regenerated by .github/workflows/docs.yml on push to main)
11+
/docs/book

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ rust-version = "1.85"
66
description = "SBOM diff with supply-chain risk signals (CVEs, typosquats, maintainer-age)."
77
license = "Apache-2.0"
88
repository = "https://github.com/Metbcy/bomdrift"
9-
homepage = "https://github.com/Metbcy/bomdrift"
9+
homepage = "https://metbcy.github.io/bomdrift/"
1010
readme = "README.md"
1111
keywords = ["sbom", "security", "supply-chain", "cyclonedx", "spdx"]
1212
categories = ["command-line-utilities", "development-tools"]

README.md

Lines changed: 87 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
> SBOM diff with supply-chain risk signals — flags **new CVEs**, **typosquats**, **multi-major version jumps**, and **young maintainers** on added or upgraded dependencies, surfaced as a GitHub PR comment.
44
55
[![CI](https://github.com/Metbcy/bomdrift/actions/workflows/ci.yml/badge.svg)](https://github.com/Metbcy/bomdrift/actions/workflows/ci.yml)
6+
[![Release](https://img.shields.io/github/v/release/Metbcy/bomdrift?sort=semver&display_name=tag)](https://github.com/Metbcy/bomdrift/releases/latest)
7+
[![Docs](https://img.shields.io/badge/docs-mdbook-blue)](https://metbcy.github.io/bomdrift/)
68
[![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](./LICENSE)
79

10+
**Quick links:** [Why?](#why) · [Install](#install) · [Usage](#usage) · [Example output](#example-output) · [Features](#features) · [Release signing](#release-signing) · [Docs site](https://metbcy.github.io/bomdrift/) · [Examples](./examples/)
11+
812
## Why?
913

1014
The most actionable supply-chain question on a pull request is:
@@ -46,23 +50,29 @@ jobs:
4650
with:
4751
before-sbom: before.json
4852
after-sbom: after.json
53+
fail-on: critical-cve # optional: exit 2 on HIGH/CRITICAL advisories
4954
```
5055
56+
The `@v1` mutable tag tracks the latest v0.x release; pin to a specific version (`@v0.3.0`) if you prefer reproducible builds. See the [Action reference](https://metbcy.github.io/bomdrift/github-action.html) for every input.
57+
5158
### As a binary (local / CI)
5259

53-
Download a signed release archive for your platform from the [Releases page](https://github.com/Metbcy/bomdrift/releases/latest) and verify it with cosign — see [Release signing](#release-signing) below.
60+
Download a signed release archive for your platform from the [Releases page](https://github.com/Metbcy/bomdrift/releases/latest) and verify it with cosign — see [Release signing](#release-signing) below. Pre-built binaries cover **Linux x86_64 + aarch64**, **macOS aarch64**, and **Windows x86_64**.
5461

5562
```bash
56-
# Linux x86_64 example
57-
curl -sSL -o bomdrift.tar.gz https://github.com/Metbcy/bomdrift/releases/latest/download/bomdrift-v0.1.0-x86_64-unknown-linux-gnu.tar.gz
63+
# Linux x86_64 example (replace VERSION/TARGET as needed)
64+
VERSION=v0.3.0
65+
TARGET=x86_64-unknown-linux-gnu
66+
curl -sSL -o bomdrift.tar.gz \
67+
"https://github.com/Metbcy/bomdrift/releases/download/${VERSION}/bomdrift-${VERSION}-${TARGET}.tar.gz"
5868
tar -xzf bomdrift.tar.gz
59-
./bomdrift-v0.1.0-x86_64-unknown-linux-gnu/bomdrift --version
69+
./bomdrift-${VERSION}-${TARGET}/bomdrift --version
6070
```
6171

6272
### From source
6373

6474
```bash
65-
cargo install --locked --git https://github.com/Metbcy/bomdrift --tag v0.1.0 bomdrift
75+
cargo install --locked --git https://github.com/Metbcy/bomdrift --tag v0.3.0 bomdrift
6676
```
6777

6878
## Usage
@@ -74,40 +84,98 @@ bomdrift diff before.json after.json
7484
# Offline mode (no OSV / no GitHub-API maintainer-age lookups)
7585
bomdrift diff before.json after.json --no-osv --no-maintainer-age
7686
77-
# Machine-readable JSON for downstream tooling
87+
# Machine-readable formats for downstream tooling
7888
bomdrift diff before.json after.json --output json
89+
bomdrift diff before.json after.json --output sarif
90+
91+
# Exit 2 on findings (the action wraps this for PR-comment workflows)
92+
bomdrift diff before.json after.json --fail-on critical-cve
7993
80-
# Refresh the bundled npm popular-package list (used by the typosquat enricher)
81-
bomdrift refresh-typosquat --ecosystem npm
94+
# Suppress findings already present in a baseline snapshot
95+
bomdrift diff before.json after.json --baseline previous-diff.json
96+
97+
# Refresh the bundled popular-package lists (used by the typosquat enricher)
98+
bomdrift refresh-typosquat # all ecosystems
99+
bomdrift refresh-typosquat --ecosystem pypi # one specific list
82100
```
83101

84-
`bomdrift diff` exits 0 on success regardless of findings. It emits Markdown by default when stdout is piped/redirected (the PR-comment path), and ANSI-colored terminal output when stdout is a TTY. `--output markdown|json|terminal` overrides detection.
102+
`bomdrift diff` exits 0 on success regardless of findings unless `--fail-on` is set — then it exits 2 when the threshold trips. Stdout is Markdown by default when piped/redirected (the PR-comment path) and ANSI-colored when stdout is a TTY. `--output markdown|json|terminal|sarif` overrides detection.
103+
104+
See the [`examples/`](./examples/) directory for end-to-end scenarios (axios incident, multi-ecosystem typosquats, version jumps, baseline suppression).
105+
106+
## Example output
107+
108+
Running `bomdrift diff` against the bundled axios-incident fixture pair (`tests/fixtures/cdx-minimal.json` → `tests/fixtures/cdx-after.json`) produces:
109+
110+
```markdown
111+
## SBOM diff
112+
113+
| Change | Count |
114+
|---|---:|
115+
| Added | 1 |
116+
| Removed | 1 |
117+
| Version changed | 1 |
118+
| License changed | 0 |
119+
| Possible typosquats | 1 |
120+
121+
### Added
122+
| Ecosystem | Name | Version |
123+
|---|---|---|
124+
| npm | plain-crypto-js | 4.2.1 |
125+
126+
### Version changed
127+
| Ecosystem | Name | Before | After |
128+
|---|---|---|---|
129+
| npm | axios | 1.14.0 | 1.14.1 |
130+
131+
### Possible typosquats
132+
| Ecosystem | Name | Version | Similar to | Similarity |
133+
|---|---|---|---|---:|
134+
| npm | plain-crypto-js | 4.2.1 | crypto-js | 0.95 |
135+
```
136+
137+
With network access, the **Vulnerabilities** section additionally lists each advisory ID (CVE / GHSA / MAL) per affected component, alongside its OSV.dev-sourced severity.
85138

86139
## Features
87140

88141
- Diff **CycloneDX 1.5/1.6**, **SPDX 2.3**, and **Syft** JSON SBOMs against each other (any combination), via a unified component model.
89-
- For added & upgraded packages, enrich with **OSV.dev CVE data** through the `/v1/querybatch` endpoint.
90-
- Flag possible **typosquats** via Jaro-Winkler similarity to top-1000 npm packages, with a suffix-containment boost rule that catches the `plain-crypto-js``crypto-js` pattern that pure JW alone misses.
142+
- For added & upgraded packages, enrich with **OSV.dev CVE data** through `/v1/querybatch`, then a per-advisory `/v1/vulns/{id}` follow-up to populate **severity** (Critical / High / Medium / Low).
143+
- 24h on-disk **OSV severity cache** (`<XDG_CACHE_HOME>/bomdrift/osv/`) so reruns within a working day don't re-fetch — opt out with `--no-osv-cache`.
144+
- Flag possible **typosquats** across **npm**, **PyPI**, **Cargo**, and **Maven** via Jaro-Winkler similarity (Levenshtein for Maven artifactIds), with a suffix-containment boost rule that catches the `plain-crypto-js` → `crypto-js` pattern that pure JW alone misses. Refreshable from each ecosystem's canonical upstream via `bomdrift refresh-typosquat`.
91145
- Flag deps whose **top GitHub maintainer joined the project recently** (the xz-style takeover signal). Honors `GITHUB_TOKEN`, rate-limit-aware, skipped when the repo has > 50 contributors.
92146
- Flag **multi-major version jumps** (≥ 2 majors) in a single diff — often correlates with takeover swaps and namespace reuse.
93-
- Output formats: terminal (colored, TTY-aware), Markdown (PR comment), JSON. SARIF planned for v0.2.
94-
- Ships as a single Rust binary **and** a composite GitHub Action — no Docker.
95-
- Releases are signed with [cosign keyless](https://docs.sigstore.dev/) — eat-your-own-supply-chain-dogfood.
147+
- **Output formats**: terminal (colored, TTY-aware), Markdown (PR comment), **JSON**, and **SARIF v2.1.0** for GitHub Code Scanning ingestion.
148+
- **`--fail-on`** thresholds (`cve` / `critical-cve` / `typosquat` / `any`) exit code 2 on trip while still emitting the comment body, so the PR comment posts even when the workflow step fails.
149+
- **`--baseline <path.json>`** suppresses findings already captured in a previously stored `bomdrift diff --output json` snapshot — adopt bomdrift on a project with pre-existing findings without drowning the first PR.
150+
- **`--summary-only`** + automatic comment-size fallback (default 60 KB) keeps big SBOM diffs under GitHub's 65,536-char comment-body cap.
151+
- Ships as a **single Rust binary** (~3.4 MB, stripped + LTO) **and** a composite GitHub Action — no Docker.
152+
- Releases are **cosign-signed** keyless via Sigstore + GitHub OIDC — eat-your-own-supply-chain-dogfood.
96153

97154
## Release signing
98155

99156
Every release archive is signed with cosign keyless via Sigstore (GitHub OIDC).
100157

101158
```bash
159+
# Replace VERSION + TARGET with your downloaded archive's pair
160+
VERSION=v0.3.0
161+
TARGET=x86_64-unknown-linux-gnu
162+
ARCHIVE=bomdrift-${VERSION}-${TARGET}.tar.gz
163+
102164
cosign verify-blob \
103-
--certificate-identity 'https://github.com/Metbcy/bomdrift/.github/workflows/release.yml@refs/tags/v0.1.0' \
165+
--certificate-identity "https://github.com/Metbcy/bomdrift/.github/workflows/release.yml@refs/tags/${VERSION}" \
104166
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
105-
--certificate bomdrift-v0.1.0-x86_64-unknown-linux-gnu.tar.gz.pem \
106-
--signature bomdrift-v0.1.0-x86_64-unknown-linux-gnu.tar.gz.sig \
107-
bomdrift-v0.1.0-x86_64-unknown-linux-gnu.tar.gz
167+
--certificate "${ARCHIVE}.pem" \
168+
--signature "${ARCHIVE}.sig" \
169+
"${ARCHIVE}"
108170
```
109171

110-
The Action verifies signatures automatically when cosign is available on the runner.
172+
The Action verifies signatures automatically by default. Set `verify-signatures: false` on trusted mirrors to skip the cosign install step (~15s saved per run).
173+
174+
## Documentation
175+
176+
- **[Docs site (mdBook)](https://metbcy.github.io/bomdrift/)** — full reference: CLI flags, every action input, output-format anatomy, per-enricher deep dives, architecture notes, roadmap.
177+
- **[`examples/`](./examples/)** — runnable scenarios with synthetic SBOM pairs.
178+
- **[CHANGELOG](./CHANGELOG.md)** — release notes per version, including breaking-change migration notes.
111179

112180
## Non-goals
113181

docs/book.toml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[book]
2+
title = "bomdrift"
3+
description = "SBOM diff with supply-chain risk signals"
4+
authors = ["Amir B."]
5+
language = "en"
6+
src = "src"
7+
8+
[output.html]
9+
default-theme = "rust"
10+
preferred-dark-theme = "navy"
11+
git-repository-url = "https://github.com/Metbcy/bomdrift"
12+
edit-url-template = "https://github.com/Metbcy/bomdrift/edit/main/docs/{path}"
13+
site-url = "/bomdrift/"
14+
15+
[output.html.fold]
16+
enable = true
17+
level = 1
18+
19+
[output.html.search]
20+
enable = true
21+
limit-results = 30
22+
teaser-word-count = 30
23+
use-boolean-and = true
24+
boost-title = 2
25+
boost-hierarchy = 1
26+
boost-paragraph = 1
27+
expand = true
28+
heading-split-level = 3

docs/src/SUMMARY.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Summary
2+
3+
[Introduction](./introduction.md)
4+
5+
# Getting started
6+
7+
- [Quickstart](./quickstart.md)
8+
- [GitHub Action](./github-action.md)
9+
- [CLI reference](./cli-reference.md)
10+
11+
# Output
12+
13+
- [Output formats](./output-formats.md)
14+
- [Baseline & suppression](./baseline.md)
15+
16+
# Enrichers
17+
18+
- [Overview](./enrichers/overview.md)
19+
- [OSV.dev CVE lookup](./enrichers/osv-cve.md)
20+
- [Typosquat detection](./enrichers/typosquat.md)
21+
- [Multi-major version jumps](./enrichers/version-jump.md)
22+
- [Maintainer age signal](./enrichers/maintainer-age.md)
23+
24+
# Operations
25+
26+
- [Release signing](./release-signing.md)
27+
- [Architecture](./architecture.md)
28+
29+
# Project
30+
31+
- [Roadmap](./roadmap.md)
32+
- [Contributing](./contributing.md)

0 commit comments

Comments
 (0)