server-monitor-manager/docs/integration-kagent.md
Ochenstarik 4de849e3bf docs: add product horizons, approval policies and KAgent integration spec
Adopt the reviewed parts of the external vision document as repository
specifications, and record the work-order gates that keep unimplemented
subsystems from starting before their prerequisites are closed.

- product-horizons.md: four horizons with hard exit criteria; Horizon 0
  closes physical acceptance, signed delivery, the Monitor role and
  certificate rotation before anything new begins.
- approval-policies.md: nine approval modes over the existing binary
  confirmation, mapped onto ProvisioningJob, TTL and execution grants.
- integration-kagent.md: capability model split into read, request and
  never-grantable; untrusted-executor invariant for KAgent Worker;
  SO_PEERCRED on the discovery socket; API designed against entities
  that exist today.
- security-model.md: untrusted executors on a Node, the public web
  surface decision that must be recorded before that work starts, and
  never-grantable capabilities.
- roadmap.md: stages 14-18 for the adopted scope, pinned to horizons.

All three new documents state that nothing in them is implemented.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 18:31:09 +07:00

11 KiB
Raw Permalink Blame History

Интеграция с KAgent

Статус: спецификация. Ничего из описанного не реализовано. Работы разрешены после закрытия Горизонта 1 — см. горизонты продукта.

Принцип

KAgent — внешняя AI-система. Она просит, Server Monitor Manager решает и исполняет. Никакая часть интеграции не даёт KAgent исполнения на хосте: запрос от KAgent порождает обычный typed provisioning job с immutable plan, режимом подтверждения из политик, execution grant, factual verification, audit и rollback. Отдельного быстрого пути для AI не существует.

SMM обязан полностью работать без KAgent. Недоступность KAgent не влияет на мониторинг, Links, provisioning, alerts, backups и аудит.

Инвариант недоверенного исполнителя

Это главное требование раздела. KAgent Worker — процесс, исполняющий произвольный код по построению: сборка репозитория запускает его build-скрипты. Worker считается недоверенным субъектом, и изолируется он от control plane, а не только от внешней сети.

Из инварианта следуют обязательные условия установки Worker на Node:

  • отдельный системный пользователь без sudo, отдельные каталоги, отдельный cgroup;
  • нет доступа к сокету provisioning-helper /run/ochenstarik-server-monitor-manager/provisioning.sock; членство в группе ochenstarik-smm-agent запрещено;
  • нет доступа к agent.pfx, control-ca.crt, agent.env, nodes.tsv, каталогу mesh и каталогу rollback;
  • нет сетевого доступа к Control API и к порту Control;
  • исполнение в контейнере: read-only rootfs, seccomp, AppArmor, сброшенные capabilities, ограничение pids;
  • системные лимиты (CPUQuota, MemoryMax, TasksMax, IOWeight) дополняют изоляцию, но не заменяют её;
  • порт Worker не публикуется наружу.

Компрометация Worker не должна давать ни управления Node, ни доступа к другим Node, ни возможности создать Link.

Модель возможностей

Три класса, а не два.

Чтение. Не меняет состояние.

infrastructure.nodes.read
infrastructure.metrics.read
infrastructure.alerts.read
infrastructure.links.read
infrastructure.jobs.read
infrastructure.drift.read
infrastructure.services.read      (после Горизонта 1)
infrastructure.containers.read    (после Горизонта 1)
infrastructure.logs.read          (после Горизонта 2)
infrastructure.backups.read       (после Горизонта 1)

Запрос. Создаёт предложение, которое проходит обычный конвейер подтверждения. Само по себе ничего не меняет.

infrastructure.diagnostics.request
infrastructure.link.plan
infrastructure.link.request
infrastructure.provisioning.plan
infrastructure.provisioning.request
infrastructure.backup.request
infrastructure.service.restart.request
infrastructure.remediation.request

Невыдаваемые. Не «выключены по умолчанию», а отсутствуют как код в пути KAgent-идентичности. Их нельзя включить настройкой.

root.execute
ca.rotate
secrets.read
audit.disable
firewall.apply          (доступен только через .request с режимом operator_reauth)
users.modify            (доступен только через .request)
node.delete

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

Идентичность

