Descargo de responsabilidad: soy un desarrollador, no un abogado; esta información se cree que es correcta, pero no es un consejo legal; si crees que algo es incorrecto, por favor, escribe un comentario y lo arreglaremos juntos🔧

Antes no me preocupaba por la licencia del paquete npm. Podía comprobar la licencia de la dependencia inmediata pero nunca comprobar las dependencias de terceros (transitorias).

🚓 Y entonces conocí a los chicos del departamento legal 🚓

Ahora creo que los desarrolladores deben tener un conocimiento básico de las licencias de software para tener un diálogo constructivo con los equipos legales de sus empresas. Este post recoge un conocimiento general sobre las licencias Open-Source y cómo se aplica a las dependencias de npm y al desarrollo Full-Stack JavaScript en general.

Descubramos cuándo deberías empezar a preocuparte por las licencias.

¿Cuándo se activan los requisitos de las licencias?

Si realiza la vinculación con bibliotecas de código abierto y luego distribuye el software resultante, entonces su software debe cumplir con los requisitos de las bibliotecas vinculadas.

Veamos más de cerca la vinculación y la distribución aplicada a las aplicaciones de JavaScript.

Enlace

Usar librerías de terceros normalmente significa enlazarlas:

  • Si agrupas (es decir, con webpack) tu código con paquetes de código abierto cuenta como enlace estático
  • Si usas paquetes de código abierto en tu aplicación Node.JS (es decir. a través de require) o lo conectas a una página web a través de una etiqueta script, se trata de una vinculación dinámica

Nota: cuando construyes un paquete o ejecutas una aplicación Node.JS realizas el mismo tipo de vinculación tanto con dependencias inmediatas (listadas en tu package.json) como transitivas (listadas en package.json de terceros). Las licencias de dependencias inmediatas y transitivas tienen el mismo efecto en tu software.

Esto no era intuitivo para mí antes 🤔

Distribución

El simple hecho de usar librerías de código abierto no desencadena necesariamente requisitos de licencia. Normalmente, los requisitos de licencia se activan cuando se distribuye software:

  • Transferir software entre empleados de la misma empresa no es una distribución
  • Cuando los usuarios interactúan con su aplicación Node.JS a través de la red, no es una distribución para la mayoría de las licencias de código abierto; pero es una distribución para las licencias de protección de la red como AGPL
  • Colocar archivos JavaScript en un servidor web público es una distribución

¿Qué licencia está bien

La mayoría de las licencias de código abierto generalmente caen en uno de estos tipos:

  • Dominio público y licencias permisivas como el MIT que permiten hacer cualquier cosa excepto demandar al autor
  • Licencias Copyleft o Protectoras como la GPL impiden enlazar (ver arriba) con software propietario; el caso límite son las licencias Protectoras de Red como la Affero GPLv3 que se activa por la interacción a través de la red;
  • En medio de las dos anteriores están las licencias de protección débil como la MPL que tiene menos restricciones para el enlace dinámico (hasta que la biblioteca esté en su propio archivo)

Veamos los escenarios comunes para un desarrollador de JavaScript:

Estás haciendo una aplicación web

Lo más probable es que agrupes todos tus archivos, incluyendo las librerías en un archivo JS y lo pongas en un servidor web. Usted está realizando la vinculación estática y la distribución. Está bien usar paquetes con licencias permisivas en un bundle.

Si necesitas usar un paquete con licencia débilmente protectora como MPL tienes opciones:

  1. Cargar la librería desde un archivo separado (i.e. a través de la etiqueta de script)
  2. Aplicar una licencia de código abierto compatible a su paquete (pero revise el comentario de abajo y hable con su equipo legal antes)

Si su paquete no tiene ✨propiedad intelectual valiosa✨ entonces el segundo debería estar bien. No creo que los competidores se beneficien de tu código ofuscado. Pero si el paquete contiene propiedad intelectual valiosa, entonces la aplicación de la licencia de código abierto está concediendo el uso libre de la misma.

Estás haciendo una aplicaciónNode.JS

En este caso, normalmente se conectan las bibliotecas a través de una llamada require(). Es una vinculación dinámica. Está bien usar licencias Permisivas e incluso Débiles Protectoras. Sólo asegúrese de que los paquetes permanezcan en sus propios archivos con sus respectivas licencias.

Si usted está proporcionando SaaS sólo y no está distribuyendo de ninguna otra manera, puede utilizar incluso paquetes con una licencia Protective. Para muchas licencias Protective, la interacción en red no es una distribución. La excepción son las licencias Network Protective como Affero GPLv3

