server-monitor-manager/agents/codex/inbox/from-smm-deliverables/Старые задачи/smm-codex-task-alpha15-2026-08-15.md
Ochenstarik 23eb3f5233 chore(agents): разбор рабочих папок с диска на 2026-08-18
Задания, отчёты и патчи, лежавшие в C:\Users\Ochenstarik\projects и в
домашней папке, перенесены в agents/. Разложено по агентам там, где имя
файла позволяло определить автора; остальное — в _salvage-2026-08-18/
и разбирается вручную.

Патчи в notes/salvage-2026-08-18/ — незакоммиченная работа из брошенных
рабочих копий: она существовала только на диске.

Тяжёлое (релизные архивы, инсталляторы, наборы данных) в репозиторий не
попало: оно лежит рядом, в Agent_projects/_archive и Agent_projects/_data.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 14:19:54 +07:00

17 KiB
Raw Blame History

Codex: cosign в поставке и работающий автозапуск проверки релиза → v0.1.0-alpha.15

Задание самодостаточно: истории работы по этому репозиторию у вас нет, всё нужное ниже.

Репозиторий

Server Monitor Manager — Windows-клиент, ASP.NET Core Control Hub, Linux-агент и WireGuard-mesh с политиками nftables. На серверы ставится bash-скриптом deploy/ochenstarik-server-monitor-manager.sh (bootstrap); deploy/smm-setup.sh — обёртка, скачивающая релизные ассеты и дающая команды install-hub и install-node.

Правила репозитория

  • main защищён: PR обязателен, обязательны статусы build-and-test и build, force-push запрещён;
  • один PR — одна тема;
  • описание PR заполняется после завершения CI, со ссылками на конкретные прогоны;
  • отсутствие проверки не является дефектом отчёта; утверждение о проверке, противоречащее статусу CI, — является;
  • docs/release-policy.md запрещает двигать опубликованные теги и заменять ассеты: исправление выпускается следующей версией;
  • .github/workflows/linux-release.yml — единственный публикатор релизов.

Что произошло

v0.1.0-alpha.14 выпущен и содержит полный набор из 17 ассетов, включая server-monitor-manager-manifest.pem. Это первый релиз, подпись которого проверяема.

Release Verification против него упал, и это ровно тот результат, ради которого workflow писался. Он нашёл два независимых дефекта.

Дефект 1 — cosign не поставляется, установка на чистый сервер невозможна

Прогон 31894428693, шаг Run Positive Installation:

ochenstarik-server-monitor-manager.sh: OK
[ochenstarik-server-monitor-manager] Supported platform: ubuntu 24.04, x86_64
[ochenstarik-server-monitor-manager] ERROR: Required command is missing: cosign

verify_manifest в bootstrap (deploy/ochenstarik-server-monitor-manager.sh:298) вызывает require_command cosign. При этом:

  • cosign не входит в стандартные репозитории Ubuntu;
  • install_dependencies ставит только wireguard-tools nftables iproute2;
  • smm-setup.sh не упоминает cosign вообще;
  • docs/linux-bootstrap.md объясняет, зачем нужен сертификат, но нигде не говорит, откуда взять cosign.

Следствие: install-hub на чистой Ubuntu скачивает все файлы, доходит до проверки подписи и умирает. Владелец проекта не может поставить систему на свои серверы — при том, что установка «одной командой» и была смыслом PR #42.

Дополнительно, в CI отказ произошёл по смежной причине, которую тоже надо устранить: шаг Setup cosign (sigstore/cosign-installer) кладёт бинарь в каталог, который добавляется в PATH через GITHUB_PATH, а тест вызывает bootstrap через sudo, и secure_path в /etc/sudoers эту запись отбрасывает. То есть даже установленный на runner'е cosign невидим для проверяемого кода.

Дефект 2 — Release Verification никогда не запускается сам

.github/workflows/release-verification.yml объявлен с on: release: types: [published]. Релиз создаёт linux-release.yml под GITHUB_TOKEN, а события, порождённые этим токеном, по правилам GitHub не запускают другие workflow — защита от рекурсии. Прогон по alpha.14 пришлось запускать вручную через workflow_dispatch.