Отдельная роль KAgentIntegration, связанная с installation ID, организацией, списком разрешённых Nodes, набором возможностей, сроком действия, отпечатком сертификата и состоянием отзыва. Выдаётся по одноразовому token, как остальные identity. Не наследует прав Operator и не может выдавать себе новые возможности.

Локальное обнаружение

/run/server-monitor-manager/integration.json
/run/server-monitor-manager/integration.sock

Права root:smm-integrations, 0640, каталог 0750.

Членства в группе недостаточно. Сокет обязан повторить меры, уже реализованные в ProvisioningHelperServer:

  • проверка SO_PEERCRED со сверкой uid обращающегося процесса;
  • обработка соединения вне цикла accept, ограничение параллелизма;
  • таймаут на соединение целиком;
  • чтение буфером с ограничением размера запроса;
  • ограничение частоты запросов и отдельный счётчик неавторизованных попыток.

Протокол

KAgent-SMM Integration Protocol v1

Handshake:

{
  "client": "kagent",
  "client_version": "0.8.0",
  "protocol_versions": ["1.0", "1.1"],
  "requested_capabilities": ["nodes.read", "metrics.read", "jobs.plan"]
}

Ответ содержит выбранную версию протокола и фактически выданные возможности, которые могут быть уже запрошенных:

{
  "server": "server-monitor-manager",
  "server_version": "0.2.0",
  "selected_protocol": "1.1",
  "granted_capabilities": ["nodes.read", "metrics.read"]
}

Версия сервера в ответе — реальная версия сборки. Неизвестные поля запроса отклоняются, неизвестные версии протокола не согласуются.

Поверхность API

Проектируется против того, что существует. Эндпоинты для сущностей, которых в системе нет (containers, services, logs, backups), добавляются вместе с самими сущностями, а не заранее.

Первый этап:

GET  /api/v1/integrations/capabilities
GET  /api/v1/integrations/version
GET  /api/v1/kagent/nodes
GET  /api/v1/kagent/nodes/{id}
GET  /api/v1/kagent/nodes/{id}/metrics
GET  /api/v1/kagent/nodes/{id}/health
GET  /api/v1/kagent/events

Второй этап, после появления соответствующих модулей:

POST /api/v1/kagent/links/plan
POST /api/v1/kagent/links/request
GET  /api/v1/kagent/links/{id}
POST /api/v1/kagent/links/{id}/disable-request
POST /api/v1/kagent/jobs/plan
POST /api/v1/kagent/jobs/request
GET  /api/v1/kagent/jobs/{id}
POST /api/v1/kagent/jobs/{id}/cancel-request
POST /api/v1/kagent/diagnostics
GET  /api/v1/kagent/diagnostics/{id}

Любая мутация требует idempotency key и audit reason. *.request возвращает идентификатор задания, а не результат: результат наступает после подтверждения человеком.

Обязательные поля: source, destination, протокол, порт, TTL, идентификатор задачи, причина, версия политики, владелец, режим подтверждения.

Ограничения:

  • destination не может быть Hub;
  • destination не может быть другим Worker;
  • TTL обязателен и ограничен сверху; Link без TTL для задачи не создаётся;
  • снятие выполняется по завершении задачи, отказу, таймауту, уходу Worker в offline, истечению аренды или аварийной остановке;
  • снятие проверяется фактически, как и любая другая Link-операция.

События

SMM передаёт versioned infrastructure events и не становится внутренней очередью KAgent:

node.online
node.offline
metric.threshold
link.active
link.disabled
provisioning.started
provisioning.completed
provisioning.failed
certificate.expiring
backup.failed
worker.resource_exceeded
worker.quarantined

Аварийные средства

Operator может в любой момент, без участия KAgent: отозвать сертификат интеграции, остановить все Worker, отключить задачные Links, заблокировать новые запросы, перевести интеграцию в режим только чтения, прекратить аренды, поместить Worker в карантин, отключить его сеть. Журналы для разбора сохраняются.

Поведение при отказе

Недоступность KAgent не влияет на работу SMM. Задание с неопределённым результатом получает NeedsReconciliation; после восстановления связи проверяется фактическое состояние, а не предполагается успех.

Вне области

  • root shell в любой форме;
  • выдача приватных ключей и содержимого секретов;
  • изменение или отключение аудита;
  • произвольные правила firewall;
  • прямое управление пользователями без конвейера подтверждения;
  • превращение SMM в очередь задач или планировщик KAgent.