Skip to content

feat(diff): detect license changes between SBOMs - #33

Merged
dmchaledev merged 1 commit into
mainfrom
claude/magical-ptolemy-njm6r3
Aug 7, 2026
Merged

feat(diff): detect license changes between SBOMs#33
dmchaledev merged 1 commit into
mainfrom
claude/magical-ptolemy-njm6r3

Conversation

@dmchaledev

Copy link
Copy Markdown
Contributor

What & why

sbom-diff is positioned for supply-chain and compliance auditing (the README's audience is "supply-chain risk analysts who need to … produce auditable SBOM diff reports for compliance evidence"). But diff() ignored the license field entirely: a dependency silently switching from a permissive license (MIT) to a copyleft one (GPL-3.0) produced no signal at all — even though the parser already extracts a per-component license from both CycloneDX and SPDX inputs.

For a compliance tool, an in-place relicense is exactly the kind of event a diff should surface, so this adds license-change detection alongside the existing added / removed / upgraded / CVE tracking.

Changes

  • types: new LicenseChange type; ChangeReport.licenseChanges and summary.totalLicenseChanges (exported from the package entry point).
  • diff: flags components present in both SBOMs whose declared license differs.
    • Fires only when both sides declare a license, so newly-added or dropped license metadata isn't mistaken for a relicense (avoids noise).
    • Independent of version, so an in-place relicense is caught even without a version bump.
  • reporter: text and Markdown reports render a "License Changes" section and a summary row; JSON output gains the field automatically.
  • tests: detection, version-unchanged case, metadata-only (no-op) case, and identical-license (no-op) case. Suite goes 29 → 33 tests.
  • docs: README documents the new report field and mentions license-change detection.

Verification

npm run typecheck, npm run lint, and npm test all pass. Verified end-to-end by building and running the CLI on two CycloneDX fixtures where one component switches MIT → GPL-3.0:

⚖ License Changes:
  ~ chalk: MIT → GPL-3.0

The unchanged component in the same fixture produces no entry.

Backwards compatibility

Purely additive to the public API — existing report fields are unchanged. The one caveat is that ChangeReport now has a required licenseChanges field, so any code that hand-builds a ChangeReport literal (rather than getting one from diff()) will need to add it; all reports produced by this package include it.

🤖 Generated with Claude Code

https://claude.ai/code/session_012JxAhzwjGGfRAJrv1FCC6c


Generated by Claude Code

The tool is positioned for supply-chain and compliance auditing, yet diff()
ignored the license field entirely — a dependency silently switching from a
permissive license (MIT) to a copyleft one (GPL-3.0) produced no signal at all,
even though the reader already parses per-component licenses.

Add license-change detection:
- New LicenseChange type and ChangeReport.licenseChanges / summary.totalLicenseChanges
- diff() flags components present in both SBOMs whose declared license differs.
  Only fires when both sides declare a license, so newly-added or dropped
  license metadata is not mistaken for a relicense. Independent of version, so
  an in-place relicense is caught even without a version bump.
- Text and Markdown reports render a License Changes section; JSON gains the
  field automatically
- Tests for detection, the version-unchanged case, the metadata-only case, and
  the no-change case; README documents the new report field

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012JxAhzwjGGfRAJrv1FCC6c
@dmchaledev
dmchaledev merged commit 580831c into main Aug 7, 2026
1 check passed
@dmchaledev
dmchaledev deleted the claude/magical-ptolemy-njm6r3 branch August 7, 2026 13:58
dmchaledev added a commit that referenced this pull request Aug 7, 2026
The license-change feature (#33) added totalLicenseChanges to the
ChangeReport summary and licenseChanges to the report, but the
gateFailures test fixture in cli.test.ts was never updated, so
tsc --noEmit fails on main and every dependabot PR. Restore green
CI by completing the fixture.

Co-authored-by: Hermes Agent <agent@hermes.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants