# Оценка документа «Полные доработки и интеграция с KAgent»

Оценивается против фактического состояния `main` @ `b11c277` (+ незакоммиченный B-3R).

---

## 1. Общий вердикт

Документ качественный по содержанию и неверный по калибровке.

**Что в нём хорошо.** Он написан на языке, который проект уже установил: desired/factual state, typed provisioning, immutable plan, execution grant, deny-by-default, `NeedsReconciliation`, emergency recovery, capability model. Это не наивный список желаний — автор понимает модель безопасности SMM и почти нигде её не нарушает. Пункт 42 ставит физический acceptance первым приоритетом, что ровно соответствует тому, что блокирует проект четвёртый блок подряд.

**В чём проблема.** Это не «доработки». Это спецификация другого продукта, примерно в 5–10 раз больше существующего, поданная как список улучшений — без разделения на «следующий релиз» и «когда-нибудь», без единого упоминания того, что уже начато и не закончено, и без признания одного факта: **provisioning-движок сегодня выполняет ровно одно мутирующее действие — смену таймзоны**, и то с жёстким гейтом `IsTimezoneOnly`, который отвергает всё остальное.

Для сопоставления масштабов: в документе 21 provisioning-действие, 6 VPN-модулей, полноценный Web UI с паролями, TOTP, WebAuthn и RBAC, централизованные логи, Secret Vault, Backup Manager с четырьмя типами хранилищ, multi-Hub с защитой от split-brain и весь слой KAgent с протоколом, capability-моделью и жизненным циклом Worker'ов. Существующая кодовая база — около 5 тысяч строк C# — потребовала двенадцати PR, чтобы дойти до двух provisioning-действий, из которых одно read-only.

Отдельно: в существующем ТЗ `docs/provisioning-vpn-requirements.md` этапы 9–13 не начаты вообще. Новый документ не отменяет их и не ссылается на них — он кладётся сверху.

---

## 2. Что пропущено, хотя уже в работе

Это самое серьёзное замечание к документу: он не упоминает ни один из открытых пунктов, от которых зависит всё остальное.

| Пропущено | Почему это блокирует документ |
|---|---|
| **Подписанная поставка (Блок C)** | Каждый Node обновляется из release-архива, а bootstrap сверяет хэш с файлом, лежащим рядом в том же релизе. Кто может опубликовать релиз, тот ставит произвольный root-код на весь парк. Документ добавляет установку KAgent Worker'ов и шесть VPN-модулей — то есть увеличивает поверхность поставки, не закрыв её. |
| **Роль Monitor в bootstrap** | SSH-мониторинг — флагманская функция Desktop — не имеет серверной части: нет `install-monitor`, нет forced-command скрипта, нет создания пользователя. Документ строит поверх мониторинга alert engine, Docker, systemd и security posture. |
| **Физический acceptance** | Не выполнялся ни разу за четыре блока. Пункт 42 его называет, но не как гейт, а как первый пункт списка. |
| **Ротация сертификатов** | Клиентские сертификаты живут год, автопродления нет. Документ добавляет ещё одну identity (`KAgentIntegration`) с собственным сроком и revocation state. |
| **Доверенная подпись Windows MSIX** | До сих пор test-signed. |

Любой из этих пунктов дешевле любого раздела нового документа и является для него предусловием.

---

## 3. Конкретные архитектурные возражения

### 3.1. Web UI ломает текущую модель угроз, и это не отмечено (§3, §17)

Вся конструкция SMM держится на трёх утверждениях: у Node нет публичного API, Control доступен только по mTLS, порт Control не должен быть открыт без ограничений firewall. README говорит это прямым текстом.

Раздел 3 вводит браузерный HTTPS-интерфейс с email + паролем на том же Hub. Это ровно тот публичный аутентифицируемый surface, от которого проект отказался. Плюс появляется вторая система идентичности: mTLS-сертификаты устройств (поток `SMMDEV1`) и веб-сессии должны как-то согласовываться в RBAC — в документе об этом ни слова.

Если Web UI нужен, требуется явно решить: отдельный listener и порт, отдельная цепочка сертификатов, обязательный reverse proxy, rate limiting, CSRF, привязка сессии к устройству, и правило, что операции класса «firewall / CA / удаление Node» доступны **только** по mTLS-идентичности, а не по веб-сессии. Иначе компрометация пароля даёт то, чего не давал даже Operator-сертификат.

### 3.2. Централизованные логи не лягут на текущее хранилище (§8)

