# Antigravity: довести сертификаты до PR и разобрать dependabot ## Состояние - `main` @ `80b4797` — содержит `fix(enrollment): repair node enrollment path (#24)` от Hermes; - ветка `antigravity/cert-lifecycle` @ `9d2fe1c` — CI зелёный, с `main` сливается без конфликтов, PR не открыт; - открыто шесть PR от dependabot: #18–#23. --- ## Часть 1 — доделать `antigravity/cert-lifecycle` Работа принята по существу: `ClientCertificateDays` в `ControlOptions` с умолчанием 30 и сохранённым `[DynamicDependency]`, `AddYears(1)` заменён на `AddDays(...)`, автопродление Agent при остатке меньше трети с сохранением работы при недоступном Hub, событие `certificate.expiring`, `docs/certificate-rotation.md`, все семь обязательных тестов, 101 тест зелёный. Границы соблюдены — ни одного файла из области Hermes. Осталось пять пунктов. ### 1.1. Ребейз на текущий `main` Ветка сделана до merge #24. Конфликтов нет, но база должна быть актуальной: #24 менял привязку конфигурации Agent, а ваша работа трогает `AgentClient.cs`. ### 1.2. Убрать `TEST_EVIDENCE.md` из репозитория Файл закоммичен в корень. Отчёт — артефакт PR, а не содержимое репозитория. Перенести содержимое в описание PR, файл удалить из ветки. ### 1.3. Проверка на trimmed-артефакте по production-пути Сделано было так: ``` dotnet publish ... -r win-x64 --self-contained -p:PublishTrimmed=true .\ochenstarik-smm-control.exe --Control:ClientCertificateDays 999 ``` Это командная строка на `win-x64`. В проде конфигурация приходит **переменными окружения** из `control.env` через `EnvironmentFile=` в systemd-юните, на **linux-x64**. Сломанным под триммингом был именно env-путь — в `AgentOptions` не оказалось `[DynamicDependency]`, и Agent молча брал умолчания. Повторить проверку так, как оно работает в бою: ```bash dotnet publish src/ServerMonitorManager.Control/ServerMonitorManager.Control.csproj \ -c Release -r linux-x64 --self-contained -p:PublishTrimmed=true -p:PublishSingleFile=true -o /tmp/ctl Control__ClientCertificateDays=999 /tmp/ctl/ochenstarik-smm-control ``` Ожидается отказ старта с ошибкой валидации. Если сервис стартует — значение не дошло, и настройка в проде работать не будет. Дополнительно проверить обратное: валидное значение из переменной окружения действительно применяется к выпускаемому сертификату, а не подменяется умолчанием 30. Например `Control__ClientCertificateDays=45`, выпустить сертификат, посмотреть `notAfter`. Вывод обеих проверок приложить к PR. ### 1.4. Убрать дублирующий эндпоинт продления В `Control/Program.cs` появились два пути продления: - `agents.MapPost("/certificate/renew")` — в группе с `RequireAuthorization("Agent")`, всё правильно; - `app.MapPost("/api/v1/certificates/renew")` — без `RequireAuthorization`, отсекает чужих случайной проверкой на пустой `entityId` и разветвляется по claim роли внутри. Второй ведёт себя fail-closed, но держится не на конвейере авторизации, а на том, что у неаутентифицированного запроса не окажется claims. Это не соглашение проекта: рядом в том же файле все защищённые эндпоинты объявлены через группы с политикой. Выбрать одно: - **предпочтительно** — удалить `app.MapPost("/api/v1/certificates/renew")`, оставив продление Agent в группе `agents`, а продление Operator добавить в группу `control` с `RequireAuthorization("Operator")`; - либо оставить один общий эндпоинт, но объявить его через группу с политикой, требующей аутентифицированную identity, и разветвление по роли выполнять уже внутри. Добавить тест: запрос на продление **без клиентского сертификата** отклоняется, и отклоняется конвейером, а не обработчиком. ### 1.5. Открыть PR После пунктов 1.1–1.4. Описание PR заполнять **после** завершения CI, со ссылками на конкретные прогоны. --- ## Часть 2 — dependabot, отдельным PR каждый Шесть открытых PR. Сливать пачкой нельзя: три из них меняют то, от чего зависит воспроизводимость и цепочка поставки. ### 2.1. Безопасные — слить после зелёного CI - **#22** `Microsoft.NET.Test.Sdk` 18.0.1 → 18.8.1; - **#19** `actions/setup-dotnet` 5.4.0 → 6.0.0; - **#18** `softprops/action-gh-release` 2.6.2 → 3.0.2. Для двух последних убедиться, что dependabot заменил SHA, а не вернул плавающий тег: инвариант «ни одного плавающего тега в `uses:`» из PR #14 должен сохраниться. Проверять на каждом PR: ```bash grep -rn 'uses:.*@v[0-9]' .github/workflows/ && echo "НАЙДЕН ПЛАВАЮЩИЙ ТЕГ" || echo "все запинены" ``` `action-gh-release` 3.0.x — мажорный скачок, посмотреть changelog на предмет изменения имён входных параметров: он используется в release-workflow, а те **не запускаются на pull request**, поэтому CI поломку не покажет. Это ровно тот класс дефектов, что вы уже ловили в PR #14 с `permissions`. Проверять `actionlint`, а не полагаться на зелёный PR. ### 2.2. Требуют внимания - **#21** `actions/checkout` 6.1.0 → 7.0.1 и **#20** `actions/upload-artifact` 6.0.0 → 7.0.1 — мажорные. `upload-artifact` v7 может менять поведение при отсутствии файлов и формат имён артефактов; в `linux-release.yml` и `windows-release.yml` от имён артефактов зависит сборка релиза. Проверить, что после обновления релизные ассеты собираются с теми же именами: их знает установщик `smm-setup.sh` и bootstrap. ### 2.3. Не сливать без отдельной проверки - **#23** `SQLitePCLRaw.bundle_e_sqlite3` 2.1.12 → **3.0.5**. Это мажорное обновление нативной библиотеки под SQLite, на которой держится вся база Control: enrollment, identities, links, provisioning, audit. Требуется: - прогон полного Control suite на Linux, не только на Windows; - проверка миграций на **существующей** базе: взять `control.db`, созданную текущей версией, открыть новой сборкой, убедиться, что `PRAGMA user_version` и данные читаются; - проверка `backup-create` и `backup-restore` на этой же базе; - проверка, что self-contained trimmed-публикация под `linux-arm64` не ломается — нативные библиотеки в trimmed single-file собираются иначе, чем под x64. Если хоть одна проверка не выполнена, PR не сливать и написать это прямо. Обновление некритично и подождёт. --- ## Порядок Часть 1 → 2.1 → 2.2 → 2.3. Сертификаты первыми: это пункт Горизонта 0, а обновления зависимостей подождут. ## Отчёт Раздельно: что проверено локально, что в CI со ссылками, что не проверялось и почему. По части 2 — по каждому PR отдельной строкой с вердиктом «слит / отложен / отклонён» и причиной.