Механизм выглядит настроенным и не может сработать ни разу. Пункт «Release Verification отработал автоматически» в приёмке предыдущего задания был недостижим в принципе — это дефект задания, не исполнителя.


Часть 1 — обеспечить cosign

Требование: оператор на чистой Ubuntu выполняет одну команду и получает установленную систему с проверенной подписью. Ни ручной установки cosign, ни SMM_ALLOW_UNSIGNED.

Реализовать провижининг cosign в поставке:

  • закреплённая версия и закреплённая контрольная сумма на каждую архитектуру, обе константами в скрипте, а не вычисляемые на лету;
  • скачивание бинаря публичным curl с https://github.com/sigstore/cosign/releases/download/<version>/cosign-linux-<amd64|arm64>;
  • сверка sha256 с закреплённой константой до запуска бинаря; несовпадение — отказ;
  • установка в /usr/local/bin/cosign режимом 0755 (каталог входит в secure_path, поэтому cosign станет виден и под sudo);
  • если пригодный cosign уже в PATH — не трогать существующий, но проверить, что он запускается;
  • версия и её контрольные суммы записываются в docs/linux-bootstrap.md, чтобы обновление было осознанным действием, а не молчаливым дрейфом.

Где размещать вызов — ваше решение, но оно должно закрывать оба пути: короткий (install-hub / install-node в smm-setup.sh) и сквозной (preflight / verify-release в bootstrap). Второй используется в tests/acceptance/three-server-mesh.sh.

Отдельно предусмотреть отказ с внятным текстом, если скачать cosign невозможно (нет сети, недоступен github). Сообщение должно называть версию, ожидаемую сумму и путь установки — оператору должно хватить его, чтобы поставить cosign вручную.

Часть 2 — сделать проверку честной

Удалить шаг Setup cosign из .github/workflows/release-verification.yml.

Пока cosign даёт runner, тест проверяет окружение GitHub, а не поставку. После удаления шага Run Positive Installation проходит только если cosign обеспечивает сам установщик — то есть ровно в том случае, когда пройдёт и установка у оператора.

Убедиться, что негативные проверки подписи (run-negative-tests.sh) остаются работоспособны и продолжают отвергать подделанные manifest, подпись и сертификат.

Часть 3 — починить автозапуск

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

  • перевести release-verification.yml на on: workflow_run по завершении Release pipeline с фильтром по успешному завершению и по тегу — workflow_run срабатывает на завершение другого workflow и ограничением GITHUB_TOKEN не блокируется;
  • либо вынести проверку в отдельный job внутри linux-release.yml, зависящий от публикации.

Первый путь сохраняет разделение и оставляет workflow_dispatch для ручного перепрогона; второй проще, но смешивает выпуск и проверку в одном workflow. Выберите один и обоснуйте выбор в отчёте.

workflow_dispatch с параметром tag сохранить в любом случае — им перепроверяют старые релизы.

Часть 4 — выпустить v0.1.0-alpha.15

  1. До тегирования прогнать Release pipeline через workflow_dispatch на своей ветке. Шаги публикации защищены if: startsWith(github.ref, 'refs/tags/') и пропустятся, но сборка и подпись выполнятся. Пропуск этого шага уже сжёг два номера (alpha.10, alpha.11).
  2. Создать и запушить тег обычным git push — не через gh release create: релиз создаёт сам workflow по событию push: tags: v*.
  3. Убедиться, что Release Verification запустился сам и зелёный. Это главный результат задания.
  4. Тег не двигать ни при каких обстоятельствах.

Часть 5 — эргономика install-hub и install-node

Найдено живой установкой на Ubuntu 24.04, обе вещи стоили оператору прерванных попыток.

Аргументы проверяются после скачивания. Вызов install-hub ВАШ-ХОСТ 178.212.13.102 — плейсхолдер вместо адреса, IP на месте порта — прошёл проверку арности, после чего скрипт скачал 24 МБ и только потом дошёл бы до разбора значений. Валидация PUBLIC_HOST, HTTPS_PORT и WG_PORT должна выполняться до первого сетевого запроса. Отдельно отвергать очевидный плейсхолдер: значение, не являющееся ни IPv4-литералом, ни синтаксически годным DNS-именем.