Модель хранения сегодня — SQLite с retention по `metric_samples`. Логи journald + Docker + nftables + SSH + reverse proxy со всех узлов — это другой порядок объёма. «Search, filters, retention, correlation» поверх SQLite на Hub с одним диском не работает; заодно раздувается Control DB, а с ней и все резервные копии, которые документ же требует шифровать и проверять восстановлением.

Нужно принять решение явно: либо отдельное хранилище, либо выгрузка вовне, либо только tail на узле без центрального retention. Сейчас раздел написан так, будто это ещё одна таблица.

### 3.3. KAgent Worker — самая опасная функция документа, и её инвариант не сформулирован (§30–32, §36)

Суть: внешняя AI-система просит SMM установить на сервер runtime исполнения кода и открыть к нему сетевой путь. `allowed_capabilities: git.clone, code.build, code.test` означает **произвольное исполнение кода по построению** — сборка репозитория запускает его build-скрипты.

Документ делает многое правильно: Operator approval в жизненном цикле (§31), лимиты ресурсов (§36), emergency controls (§35), карантин. Но нигде не сказано главное:

> Worker недоверенный. Он изолируется не от внешнего мира, а от control plane.

Отсюда конкретные требования, которых в документе нет: Worker не имеет доступа к сокету provisioning-helper, к сертификатам Agent, к `nodes.tsv` и к Control API; работает в отдельном network namespace; временные Links (§32) **никогда** не могут иметь destination = Hub или другой Worker; лимиты систем­ные (`CPUQuota`, `MemoryMax`) не заменяют seccomp/AppArmor/read-only rootfs, а дополняют их.

Это не придирка: сейчас provisioning-helper слушает Unix-сокет с правами `0660 root:ochenstarik-smm-agent`, и в B-2 пришлось добавлять `SO_PEERCRED`, потому что членства в группе оказалось недостаточно. Worker на той же машине — новый локальный субъект рядом с этим сокетом.

### 3.4. «Denied by default» для части возможностей должно быть «never grantable» (§28)

Список `firewall.apply, users.modify, ca.rotate, node.delete, secrets.read, root.execute` назван «denied by default» — формулировка подразумевает, что их можно включить. Для `ca.rotate`, `root.execute` и `secrets.read` это должно быть архитектурным запретом, а не настройкой: соответствующий код просто не должен существовать в пути KAgent-идентичности.

Прецедент в проекте уже есть и он правильный: Automation-сертификат физически не может мутировать Links — не «по умолчанию», а вообще. Ту же строгость нужно перенести сюда.

### 3.5. Discovery-сокет повторяет решённую проблему (§26)

`/run/server-monitor-manager/integration.sock` с правами `0640 root:smm-integrations` — та же схема, что у provisioning-helper. И тот же дефект, если не оговорить: членства в группе недостаточно, нужна проверка `SO_PEERCRED` с фиксацией ожидаемого uid, таймаут соединения, ограничение параллелизма и rate limit. Всё это уже написано в `ProvisioningHelperServer` — переиспользовать, а не изобретать заново.

### 3.6. Шесть VPN-модулей вместо одного доведённого (§16)

WireGuard, AmneziaWG, Xray Reality, Hysteria2, TUIC, Shadowsocks — каждый со своим preflight, install, update, disable, verify, rollback, kill switch, routing exclusions, reboot-тестом и ротацией секретов. В существующем ТЗ был один Xray, и он не начат.

Шесть наполовину сделанных VPN-модулей хуже, чем ноль: каждый — это правила маршрутизации и kill switch, то есть потенциальная потеря доступа к серверу. Довести один до физической приёмки, и только потом обсуждать второй.

### 3.7. Multi-Hub: фаза 1 разумна, фазы 2–3 преждевременны (§15)

«Backup DB/CA, encrypted storage, restore verification, manual failover» — по сути уже почти есть (`backup-create` / `backup-restore` и проверенные архивы). Реплика­ция, split-brain protection и кворум для двух Hub'ов с общим CA — это отдельный сложный проект, который не имеет смысла до физической приёмки одного Hub'а.

### 3.8. AI diagnostics и remediation должны идти через тот же конвейер (§22, §25)

Раздел 22 корректен как read-only совет. Но §25 говорит, что SMM принимает от KAgent запросы на `remediation` — и вот здесь нужно явно: любой такой запрос порождает обычный typed provisioning job с immutable plan, execution grant, подтверждением Operator'а и factual verification. Никакого отдельного «быстрого пути для AI». Формально это следует из §10, но написано недостаточно жёстко для функции, которая будет соблазнять сделать исключение.

### 3.9. Версии в примерах не соответствуют реальности (§29, §40)

