licenseguard-cli 2.0.0 → 2.1.1
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/CHANGELOG.md +210 -0
- package/README.md +111 -9
- package/bin/licenseguard.js +26 -0
- package/lib/commands/init-fast.js +2 -10
- package/lib/commands/init.js +3 -11
- package/lib/commands/scan.js +122 -0
- package/lib/scanner/color-mapper.js +87 -0
- package/lib/scanner/compat-checker.js +369 -50
- package/lib/scanner/index.js +75 -117
- 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 +420 -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/lib/utils/update-notifier.js +141 -0
- package/package.json +2 -2
package/lib/scanner/index.js
CHANGED
|
@@ -1,146 +1,75 @@
|
|
|
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 color mapper for license color-coding
|
|
12
|
+
const { colorizeWithEmoji } = require('./color-mapper')
|
|
13
|
+
|
|
14
|
+
// Import ecosystem plugins
|
|
15
|
+
const nodePlugin = require('./plugins/node')
|
|
16
|
+
const cppPlugin = require('./plugins/cpp')
|
|
17
|
+
const rustPlugin = require('./plugins/rust')
|
|
18
|
+
const pythonPlugin = require('./plugins/python')
|
|
19
|
+
const goPlugin = require('./plugins/go')
|
|
20
|
+
|
|
21
|
+
// Plugin registry with priority ordering
|
|
22
|
+
// Priority: node > cpp > rust > python > go
|
|
23
|
+
const plugins = {
|
|
24
|
+
node: nodePlugin,
|
|
25
|
+
cpp: cppPlugin,
|
|
26
|
+
rust: rustPlugin,
|
|
27
|
+
python: pythonPlugin,
|
|
28
|
+
go: goPlugin
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
// Plugin detection order (first match wins)
|
|
32
|
+
const pluginOrder = ['node', 'cpp', 'rust', 'python', 'go']
|
|
33
|
+
|
|
30
34
|
/**
|
|
31
|
-
*
|
|
32
|
-
* @
|
|
33
|
-
* @returns {{name: string, version: string, license: string, path: string}} License info
|
|
35
|
+
* Auto-detect project type and get the appropriate plugin
|
|
36
|
+
* @returns {{name: string, plugin: Object}|null} Detected plugin or null
|
|
34
37
|
*/
|
|
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
|
|
38
|
+
function detectPlugin() {
|
|
39
|
+
for (const name of pluginOrder) {
|
|
40
|
+
const plugin = plugins[name]
|
|
41
|
+
if (plugin && plugin.detect()) {
|
|
42
|
+
return { name, plugin }
|
|
63
43
|
}
|
|
64
44
|
}
|
|
45
|
+
return null
|
|
65
46
|
}
|
|
66
47
|
|
|
67
48
|
/**
|
|
68
49
|
* Scan all dependencies for license compatibility
|
|
50
|
+
* Auto-detects project type and delegates to appropriate plugin
|
|
69
51
|
* @param {string} projectLicense - The project's license
|
|
70
52
|
* @returns {Promise<Object>} Scan results
|
|
71
53
|
*/
|
|
72
54
|
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
|
-
}
|
|
55
|
+
const detected = detectPlugin()
|
|
84
56
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
showProgress(i + 1, deps.length)
|
|
88
|
-
|
|
89
|
-
const depName = deps[i]
|
|
90
|
-
const depInfo = extractLicense(depName)
|
|
91
|
-
|
|
92
|
-
// Skip if not installed
|
|
93
|
-
if (depInfo.license === 'NOT_INSTALLED') {
|
|
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
|
-
}
|
|
57
|
+
if (!detected) {
|
|
58
|
+
throw new Error('No supported package manager detected')
|
|
132
59
|
}
|
|
133
60
|
|
|
134
|
-
return
|
|
61
|
+
return await detected.plugin.scanDependencies(projectLicense)
|
|
135
62
|
}
|
|
136
63
|
|
|
137
64
|
/**
|
|
138
65
|
* Display conflict report to console
|
|
139
66
|
* @param {Object} scanResult - Scan results
|
|
140
67
|
* @param {string} projectLicense - The project's license
|
|
68
|
+
* @param {Object} options - Display options
|
|
69
|
+
* @param {boolean} options.explain - Show authoritative source citations
|
|
141
70
|
* @returns {boolean} True if conflicts found (incompatible licenses), false otherwise
|
|
142
71
|
*/
|
|
143
|
-
function displayConflictReport(scanResult, projectLicense) {
|
|
72
|
+
function displayConflictReport(scanResult, projectLicense, options = {}) {
|
|
144
73
|
if (scanResult.incompatible === 0 && scanResult.unknown === 0) {
|
|
145
74
|
console.log(chalk.green(`\n✅ All ${scanResult.totalDependencies} dependencies compatible with ${projectLicense.toUpperCase()}!`))
|
|
146
75
|
return false // No conflicts
|
|
@@ -157,13 +86,36 @@ function displayConflictReport(scanResult, projectLicense) {
|
|
|
157
86
|
}
|
|
158
87
|
|
|
159
88
|
for (const issue of scanResult.issues) {
|
|
89
|
+
// Color-code the license based on safety level
|
|
90
|
+
const coloredLicense = colorizeWithEmoji(issue.license, issue.license)
|
|
91
|
+
|
|
160
92
|
if (issue.type === 'conflict') {
|
|
161
|
-
console.log(chalk.red(`❌ ${issue.package} (${
|
|
93
|
+
console.log(chalk.red(`❌ ${issue.package} (${coloredLicense})`))
|
|
162
94
|
} else {
|
|
163
|
-
console.log(chalk.yellow(`⚠️ ${issue.package} (${
|
|
95
|
+
console.log(chalk.yellow(`⚠️ ${issue.package} (${coloredLicense})`))
|
|
164
96
|
}
|
|
165
97
|
console.log(chalk.gray(` ${issue.reason}`))
|
|
166
|
-
console.log(chalk.gray(` Location: ${issue.location}
|
|
98
|
+
console.log(chalk.gray(` Location: ${issue.location}`))
|
|
99
|
+
|
|
100
|
+
// Show authoritative source citations when --explain is used
|
|
101
|
+
if (options.explain && issue.license && issue.license !== 'UNKNOWN') {
|
|
102
|
+
const explanation = explainCompatibility(projectLicense, issue.license)
|
|
103
|
+
// Extract source citation from explanation (after "📚 Source:")
|
|
104
|
+
const sourceMatch = explanation.match(/📚 Source: (.+?)(?:\n|$)/)
|
|
105
|
+
const urlMatch = explanation.match(/🔗 URL: (.+?)(?:\n|$)/)
|
|
106
|
+
|
|
107
|
+
if (sourceMatch || urlMatch) {
|
|
108
|
+
console.log(chalk.blue(' ────────────────────────'))
|
|
109
|
+
if (sourceMatch) {
|
|
110
|
+
console.log(chalk.blue(` 📚 ${sourceMatch[1]}`))
|
|
111
|
+
}
|
|
112
|
+
if (urlMatch) {
|
|
113
|
+
console.log(chalk.blue(` 🔗 ${urlMatch[1]}`))
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log() // Blank line between issues
|
|
167
119
|
}
|
|
168
120
|
|
|
169
121
|
// Only return true if there are actual conflicts (incompatible licenses)
|
|
@@ -171,9 +123,15 @@ function displayConflictReport(scanResult, projectLicense) {
|
|
|
171
123
|
return hasConflicts
|
|
172
124
|
}
|
|
173
125
|
|
|
126
|
+
// Re-export plugin functions for backward compatibility
|
|
127
|
+
// These are deprecated but kept for BC
|
|
128
|
+
const { parsePackageJson, extractLicense } = nodePlugin
|
|
129
|
+
|
|
174
130
|
module.exports = {
|
|
175
131
|
scanDependencies,
|
|
176
132
|
parsePackageJson,
|
|
177
133
|
extractLicense,
|
|
178
|
-
displayConflictReport
|
|
134
|
+
displayConflictReport,
|
|
135
|
+
// Additional exports for testing
|
|
136
|
+
detectPlugin
|
|
179
137
|
}
|
|
@@ -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
|
+
}
|