Анализ лицензий зависимостей

Лицензионная чистота зависимостей в JavaScript-проектах становится критическим аспектом сборки, особенно в связке с Rollup, где итоговый бандл часто включает десятки и сотни сторонних пакетов. Любая зависимость транзитивного уровня может нести ограничения, влияющие на возможность коммерческого использования, распространения или модификации продукта. Поэтому анализ лицензий в процессе сборки перестает быть формальной проверкой и превращается в часть инфраструктуры контроля качества.

Основная сложность заключается в том, что Rollup сам по себе не выполняет анализ лицензий. Он работает исключительно с модулями и их трансформацией, не учитывая юридический контекст импортируемых пакетов. Это означает, что ответственность за проверку переносится на плагины, инструменты анализа зависимостей и этапы CI/CD.

Каждый пакет в npm может содержать поле license в package.json, а также отдельный файл LICENSE. Формат записи может варьироваться:

  • SPDX-идентификаторы: MIT, Apache-2.0, BSD-3-Clause
  • составные выражения: MIT OR Apache-2.0
  • нестандартные или отсутствующие значения
  • ссылки на внешние тексты лицензий

SPDX-формат является основой автоматического анализа, однако на практике значительная часть пакетов содержит некорректные или неполные данные, что требует дополнительной обработки.

Особое внимание уделяется транзитивным зависимостям. Даже если прямые зависимости проекта имеют допустимые лицензии, вложенные пакеты могут содержать более строгие ограничения, включая:

  • GPL-семейство с требованиями открытого распространения производных работ
  • лицензии с ограничением коммерческого использования
  • кастомные лицензии без стандартизированного текста

Роль Rollup в контексте лицензий

Rollup формирует граф модулей, начиная с entry point и рекурсивно разрешая зависимости через плагины. Этот граф может быть использован как основа для анализа, поскольку он отражает фактический состав итогового бандла.

Однако Rollup не хранит метаданные лицензий на уровне модулей. Для этого используется расширение функциональности через плагины, которые перехватывают процесс резолва и загрузки модулей.

На практике анализ лицензий интегрируется либо на этапе pre-bundle анализа, либо post-bundle проверки.

Подходы к анализу лицензий в сборке

Существует несколько архитектурных стратегий проверки лицензий:

1. Анализ package.json до сборки

В этом подходе используется обход дерева зависимостей через node_modules с построением полного dependency graph. Инструменты типа license-checker или license-report анализируют:

  • прямые зависимости проекта
  • транзитивные зависимости
  • лицензии каждого пакета
  • исключения и whitelist/blacklist

Этот подход независим от Rollup и выполняется до начала bundling-процесса.

Ключевое преимущество заключается в детерминированности результата до выполнения сборки.

2. Интеграция через Rollup плагины

Существуют плагины, которые позволяют встроить анализ лицензий непосредственно в pipeline:

  • сбор информации о загруженных модулях
  • сопоставление файлов с npm пакетами
  • извлечение лицензий из package.json
  • генерация отчета в процессе сборки

Подобные плагины работают на уровне resolveId и load хуков Rollup.

Типичный поток выглядит следующим образом:

  1. Rollup запрашивает модуль
  2. Плагин определяет пакет-владелец модуля
  3. Извлекается package.json
  4. Считывается поле license
  5. Данные агрегируются в отчёт

Такой подход позволяет формировать лицензированный отчет строго по фактическому бандлу, а не по установленным зависимостям.

3. Post-build анализ бандла

После генерации итогового файла Rollup можно использовать для анализа уже включённых модулей. Однако этот метод менее точен, так как:

  • теряется связь с оригинальными пакетами
  • возможна агрегация модулей
  • tree-shaking скрывает часть зависимостей

Тем не менее, он полезен для финального аудита артефактов.

Использование rollup-plugin-license

Одним из наиболее распространённых решений является rollup-plugin-license, который позволяет автоматически генерировать отчёты по лицензиям.

Он поддерживает:

  • сбор информации о зависимостях
  • генерацию NOTICE-файлов
  • включение лицензий в итоговый бандл
  • кастомные форматы вывода

Плагин работает на этапе генерации чанков и использует информацию о модулях Rollup для построения карты зависимостей.

Внутренний механизм основан на обходе module graph:

  • каждый модуль ассоциируется с пакетом
  • пакеты дедуплицируются
  • лицензии агрегируются
  • формируется единый отчет