Скачивание идёт молча. curl -fsSL на 24 МБ не печатает ничего, и оператор дважды принимал это за зависание и жал Ctrl+C. Показывать индикатор и имя файла: curl -fL --progress-bar -o <имя>. То же относится к любому крупному файлу, который скрипт тянет сам.

Имя install-node перекрыто. У обёртки есть своя команда install-node без аргументов, а у bootstrap — одноимённая, принимающая путь к архиву. Оператор, скачавший файлы заранее, получает install-node takes no arguments и не имеет способа догадаться, что нужен разделитель --. Либо принимать необязательный путь к архиву и, если он задан, пропускать скачивание, либо в тексте отказа прямо называть обходной путь: smm-setup.sh -- install-node ARCHIVE. Первое лучше: скачивание заново — это ещё 24 МБ поверх уже имеющихся.

Проверка подписи виснет молча и без таймаута. verify_manifest вызывает cosign verify-blob ... >/dev/null 2>&1. При медленной или частично недоступной сети cosign уходит к службам sigstore и не возвращается, а оператор видит только строку Verifying manifest signature... и не имеет ни малейшего указания, что происходит. Наблюдалось на живой машине. Требуется: не глушить вывод cosign (или сохранять его в лог и печатать при отказе), обернуть вызов в timeout с внятным сообщением по истечении, и в тексте отказа прямо называть службы, к которым нужен доступ. Отдельно задокументировать в docs/linux-bootstrap.md, что проверка подписи требует исходящего доступа к sigstore — сейчас об этом не сказано нигде, и оператор в закрытом контуре узнает это зависанием.

mesh-status печатает сырой Unix-time. Колонка HANDSHAKE показывает 1786843345. Оператор смотрит в неё ровно затем, чтобы понять, свежий ли handshake, и обязан считать это в уме. Выводить относительное время (12s ago, 3m ago) либо never, если рукопожатия не было.

Покрыть контрактным тестом: неверный порт и плейсхолдер в PUBLIC_HOST отвергаются без обращения в сеть; install-node с путём к архиву не приводит к сообщению об аргументах.

Часть 6 — записать судьбу alpha.14

В docs/release-policy.md:

  • v0.1.0-alpha.14 — первый релиз с полным набором подписи, но установка из него на чистый хост невозможна: cosign не поставляется. Проверяем, не устанавливаем;
  • v0.1.0-alpha.15 — первый релиз, устанавливаемый на чистый хост.

Границы

Antigravity ведёт проверку подписи на стороне Desktop. Не трогать: src/ServerMonitorManager.Desktop/**, tests/ServerMonitorManager.Desktop.Security.Tests/**, .github/workflows/windows-build.yml.

Ваша область: deploy/**, .github/workflows/linux-release.yml, .github/workflows/release-verification.yml, tests/release-verification/**, tests/bootstrap/**, docs/linux-bootstrap.md, docs/release-policy.md.

Критерий приёмки

  • cosign обеспечивается поставкой; закреплены версия и контрольные суммы обеих архитектур;
  • подделанная контрольная сумма cosign даёт отказ — покрыто тестом;
  • шаг Setup cosign из release-verification.yml удалён;
  • Release Verification по v0.1.0-alpha.15 запустился по событию, без workflow_dispatch, и зелёный; ссылка на прогон в отчёте;
  • workflow_dispatch с параметром tag продолжает работать; ссылка на прогон по произвольному тегу;
  • install-hub и install-node доводят установку до конца на хосте без cosign;
  • неверные аргументы отвергаются до первого сетевого запроса; крупные загрузки показывают индикатор;
  • SMM_ALLOW_UNSIGNED не используется ни в одном новом пути и остаётся тем, чем был — аварийным флагом;
  • workflow_dispatch-прогон Release pipeline выполнен до тегирования, ссылка в отчёте;
  • судьба alpha.14 записана в docs/release-policy.md;
  • всё через PR, CI зелёный, PR не смержен до зелёного.

Отчёт

Раздельно: что проверено локально, что в CI со ссылками на прогоны, что не проверялось и почему.

Физическая приёмка на реальных серверах в задание не входит — её выполняет владелец после выпуска релиза.