Как читать авторский курс и нормативные материалы
Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин OSA в разных материалах имеет разный охват. Статус и обязательность нормативного документа проверяются отдельно; проект КАПО опубликован как проект первой редакции.
П11. ScanCode для лицензий
Зачем эта практика Метаданные пакета говорят «лицензия проекта MIT», а внутри дерева может лежать файл под GPL — посборочный детектор находит лицензию по тексту в файлах, а не по заявлению в
package.json. ScanCode даёт два разных слоя:detected_license_expression(что распознал движок) и место, где это найдено. Задача практики — отделить detected (машинная находка с уровнем уверенности) от concluded (вердикт, который выносит человек), и научиться читать spurious-совпадения.
Цель
Запустить ScanCode по согласованному дереву исходников и получить машинный JSON, в котором по каждому файлу видны: распознанное SPDX-выражение, уровень уверенности (score), координаты совпадения (start_line/end_line) и фрагмент текста-улики. Проверяемый результат — выгрузка, где найдено минимум одно GPL/LGPL-совпадение внутри проекта, заявленного как permissive, либо обоснованный вывод, что таких нет.
Команда или действие
# Версия движка фиксируется в отчёте (нужно для воспроизводимости).
# Практика рассчитана на ScanCode 32.x: с этой версии поле называется
# detected_license_expression. На 31.x JSON-ключи другие (licenses[]),
# и jq-срез ниже придётся править.
scancode --version
# Полное сканирование лицензий с текстом-уликой и классификацией файлов
scancode \
--license \
--license-text \
--classify \
--info \
--processes 4 \
--json-pp scancode-licenses.json \
./vendor
# Быстрый срез: какие выражения и с какой уверенностью нашлись
jq -r '.files[]
| select(.detected_license_expression != null)
| "\(.detected_license_expression_spdx)\t\(.path)"' \
scancode-licenses.json | sort | uniq -c | sort -rn
Низкий
score— не мусор, а очередь на ручной просмотр Совпадения сscoreниже ~80 часто это упоминание лицензии в README или changelog, а не сам лицензионный текст. Не отбрасывайте их автоматически: именно там прячется «в одном файле GPL-хедер» при общем MIT. Фильтруйте через--license-score 80только когда сознательно сокращаете шум для отчёта.
Что вы должны увидеть
Структура --json-pp (сокращённый скелет одного файла):
{
"headers": [{ "tool_name": "scancode-toolkit", "tool_version": "32.x" }],
"files": [
{
"path": "vendor/somelib/parser.c",
"type": "file",
"detected_license_expression": "gpl-2.0",
"detected_license_expression_spdx": "GPL-2.0-only",
"license_detections": [
{
"license_expression_spdx": "GPL-2.0-only",
"matches": [
{
"score": 99.0,
"start_line": 3,
"end_line": 18,
"matched_text": "This program is free software; you can redistribute..."
}
]
}
]
}
]
}
Ориентир по объёму: на среднем vendor-дереве из 30–50 пакетов это сотни файлов, из которых лицензионные совпадения дают десятки уникальных выражений. Срез через jq должен показать таблицу вида:
142 MIT vendor/...
17 Apache-2.0 vendor/...
3 GPL-2.0-only vendor/somelib/...
1 LGPL-3.0-or-later vendor/otherlib/...
Ключевой момент: строки GPL-2.0-only / LGPL-3.0-or-later в проекте, который в package.json объявлен как MIT, — это и есть та самая находка «лицензия файла ≠ лицензия проекта». ScanCode выдал detected; перевод в concluded (блокер / условно / ложное срабатывание) делается уже руками и не живёт в этом JSON.
Если не получилось
Типичные ошибки -
scancode: command not found— Toolkit не в PATH. Ставится черезpip install scancode-toolkitв venv (Python 3.9+); проверьтеwhich scancode. Не путать с лёгкимscancode-toolkit-miniбез полного индекса лицензий. - JSON пустой /"files": []— указали несуществующий путь или каталог без прав чтения. ScanCode не падает, а молча сканирует пустоту; сверьте путь в конце команды и наличие файлов. - Сканирование висит/упало по памяти — натравили наnode_modulesцеликом или на бинарные артефакты. Сканируйте согласованный фрагмент (./vendor, конкретный пакет), исключайте мусор через--ignore "*.min.js" --ignore "node_modules/.cache/*". - Вездеscoreоколо 100, но выражения подозрительно однообразны — сканировали уже собранный дистрибутив с вырезанными хедерами вместо исходников. Лицензионные улики живут в исходном дереве, не в минифицированном бандле.
Критерий зачёта
Показать преподавателю: (1) scancode-licenses.json с зафиксированной версией движка в headers; (2) jq-срез с таблицей выражений; (3) минимум один разобранный кейс «detected ≠ concluded» — файл с copyleft-находкой внутри permissive-проекта, с вашим устным выводом, блокер это, ложное срабатывание или требует заключения. Голое число findings без интерпретации не засчитывается.
Нормативная связка
- Модуль: М07 Лицензионная чистота и юридический workflow
- Смежные практики: П12. ORT и license policy · П13. FOSSology как юридический workflow · П26. Лицензионная классификация · П27. Юридическое заключение и реестр лицензий
- Нормативка: SPDX ISO/IEC 5962 · OpenChain ISO/IEC 5230
- Шаблоны: Порядок работы с неизвестной лицензией · Матрица evidence для аудита
- Инструмент: ScanCode Toolkit