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.
@@ -1,146 +1,75 @@
1
1
  /**
2
- * Dependency License Scanner
3
- * Scans node_modules for license conflicts
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
- * Parse package.json to get dependencies
14
- * @returns {{deps: string[], packageJson: Object}} Dependency list and package.json
15
- */
16
- function parsePackageJson() {
17
- try {
18
- const content = fs.readFileSync('package.json', 'utf8')
19
- const packageJson = JSON.parse(content)
20
-
21
- // Only scan production dependencies
22
- const deps = Object.keys(packageJson.dependencies || {})
23
-
24
- return { deps, packageJson }
25
- } catch (error) {
26
- throw new Error('Failed to read package.json: ' + error.message)
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
- * Extract license info from a dependency
32
- * @param {string} depName - Dependency name
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 extractLicense(depName) {
36
- const depPath = path.join('node_modules', depName, 'package.json')
37
-
38
- if (!fs.existsSync(depPath)) {
39
- return {
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
- // 1. Read project package.json
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
- // 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)
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 results
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} (${issue.license})`))
93
+ console.log(chalk.red(`❌ ${issue.package} (${coloredLicense})`))
162
94
  } else {
163
- console.log(chalk.yellow(`⚠️ ${issue.package} (${issue.license})`))
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}\n`))
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
+ }