There is no licence handling anywhere in src/ today. Two things make it worth adding.
The SBOM is incomplete without it. _component in src/icebergsca/report/cyclonedx.py:106 emits type, bom-ref, name, purl, version and custom properties — no licenses array. A lot of downstream SBOM tooling treats a licence-free BOM as near-worthless, and it is a field consumers specifically expect.
"Software composition analysis" sets the expectation. SCA conventionally covers vulnerabilities and licence compliance. Having renamed the category (#8), the absence is more conspicuous than it was.
The trap to avoid
Declared licence metadata is unreliable — PyPI classifiers disagreeing with the license field, dual licensing expressed a dozen ways, UNKNOWN in a meaningful fraction of packages, and metadata that does not match the LICENSE file actually shipped in the artefact.
So this must not become a compliance verdict. "All dependencies MIT ✅" derived from declared metadata is the licence-shaped version of the false clean everything else here is designed to prevent. The honest framing is what each package declares, and which packages declare nothing — with "undeclared" reported as prominently as any other unchecked state, not folded into a total. No pass/fail, no policy engine, at least not in the first cut.
None vs [] matters here as much as anywhere: "we could not fetch the metadata" and "the package declares no licence" are different facts and must not collapse.
Architectural cost, worth knowing before starting
registry/ is currently used only for range resolution (RegistryClient.versions, src/icebergsca/registry/client.py:103), so a lockfile-first scan can make zero registry calls today. Licences mean per-package metadata fetches on every scan, which brings:
- a new cache namespace with its own freshness rules
- a materially different network profile, including under
--offline and --no-resolve
- a new failure mode needing somewhere honest to go, rather than being silently dropped
- the endpoints diverging per ecosystem (PyPI JSON, npm packument, crates.io, RubyGems, NuGet catalog, Maven POM) — the POM case overlaps with work
MavenResolver already does
This is the most expensive item on the list, which is a fair reason to schedule it after #10 and #11.
Scope
There is no licence handling anywhere in
src/today. Two things make it worth adding.The SBOM is incomplete without it.
_componentinsrc/icebergsca/report/cyclonedx.py:106emitstype,bom-ref,name,purl,versionand custom properties — nolicensesarray. A lot of downstream SBOM tooling treats a licence-free BOM as near-worthless, and it is a field consumers specifically expect."Software composition analysis" sets the expectation. SCA conventionally covers vulnerabilities and licence compliance. Having renamed the category (#8), the absence is more conspicuous than it was.
The trap to avoid
Declared licence metadata is unreliable — PyPI classifiers disagreeing with the
licensefield, dual licensing expressed a dozen ways,UNKNOWNin a meaningful fraction of packages, and metadata that does not match the LICENSE file actually shipped in the artefact.So this must not become a compliance verdict. "All dependencies MIT ✅" derived from declared metadata is the licence-shaped version of the false clean everything else here is designed to prevent. The honest framing is what each package declares, and which packages declare nothing — with "undeclared" reported as prominently as any other unchecked state, not folded into a total. No pass/fail, no policy engine, at least not in the first cut.
Nonevs[]matters here as much as anywhere: "we could not fetch the metadata" and "the package declares no licence" are different facts and must not collapse.Architectural cost, worth knowing before starting
registry/is currently used only for range resolution (RegistryClient.versions,src/icebergsca/registry/client.py:103), so a lockfile-first scan can make zero registry calls today. Licences mean per-package metadata fetches on every scan, which brings:--offlineand--no-resolveMavenResolveralready doesThis is the most expensive item on the list, which is a fair reason to schedule it after #10 and #11.
Scope
licenseson CycloneDX components, using SPDXexpressionwhere the declaration parses andnamewhere it does notreferences/json-report.mdtable/csv, most likely a count of undeclared rather than a column