`"version": "1.4.0"` при фактическом `v0.1.0-alpha.5`. Мелочь, но она задаёт неверную рамку: документ читается как описание существующей системы, хотя описывает желаемую. В протоколе интеграции версии — это контракт, и путать их нельзя.

---

## 4. Что в документе просто хорошо

- **Пункт 42** — приоритеты расставлены здраво, и физический acceptance стоит первым. Это правильно и совпадает с тем, что я пишу четвёртый блок подряд.
- **§10 provisioning catalog и §11 desired/factual** — прямое и корректное продолжение существующей модели, без изобретения новых механизмов.
- **§18 approval policies** — режимы `none / operator / re-auth / owner / two-person / time-window / emergency-only` это то, чего сейчас не хватает: сегодня подтверждение бинарное. Хорошая и недорогая идея.
- **§35 emergency controls** и **§39 поведение при недоступном KAgent** — правильный fail-safe: SMM продолжает работать без AI-слоя, неопределённый результат уходит в `NeedsReconciliation`. Это ровно та дисциплина, которую проект уже соблюдает.
- **§28 capability model** структурно верна: разделение `.read` и `.request` означает, что KAgent не исполняет, а просит. Это единственно правильная форма интеграции с AI-системой.
- **§5 формат alert rule** и **§18 формат политик** — компактные, версионируемые, пригодны как есть.

---

## 5. Рекомендация по структуре работ

Разбить на горизонты с жёсткими гейтами. Переход к следующему горизонту запрещён до закрытия предыдущего.

### Горизонт 0 — закрыть начатое (ничто новое не стартует)

- B-3R до merge, Linux CI, зелёный PR;
- **физический acceptance** на реальной тройке — снимает блокер, висящий четыре блока;
- Блок C: подписанный manifest, проверка совместимости версий, пиннинг Actions;
- роль Monitor в bootstrap — иначе флагманская функция не устанавливается;
- ротация и срок жизни сертификатов.

### Горизонт 1 — сделать продукт пригодным для одного владельца

- provisioning: `locale`, `packages`, `swap`, `user.create/disable`, `ssh.key.add/remove` — по одному модулю через уже готовый каркас;
- firewall editor и двухфазная миграция SSH (этап 10 существующего ТЗ, самая опасная и самая ценная часть);
- alert engine + Telegram **только на чтение** (`/status`, `/servers`, `/alerts`);
- Docker и systemd — сначала read-only наблюдение, действия позже;
- Backup Manager: local + S3, расписания, проверка восстановлением.

### Горизонт 2 — платформа

- Web UI и вся аутентификация, с явным решением по §3.1;
- Secret Vault (он же предусловие для Telegram-токена, S3-ключей и VPN-подписок);
- централизованные логи с принятым решением по хранилищу;
- security posture;
- multi-Hub фаза 1;
- **один** VPN-модуль до физической приёмки.

### Горизонт 3 — KAgent

Только после Горизонта 1, и вот почему: безопасность всего слоя KAgent держится не на коде KAgent, а на том, что typed provisioning, approval, audit, execution grant и factual verification **реально работают**. Сегодня они работают для одной таймзоны. Строить поверх них установку удалённых исполнителей кода — значит проверять эту машинерию сразу на самом опасном сценарии.

Внутри горизонта порядок из §42 (пункты 8 → 9) правильный: сначала discovery, identity, чтение Nodes и метрик, и только потом Worker lifecycle.

Отдельно: §25 обещает KAgent'у доступ к Docker, services, backups, drift, capacity и security posture — ничего из этого не существует. API для KAgent нельзя проектировать против несуществующих данных; спроектировать нужно против того, что есть (nodes, metrics, links, jobs), и расширять по мере появления.

---

## 6. Итог

Документ стоит сохранить как **целевое видение продукта**, но нельзя использовать как план работ: в нём нет ни одного гейта, он не упоминает незакрытое и уравнивает по важности физическую приёмку WireGuard и мониторинг GPU.

Практический вывод: взять из него §18 (approval policies), §28 (capability model), §35 (emergency controls) и §42 (приоритеты) — это готовые к применению вещи. Остальное разложить по горизонтам выше и вернуться к разделу KAgent после того, как хотя бы пять provisioning-модулей и миграция SSH пройдут физическую приёмку.

И до всего этого — выдать topology inputs и прогнать `SMM_ACCEPT_RESTORE=1 SMM_ACCEPT_REBOOT=1 tests/acceptance/three-server-mesh.sh`. Это по-прежнему единственное, что не может сделать исполнитель, и оно дешевле любого раздела этого документа.
