You have hundreds of dependencies. Can you legally keep your app proprietary? Let's find out in 15 lines of Prolog.
Table of Contents
Disclaimer
This is a simplified model, for fun. Real license compatibility is complex and varies by jurisdiction. This is not legal advice. When in doubt, consult a lawyer.
The hidden problem
Your Node.js project probably has 500+ dependencies. Each has a license. Some of those licenses say "if you use me, you can't keep your software proprietary."
Most developers discover this too late.
Three licenses that matter
For 90% of cases, you only need to understand three licenses:
- MIT: Do whatever you want, just keep the copyright notice (and the full license text, I guess)
- Apache 2.0: Like MIT, but with patent protections
- GPL: If you distribute software using this, your code must be GPL too
That last one is the killer. GPL is "viral" – if you use GPL code and distribute your software, your entire project must also be GPL. This "infection" spreads through your dependency tree. One GPL library deep in your dependencies can block you from keeping your software proprietary.
The term "viral" captures how GPL's requirements propagate: just like a virus, it spreads from the infected library up through all the code that depends on it.
GPL's "virality" is complex. Even Linus Torvalds admits there are "gray areas" in what constitutes a derived work. Static vs dynamic linking matters. SaaS is different from distributed software. But for this simplified model, we'll treat it as universally contagious.
Why most tools fail
License checkers typically scan your direct dependencies. But what about the dependencies of your dependencies? A seemingly innocent MIT library might depend on a GPL library three levels deep.
You need a lawyer. Call Prolog.
The 15-line solution
% Define which licenses are viral (they "infect" the whole project)
viral(gpl).
% Define compatibility (who can include whom)
compatible(mit, mit).
compatible(apache, mit).
compatible(apache, apache).
compatible(gpl, _). % GPL can include anything
% Your app's dependency tree (declare as dynamic so we can modify)
:- dynamic uses/3.
uses(myapp, react, mit).
uses(myapp, tensorflow, apache).
uses(tensorflow, helper_lib, gpl). % Ouch!
% Find viral infections recursively
% A project is "infected" if it uses GPL directly or indirectly
infected(Project) :-
uses(Project, _, License), viral(License). % Direct GPL dependency
infected(Project) :-
uses(Project, Dep, _), infected(Dep). % Transitive GPL dependency
% The key question: Can we keep it proprietary?
% Only if we're NOT infected by a viral license
can_be_proprietary(Project) :- \+ infected(Project).
That's it. The entire license compatibility checker.
Well, sort of. This simplified model captures the basic idea, but real license compatibility has dozens of edge cases. GPL2 vs GPL3? LGPL's linking exceptions? Apache's patent clauses? Dual licensing? We're ignoring all that to show the core concept.
See it in action
?- can_be_proprietary(myapp).
false.
Why? Let's trace the infection:
?- infected(myapp).
true.
?- uses(myapp, What, _), infected(What).
What = tensorflow.
So tensorflow
is infected. Why?
?- uses(tensorflow, What, License), viral(License).
What = helper_lib,
License = gpl.
There it is. Your app → TensorFlow → helper_lib (GPL). You can't distribute your app as proprietary software.
(In reality: Maybe you can. Are you distributing the software or running it as a service? Are you linking statically or dynamically? Is there a GPL exception clause? These questions matter legally but not for our simple model.)
Fix it
What if we replace that GPL library?
?- retract(uses(tensorflow, helper_lib, gpl)),
assertz(uses(tensorflow, helper_lib, mit)),
can_be_proprietary(myapp).
true.
By swapping one dependency, we changed the entire legal status of our project.
Of course, in practice you'd need to ensure the replacement library actually does what you need, has compatible APIs, and doesn't introduce new issues. But the legal principle holds.
The clever part
Notice what we didn't write:
- No tree traversal algorithms
- No recursive dependency scanning code
- No complex boolean logic
We just stated facts and rules. Prolog figures out the implications.
You can ask questions we didn't explicitly program:
% What's infected in my project?
?- infected(What).
% What licenses am I using?
?- uses(_, _, License).
% What depends on GPL code?
?- uses(What, _, gpl).
Why this matters
In 2004, the XFree86 project added an advertising clause to their license. It made them incompatible with GPL. The entire project died as developers fled to X.org.
MongoDB created SSPL because companies were reselling their database as a service. Now many organizations ban SSPL dependencies entirely.
These aren't edge cases. License incompatibility kills projects.
Try it yourself
The code above is a simple license checker. You can run it here or expand it to handle your specific needs:
- Add more licenses (BSD, ISC, LGPL)
- Model dual-licensing
- Handle license exceptions
- Add company policies ("no AGPL in production")
Next time you npm install
, remember: you're not just adding code. You're adding legal constraints.
Important: This post demonstrates a concept, not a complete solution. Real license analysis should consider:
- How you're distributing your software (binary, source, SaaS)
- Linking methods (static, dynamic, network)
- Whether your code is a "derived work" (as Linus discusses here) can be a gray area
- License versions and exceptions
- Jurisdiction-specific interpretations
- Your specific use case
The reality is that license compatibility often comes down to interpretation and intent, not just mechanical rules. When it matters (and it often does), get real legal advice.
References
The viral nature of GPL is well-documented but often misunderstood. See the FSF's GPL FAQ for authoritative answers.