Spec-Zone.ru › Deno 2

Управление цепочкой поставок

Современные проекты на JavaScript получают код из множества источников (JSR, npm, локальные рабочие пространства). Грамотное управление цепочкой поставок помогает достичь четырёх целей:

  • Детерминированность: все (включая CI) используют один и тот же код.
  • Безопасность: неожиданные изменения или компрометации в исходных репозиториях обнаруживаются на ранней стадии.
  • Скорость: вы можете обновлять зависимости тогда, когда сами решите.
  • Устойчивость: сборки продолжают работать без подключения к сети или при сбоях реестров.

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

Основные практики

  1. Фиксируйте версии осознанно
    • Для приложений предпочтительны точные версии (например, jsr:@luca/cases@1.2.3).
    • Для библиотек диапазон с кареткой (^1.2.3) позволяет пользователям получать обратно совместимые исправления.
    • Избегайте неограниченных (*) или слишком широких диапазонов в производственных приложениях.
  2. Добавьте файл deno.lock в систему контроля версий.
  3. Включите режим замороженного файла блокировки в CI / production (--frozen или "lock": { "frozen": true }), чтобы новые, ранее не встречавшиеся зависимости приводили к сбою сборки, а не появлялись незаметно.
  4. Используйте вендоринг, если нужны герметичные сборки или сборки без подключения к сети ("vendor": true), либо если требуется локально исправить сторонний код. Вендоринг не отменяет необходимости в файле блокировки — он дополняет его.
  5. Используйте спецификаторы jsr: и npm: с записями import map (imports), чтобы централизованно управлять версиями.
  6. Периодически снимайте фиксацию и осознанно обновляйте зависимости (например, еженедельно или в каждом спринте), а не обновляйте их от случая к случаю во время работы над функциями.
  7. Установите минимальный возраст зависимости, чтобы только что опубликованные версии не попадали в установку до того, как экосистема успеет выявить скомпрометированный релиз.
  8. Включите политику доверия к публикации, чтобы версии, опубликованные менее надёжным способом, чем версия, уже зафиксированная вами, отклонялись, а не принимались незаметно.

Минимальный возраст зависимости

Deno отказывается устанавливать версии пакетов, возраст которых меньше заданного. Это простой способ широко защититься от атак на цепочку поставок npm: обнаружение и удаление вредоносных версий обычно занимает несколько дней, поэтому задержка установки на аналогичный срок позволяет отсеять большинство таких версий.

Начиная с Deno 2.9 эта настройка по умолчанию включена и равна 24 часам: версии, опубликованные за последние сутки, пропускаются даже без конфигурации. Приведённые ниже параметры изменяют это окно или отключают его (задайте возраст 0).

Один и тот же параметр можно настроить в нескольких местах; выберите подходящее для проекта:

  • deno.json, действует на весь проект:

    deno.json
    {
      "minimumDependencyAge": "P3D"
    }
    
  • Флаг CLI, применяется для разового использования, например при однократной установке или на шаге CI:

    ›_
    deno install --minimum-dependency-age=P3D
    
  • .npmrc (Deno 2.8+), соответствует принятому в npm соглашению и удобен, если один и тот же .npmrc используется инструментами npm и Deno. Параметр npm принимает только целое количество дней:

    .npmrc
    min-release-age=3
    

deno.json и --minimum-dependency-age принимают длительность в формате ISO-8601, например P3D (3 дня) или PT72H (72 часа), целое число (интерпретируется как количество минут), абсолютную дату отсечения (2025-09-16) или временную метку RFC3339 либо 0 для отключения. Поле также поддерживает объектную форму, позволяющую исключать отдельные пакеты; полный формат см. в справочнике minimumDependencyAge, а другие параметры реестра npm, которые считывает Deno, описаны в разделе конфигурации .npmrc.

Политика доверия к публикации

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

Полные метаданные пакета npm содержат сведения о способе публикации каждой версии. Deno считывает из них три сигнала:

  • Доверенная публикация (OIDC) — версия опубликована из CI посредством механизма доверенной публикации npm через OIDC, без долгоживущего токена.
  • Аттестация происхождения — версия содержит подписанную аттестацию происхождения SLSA, связывающую её с исходным коммитом и сборкой (публикуется с помощью --provenance).
  • Поэтапная публикация — сопровождающий одобрил версию с помощью действующего запроса 2FA до того, как она стала доступна для установки.

Deno объединяет эти сигналы в единый уровень доверия — от наименьшего к наибольшему:

Уровень доверия Сигнал
Обычный Сигналов доверия к публикации нет
Происхождение Только аттестация происхождения
Доверенная публикация Только доверенная публикация через OIDC
Доверенная публикация + происхождение Оба перечисленных выше сигнала
Поэтапная публикация Публикация поэтапно, одобренная человеком (имеет наивысший уровень)

Поэтапная публикация имеет наивысший уровень, поскольку её одобрил человек с помощью действующего запроса 2FA. Такой порядок соответствует trustPolicy: no-downgrade в pnpm.

Причина — безопасность цепочки поставок: если токен сопровождающего украдут, злоумышленник сможет опубликовать новую версию менее надёжным способом, чем версии, которым вы доверяли. Политика no-downgrade превращает такое незаметное снижение уровня доверия в явную ошибку.

Включите её в .npmrc:

.npmrc
trust-policy=no-downgrade

