Релизы и обновления
Текущие релизы:
| Продукт | Версия | Примечания |
|---|---|---|
| Движок | lv24-seo 0.5.2 | Bugfix-релиз; без миграции схемы, без новых CLI-команд и MCP-инструментов |
| Приложение | 0.2.2 | Hardening-патч: очистка sidecar перед обновлением, надёжная запись, секреты и сброс устаревшего состояния; включает движок 0.5.2 |
Версия приложения и версия движка независимы, но приложение закрепляет точный движок и отказывается работать с версией ниже минимальной.
Движок 0.5.2
Это bugfix-релиз линии 0.5.x. Он закрывает блокеры, найденные после 0.5.1: относительный storage.data_dir в seo.toml следовал за рабочим каталогом оболочки, CLI собирал write-gate без журнала идемпотентности, ошибки загрузки sitemap эхом возвращали URL с query-токенами, а GSC заявлял полное покрытие, когда последняя страница ровно заполняла лимит строк.
Без миграции схемы и без новых CLI-команд или MCP-инструментов. JSON-конверт сохраняет прежние ключи; doctor добавляет аддитивные поля meta.data_dir / meta.data_dir_source и может нести предупреждение. Существующие хранилища открываются без изменений, а конфиги с абсолютным data_dir работают как раньше.
Что изменилось:
- Привязка data-dir. Относительный
storage.data_dirизseo.tomlтеперь разрешается относительно каталога этого файла, поэтомуlv24-seo --config /srv/site/seo.tomlиспользует/srv/site/dataиз любого рабочего каталога.initсоздаёт<config dir>/dataи пишетdata_dir = "./data". Встроенное значение по умолчанию (без блока[storage]) иLV24_SEO_DATA_DIRнамеренно остаются привязанными к процессу.doctor --jsonсообщаетmeta.data_dirиmeta.data_dir_source(configилиworking directory), аconfig show --jsonпоказывает эффективный путь. - Абсолютные пути планировщика.
resolve_config_pathвсегда возвращает абсолютный нормализованный путь.schedule installиschedule printвстраивают абсолютный аргумент--configи используют родительский каталог конфига как рабочий каталог, поэтому задание запускает тот же конфиг из любого каталога планировщика. - Повторобезопасные записи CLI. Команда записи с
--confirmоткрывает SQLite-журнал рабочей области и передаёт его вWriteGate. Повторный токен возвращаетstatus: skippedсreason: duplicate, и провайдер вызывается ровно один раз. Dry run не открывает журнал и не создаёт базу. Без инициализированной рабочей области команда всё равно работает, но конверт предупреждает, что защита от повтора отключена на пять минут жизни токена. - Маскирование URL в предупреждениях sitemap. Неудачная загрузка sitemap сообщает только тип исключения (
HTTPError,TimeoutError, …), но не URL и не query-строку. Сбой остаётся видимым и машиночитаемым, но?key=…не попадает в предупреждения,limitations[]или MCP-полезную нагрузку. - Честность точного лимита GSC. Последняя страница GSC, которая ровно заполняет лимит в 50 000 строк, помечается
truncated: trueсrows_cap_50000; меньший лимит вызывающего даёт предупреждение с его значением. Нулевой лимит считается лимитом, а не пустым результатом. Полная страница не доказывает, что за лимитом нет строк. - Опциональное маскирующее логирование.
LV24_SEO_LOG_LEVELустанавливает redacting-handler ровно в двух точках входа: callback CLI иlv24-seo mcp serve. Если переменная не задана, конфигурация логирования вызывающего не меняется. Вывод — одна JSON-строка на запись, когда stderr не терминал (pipe, лог планировщика, MCP-хост), и обычная строка в терминале. MCP-транспорт пишет только в stderr; stdout остаётся протоколом. - Мелкие исправления. Pending-заявка записи после падения по-прежнему не имеет TTL; удаление
data/seo.sqlite3сбрасывает журнал;doctorне падает на относительном data-dir.
Проверки этого релиза:
| Проверка | Результат |
|---|---|
| Офлайн-набор тестов | 1141 passed, 1 skipped |
ruff check | Чисто |
ruff format --check | Чисто |
mypy src | Чисто |
MCP registry --check | Чисто (поверхность не менялась) |
Известные ограничения 0.5.2:
- Конфиг, открытый через symlink, привязывает data-dir рядом со ссылкой, а не с целью: symlinks намеренно сохраняются.
LV24_SEO_DATA_DIRостаётся process-scoped переопределением. - Pending-заявка записи после падения не имеет TTL и считается выполняющейся, пока оператор её не освободит. Это намеренно: ложный повтор может дублировать запись провайдера.
- Без data-dir защиты от повтора нет; токен остаётся валидным все пять минут.
- Сайт ровно с 50 000 строк GSC и без строк за лимитом тоже помечается truncated. Это намеренно: полная страница не доказывает отсутствие следующей строки.
- Логирование остаётся опциональным. Правила редактирования покрывают чувствительные ключи, известные префиксы токенов и длинные непрозрачные значения, но не каждый формат секрета конкретного провайдера.
Артефакты приложения 0.2.2
0.2.2 — hardening-патч для превью 0.2.x. Он исправляет сбой обновления из-за заблокированного sidecar движка, делает запись конфигурации и настроек в Rust надёжной и приватной, сбрасывает устаревшее состояние UI и включает lv24-seo 0.5.2.
| Артефакт | Платформа | Назначение |
|---|---|---|
LV24.SEO.Optimizer_0.2.2_x64-setup.exe + .exe.sig | Windows x64 | NSIS-установщик для пользователя; подписанный пакет обновления |
LV24-SEO-Optimizer_0.2.2_x64-portable.zip | Windows x64 | Portable-сборка; manual-only |
LV24.SEO.Optimizer_0.2.2_aarch64.dmg | macOS Apple silicon | Первая установка |
LV24.SEO.Optimizer_0.2.2_x64.dmg | macOS Intel | Первая установка |
LV24.SEO.Optimizer_0.2.2_aarch64.app.tar.gz + .sig | macOS Apple silicon | Подписанный пакет обновления |
LV24.SEO.Optimizer_0.2.2_x64.app.tar.gz + .sig | macOS Intel | Подписанный пакет обновления |
LV24.SEO.Optimizer_0.2.2_amd64.AppImage + .AppImage.sig | Linux x64 | AppImage; подписанный пакет обновления |
LV24.SEO.Optimizer_0.2.2_amd64.deb, LV24.SEO.Optimizer-0.2.2-1.x86_64.rpm | Linux x64 | Установка менеджером пакетов; manual-only |
latest.json | Все | Подписанный манифест обновлений |
SHA256SUMS.txt | Все | SHA-256 каждого опубликованного артефакта |
Установщику Windows нужны Windows 10/11 x64 и runtime WebView2; NSIS-установщик может его скачать, portable ZIP — нет. Linux-пакеты собраны на Ubuntu 22.04 с базой glibc 2.35 и только для x64. macOS требует macOS 13 или новее; используйте aarch64 DMG на Apple silicon и x64 DMG на Intel.
Очистка sidecar перед обновлением
Sidecar движка лежит внутри установленного каталога ресурсов, поэтому запущенный процесс lv24-seo держит файл заблокированным и NSIS-установщик не может его заменить. Перед запуском установщика оболочка вызывает prepare_update, который останавливает только те PID движка, которые зарегистрировал этот экземпляр приложения при их запуске. Ничего не ищется по имени образа, поэтому другая установленная копия, portable-сборка, запущенный в терминале lv24-seo или посторонний процесс не затрагиваются. Короткое ожидание (2 с) подтверждает завершение.
Если очистка не удалась, установка блокируется с UPDATE_ENGINE_BUSY, а не запускает установщик, который сломается на середине. Ошибка повторяемая: закройте запуск, удерживающий sidecar, и нажмите кнопку снова.
Секреты и конфигурация
- Yandex Metrika сохраняет собственный auth-провайдер (
metrika,yandex_metrika_token) в списке провайдеров, бейдже Settings, окне секретов и подписях en/ru/zh. Он никогда не берёт токен Webmaster. - Приложение и CLI используют одну запись OS keychain на провайдера (сервис
lv24-seo). Токен, введённый черезlv24-seo auth set --provider <p> --stdinв терминале, появляется вauth statusприложения без повторного ввода, а токен из приложения виден CLI. - Токен из
LV24_SEO_*показывается в UI как read-only: приложение не может удалить переменную окружения и говорит об этом, а не предлагает кнопку удаления, которая ничего не делает.auth logoutсdeleted: falseпоказывается честно. - Состояние workspace, отчёта, doctor и секретов очищается при смене workspace или переходе движка в offline. Действия, которые не могут работать, отключаются, а не падают по клику. Каталоги сообщений en/ru/zh согласованы; отсутствующий ключ — ошибка теста.
- Запись конфигурации и настроек атомарна и fsynced (файл и родительский каталог). Временные черновики и резервные копии имеют режим
0600; чтение конфига ограничено 8 MiB; настройки загружаются по полям; зарезервированные имена Windows и завершающие точки/пробелы отклоняются в каждом компоненте пути. stderr валидации конфигурации редактируется до попадания в UI или лог.
Матрица автообновления
| Пакет | Обновление в приложении | Что происходит |
|---|---|---|
| Windows NSIS | Да | Скачивает подписанный setup .exe, останавливает отслеживаемые PID sidecar, запускает установщик в passive-режиме, перезапускает |
macOS .app | Да | Скачивает подписанный .app.tar.gz, заменяет приложение, перезапускает |
| Linux AppImage | Да | Скачивает подписанный AppImage, заменяет его, перезапускает |
| Windows portable ZIP | Нет | Settings ведёт на страницу релиза; скачайте и распакуйте новый ZIP |
| Linux deb | Нет | Settings ведёт на страницу релиза; обновление менеджером пакетов |
| Linux rpm | Нет | Settings ведёт на страницу релиза; обновление менеджером пакетов |
| MSI | Нет | MSI не производится; установка MSI считается ручной |
| Неизвестный пакет | Нет | Settings ведёт на страницу релиза |
Manual-only — намеренно. Пакет deb или rpm принадлежит базе пакетов; MSI этим проектом не производится, и NSIS-пакет обновления не может его заменить; portable ZIP не имеет установщика, который можно заменить, и может лежать на съёмном носителе. Приложение сообщает тип установленного пакета и отключает встроенный установщик для таких случаев. Оно не делает вид, что ручной пакет был обновлён.
Путь Windows NSIS теперь проверен end-to-end дважды: 0.2.0 → 0.2.1 и 0.2.1 → 0.2.2. Во втором запуске установленная сборка 0.2.1 обнаружила 0.2.2, скачала и проверила подписанный пакет, установила его в passive-режиме, перезапустилась и сообщила 0.2.2 с готовым движком 0.5.2. 0.2.2 обновляется напрямую с 0.2.0; у 0.1.0 нет обновлятора, нужна одна ручная установка.
Обновление 0.2.1 → 0.2.2 выполняет старый обновлятор 0.2.1, в котором нет новой очистки отслеживаемых PID. Если во время первого обновления активен sidecar, повторите после его выхода или установите 0.2.2 вручную. 0.2.2 → later использует очистку отслеживаемых PID и блокируется с UPDATE_ENGINE_BUSY, если отслеживаемый sidecar не удаётся остановить.
Релизный конвейер
Workflow приложения ручной и owner-gated. У него нет триггеров push, pull-request или tag. Владелец запускает Actions → Desktop build → Run workflow и подтверждает окружение desktop-release; запуск не владельцем пропускается.
| Вход | Значение по умолчанию | Смысл |
|---|---|---|
engine_version | 0.5.2 | Точная версия движка в sidecar |
signed | false | Запросить подпись/нотаризацию ОС; в этом zero-spend репозитории не настроено |
publish | false | Создать GitHub release после прохождения всей матрицы |
tag | Пусто | Тег релиза vX.Y.Z; обязателен при publish=true |
Значение по умолчанию соответствует пину 0.2.2. Релизный гейт отклоняет несоответствие манифеста, если передана другая версия.
| Runner | Target | Пакеты |
|---|---|---|
windows-latest | x86_64-pc-windows-msvc | NSIS |
ubuntu-22.04 | x86_64-unknown-linux-gnu | AppImage, deb, rpm |
macos-15 | aarch64-apple-darwin | DMG + app |
macos-15-intel | x86_64-apple-darwin | DMG + app |
Все runner'ы — стандартные GitHub-hosted. Не используются larger runner, платные минуты, платное хранилище или платный сервис подписи. Артефакты сборки хранятся 7 дней; GitHub release — долговечный канал распространения.
Пин sidecar и контрольные суммы
Релизный sidecar — дерево PyInstaller onedir, собранное на соответствующем хосте; PyInstaller не кросс-компилирует. Версии движка, Python, Pydantic, Typer и PyInstaller закреплены в scripts/cli-checksums.json. 0.2.2 закрепляет движок 0.5.2, Python 3.12, Pydantic 2.14.3, Typer 0.29.0 и PyInstaller 6.22.3.
Вывод PyInstaller onedir не байт-воспроизводим. Поэтому политика контрольных сумм разделена:
- Локальная релизная сборка — строгая.
scripts/verify-sidecar.mjsдолжен совпасть с закоммиченными SHA-256 и размером;--writeобновляет пин после ревью.nullозначает «ещё не проверено», а не «проверено». - CI-пересборка — rebuild-aware. Job сборки запускает верификатор с
--no-hashи записывает фактический SHA-256 вrelease/sidecar-checksums-<target>.json. - Релизный гейт — по отчётам. Релизный job требует валидный отчёт для каждого отгружаемого target: совпадение имени target,
hashPolicy: "rebuild",ok: true, 64-hex хеш, положительный размер и точную версию движка.
Для 0.5.2 Windows x64 имеет проверенный локальный пин; target'ы Linux и macOS остаются null, пока sidecar 0.5.2 не будет пересобран и проверен на соответствующем хосте. Windows-пин 0.5.1 не переносился, потому что исполняемый файл меняется вместе с движком. Отчёты контрольных сумм — доказательства CI, а не релизные артефакты. SHA256SUMS.txt покрывает установщики, пакеты обновления, подписи и latest.json; исполняемый файл sidecar находится внутри этих пакетов и отдельно не указан. При ручной установке сверяйте скачанный артефакт с SHA256SUMS.txt.
node scripts/verify-sidecar.mjs \
--root src-tauri/engine \
--target x86_64-pc-windows-msvc \
--engine-version 0.5.2latest.json, подпись и публикация
Подписи обновлений используют бесплатный ключ Ed25519/minisign, отдельный от подписи кода ОС. Публичный ключ встроен в приложение; приватный — секрет репозитория, передаваемый только на шаг сборки. Включён requireSignedVersion, поэтому объявленная версия привязана к подписанному пакету. Обновление принимает только версию выше текущей, поэтому откатиться нельзя.
scripts/stage-release-assets.mjs выравнивает и нормализует имена пакетов и пишет метаданные updater-<platform>.json для каждой платформы. scripts/merge-latest-json.mjs объединяет их в latest.json:
- обязательные generic-ключи:
windows-x86_64,linux-x86_64,darwin-aarch64,darwin-x86_64; - bundle-алиасы, которые проверяет обновлятор:
windows-x86_64-nsis,linux-x86_64-appimage,darwin-aarch64-app,darwin-x86_64-app; - необязательные
linux-x86_64-debиlinux-x86_64-rpmтолько если Tauri создал их подписи; - каждый URL указывает под
releases/download/<tag>/; - каждая подпись сверяется с файлом
.sigна диске; - каждый упомянутый артефакт должен существовать;
- примечания берутся из
docs/releases/<version>.md, если файл есть.
Релиз сначала создаётся как draft. Артефакты загружаются, пока он draft, latest.json — последним, затем job публикует через gh release edit --draft=false и проверяет удалённые имена артефактов. releases/latest/download/latest.json разрешается только на опубликованный релиз, поэтому пользователи не видят частично загруженный манифест. Повторный запуск переиспользует существующий draft, очищает его артефакты и отказывается перезаписывать опубликованный релиз.
Закрепление версий
Версия приложения должна совпадать в package.json, src-tauri/tauri.conf.json, src-tauri/Cargo.toml, Git-теге и заголовке релиза. Пин движка живёт в scripts/cli-checksums.json; workflow передаёт engine_version явно, а релизный гейт требует совпадения с манифестом.
MIN_ENGINE_VERSION в src-tauri/src/commands.rs в текущем исходнике равен 0.5.2. Оболочка принимает движок не старше этой версии и помечает более старый как offline с уведомлением. Более новый движок проходит гейт, но не является релизно-проверенным пином. Сборочная версия может использовать LV24_SEO_BIN с другой версией; UI помечает его внешним и всё равно проверяет минимум. Движок из PATH используется только при LV24_SEO_ALLOW_PATH_ENGINE=1.
Однократное обновление с 0.1.0
У 0.1.0 нет updater, endpoint и публичного ключа. Он не может найти или установить 0.2.2. Скачайте и установите 0.2.2 вручную один раз (NSIS-установщик или portable ZIP в Windows). После этого установка 0.2.2 может автоматически обновляться до следующих релизов, если использует пакет с поддержкой автообновления.
Предыдущие релизы
- Приложение 0.2.1 исправило поверхность токена Yandex Metrika и сделало общий keychain CLI/приложения явным. Это был первый релиз, доставленный встроенным обновлятором с
0.2.0. - Приложение 0.2.0 было первым мультиплатформенным релизом: Windows NSIS и portable ZIP, Linux AppImage/deb/rpm, macOS DMG и подписанные пакеты обновления.
- Движок 0.5.1 исправил повторы write-gate, ограничил текст обхода, поправил MCP-аннотации и достижимые лимиты. Он считал последнюю страницу GSC на точном лимите полной;
0.5.2меняет это решение и считает полную последнюю страницу потенциально усечённой.
Откат
Автоматического отката нет. Откат — ручная установка более старого релиза.
| Сбой | Действие |
|---|---|
| Плохой установщик, но рабочее приложение | Выпустить исправленный патч; не перезаписывать артефакты под тем же тегом |
Плохой latest.json | Выпустить исправленный патч; draft-гейт не даёт частичному манифесту стать видимым |
| Скомпрометированный ключ обновлений | Ротировать ключ, выпустить ручной релиз с новым публичным ключом; автообновление не переживает ротацию |
| Регрессия движка | Закрепить предыдущую версию движка, пересобрать и выпустить патч |
| Нужна старая сборка приложения | Установить вручную; обновлятор отказывается от понижения |
Не перемещайте и не переиспользуйте опубликованный тег. Держите артефакты предыдущего релиза доступными для отката. Если endpoint нужно отключить, выпустите ручной релиз и задокументируйте это.
Проверка загрузки
SHA256SUMS.txt покрывает каждый опубликованный артефакт. Проверьте файлы, которые собираетесь устанавливать:
sha256sum -c SHA256SUMS.txt --ignore-missingНа macOS shasum -a 256 -c SHA256SUMS.txt доступен в базовой системе. В Windows сравните Get-FileHash <file> -Algorithm SHA256 с соответствующей строкой. Не запускайте файл, хеш которого не совпадает.
По умолчанию пакеты ОС не подписаны (Windows, Linux) или подписаны ad-hoc (macOS). Подпись обновления аутентифицирует обновления, а не первую ручную загрузку. Предупреждения SmartScreen и Gatekeeper ожидаемы; сверьте контрольную сумму и используйте документированный путь More info → Run anyway или Open Anyway. Не отключайте эти защиты глобально.
См. Безопасность и приватность для доверия к обновлениям и Архитектуру для раскладки sidecar.
Source: _source/engine-releases-0.5.2.md, _source/desktop-releases-0.2.2.md, _source/desktop-releases-0.2.1.md, _source/desktop-releases-0.2.0.md, _source/desktop-release.md, _source/desktop-security.md.