licenseguard-cli 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -9
- package/bin/licenseguard.js +1 -0
- package/lib/commands/init-fast.js +2 -10
- package/lib/commands/init.js +3 -11
- package/lib/commands/scan.js +121 -0
- package/lib/scanner/compat-checker.js +369 -50
- package/lib/scanner/index.js +67 -115
- package/lib/scanner/license-compatibility-matrix.json +338 -0
- package/lib/scanner/license-detector.js +847 -0
- package/lib/scanner/license-normalizer.js +357 -0
- package/lib/scanner/plugins/cpp.js +267 -0
- package/lib/scanner/plugins/go.js +421 -0
- package/lib/scanner/plugins/node.js +149 -0
- package/lib/scanner/plugins/python-license-scanner.py +173 -0
- package/lib/scanner/plugins/python.js +336 -0
- package/lib/scanner/plugins/rust.js +196 -0
- package/lib/utils/license-mapper.js +28 -0
- package/package.json +2 -2
package/lib/scanner/index.js
CHANGED
|
@@ -1,146 +1,72 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dependency License Scanner
|
|
3
|
-
*
|
|
2
|
+
* Dependency License Scanner - Orchestrator
|
|
3
|
+
* Auto-detects project type and delegates to appropriate plugin
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const fs = require('fs')
|
|
7
|
-
const path = require('path')
|
|
8
6
|
const chalk = require('chalk')
|
|
9
|
-
const { checkCompatibility } = require('./compat-checker')
|
|
10
|
-
const { showProgress } = require('./progress')
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
8
|
+
// Import explainCompatibility for --explain flag support
|
|
9
|
+
const { explainCompatibility } = require('./compat-checker')
|
|
10
|
+
|
|
11
|
+
// Import ecosystem plugins
|
|
12
|
+
const nodePlugin = require('./plugins/node')
|
|
13
|
+
const cppPlugin = require('./plugins/cpp')
|
|
14
|
+
const rustPlugin = require('./plugins/rust')
|
|
15
|
+
const pythonPlugin = require('./plugins/python')
|
|
16
|
+
const goPlugin = require('./plugins/go')
|
|
17
|
+
|
|
18
|
+
// Plugin registry with priority ordering
|
|
19
|
+
// Priority: node > cpp > rust > python > go
|
|
20
|
+
const plugins = {
|
|
21
|
+
node: nodePlugin,
|
|
22
|
+
cpp: cppPlugin,
|
|
23
|
+
rust: rustPlugin,
|
|
24
|
+
python: pythonPlugin,
|
|
25
|
+
go: goPlugin
|
|
28
26
|
}
|
|
29
27
|
|
|
28
|
+
// Plugin detection order (first match wins)
|
|
29
|
+
const pluginOrder = ['node', 'cpp', 'rust', 'python', 'go']
|
|
30
|
+
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
-
* @
|
|
33
|
-
* @returns {{name: string, version: string, license: string, path: string}} License info
|
|
32
|
+
* Auto-detect project type and get the appropriate plugin
|
|
33
|
+
* @returns {{name: string, plugin: Object}|null} Detected plugin or null
|
|
34
34
|
*/
|
|
35
|
-
function
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
name: depName,
|
|
41
|
-
version: 'unknown',
|
|
42
|
-
license: 'NOT_INSTALLED',
|
|
43
|
-
path: depPath
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
const content = fs.readFileSync(depPath, 'utf8')
|
|
49
|
-
const depPackageJson = JSON.parse(content)
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
name: depName,
|
|
53
|
-
version: depPackageJson.version || 'unknown',
|
|
54
|
-
license: depPackageJson.license || 'UNKNOWN',
|
|
55
|
-
path: depPath
|
|
56
|
-
}
|
|
57
|
-
} catch (error) {
|
|
58
|
-
return {
|
|
59
|
-
name: depName,
|
|
60
|
-
version: 'unknown',
|
|
61
|
-
license: 'PARSE_ERROR',
|
|
62
|
-
path: depPath
|
|
35
|
+
function detectPlugin() {
|
|
36
|
+
for (const name of pluginOrder) {
|
|
37
|
+
const plugin = plugins[name]
|
|
38
|
+
if (plugin && plugin.detect()) {
|
|
39
|
+
return { name, plugin }
|
|
63
40
|
}
|
|
64
41
|
}
|
|
42
|
+
return null
|
|
65
43
|
}
|
|
66
44
|
|
|
67
45
|
/**
|
|
68
46
|
* Scan all dependencies for license compatibility
|
|
47
|
+
* Auto-detects project type and delegates to appropriate plugin
|
|
69
48
|
* @param {string} projectLicense - The project's license
|
|
70
49
|
* @returns {Promise<Object>} Scan results
|
|
71
50
|
*/
|
|
72
51
|
async function scanDependencies(projectLicense) {
|
|
73
|
-
|
|
74
|
-
const { deps } = parsePackageJson()
|
|
75
|
-
|
|
76
|
-
const results = {
|
|
77
|
-
timestamp: new Date().toISOString(),
|
|
78
|
-
totalDependencies: deps.length,
|
|
79
|
-
compatible: 0,
|
|
80
|
-
incompatible: 0,
|
|
81
|
-
unknown: 0,
|
|
82
|
-
issues: []
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// 2. Scan each dependency
|
|
86
|
-
for (let i = 0; i < deps.length; i++) {
|
|
87
|
-
showProgress(i + 1, deps.length)
|
|
88
|
-
|
|
89
|
-
const depName = deps[i]
|
|
90
|
-
const depInfo = extractLicense(depName)
|
|
52
|
+
const detected = detectPlugin()
|
|
91
53
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
continue
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Handle parse errors as unknown
|
|
98
|
-
if (depInfo.license === 'PARSE_ERROR') {
|
|
99
|
-
results.unknown++
|
|
100
|
-
results.issues.push({
|
|
101
|
-
package: `${depName}@${depInfo.version}`,
|
|
102
|
-
license: 'UNKNOWN',
|
|
103
|
-
type: 'warning',
|
|
104
|
-
reason: 'Failed to parse package.json',
|
|
105
|
-
location: depInfo.path
|
|
106
|
-
})
|
|
107
|
-
continue
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// 3. Check compatibility
|
|
111
|
-
const compatResult = checkCompatibility(projectLicense, depInfo.license)
|
|
112
|
-
|
|
113
|
-
if (!compatResult.compatible) {
|
|
114
|
-
const isUnknown = depInfo.license === 'UNKNOWN'
|
|
115
|
-
|
|
116
|
-
if (isUnknown) {
|
|
117
|
-
results.unknown++
|
|
118
|
-
} else {
|
|
119
|
-
results.incompatible++
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
results.issues.push({
|
|
123
|
-
package: `${depName}@${depInfo.version}`,
|
|
124
|
-
license: depInfo.license,
|
|
125
|
-
type: isUnknown ? 'warning' : 'conflict',
|
|
126
|
-
reason: compatResult.reason,
|
|
127
|
-
location: depInfo.path
|
|
128
|
-
})
|
|
129
|
-
} else {
|
|
130
|
-
results.compatible++
|
|
131
|
-
}
|
|
54
|
+
if (!detected) {
|
|
55
|
+
throw new Error('No supported package manager detected')
|
|
132
56
|
}
|
|
133
57
|
|
|
134
|
-
return
|
|
58
|
+
return await detected.plugin.scanDependencies(projectLicense)
|
|
135
59
|
}
|
|
136
60
|
|
|
137
61
|
/**
|
|
138
62
|
* Display conflict report to console
|
|
139
63
|
* @param {Object} scanResult - Scan results
|
|
140
64
|
* @param {string} projectLicense - The project's license
|
|
65
|
+
* @param {Object} options - Display options
|
|
66
|
+
* @param {boolean} options.explain - Show authoritative source citations
|
|
141
67
|
* @returns {boolean} True if conflicts found (incompatible licenses), false otherwise
|
|
142
68
|
*/
|
|
143
|
-
function displayConflictReport(scanResult, projectLicense) {
|
|
69
|
+
function displayConflictReport(scanResult, projectLicense, options = {}) {
|
|
144
70
|
if (scanResult.incompatible === 0 && scanResult.unknown === 0) {
|
|
145
71
|
console.log(chalk.green(`\n✅ All ${scanResult.totalDependencies} dependencies compatible with ${projectLicense.toUpperCase()}!`))
|
|
146
72
|
return false // No conflicts
|
|
@@ -163,7 +89,27 @@ function displayConflictReport(scanResult, projectLicense) {
|
|
|
163
89
|
console.log(chalk.yellow(`⚠️ ${issue.package} (${issue.license})`))
|
|
164
90
|
}
|
|
165
91
|
console.log(chalk.gray(` ${issue.reason}`))
|
|
166
|
-
console.log(chalk.gray(` Location: ${issue.location}
|
|
92
|
+
console.log(chalk.gray(` Location: ${issue.location}`))
|
|
93
|
+
|
|
94
|
+
// Show authoritative source citations when --explain is used
|
|
95
|
+
if (options.explain && issue.license && issue.license !== 'UNKNOWN') {
|
|
96
|
+
const explanation = explainCompatibility(projectLicense, issue.license)
|
|
97
|
+
// Extract source citation from explanation (after "📚 Source:")
|
|
98
|
+
const sourceMatch = explanation.match(/📚 Source: (.+?)(?:\n|$)/)
|
|
99
|
+
const urlMatch = explanation.match(/🔗 URL: (.+?)(?:\n|$)/)
|
|
100
|
+
|
|
101
|
+
if (sourceMatch || urlMatch) {
|
|
102
|
+
console.log(chalk.blue(' ────────────────────────'))
|
|
103
|
+
if (sourceMatch) {
|
|
104
|
+
console.log(chalk.blue(` 📚 ${sourceMatch[1]}`))
|
|
105
|
+
}
|
|
106
|
+
if (urlMatch) {
|
|
107
|
+
console.log(chalk.blue(` 🔗 ${urlMatch[1]}`))
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.log() // Blank line between issues
|
|
167
113
|
}
|
|
168
114
|
|
|
169
115
|
// Only return true if there are actual conflicts (incompatible licenses)
|
|
@@ -171,9 +117,15 @@ function displayConflictReport(scanResult, projectLicense) {
|
|
|
171
117
|
return hasConflicts
|
|
172
118
|
}
|
|
173
119
|
|
|
120
|
+
// Re-export plugin functions for backward compatibility
|
|
121
|
+
// These are deprecated but kept for BC
|
|
122
|
+
const { parsePackageJson, extractLicense } = nodePlugin
|
|
123
|
+
|
|
174
124
|
module.exports = {
|
|
175
125
|
scanDependencies,
|
|
176
126
|
parsePackageJson,
|
|
177
127
|
extractLicense,
|
|
178
|
-
displayConflictReport
|
|
128
|
+
displayConflictReport,
|
|
129
|
+
// Additional exports for testing
|
|
130
|
+
detectPlugin
|
|
179
131
|
}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"last_updated": "2025-11-22",
|
|
4
|
+
"description": "Authoritative license compatibility matrix for top 20 open source licenses covering ~95% of packages",
|
|
5
|
+
"methodology": "Based on FSF GPL Compatibility List, Mozilla MPL FAQ, Apache Foundation guidance, and SPDX specifications",
|
|
6
|
+
|
|
7
|
+
"sources": {
|
|
8
|
+
"fsf_gpl_compat": {
|
|
9
|
+
"title": "FSF GPL Compatibility List",
|
|
10
|
+
"url": "https://www.gnu.org/licenses/license-compatibility.html"
|
|
11
|
+
},
|
|
12
|
+
"fsf_license_list": {
|
|
13
|
+
"title": "FSF License List",
|
|
14
|
+
"url": "https://www.gnu.org/licenses/license-list.html"
|
|
15
|
+
},
|
|
16
|
+
"mozilla_mpl_faq": {
|
|
17
|
+
"title": "Mozilla MPL 2.0 FAQ",
|
|
18
|
+
"url": "https://www.mozilla.org/en-US/MPL/2.0/FAQ/"
|
|
19
|
+
},
|
|
20
|
+
"mozilla_mpl_gpl": {
|
|
21
|
+
"title": "Mozilla MPL-GPL Combining Guide",
|
|
22
|
+
"url": "https://www.mozilla.org/en-US/MPL/2.0/combining-mpl-and-gpl/"
|
|
23
|
+
},
|
|
24
|
+
"apache_gpl_compat": {
|
|
25
|
+
"title": "Apache-GPL Compatibility",
|
|
26
|
+
"url": "https://www.apache.org/licenses/GPL-compatibility.html"
|
|
27
|
+
},
|
|
28
|
+
"spdx_spec": {
|
|
29
|
+
"title": "SPDX License Expressions",
|
|
30
|
+
"url": "https://spdx.github.io/spdx-spec/v2.3/SPDX-license-expressions/"
|
|
31
|
+
},
|
|
32
|
+
"lgpl_section_3": {
|
|
33
|
+
"title": "LGPL Section 3 (Upgrade Clause)",
|
|
34
|
+
"url": "https://www.gnu.org/licenses/lgpl-3.0.html#section3"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
"licenses": {
|
|
39
|
+
"MIT": {
|
|
40
|
+
"type": "permissive",
|
|
41
|
+
"description": "Highly permissive license with minimal restrictions",
|
|
42
|
+
"compatible_with": ["*permissive*"],
|
|
43
|
+
"incompatible_with": ["*copyleft*"],
|
|
44
|
+
"can_upgrade_from": [],
|
|
45
|
+
"sources": {
|
|
46
|
+
"citation": "FSF: MIT license is permissive and GPL-compatible",
|
|
47
|
+
"url": "https://www.gnu.org/licenses/license-list.html#Expat"
|
|
48
|
+
},
|
|
49
|
+
"reasoning": "Permissive licenses cannot incorporate copyleft-licensed code without violating copyleft requirements"
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
"Apache-2.0": {
|
|
53
|
+
"type": "permissive-with-patent-grant",
|
|
54
|
+
"description": "Permissive license with explicit patent grant",
|
|
55
|
+
"compatible_with": ["*permissive*", "GPL-3.0-only", "GPL-3.0-or-later"],
|
|
56
|
+
"incompatible_with": ["GPL-2.0-only", "GPL-2.0-or-later", "LGPL-2.1-only", "LGPL-2.1-or-later"],
|
|
57
|
+
"can_upgrade_from": [],
|
|
58
|
+
"sources": {
|
|
59
|
+
"citation": "Apache 2.0 patent clause incompatible with GPL-2.0, but compatible with GPL-3.0",
|
|
60
|
+
"url": "https://www.apache.org/licenses/GPL-compatibility.html"
|
|
61
|
+
},
|
|
62
|
+
"reasoning": "Apache 2.0's patent grant conflicts with GPLv2 section 6, but GPLv3 was designed to resolve this"
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
"BSD-3-Clause": {
|
|
66
|
+
"type": "permissive",
|
|
67
|
+
"description": "Permissive BSD license with 3 clauses",
|
|
68
|
+
"compatible_with": ["*permissive*"],
|
|
69
|
+
"incompatible_with": ["*copyleft*"],
|
|
70
|
+
"can_upgrade_from": [],
|
|
71
|
+
"sources": {
|
|
72
|
+
"citation": "FSF: 3-clause BSD is permissive and GPL-compatible",
|
|
73
|
+
"url": "https://www.gnu.org/licenses/license-list.html#ModifiedBSD"
|
|
74
|
+
},
|
|
75
|
+
"reasoning": "Permissive license, same reasoning as MIT"
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
"BSD-2-Clause": {
|
|
79
|
+
"type": "permissive",
|
|
80
|
+
"description": "Simplified BSD license with 2 clauses",
|
|
81
|
+
"compatible_with": ["*permissive*"],
|
|
82
|
+
"incompatible_with": ["*copyleft*"],
|
|
83
|
+
"can_upgrade_from": [],
|
|
84
|
+
"sources": {
|
|
85
|
+
"citation": "FSF: 2-clause BSD is permissive and GPL-compatible",
|
|
86
|
+
"url": "https://www.gnu.org/licenses/license-list.html#FreeBSD"
|
|
87
|
+
},
|
|
88
|
+
"reasoning": "Even more permissive than BSD-3-Clause"
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
"ISC": {
|
|
92
|
+
"type": "permissive",
|
|
93
|
+
"description": "Functionally equivalent to MIT/BSD-2-Clause",
|
|
94
|
+
"compatible_with": ["*permissive*"],
|
|
95
|
+
"incompatible_with": ["*copyleft*"],
|
|
96
|
+
"can_upgrade_from": [],
|
|
97
|
+
"sources": {
|
|
98
|
+
"citation": "FSF: ISC license is permissive and GPL-compatible",
|
|
99
|
+
"url": "https://www.gnu.org/licenses/license-list.html#ISC"
|
|
100
|
+
},
|
|
101
|
+
"reasoning": "Permissive license, same reasoning as MIT"
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
"0BSD": {
|
|
105
|
+
"type": "public-domain",
|
|
106
|
+
"description": "BSD Zero Clause (public domain equivalent)",
|
|
107
|
+
"compatible_with": ["*"],
|
|
108
|
+
"incompatible_with": [],
|
|
109
|
+
"can_upgrade_from": [],
|
|
110
|
+
"sources": {
|
|
111
|
+
"citation": "FSF: 0BSD is ultra-permissive public domain equivalent",
|
|
112
|
+
"url": "https://www.gnu.org/licenses/license-list.html#0BSD"
|
|
113
|
+
},
|
|
114
|
+
"reasoning": "Public domain equivalent - compatible with everything"
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
"GPL-3.0-only": {
|
|
118
|
+
"type": "strong-copyleft",
|
|
119
|
+
"description": "GNU General Public License v3.0",
|
|
120
|
+
"compatible_with": ["*permissive*", "GPL-2.0-or-later", "GPL-3.0-only", "GPL-3.0-or-later", "LGPL-2.1-or-later", "LGPL-3.0-only", "LGPL-3.0-or-later", "MPL-2.0", "Apache-2.0"],
|
|
121
|
+
"incompatible_with": ["GPL-2.0-only", "AGPL-3.0-only", "AGPL-3.0-or-later"],
|
|
122
|
+
"can_upgrade_from": ["LGPL-2.1-or-later", "LGPL-3.0-only", "LGPL-3.0-or-later"],
|
|
123
|
+
"sources": {
|
|
124
|
+
"citation": "FSF: GPL-3.0 is compatible with LGPL (via Section 3 upgrade), Apache-2.0, MPL-2.0",
|
|
125
|
+
"url": "https://www.gnu.org/licenses/gpl-faq.html#AllCompatibility"
|
|
126
|
+
},
|
|
127
|
+
"reasoning": "Strong copyleft - requires all combined code to be GPL-3.0. LGPL can upgrade to GPL (Section 3). MPL 2.0 Section 3.3 allows GPL combination. Apache-2.0 patent clause resolved in GPLv3."
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
"GPL-3.0-or-later": {
|
|
131
|
+
"type": "strong-copyleft",
|
|
132
|
+
"description": "GNU General Public License v3.0 or any later version",
|
|
133
|
+
"compatible_with": ["*permissive*", "GPL-2.0-or-later", "GPL-3.0-only", "GPL-3.0-or-later", "LGPL-2.1-or-later", "LGPL-3.0-only", "LGPL-3.0-or-later", "MPL-2.0", "Apache-2.0"],
|
|
134
|
+
"incompatible_with": ["GPL-2.0-only"],
|
|
135
|
+
"can_upgrade_from": ["LGPL-2.1-or-later", "LGPL-3.0-only", "LGPL-3.0-or-later"],
|
|
136
|
+
"sources": {
|
|
137
|
+
"citation": "FSF: GPL-3.0-or-later provides upgrade path flexibility",
|
|
138
|
+
"url": "https://www.gnu.org/licenses/gpl-faq.html#VersionThreeOrLater"
|
|
139
|
+
},
|
|
140
|
+
"reasoning": "Same as GPL-3.0-only but with upgrade flexibility"
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
"GPL-2.0-only": {
|
|
144
|
+
"type": "strong-copyleft",
|
|
145
|
+
"description": "GNU General Public License v2.0",
|
|
146
|
+
"compatible_with": ["*permissive*", "GPL-2.0-only", "GPL-2.0-or-later", "LGPL-2.1-only", "LGPL-2.1-or-later"],
|
|
147
|
+
"incompatible_with": ["GPL-3.0-only", "GPL-3.0-or-later", "Apache-2.0", "MPL-2.0"],
|
|
148
|
+
"can_upgrade_from": ["LGPL-2.1-only", "LGPL-2.1-or-later"],
|
|
149
|
+
"sources": {
|
|
150
|
+
"citation": "FSF: GPL-2.0 incompatible with Apache-2.0 (patent clause), MPL-2.0, and GPL-3.0",
|
|
151
|
+
"url": "https://www.gnu.org/licenses/gpl-faq.html#v2v3Compatibility"
|
|
152
|
+
},
|
|
153
|
+
"reasoning": "Strong copyleft. Incompatible with Apache-2.0 (patent clause conflict), MPL-2.0 (file-level copyleft incompatibility), and GPL-3.0 (different copyleft terms)"
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
"GPL-2.0-or-later": {
|
|
157
|
+
"type": "strong-copyleft",
|
|
158
|
+
"description": "GNU General Public License v2.0 or any later version",
|
|
159
|
+
"compatible_with": ["*permissive*", "GPL-2.0-only", "GPL-2.0-or-later", "GPL-3.0-only", "GPL-3.0-or-later", "LGPL-2.1-only", "LGPL-2.1-or-later", "LGPL-3.0-only", "LGPL-3.0-or-later", "MPL-2.0", "Apache-2.0"],
|
|
160
|
+
"incompatible_with": [],
|
|
161
|
+
"can_upgrade_from": ["LGPL-2.1-or-later", "LGPL-3.0-or-later"],
|
|
162
|
+
"sources": {
|
|
163
|
+
"citation": "FSF: GPL-2.0-or-later can upgrade to GPL-3.0, resolving compatibility issues",
|
|
164
|
+
"url": "https://www.gnu.org/licenses/gpl-faq.html#v2v3Compatibility"
|
|
165
|
+
},
|
|
166
|
+
"reasoning": "Upgrade path to GPL-3.0 resolves Apache-2.0 and MPL-2.0 incompatibilities"
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
"LGPL-2.1-only": {
|
|
170
|
+
"type": "weak-copyleft",
|
|
171
|
+
"description": "GNU Lesser General Public License v2.1",
|
|
172
|
+
"compatible_with": ["*permissive*", "GPL-2.0-only", "GPL-2.0-or-later", "GPL-3.0-only", "GPL-3.0-or-later", "LGPL-2.1-only", "LGPL-2.1-or-later"],
|
|
173
|
+
"incompatible_with": ["Apache-2.0"],
|
|
174
|
+
"can_upgrade_from": [],
|
|
175
|
+
"sources": {
|
|
176
|
+
"citation": "LGPL Section 3: Can upgrade to corresponding GPL version",
|
|
177
|
+
"url": "https://www.gnu.org/licenses/lgpl-3.0.html#section3"
|
|
178
|
+
},
|
|
179
|
+
"reasoning": "Weak copyleft - Section 3 allows upgrading to GPL. Incompatible with Apache-2.0 due to GPLv2 patent clause conflict."
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
"LGPL-2.1-or-later": {
|
|
183
|
+
"type": "weak-copyleft",
|
|
184
|
+
"description": "GNU Lesser General Public License v2.1 or any later version",
|
|
185
|
+
"compatible_with": ["*permissive*", "GPL-2.0-only", "GPL-2.0-or-later", "GPL-3.0-only", "GPL-3.0-or-later", "LGPL-2.1-only", "LGPL-2.1-or-later", "LGPL-3.0-only", "LGPL-3.0-or-later", "MPL-2.0", "Apache-2.0"],
|
|
186
|
+
"incompatible_with": [],
|
|
187
|
+
"can_upgrade_from": [],
|
|
188
|
+
"sources": {
|
|
189
|
+
"citation": "LGPL Section 3: Upgrade path to GPL resolves incompatibilities",
|
|
190
|
+
"url": "https://www.gnu.org/licenses/lgpl-3.0.html#section3"
|
|
191
|
+
},
|
|
192
|
+
"reasoning": "Can upgrade to LGPL-3.0 or GPL-3.0, resolving Apache-2.0 incompatibility"
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
"LGPL-3.0-only": {
|
|
196
|
+
"type": "weak-copyleft",
|
|
197
|
+
"description": "GNU Lesser General Public License v3.0",
|
|
198
|
+
"compatible_with": ["*permissive*", "GPL-3.0-only", "GPL-3.0-or-later", "LGPL-2.1-or-later", "LGPL-3.0-only", "LGPL-3.0-or-later", "MPL-2.0", "Apache-2.0"],
|
|
199
|
+
"incompatible_with": ["GPL-2.0-only", "GPL-2.0-or-later"],
|
|
200
|
+
"can_upgrade_from": [],
|
|
201
|
+
"sources": {
|
|
202
|
+
"citation": "LGPL-3.0 Section 3: Can upgrade to GPL-3.0",
|
|
203
|
+
"url": "https://www.gnu.org/licenses/lgpl-3.0.html#section3"
|
|
204
|
+
},
|
|
205
|
+
"reasoning": "Weak copyleft with GPL upgrade path. Compatible with Apache-2.0 and MPL-2.0 via GPL-3.0 upgrade."
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
"LGPL-3.0-or-later": {
|
|
209
|
+
"type": "weak-copyleft",
|
|
210
|
+
"description": "GNU Lesser General Public License v3.0 or any later version",
|
|
211
|
+
"compatible_with": ["*permissive*", "GPL-3.0-only", "GPL-3.0-or-later", "LGPL-2.1-or-later", "LGPL-3.0-only", "LGPL-3.0-or-later", "MPL-2.0", "Apache-2.0"],
|
|
212
|
+
"incompatible_with": ["GPL-2.0-only", "GPL-2.0-or-later"],
|
|
213
|
+
"can_upgrade_from": [],
|
|
214
|
+
"sources": {
|
|
215
|
+
"citation": "LGPL-3.0-or-later provides upgrade flexibility",
|
|
216
|
+
"url": "https://www.gnu.org/licenses/lgpl-3.0.html"
|
|
217
|
+
},
|
|
218
|
+
"reasoning": "Same as LGPL-3.0-only but with upgrade flexibility"
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
"MPL-2.0": {
|
|
222
|
+
"type": "weak-copyleft",
|
|
223
|
+
"description": "Mozilla Public License 2.0 (file-level copyleft)",
|
|
224
|
+
"compatible_with": ["*permissive*", "GPL-2.0-or-later", "GPL-3.0-only", "GPL-3.0-or-later", "LGPL-2.1-or-later", "LGPL-3.0-only", "LGPL-3.0-or-later", "MPL-2.0", "Apache-2.0"],
|
|
225
|
+
"incompatible_with": ["GPL-2.0-only", "LGPL-2.1-only"],
|
|
226
|
+
"can_upgrade_from": [],
|
|
227
|
+
"sources": {
|
|
228
|
+
"citation": "MPL 2.0 Section 3.3: Secondary licenses allow GPL combination",
|
|
229
|
+
"url": "https://www.mozilla.org/en-US/MPL/2.0/combining-mpl-and-gpl/"
|
|
230
|
+
},
|
|
231
|
+
"reasoning": "Section 3.3 allows MPL-2.0 code to be relicensed under GPL/LGPL when combined. Incompatible with GPL-2.0-only due to terms conflict."
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
"AGPL-3.0-only": {
|
|
235
|
+
"type": "network-copyleft",
|
|
236
|
+
"description": "GNU Affero General Public License v3.0 (network use = distribution)",
|
|
237
|
+
"compatible_with": ["*permissive*", "AGPL-3.0-only", "AGPL-3.0-or-later", "Apache-2.0"],
|
|
238
|
+
"incompatible_with": ["GPL-2.0-only", "GPL-2.0-or-later", "GPL-3.0-only", "GPL-3.0-or-later"],
|
|
239
|
+
"can_upgrade_from": [],
|
|
240
|
+
"sources": {
|
|
241
|
+
"citation": "FSF: AGPL-3.0 incompatible with GPL (stricter terms)",
|
|
242
|
+
"url": "https://www.gnu.org/licenses/gpl-faq.html#AllCompatibility"
|
|
243
|
+
},
|
|
244
|
+
"reasoning": "Network copyleft - stricter than GPL. Cannot combine AGPL with GPL due to additional restrictions."
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
"AGPL-3.0-or-later": {
|
|
248
|
+
"type": "network-copyleft",
|
|
249
|
+
"description": "GNU Affero General Public License v3.0 or any later version",
|
|
250
|
+
"compatible_with": ["*permissive*", "AGPL-3.0-only", "AGPL-3.0-or-later", "Apache-2.0"],
|
|
251
|
+
"incompatible_with": ["GPL-2.0-only", "GPL-2.0-or-later", "GPL-3.0-only", "GPL-3.0-or-later"],
|
|
252
|
+
"can_upgrade_from": [],
|
|
253
|
+
"sources": {
|
|
254
|
+
"citation": "FSF: AGPL-3.0-or-later incompatible with GPL",
|
|
255
|
+
"url": "https://www.gnu.org/licenses/gpl-faq.html#AllCompatibility"
|
|
256
|
+
},
|
|
257
|
+
"reasoning": "Same as AGPL-3.0-only"
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
"Unlicense": {
|
|
261
|
+
"type": "public-domain",
|
|
262
|
+
"description": "Public domain dedication",
|
|
263
|
+
"compatible_with": ["*"],
|
|
264
|
+
"incompatible_with": [],
|
|
265
|
+
"can_upgrade_from": [],
|
|
266
|
+
"sources": {
|
|
267
|
+
"citation": "Public domain dedication - no restrictions",
|
|
268
|
+
"url": "https://unlicense.org/"
|
|
269
|
+
},
|
|
270
|
+
"reasoning": "No restrictions - compatible with everything"
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
"CC0-1.0": {
|
|
274
|
+
"type": "public-domain",
|
|
275
|
+
"description": "Creative Commons Zero (public domain)",
|
|
276
|
+
"compatible_with": ["*"],
|
|
277
|
+
"incompatible_with": [],
|
|
278
|
+
"can_upgrade_from": [],
|
|
279
|
+
"sources": {
|
|
280
|
+
"citation": "Public domain waiver - no restrictions",
|
|
281
|
+
"url": "https://creativecommons.org/publicdomain/zero/1.0/"
|
|
282
|
+
},
|
|
283
|
+
"reasoning": "Public domain waiver - compatible with everything"
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
"WTFPL": {
|
|
287
|
+
"type": "public-domain",
|
|
288
|
+
"description": "Do What The F*ck You Want To Public License",
|
|
289
|
+
"compatible_with": ["*"],
|
|
290
|
+
"incompatible_with": [],
|
|
291
|
+
"can_upgrade_from": [],
|
|
292
|
+
"sources": {
|
|
293
|
+
"citation": "Ultra-permissive - no restrictions",
|
|
294
|
+
"url": "http://www.wtfpl.net/"
|
|
295
|
+
},
|
|
296
|
+
"reasoning": "No restrictions - compatible with everything"
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
"wildcards": {
|
|
301
|
+
"*permissive*": [
|
|
302
|
+
"MIT",
|
|
303
|
+
"Apache-2.0",
|
|
304
|
+
"BSD-3-Clause",
|
|
305
|
+
"BSD-2-Clause",
|
|
306
|
+
"BSD-1-Clause",
|
|
307
|
+
"ISC",
|
|
308
|
+
"0BSD",
|
|
309
|
+
"Zlib",
|
|
310
|
+
"bzip2-1.0.6",
|
|
311
|
+
"BSL-1.0",
|
|
312
|
+
"PSF-2.0"
|
|
313
|
+
],
|
|
314
|
+
"*copyleft*": [
|
|
315
|
+
"GPL-2.0-only",
|
|
316
|
+
"GPL-2.0-or-later",
|
|
317
|
+
"GPL-3.0-only",
|
|
318
|
+
"GPL-3.0-or-later",
|
|
319
|
+
"LGPL-2.1-only",
|
|
320
|
+
"LGPL-2.1-or-later",
|
|
321
|
+
"LGPL-3.0-only",
|
|
322
|
+
"LGPL-3.0-or-later",
|
|
323
|
+
"MPL-2.0",
|
|
324
|
+
"MPL-1.1",
|
|
325
|
+
"AGPL-3.0-only",
|
|
326
|
+
"AGPL-3.0-or-later",
|
|
327
|
+
"EPL-2.0",
|
|
328
|
+
"EUPL-1.2",
|
|
329
|
+
"CDDL-1.0"
|
|
330
|
+
],
|
|
331
|
+
"*public-domain*": [
|
|
332
|
+
"Unlicense",
|
|
333
|
+
"CC0-1.0",
|
|
334
|
+
"WTFPL",
|
|
335
|
+
"0BSD"
|
|
336
|
+
]
|
|
337
|
+
}
|
|
338
|
+
}
|