Как это работает:

  • Deno записывает разрешённый уровень доверия для каждой записи npm в deno.lock (поле trust, которое не указывается для обычной версии). Записанный уровень становится базовым для следующего разрешения.
  • Когда no-downgrade включён, Deno отказывается разрешать любые версии-кандидаты, уровень доверия которых ниже зафиксированного базового уровня для этого пакета, и загружает полный packument, чтобы получить доступ к сигналам.
  • Базовый уровень — это наивысший уровень доверия, записанный для пакета в файле блокировки, поэтому защита усиливается по мере фиксации версий с более высоким уровнем доверия. При первой фиксации пакета сравнивать ещё не с чем.
  • По умолчанию политика отключена. На существующие файлы блокировки она не влияет, пока вы её не включите; любое значение, кроме no-downgrade, оставляет её отключённой.

Типичный сценарий CI

В Deno 2.8+ одна команда deno ci объединяет рекомендуемые шаги установки в CI (замороженный файл блокировки + скрипты жизненного цикла):

›_
deno ci

Для более старых версий Deno или если нужно выполнить шаги вручную:

›_
# Install (resolve) dependencies exactly as locked; fail if drift or new deps
deno install --frozen --entrypoint main.ts

# (optional) Run with only cached modules to guarantee no network access
deno run --cached-only main.ts

Если вы используете пакеты npm (указано package.json), добавьте deno install (или deno ci) в CI перед запуском тестов, чтобы каталог node_modules создавался детерминированно.

Осознанное обновление зависимостей

Когда вы решите выполнить обновление:

  1. Временно разрешите запись в файл блокировки: добавьте --frozen=false или установите "lock": { "frozen": false }.
  2. Измените версии (отредактируйте deno.json, используйте deno add <specifier>@<newVersion> или удалите с помощью deno remove).
  3. Повторно запустите deno install --entrypoint main.ts (при необходимости --reload), чтобы обновить разрешённые версии и хеши целостности.
  4. Проверьте diff для deno.lock (и vendor/, если используется) в pull request.
  5. Снова включите режим замороженного файла блокировки.

Устранение неполадок с замороженным файлом блокировки

Вы можете столкнуться с такими ошибками:

error: The lockfile is frozen. Cannot add new entry for "jsr:@scope/pkg@1.3.0".

или:

error: Module not found in frozen lockfile: https://example.com/dependency/mod.ts

Распространённые причины и решения:

Симптом Причина Решение
Нужно повысить версию, но команда завершается с ошибкой из-за замороженного файла Файл блокировки находится в замороженном режиме Повторно запустите команду с --frozen=false (однократно) или временно установите "lock": { "frozen": false }, затем обновите зависимости и снова включите замороженный режим
После редактирования кода появляется новая транзитивная зависимость Теперь код импортирует то, чего нет в файле блокировки Снимите заморозку (--frozen=false) и запустите deno install --entrypoint <entry>.ts, чтобы записать зависимость
Импорты удалены, но в файле блокировки остались старые записи Файл блокировки дополняется; записи сохраняются (Необязательно) пересоздайте файл: отложите deno.lock в сторону (mv deno.lock deno.lock.old), запустите установку, чтобы создать его заново, сравните изменения и зафиксируйте результат
Повреждение файла блокировки / конфликт слияния Ручное редактирование или конфликт привели к несогласованному JSON Удалите конфликтующие разделы и повторно запустите установку либо пересоздайте файл целиком
Используются вендорированные зависимости, но файл блокировки сообщает об ошибке Каталог вендорированных зависимостей не синхронизирован с файлом блокировки Повторно запустите deno install --entrypoint <entry> (без заморозки), чтобы синхронизировать оба объекта, и зафиксируйте результат

Контрольный список безопасного пересоздания

Пересоздавайте весь файл deno.lock только при необходимости (повреждение, массовая очистка). Если это необходимо:

  1. Создайте резервную копию: cp deno.lock deno.lock.bak.
  2. Удалите файл: rm deno.lock.
  3. (При использовании вендоринга) удалите или переместите каталог vendor/.
  4. Запустите deno install --entrypoint main.ts, чтобы создать файл заново.
  5. Изучите различия между старой и новой версиями, чтобы выявить неожиданные добавления.

Вендоринг и файл блокировки

Эти подходы дополняют друг друга:

  • Файл блокировки: хранит точные разрешённые версии и хеши целостности для удалённых зависимостей, а также зависимостей npm/JSR.
  • Каталог вендорированных зависимостей: хранит фактический исходный код локально для герметичных сборок, сборок без подключения к сети и сборок с возможностью внесения исправлений.

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

Краткое руководство по выбору

Задача Решение
Обнаружить подмену в исходном репозитории Файл блокировки (добавить в систему контроля версий и заморозить)
Сборка без подключения к сети / в изолированной среде vendor: true + файл блокировки
Исправить сторонний код Вендоринг или переопределения scopes (краткосрочное решение)
Быстрый CI с проверкой целостности deno install --frozen
Осознанно обновить версии Временно снять заморозку, запустить установку, проверить diff
Заблокировать снижение уровня доверия к публикации trust-policy=no-downgrade в .npmrc

Минимальные базовые меры для цепочки поставок (рекомендуется)

deno.json
{
  "imports": {/* centralize versions */},
  "vendor": true,
  "lock": { "frozen": true }
}

Добавьте в систему контроля версий deno.json, deno.lock и (при использовании вендоринга) весь каталог vendor/.

Автоматизируйте еженедельное обновление зависимостей

Запланированное задание CI, которое снимает заморозку, запускает deno add --latest (или вручную обновляет ключевые пакеты), выполняет тесты и открывает pull request с обновлённым файлом deno.lock (и vendor/), обеспечивает регулярное поступление исправлений безопасности и сохраняет детерминированность повседневных сборок.

Последнее обновление: 25 июня 2026 г.

© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/runtime/packages/supply_chain

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API