Estás haciendo un paquete Open Source NPM

Normalmente, conectas las dependencias de terceros a través de un package.json. Hasta donde yo sé, listar la dependencia en package.json no puede considerarse como vinculación. La vinculación será realizada por un desarrollador de aplicaciones que utilizará su paquete en una etapa de construcción o ejecución.

Si no quiere confundir a los usuarios del paquete asegúrese de que todas las dependencias (tanto inmediatas como transitivas) tienen licencias compatibles con la licencia de su paquete.

Típicamente las licencias de las dependencias deben ser más permisivas o del mismo nivel de permisividad que la licencia de su paquete.

Por ejemplo, si su paquete tiene licencia Apache 2.0 puede usar dependencias con licencia MIT y BSD. Pero no debería usar dependencias con licencia MPL1.1 o LGPLv3, porque tienen un copyleft más fuerte.

Una flecha desde la caja A a la caja B significa que se puede combinar software con estas licencias; el resultado combinado tiene efectivamente la licencia de B, posiblemente con adiciones de A; imagen del trabajo de David A. Wheeler

Cuando necesite poner paquetes o fuentes de terceros en el paquete NPM, no olvide listar las licencias y derechos de autor de terceros. La mayoría de las licencias de código abierto requieren el reconocimiento del autor.

También es una buena práctica especificar una expresión SPDX válida en su licencia package.json. Creo que este campo debe ser obligatorio para la publicación en npm.org.

Cómo se resuelve

Muchos equipos comienzan a pensar en las licencias cuando el software está listo para ser enviado. He estado usando la utilidad ScanCode para esto. Realmente va a cada carpeta de tu proyecto e intenta detectar cada licencia o copyright.

Captura de pantalla de https://github.com/nexB/scancode-toolkit

Probablemente tengas que usar esta herramienta o una similar antes de distribuir tu app. Asegúrate de que compruebas lo suficiente y no demasiado:

  • Instala todas tus dependencias de producción antes de ejecutar la herramienta
  • Asegúrate de que las devDependencias no son comprobadas por la herramienta; normalmente no distribuyes con tus dependencias de desarrollo;

Nota: si estás, como yo, mirando las licencias de los paquetes después de haberlos integrado en tu aplicación, puedes encontrarte en una situación difícil.

Ejecutando ScanCode justo antes de la fecha límite; imagen de https://giphy.com

Cómo descubrirlo antes de que sea demasiado tarde

Me preguntaba, cuándo es el mejor momento para aprender sobre las licencias de dependencia de paquetes. Para mí, el flujo normal de descubrir paquetes es:

🔍 Google 👉 npm.org 👉 GitHub 👉 $ npm install

Desgraciadamente npm.org no se ocupa realmente de las dependencias transitivas. Hay herramientas web como http://npm.anvaka.com/; pero no se ajusta a mi flujo de descubrimiento de paquetes y sigo olvidando usarlo. Pensé que el mejor momento para conocer las dependencias de los paquetes es cuando escribes $ npm install <pkg>

Ese fue mi pensamiento cuando construí una herramienta CLI llamada npm-consider que analiza el paquete con todas las dependencias transitivas antes de instalarlo o incluso descargarlo.

https://github.com/delfrrr/npm-consider

Para ahorrarte un comando, envuelve $ npm install y tiene los mismos argumentos. Si usted está bien con las dependencias sólo elija Instalar y se ejecutará npm install como de costumbre. Si le preocupa escoja Details y vea todo el árbol de dependencias:

Mostrando detalles al instalar el componente de la popular biblioteca geoespacial Turf.js; nota que el paquete en sí tiene una licencia Permisiva, pero una de las dependencias transitivas tiene licencia AGPL; realmente no se puede usar para software propietario;

Creo que tal funcionalidad debe ser parte de npm CLI. Si estás de acuerdo, por favor ⭐️ proyecto en GitHub y empujaré la idea hacia adelante.

Fuentes

Enumero mis fuentes por si quieres volver a comprobar mis conclusiones:

  • Entendiendo el modelo de dependencias de npm
  • Licencias de código abierto: Lo que todo tecnólogo debe saber | Opensource.com
  • Varias licencias y comentarios sobre ellas
  • La diapositiva de la licencia de software libre / de código abierto (FLOSS)
  • Centro de licencias | ifrOSS
  • Comparación de licencias de software libre y de código abierto – Wikipedia
  • Biblioteca (informática) – Wikipedia

Si el artículo ha sido útil, por favor 👏 y quizás escriba uno más 😀