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

151 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Codex: cosign в поставке и работающий автозапуск проверки релиза → `v0.1.0-alpha.15`
Задание самодостаточно: истории работы по этому репозиторию у вас нет, всё нужное ниже.
## Репозиторий
- https://github.com/ochenstarik-ui/server-monitor-manager
- База: `main` @ `0405b0b` (merge PR #42)
- Ветка: `codex/cosign-provisioning`
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](https://github.com/ochenstarik-ui/server-monitor-manager/actions/runs/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 со ссылками на прогоны, что не проверялось и почему.
Физическая приёмка на реальных серверах в задание не входит — её выполняет владелец после выпуска релиза.