SPDX data
osslili ships the SPDX license list rather than fetching it at runtime, so scans are deterministic and work offline. This page covers refreshing that data — a maintainer task, not something users need to do.
What is bundled
All under osslili/data/:
| File | Contents |
|---|---|
spdx_licenses.json |
The SPDX license list: identifiers, names, deprecation status, OSI/FSF flags, and license text for a subset |
exact_hashes.json |
SHA-256 and MD5 hashes of normalized license texts, used by the tier 0 exact matcher |
license_hashes.json |
TLSH fuzzy hashes, used by the tier 2 matcher |
license_normalization.json |
Text normalization rules applied before comparison |
regex_patterns.json |
Patterns for the tier 3 reference matcher |
spdx_licenses.json records the upstream licenseListVersion, its release date, and
the date it was downloaded.
Not every entry carries its license text. Entries without text can still be matched by tag, keyword, or fuzzy hash, but cannot be confirmed by full-text comparison — which is why the TLSH tier declines to assert a candidate whose text it cannot check. Widening text coverage widens what that tier can confirm.
When to refresh
- SPDX has published a new license list version
- Before a significant release
- Roughly quarterly
scripts/build_hook.py reports the age of the bundled data and refreshes it if it is
more than 30 days old.
python scripts/build_hook.py
Refreshing
scripts/download_spdx_licenses.pytakes no arguments and rewritesosslili/data/spdx_licenses.jsonas soon as it is run — there is no dry run and no--help. Work on a branch and checkgit diffbefore committing.
1. Download the license list
python scripts/download_spdx_licenses.py
Fetches from the SPDX license-list-data
repository and rewrites spdx_licenses.json.
2. Regenerate the exact hash table
python scripts/compute_exact_hashes.py
Recomputes SHA-256 and MD5 hashes over the normalized texts into
exact_hashes.json. This must be run after any change to the license data or to the
normalization rules — stale hashes silently stop the tier 0 matcher from firing.
3. Verify
python -m pytest tests/ -q
tests/test_license_detection_accuracy.py checks a corpus of canonical license texts
against their expected identifiers, and is what catches a normalization or hash
regression.
Then scan a few real projects and compare against the previous output. A license count that moves in the hundreds, or canonical texts that stop resolving, means something went wrong in normalization rather than upstream.
4. Review the diff
git diff --stat osslili/data/
Expect new identifiers, updated deprecation flags, and hash churn proportional to the text changes. Wholesale hash changes with no corresponding text changes indicate a normalization change, which affects detection for every user.
Deprecated identifiers
SPDX deprecates identifiers rather than removing them — the bare GNU-family ids
(GPL-2.0, LGPL-2.1) were replaced by an explicit -only / -or-later
disjunction, because the bare form does not say whether later versions are permitted.
Deprecated entries stay in the bundled data so existing tags keep matching, and
osslili normalizes them at the emission boundary: GPL-2.0 is reported as
GPL-2.0-only, and the deprecated GPL-2.0+ form as GPL-2.0-or-later.
Normalization only applies when the computed replacement is itself a valid SPDX
identifier, so an unexpected input cannot produce an invented one.
Adding a license SPDX does not list
Do not hand-edit the bundled data — the next refresh overwrites it. Map the name to a
LicenseRef- identifier through custom_aliases instead:
custom_aliases:
"My Company Internal License": "LicenseRef-MyCompany-Internal"
LicenseRef- identifiers pass the SPDX validation that rejects invented names. See
Configuration.