License Tiers
Every license is classified into one of five tiers. This table is the heart of the tool — it is the artefact legal counsel is asked to ratify in milestone M-8.
The tier model
| Tier | Rank | Categories | Meaning |
|---|---|---|---|
| CRITICAL | 5 | strong-copyleft, network-copyleft | Distribution triggers source disclosure of the derivative work |
| HIGH | 4 | weak-copyleft, file-copyleft | Obligations attach to the library or to modified files |
| UNKNOWN | 3.5 | unknown, custom-ref, unrecognised, proprietary | Release blocker until triaged |
| MEDIUM | 3 | conditional, non-commercial, no-derivatives, share-alike, ambiguous | Requires review |
| LOW | 2 | permissive, public-domain | Notice and attribution only |
Ranks are deliberately non-contiguous and unique. UNKNOWN sits at 3.5 — a fractional rank between MEDIUM and HIGH — so that a rank lookup can never match two tiers. This was BUG-01: with HIGH and UNKNOWN both at rank 4, a lookup by rank returned HIGH for an UNKNOWN license.
Because AND takes the worst case, GPL-2.0 AND NOASSERTION still resolves to CRITICAL
(5 beats 3.5) — the copyleft is not masked by the unresolved term.
The obligation catalogue
Obligations are what compliance work actually produces. Each license rule maps to a set of them:
| Obligation | What it requires |
|---|---|
notice | Include the copyright notice and a copy of the license text in the distribution |
state-changes | State that the component was modified, and the date of modification |
source-full | Provide complete corresponding source of the derivative work under the same license |
source-modified | Provide source of any modifications made to the licensed component |
relinking | Provide object files, or a mechanism letting the recipient relink against a modified library |
network-source | Offer source to users who interact with the software over a network |
install-info | Provide installation information (keys, credentials) so modified firmware can be installed — GPL-3 anti-tivoization |
patent | Include the patent grant and patent-termination notice |
no-endorsement | Do not use contributor or organisation names for endorsement |
advertising | Include an acknowledgement in advertising materials |
non-commercial | Non-commercial use only — not approved for commercial distribution |
install-info is worth noting: GPL-3 adds anti-tivoization terms, which are directly relevant to
signed ECU firmware. Whether they bite depends on facts a tool cannot see, which is one reason
the output is triage.
Rule matching
Rules live in LICENSE_RULES and are matched longest-prefix, case-insensitively:
{ match: 'lgpl-2.', tier: 'HIGH', cat: 'weak-copyleft',
obl: ['notice', 'state-changes', 'source-modified', 'relinking'],
note: 'In automotive monolithic firmware, LGPL static linking is the most common compliance gap.' }
match: 'lgpl-2.' covers LGPL-2.0-only, LGPL-2.1-or-later and LGPL-2.1+ in one entry.
Because the whole knowledge base is declarative data, adding a license is a one-line change.
SPDX expression evaluation
The grammar is a small recursive-descent parser:
expr := term (OR term)*
term := factor (AND factor)*
factor := '(' expr ')' | id ('+' | WITH id)?
AND takes the worst case, OR the best
This is not a simplification — it reflects what the operators mean. A AND B means both licenses
apply simultaneously, so the strongest obligation governs. A OR B grants a choice, so the
licensee may elect the more favourable term.
Scoring OR as the worst case would systematically over-report dual-licensed components (Qt,
ffmpeg, NSS…), which is precisely the kind of false positive that gets a compliance tool ignored.
But the election must be recorded, because it determines the obligation actually owed — hence the
LIC-007 note.
Linking exceptions
GPL-2.0-or-later WITH u-boot-exception-2.0 is not the same risk as GPL-2.0-only. Ignoring
exceptions floods the report with false positives and destroys credibility with suppliers — the
fastest way to get a tool ignored.
| Exception | Relaxes | Note |
|---|---|---|
classpath-exception-2.0 | yes | Linking does not impose GPL on the application |
u-boot-exception-2.0 | yes | Static linking of GPL-2.0+ U-Boot into firmware is permitted |
gcc-exception-3.1, gcc-exception-2.0 | yes | GCC runtime library exception |
autoconf-exception-2.0, autoconf-exception-3.0 | yes | Autoconf configure-output exception |
bison-exception-2.2 | yes | Bison parser-skeleton exception |
font-exception-2.0 | yes | Documents using the font are not covered |
llvm-exception | yes | Relinking against modified LLVM is preserved |
qt-gpl-exception-1.0 | yes | Qt GPL exception |
swift-exception, libtool-exception | yes | — |
linux-syscall-note | no | User-space programs calling the kernel are not derivative works — but the tier is unchanged |
Note the last row: an exception with no relaxation effect must not downgrade. That is TC-04, and getting it wrong in the other direction would silently under-report.
The relaxation ladder deliberately excludes UNKNOWN. When a GPL license carries a linking
exception, the tier steps down within the copyleft strength scale (CRITICAL → HIGH). If
UNKNOWN were on the ladder, CRITICAL would relax onto UNKNOWN and produce a nonsense verdict
that looks like missing data. This was BUG-02.
Compatibility conflicts
Known incompatibilities are a coarse table matched on license family prefixes, because the well-known conflicts are family-level properties. Each rule carries a rationale that is surfaced verbatim in the finding, so a reviewer sees why two licenses conflict.
| Pair | Severity | Rationale |
|---|---|---|
gpl-2.0 + apache-2.0 | HIGH | Apache-2.0 patent/indemnity terms are additional restrictions under GPL-2.0 |
gpl-2.0 + gpl-3.0 | HIGH | GPL-2.0-only and GPL-3.0 are mutually incompatible |
gpl-2.0 + lgpl-3.0 | HIGH | LGPL-3.0 requires GPL-3.0, which is incompatible with GPL-2.0-only |
gpl-2.0 + epl- | HIGH | EPL and GPL are mutually incompatible |
gpl-2.0 + cddl- | HIGH | CDDL and GPL are mutually incompatible |
gpl-2.0 + mpl- | MEDIUM | MPL-2.0 offers GPL-2.0 as a secondary license, but combination still needs review |
agpl- + gpl-2.0 | HIGH | AGPL-3.0 and GPL-2.0-only are mutually incompatible |
agpl- + apache-2.0 | MEDIUM | Generally compatible, but the combined work becomes AGPL |
epl- + cddl- | MEDIUM | Both file-level copyleft, but not cross-compatible |
cc-by-nc- + apache-2.0 / mit | HIGH | Non-commercial terms cannot be combined with commercial licenses |
cc-by-sa- + apache-2.0 | MEDIUM | Share-alike propagates to the combined work |
:::caution Granularity is the known weakness Conflicts are computed over the transitive subtree of a root, so two components in separate executables that happen to share a root would be reported as conflicting even though they never combine. Resolving this needs a process/executable boundary map from the supplier (P2-06). Until then the behaviour is conservative and documented. :::