License compliance checking

Decision

We use license-checker to automatically verify that all dependencies in our projects use licenses that allow us to use them commercially. We enforce this check in our CI pipeline.

Problems

When adding dependencies to our projects, we need to ensure they have appropriate licenses that allow us to use them commercially. Currently, there is no automated way to verify this, which could lead to:

  • Accidentally using dependencies with restrictive licenses that could force us to open-source our code
  • Legal risks from using dependencies without proper license verification
  • Time wasted manually checking licenses for each dependency

Context

We already have guidelines for choosing dependencies in ADR 0011, which includes checking for MIT or other permissive licenses. However, this check is currently manual and could be missed.

Our codebase is primarily TypeScript/JavaScript based, using npm packages. We need a solution that works well with npm-based projects.

Options

The following tools were considered:

  1. license-checker - A Node.js tool that scans npm dependencies and reports their licenses
  2. feluda - A Python-based license compliance checker
  3. Licensed - GitHub's internal tool for caching and verifying dependency license metadata
  4. FOSSA - Commercial license compliance platform
  5. License Compliance Manager - Another npm-based license checker
  6. Custom solution built on top of npm's built-in npm license command
  7. No automated checking - Continue with manual license verification

Reasoning

Why automated checking?

Manual license checking is error-prone and time-consuming. As our codebase grows and we add more dependencies, the risk of missing a problematic license increases. Automated checking ensures consistent verification.

Why license-checker?

We chose license-checker for several reasons:

  • Native npm integration - Works seamlessly with our npm-based projects
  • Active maintenance - Regular updates and good community support
  • Configurable - Allows specifying which licenses are acceptable
  • CI-friendly - Easy to integrate into our existing CI pipeline
  • Outputs machine-readable formats - Can be used for reporting and automation

Here's why we decided against the other options:

Feluda

  • Python-based which would add unnecessary complexity to our primarily JavaScript toolchain
  • Fewer npm-specific features
  • Would require additional setup and maintenance of Python environment

Licensed (GitHub)

  • Ruby-based, would introduce another language dependency
  • More complex setup compared to license-checker
  • While it supports multiple package managers, we primarily need npm support
  • The caching feature, while nice, isn't critical for our use case

FOSSA

  • Enterprise-focused commercial solution
  • Pricing model likely exceeds our current needs
  • Full compliance platform with many features we don't currently need
  • Would introduce external service dependency
  • Better suited for larger organizations with complex compliance requirements

License Compliance Manager

  • Less actively maintained than license-checker
  • Smaller community (fewer GitHub stars and npm downloads)
  • Limited configuration options
  • No significant advantages over license-checker

Custom Solution

  • Would require significant development effort
  • Ongoing maintenance overhead
  • Risk of bugs in custom implementation
  • No clear advantage over existing solutions

No Automated Checking

  • Would leave us exposed to the risks outlined in the Problems section
  • Not scalable as we add more dependencies
  • Higher risk of human error

Consequences

How do we implement this change?

  1. Add license-checker to our check-for-new-dependencies workflow
  2. Create a configuration file specifying acceptable licenses (MIT, Apache-2.0, BSD, etc.)
  3. Add a CI step that runs license-checker with --failOn for unacceptable licenses

Example configuration:

{
  "acceptableLicenses": [
    "MIT",
    "Apache-2.0",
    "BSD-2-Clause",
    "BSD-3-Clause",
    "ISC"
  ],
  "excludePrivatePackages": true
}

Who will implement the change?

This is implemented in the same PR that adds this ADR.

How do we teach this change?

  • Inform everyone via a Slack message
  • Present the implementation in a Learning Friday session

What could go wrong?

  • False positives - Some packages might have multiple licenses or custom licenses that are actually acceptable
  • CI pipeline slowdown - License checking might add time to our build process
  • Missing licenses - Some packages might not properly specify their licenses

What do we do if something goes wrong?

  • For false positives: Add exceptions to the configuration for specific packages
  • For performance issues: Optimize the CI configuration or run license checks less frequently
  • For missing licenses: Contact package maintainers or consider alternative packages

What is still unclear?

  • How much additional effort will come from managing false positives?

Related ADRs