Skip to content

feat(scanner): propagate copyleft-strength license classes to artifacts#420

Merged
haksungjang merged 1 commit into
mainfrom
feat/license-class-propagation
Jul 16, 2026
Merged

feat(scanner): propagate copyleft-strength license classes to artifacts#420
haksungjang merged 1 commit into
mainfrom
feat/license-class-propagation

Conversation

@haksungjang

Copy link
Copy Markdown
Member

Why

The copyleft-strength classification (network/strong/weak copyleft, permissive, uncategorized) existed only in the web UI. The artifacts that actually travel — the SBOM a supplier submits, the risk report a reviewer reads — carried less information than the screen showed.

What

  • license-flags.jq: mirrors the UI's tier logic; normalize stamps every component with one bomlens:licenseClass property. Precedence is identical to the UI (worst-of: network > strong > weak > uncategorized > permissive — an unknown license outranks confirmed-permissive, and no-license components are uncategorized, never assumed permissive). bomlens:licenseReview (AI behavioral-use / non-commercial) is unchanged and independent.
  • generate-risk-report.sh: the license section gains a per-class count table and, when network/strong copyleft is present, lists up to 10 driving components by name@version (md + html). The report recomputes with the shared jq instead of trusting the property, so ANALYZE inputs predating the property classify identically.
  • Drift guard: test-postprocess.sh extracts the license-id sets and tier patterns from both licenses.ts and the jq mirror and fails naming any divergence, so the two implementations stay in lock-step.
  • Determinism: property insertion follows the existing bomlens:* idiom; --byte-stable output verified byte-identical and idempotent across re-runs.
  • Snapshots regenerated deliberately; the only diff is the new property arrays.

Verification

  • tests/test-postprocess.sh 185/0 (incl. per-tier cases, dual-license worst-of, no-license fallback, drift guard, report cases)
  • tests/test-snapshot.sh 3/0, tests/test-merge.sh 17/0, tests/check-docs-drift.sh pass
  • ShellCheck clean on all touched scripts
  • Hand-run on a minimal SBOM: AGPL → network-copyleft, MIT → permissive, no license → uncategorized

Follow-ups (not in this PR)

  • server.py could expose the stored class per component so the UI reads instead of recomputing — optional; the drift guard keeps them aligned.

The copyleft-strength classification (network/strong/weak copyleft,
permissive, uncategorized) existed only in the web UI, so the SBOM a
supplier submits and the risk report a reviewer reads carried less
information than the screen showed.

Mirror the UI's tier logic in the shared license-flags.jq and stamp
every component with a bomlens:licenseClass property in normalize
(worst-of precedence identical to the UI, including unknown licenses
outranking confirmed-permissive; no-license components stay
uncategorized, never assumed permissive). The risk report gains a
per-class count table and lists the network/strong-copyleft components
driving the exposure (md + html). The report recomputes with the same
jq rather than trusting the property, so ANALYZE inputs that predate
the property classify identically.

A drift guard in test-postprocess.sh diffs the license-id sets and
tier patterns between licenses.ts and the jq mirror, so the two
implementations cannot silently diverge. Classification cases cover
each tier, dual-license worst-of, and the no-license fallback; the
normalize snapshots were deliberately regenerated (the only diff is
the new property). Output stays deterministic under --byte-stable.

Docs: reports-explained (en/ko) notes the property and the new report
section.
@haksungjang
haksungjang merged commit 3f146dd into main Jul 16, 2026
34 checks passed
@haksungjang
haksungjang deleted the feat/license-class-propagation branch July 16, 2026 09:29
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.

1 participant