126 lines
12 KiB
Markdown
126 lines
12 KiB
Markdown
# Ноябрь 2019 — тройное ревью автономного пакета P21 «Воспроизводимые сборки»
|
||
|
||
Статус: **принят в publication registry 31 июля 2026 года**. Три revision
|
||
накладываются только по stable slug и сохраняют даты и авторов базового архива:
|
||
|
||
- <code>editorial-2019-11-practice-reproducible-builds</code>;
|
||
- <code>editorial-2019-11-mechanism-reproducible-builds</code>;
|
||
- <code>editorial-2019-11-field-reproducible-builds</code>.
|
||
|
||
Модуль экспортирует ровно три revision. В объектах нет <code>date</code> и
|
||
<code>author</code>: эти поля принадлежат исходным записям архива. При прямом
|
||
запуске с <code>--print-revisions</code> stdout содержит только JSON; отдельный
|
||
<code>--run-fixture</code> печатает JSON учебной hash-проверки.
|
||
|
||
## Проход 1. Факты и техника — пройдено
|
||
|
||
| Утверждение или решение | Первичный источник | Проверенная граница |
|
||
| --- | --- | --- |
|
||
| Lockfile фиксирует конкретное дерево, включая транзитивные зависимости | [npm 6: package-locks](https://docs.npmjs.com/cli/v6/configuring-npm/package-locks/) и [package-lock.json](https://docs.npmjs.com/cli/v6/configuring-npm/package-lock-json/) | Текст не утверждает, что lockfile фиксирует OS, время, webpack config или внешний генератор. Он фиксирует разрешение пакетов, когда используется в контролируемом install. |
|
||
| <code>npm ci</code> — чистая установка с отказом при рассинхронизации lockfile и package.json | [npm 6: npm ci](https://docs.npmjs.com/cli/v6/commands/npm-ci/) | Статьи не подменяют им рабочий <code>npm install</code> и не обещают, что npm ci устраняет drift плагина или даты в asset. |
|
||
| npm config может прийти из CLI, окружения, npmrc и package.json | [npm 6: npm config](https://docs.npmjs.com/cli/v6/commands/npm-config/) | В журнал предлагается whitelist безопасных значений, а не полный <code>env</code>, токены или auth headers. |
|
||
| <code>[contenthash]</code> связан с содержимым asset, но runtime и module IDs способны расширить diff chunks | [webpack: Caching](https://webpack.js.org/guides/caching/) | Имя одного файла названо сигналом, а не доказательством равенства всего dist. Проверяется manifest всех deployable files. |
|
||
| SHA-256 нужен для сравнения выбранных bytes | [Node.js: Crypto](https://nodejs.org/api/crypto.html) | Hash не объявлен подписью релиза, доказательством работы приложения или результатом production-сборки. |
|
||
|
||
Автономная fixture не скачивает зависимости и не запускает webpack. Она
|
||
проверяет только алгоритм сравнения: перестановка одинаковых entries даёт тот
|
||
же hash manifest, изменение одного bytes даёт другой. Фактический вывод:
|
||
|
||
<pre><code>{
|
||
"fixtureOnly": true,
|
||
"lockfileSha256": "d2976c1b0ca05326497d2b8157ee39b3ffc6f5ad6481c119e2fd769d3e6c8204",
|
||
"firstManifestSha256": "adc6fefae98f7874289579da4efcf252217989cbc9caf32fc8bb830f6eeac75e",
|
||
"secondManifestSha256": "adc6fefae98f7874289579da4efcf252217989cbc9caf32fc8bb830f6eeac75e",
|
||
"changedManifestSha256": "a521a4c7df02a402a2ab7e71ff690554cdf686faf831aaefe7d171079d15e8fe",
|
||
"checks": {
|
||
"sameEntriesDifferentOrder": true,
|
||
"changedFileChangesManifest": true
|
||
}
|
||
}</code></pre>
|
||
|
||
Следовательно, fixture подтверждает только канонизацию sample manifest. В
|
||
пакете нет заявления о CI, registry install, браузерном релизе или production
|
||
output. Для настоящего проекта статьи требуют записать собственные commit,
|
||
lockfile digest, Node/npm, команду, журнал и manifest после реального запуска.
|
||
|
||
## Проход 2. Редактура и голос М2 / 2019 — пройдено
|
||
|
||
| Ревизия | Симптом и стоимость в начале | Главный технический вопрос | Проверяемый результат и ограничение |
|
||
| --- | --- | --- | --- |
|
||
| Практика | Один commit создаёт два dist; review и rollback не знают, какой набор assets был проверен | Как получить два чистых прогона, не смешав установку зависимостей и проверку output | Lockfile/log/manifest route, Node hash script и список входов; нет заявления о запуске этого проекта |
|
||
| Механизм | Одинаковый Git hash скрывает разные runtime, config или generated data | Где проходит граница функции build и что доказывает manifest SHA-256 | Карта входов, таблица владельцев, контрпримеры contenthash; hash не выдан за подпись или тест приложения |
|
||
| Полевой разбор | Коллеги получили разные release-файлы и хотят начать с очистки cache | Как по первому differing file отличить dependency, config и generated output | Карточка двух прогонов, дерево диагностики и обратимый путь исправления; CI и production не заявлены |
|
||
|
||
- Тон соответствует уровню М2 / 2019: npm 6, webpack 4, Node, проектный
|
||
npmrc, чистая установка, manifest и diff. В текст не добавлены поздние
|
||
практики вроде supply-chain attestations, SLO, распределённой трассировки
|
||
или риторика платформенного техлида.
|
||
- Во всех трёх текстах держится маршрут «симптом → причина → проверка →
|
||
действие → ожидаемый результат → ограничение». Конкретные объекты названы:
|
||
<code>package-lock.json</code>, <code>npm ci</code>, <code>dist</code>,
|
||
<code>first.manifest</code>, <code>NODE_ENV</code>, runtime chunk и
|
||
generated banner.
|
||
- Нет шаблонных призывов «очистить кэш», «закрепить всё» или «сделать CI»
|
||
без диагностического условия. Каждый такой шаг имеет место в маршруте,
|
||
владельца и границу вывода.
|
||
- Draft gate подтвердил основной текст в диапазоне 5 000–15 000 символов:
|
||
**10 061** для практики, **9 115** для механизма и **8 650** для полевого
|
||
разбора. В значение не включены title, meta и раздел источников.
|
||
- В каждой статье есть не менее пяти <code>h2</code>, доступная таблица с
|
||
<code>caption</code>, <code>thead</code> и <code>scope</code>, оригинальная
|
||
схема с содержательными <code>alt</code>/<code>figcaption</code>, код,
|
||
упорядоченный маршрут и не менее двух официальных источников.
|
||
|
||
## Проход 3. Визуал и выпуск автономного пакета — пройдено
|
||
|
||
- <code>reproducible-build-input-contract-2019.svg</code> ведёт от исходников,
|
||
зависимостей и среды/команды к чистой установке, build и manifest. Диаграмма
|
||
подчёркивает, что hash приходит после явного контракта, а не заменяет его.
|
||
- <code>reproducible-build-hash-boundary-2019.svg</code> отделяет
|
||
зафиксированные commit/lockfile от runtime, config и generated data. Нижняя
|
||
развилка не называет расхождение ошибкой сборщика: она ведёт к первому
|
||
отличающемуся файлу.
|
||
- <code>reproducible-build-diagnosis-2019.svg</code> показывает две чистые
|
||
сборки, сравнение входов и явное условие: при расхождении входов маршрут
|
||
останавливается, при совпадении сравнивается output manifest. Это
|
||
визуальный маршрут, а не скриншот несуществующего прогона.
|
||
- В каждом SVG есть <code>title</code>, <code>desc</code>,
|
||
<code>role="img"</code>, вертикальный <code>viewBox</code>, контрастные
|
||
карточки и подписи внутри заданной ширины. Нет JavaScript, внешних URL,
|
||
растровых вложений или анимации. XML-валидатор принял все три файла.
|
||
- Независимый mobile preflight отрисовал каждый SVG через Sharp в PNG шириной
|
||
375 px. Первый raster показал мелкие подписи в горизонтальных панелях и
|
||
обрезание диагностической схемы. Все три визуала пересобраны вертикально;
|
||
повторный рендер не показал обрезания, наложения или горизонтального выхода.
|
||
Это проверка статичных изображений, а не browser screenshot или
|
||
Accessibility tree.
|
||
- После подключения registry strict audit и production build пройдены. Ручной
|
||
browser-review поведения страницы остаётся отдельной выпускной проверкой и
|
||
не заявлен как выполненный.
|
||
|
||
## Выполненные команды
|
||
|
||
<pre><code>cd web
|
||
node --check scripts/upgrade-2019-11.mjs
|
||
npm run audit:draft -- scripts/upgrade-2019-11.mjs
|
||
node scripts/upgrade-2019-11.mjs --run-fixture
|
||
xmllint --noout \
|
||
public/assets/editorial/2019/reproducible-build-input-contract-2019.svg \
|
||
public/assets/editorial/2019/reproducible-build-hash-boundary-2019.svg \
|
||
public/assets/editorial/2019/reproducible-build-diagnosis-2019.svg</code></pre>
|
||
|
||
Все четыре команды завершились с кодом 0. Draft gate вывел:
|
||
|
||
<pre><code>PASS editorial-2019-11-practice-reproducible-builds: 10061 body chars
|
||
PASS editorial-2019-11-mechanism-reproducible-builds: 9115 body chars
|
||
PASS editorial-2019-11-field-reproducible-builds: 8650 body chars</code></pre>
|
||
|
||
После интеграции strict audit подтвердил: 10 061 / 9 115 / 8 650 знаков,
|
||
по одному figure и table, 3 / 1 / 1 code example. <code>npm run build</code>
|
||
завершился с кодом 0 и сгенерировал 374 статические страницы.
|
||
|
||
Выпусковой вердикт: **тройное ревью пройдено, пакет принят к публикации**.
|
||
<code>articles.json</code> не менялся; registry заменяет только редакционные
|
||
поля по stable slug. Production build и raster preflight не подменяют ручную
|
||
проверку поведения в браузере.
|