Files
obsidian-vault/personal/projects/balda/ssh-permissions-2026-10-19.md
T

58 lines
11 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.
# SSH Manager — постоянные и разовые права
Проверено и развёрнуто: 2026-10-19 22:19 UTC+6 (Asia/Bishkek).
SSH Manager **0.4.0**, implementation commit `d2806ac150363712b8baa9c40dbd37f2946b8c13`. Рабочее дерево чистое при сборке, `vcs.modified=false`. Активный binary SHA256 `536d389a4261e186fce8dfabe4a3adfe605d190d84ef188cdf105c3e8ee079bd`, inode работающего процесса совпадает с установленным файлом. HTTP MCP `127.0.0.1:17796/mcp` отдаёт **13 инструментов**.
Balda остаётся на чистом upstream `138cc4a71d6889de30fe90e368f27f129fd8d792`, binary SHA256 `31c448af84428f83491d5fb8317549466f814f51c453de11fc8f6c9bd0836672`. Каталог/кэш MCP обновлён штатным перезапуском: `2026-10-19T16:15:26.785581969Z`. Config/env/mounts, OAuth login, SSH inventory и ключи сохранены; health/login 200, Mattermost websocket подключён. Все 49 runtime sessions и metadata, 28 questions, 2 users/bindings и 24 archive sessions из остановленного snapshot сохранены. Workspace Manager не менялся.
## Что исправлено
В [разобранном треде](https://mm.qentra.top/qentra/pl/skeyf33mx3f6tcnmx11qukgs5r) штатный ключ уже работал, но bubblewrap закрывал сеть хоста, Docker socket и sudo. Модель попыталась использовать sandbox-доступ Mac как административный и запустить вложенный `ssh kraken`; он завершился DNS-ошибкой. Прав не поменялось. У менеджера тогда отсутствовало API изменения профиля. Сбой произошёл до обновления Balda на upstream.
Теперь изменения выполняются через SSH Manager существующим операторским bootstrap-доступом, без передачи его ключей агенту и без хардкода хоста. Менеджер не получил инструмент произвольного выполнения команд: он выдаёт разрешение и native SSH-команду, которую запускает клиент своим установленным ключом.
## Права
- `network`: сеть хоста вместо отдельного Linux network namespace; на Mac — IP networking через Seatbelt.
- `read_paths` / `write_paths`: конкретные канонические пути. Manager control state, личные SSH credentials, системные корни и каталоги с socket-файлами не выдаются обычным файловым grant. Linux использует проверенные открытые FD для bind mounts.
- `docker`: `none`, `read` или `manage`. Read разрешает просмотр/логи/инспекцию, но не изменения. Docker CLI работает с фиксированным локальным daemon endpoint и закрытым control HOME/config; socket не появляется в sandbox.
- `admin`: прямой `sudo` с уже существующими noninteractive правами оператора. Sudoers не изменяется. Native timeout запускается с теми же привилегиями, чтобы остановить обычную root-команду.
`docker=manage` и произвольный sudo могут обойти файловые/сетевые ограничения; форма подтверждения сообщает об этом. Это отдельные явно разрешённые исключения. Завершение вызова не откатывает его побочные эффекты и не обещает отозвать намеренно оставленную привилегированную работу.
## Постоянное изменение
1. `ssh_permissions` возвращает профиль и revision.
2. `ssh_permissions_update`: полный новый профиль плюс `expected_revision`.
3. Native owner form показывает before/after; затем выполняются реальная приёмка изоляции, CAS только managed key line и SSH-проверка из настроенного клиента. Ключ и маршрут сохраняются.
4. Ошибка активации/проверки восстанавливает и проверяет прежний профиль либо явно сообщает, что rollback не подтверждён.
Новые вызовы используют новый профиль. Старые запущенные процессы не завершаются; неиспользованные разовые допуски инвалидируются. Действующие production `mac` и `kraken` пока возвращают `managed=false`: их прежние принятые ограничения при deployment не заменялись. Первый переход на управляемый профиль — отдельное явное `ssh_permissions_update` с owner confirmation, выполняемое самой Balda через MCP; ручная настройка JSON/хоста не требуется.
## Разовый вызов
`ssh_call_request` принимает хост, точный argv и только временные overrides профиля. Например: command `["docker","ps","-a"]`, permissions `{"docker":"read"}`.
Одно owner confirmation связывает хост, argv, эффективные права и сроки. Затем Balda запускает возвращённый `ssh_command` своим установленным ключом. Сервер атомарно потребляет id **до запуска**, включая ошибочные вызовы; повтор/гонка второго подключения не дают второго запуска. Argv исполняется буквально, stdin закрыт. Start TTL 1–900 секунд (default 300), runtime 1–600 секунд (default 60). Часы — общесистемные на целевом хосте, включая macOS system Python.
`ssh_call_status` читает серверную квитанцию; issued не означает выполнение, consumed без result не означает, что процесс ещё работает. Успех — finished и exit_code 0 после реального SSH. `ssh_call_cancel` подтверждённо отменяет неиспользованный допуск, но не останавливает запущенную команду. Изменение профиля и revoke не воскрешают старые разрешения при повторной регистрации.
Постоянный профиль при разовом вызове не меняется. Штатная политика Balda для запуска локальной SSH-команды остаётся отдельным уровнем; SSH grant не выключает её. Старые диалоги с кэшированной MCP schema обновляются обычной новой сессией / `/reset`; история автоматически не сбрасывалась.
## Проверено
- Go race и vet, diff --check — pass.
- Native macOS + MCP + временный sshd: **22 проверки**, включая отказы, stale revision, rollback после сбоя SSH-проверки, буквальный argv, закрытый stdin, race двух соединений, consumption после ошибки, TTL/timeout/cancel, постоянные file/network права и отзыв/re-authorize.
- Linux strict bubblewrap в Colima: **10 проверок**, в том числе Docker read/manage отдельно, отказ управления при read, sudo от **обычного пользователя** с получением host root и остановка root-команды по тайм-ауту. Kernel/AppArmor/proc protection не ослаблялись. Временный Docker volume удалён.
- Прежний native lifecycle произвольных хостов/ProxyJump/pin/restart/revoke/remove: **14 проверок**.
- Реальная модель в работающей Balda: session `01a154e9-5b6a-7a32-ae5b-d5efcdc03ca6`. Постоянный update → one-call → проверка серверной квитанции → восстановление профиля. Ровно 3 native owner forms для этих 3 изменений, без generic MCP approval. Harness выполнил pinned native SSH из реального контейнера UID 1000 установленным **временным fixture-ключом**; успех подтверждён, повтор запрещён, исходная сеть восстановлена.
- После deployment свежий Codex ACP вызвал новый `ssh_permissions` на production Mac/Kraken: session `01a154f0-1bb2-7932-aa2d-cf2907fc4ed0`, **0 подтверждений**. Это read-only проверка установленного API, без миграции профилей.
- После перезапуска Balda прежние production-ключи к Mac и Kraken ещё раз проверены native SSH из настоящего UID 1000 Balda; оба вернули случайный marker.
Тесты используют случайные aliases/порты, временные ключи и отдельные private пути. Тестовые сообщения в Mattermost не отправлялись. Никакие bootstrap keys/passwords не передавались модели или в agent volume.
Evidence: `/Users/admin/.local/share/balda-workspace/candidate/ssh-permissions-20261019`. Backup менеджера: `/Users/admin/.local/share/balda-workspace/backups/ssh-permissions-20261019T161039Z`. Согласованный state backup Balda: `/Users/admin/.local/share/balda-workspace/backups/ssh-permissions-balda-20261019T161515Z`. Backup изменённых заметок: `/Users/admin/.local/share/balda-workspace/backups/obsidian-ssh-permissions-20261019T221941+0600`.
Исходники и contract: `/Users/admin/Developer/ssh-manager/README.md`, `docs/permissions-2026-10-19.md`. Текущий setup: [[personal/projects/balda/setup]]. План: [[personal/plans/balda-remote-agent]].