Обработка конфликтов лицензий

На практике часто возникает ситуация, когда разные зависимости содержат несовместимые лицензии. Основные сценарии конфликтов:

  • MIT + Apache-2.0 (обычно совместимы)
  • MIT + GPL-3.0 (возможные ограничения на распространение)
  • Proprietary + open-source лицензии
  • отсутствие лицензии в одном из пакетов

Стратегия обработки таких конфликтов обычно включает:

  • whitelist допустимых лицензий
  • blacklist запрещённых лицензий
  • ручную проверку исключений
  • генерацию warnings в CI

В CI-среде анализ лицензий часто рассматривается как gate-stage, блокирующий релиз при нарушениях.

Извлечение лицензий из node_modules

При отсутствии корректного поля license используются дополнительные источники:

  • файл LICENSE
  • поле licenses (устаревший формат npm)
  • README-файлы
  • метаданные репозитория

Некоторые инструменты применяют эвристики для определения лицензии по тексту файла, однако такой подход снижает точность.

SPDX и нормализация лицензий

Для унификации используется нормализация к SPDX-идентификаторам. Это позволяет:

  • сравнивать лицензии в едином формате
  • строить правила совместимости
  • автоматизировать проверки

Пример нормализации:

  • MIT LicenseMIT
  • Apache License Version 2.0Apache-2.0
  • BSDBSD-2-Clause или BSD-3-Clause (при уточнении)

При невозможности нормализации лицензия помечается как UNKNOWN, что требует ручной обработки.

Интеграция в CI/CD pipeline

Типичная схема интеграции анализа лицензий в Rollup-проекте включает несколько этапов:

  1. установка зависимостей
  2. запуск license auditor
  3. проверка отчёта на соответствие политике
  4. блокировка сборки при нарушениях
  5. генерация artifact license-report.json

Rollup в этой цепочке выступает только как источник графа модулей, а не как инструмент анализа.

Дедупликация и проблема вложенных зависимостей

Особую сложность создаёт дублирование пакетов разных версий. Например:

  • package A зависит от lodash@4.17.20
  • package B зависит от lodash@4.17.15

Каждая версия может содержать одинаковую лицензию, но анализ должен учитывать каждую как отдельный субъект. При этом Rollup может объединить модули в один chunk, что усложняет трассировку.

Для решения используется:

  • построение полного дерева зависимостей
  • сопоставление по resolved path
  • анализ package-lock.json или pnpm-lock.yaml

Лицензии и tree-shaking

Tree-shaking влияет на состав финального бандла, но не всегда на состав зависимостей. Это приводит к ситуации, когда:

  • зависимость установлена
  • но её код не попал в бандл

Вопрос, учитывать ли такие лицензии, зависит от политики проекта:

  • строгий режим: учитываются все установленные зависимости
  • мягкий режим: учитываются только реально включённые модули

Rollup предоставляет информацию о используемых модулях, что позволяет реализовать второй подход с большей точностью.

Генерация NOTICE-файлов

Во многих проектах требуется формирование файла NOTICE, содержащего:

  • список зависимостей
  • их лицензии
  • копии лицензий
  • ссылки на исходные репозитории

Rollup-плагины позволяют автоматизировать генерацию этого файла на этапе сборки, используя накопленные данные о модулях.

Структура обычно включает:

  • имя пакета
  • версия
  • лицензия
  • текст лицензии или ссылка
  • список авторов (при наличии метаданных)

Ограничения автоматического анализа

Несмотря на развитую экосистему инструментов, автоматический анализ лицензий имеет ограничения:

  • неполные или некорректные метаданные пакетов
  • кастомные лицензии без SPDX
  • динамически загружаемые зависимости
  • плагины Rollup, не отражающие зависимости в node_modules

Поэтому финальная проверка часто дополняется ручным аудитом или юридической экспертизой для критичных проектов.

Связь с безопасностью поставок (supply chain)

Анализ лицензий тесно связан с безопасностью цепочки поставок. Один и тот же механизм обхода зависимостей может использоваться для:

  • поиска уязвимостей
  • анализа лицензий
  • контроля версий

В Rollup-проектах это часто объединяется в единый слой анализа графа модулей, где каждая зависимость рассматривается как объект с набором атрибутов: версия, источник, лицензия, уязвимости, размер.

Такой подход позволяет формировать целостную картину состава бандла и его юридических ограничений без привязки к конкретному этапу сборки.