33 KiB
Balda — удалённый агент по SSH
2026-10-18 — исправлены MCP approvals и ответы 1
Лишний MCP tool-call approval убран в активных Codex-профилях штатным флагом моста --mcp-approval-policy=allow. Режим Balda остаётся ask. Точные подтверждения Workspace Connect/Renew и SSH Authorize/Revoke остаются обязательными. Подключённые MCP-серверы и их credentials не расширялись.
Upstream Codex ACP 1.11.0 требует elicitation capability, которой нет у текущего клиента Balda. В закреплённой сборке добавлен узкий fallback пустой confirmation-only формы на существующий ACP RequestPermission. Форма с полями и неподдержанные режимы без capabilities не принимаются автоматически. Explicit accept/decline/cancel и неизвестные ответы покрыты тестами. Чистая повторная сборка закреплённого source + patch прошла race/lint и дала одинаковый хеш.
В Balda исправлены две причины потерянного ответа: обычный 1 в DM теперь относится к единственному доставленному действующему вопросу той же беседы/сессии; ID отвечающего совпадает с исходным ID автора запроса, без добавления mattermost: только к ответу. Проверяются права отвечающего, expiry и время сообщения. Старый 1, в том числе в пределах той же секунды, не разрешает новый вопрос. Общие каналы и несколько pending-вопросов требуют ответа в треде.
Проверено:
- Настоящая цепочка Mattermost adapter → ChatFX → questions → SQLite:
1разрешает,2отклоняет; продолжение сохраняется для штатного возобновления. Wrong requester/session/conversation, expiry, недоставленный/неоднозначный вопрос, обычный текст и старое сообщение не выдают разрешение. - Полный
go test -race ./...: 173 пакета, exit 0; golangci-lint — 0 issues; go-arch-lint — OK. - Реальный Codex внутри production Balda: пять Manager lookup, запись в workspace и запрет записи вне него; generic permission requests = 0. Session
01a14fd8-a855-7bb2-ae76-77d5449db219. - Реальный
ssh_authorizeс возможностями клиента Balda дошёл до одного окна Owner confirmation; тест выбрал Decline и получил OWNER_DECLINED. Session01a14fd8-a84d-75d0-9624-ec816c3de844. Approved authorized_keys и registration journal не изменились. - Балda реально запущена из проверенной сборки: hash
/proc/1/exeсовпал со staged binary. Последний запуск:2026-10-18T16:41:07.023505736Z. HTTP health/login — 200; native SSH к Mac через обязательный Seatbelt — pass. State/home/work mounts сохранены; SQLite/compose/config backup —/Users/admin/.local/share/balda-workspace/backups/direct-reply-20261018T162446Z.
Коммиты: Balda 254f3e29; Workspace Manager/deployment 0c82b8f (основное MCP-исправление a5c0b66); SSH Manager 8739b1e. Рабочие деревья проверены отдельно. Подтверждение в реальном Mattermost-чате не отправлялось от имени владельца; приёмка входящего ответа выполнена сквозным тестом. Runtime evidence: ~/.local/share/balda-workspace/candidate/direct-reply-fix.json.
Kraken остаётся не настроен для execution: его filesystem isolation не provisioned/accepted; execution_ready=false сохранён. Инструмент теперь явно говорит, что chat approval не может подготовить хост, вместо ложного совета подтвердить несуществующее окно. Из Mac имя kraken не разрешается через DNS, оба IP из существующего SSH ProxyCommand (10.99.0.2, 10.99.1.2) не ответили на TCP 22; bootstrap SSH истёк на banner exchange. Запрошен доступный адрес/восстановление маршрута. Регистрация нового target-ключа и приёмка этого хоста не заявляются выполненными.
Ранее остававшиеся отдельные решения по личным Mac CLI credentials/OpenCode localhost этим исправлением не подменяются. Полная исходная настройка не помечена принятой.
Обновлено: 2026-10-18.
Отдельный проект доступа к папкам: personal/plans/workspace-gateway, /Users/admin/Developer/workspace-gateway, начальный коммит 2bc6743.
Дополнительная проверка SSH и Seatbelt: personal/projects/balda/ssh-seatbelt-2026-10-18.
Исходная задача: Balda работает с оригинальными Prism/Beads по подключённым проектам и запускает штатного агента в другой среде; подключение нового репозитория требует подтверждения владельца.
Проверка: personal/projects/balda/ssh-acp-verification-2026-10-18.
Рабочая установка: personal/projects/balda/setup.
Актуальный статус 2026-10-18
Уточнение по поиску проектов, коммит 9e5066a: рабочий root только developer (/Users/admin/Developer). Ошибочно включённый мной downloads удалён. Его зависший параллельный вызов скрывал от модели успешный ответ Developer; фактически Developer уже отвечал за 12 мс. Default query больше не обходит всё дерево исходников и dependencies: фильтруется выбранный уровень; глубокий поиск остаётся явным recursive: true. Проверены 139 папок корня, 8 вложенных папок workspace-gateway и поиск имени. Реальный Codex получил результаты и вывел их в ответе без approval (session 01a14fa7-60f2-7971-81de-b6c838ec1c31). Это конкретная новая проверка; прежнее заявление о полной приёмке было преждевременным. Системные TCC/FDA permissions не выдавались и не обходились.
Исправления после production feedback закоммичены: Workspace Manager 1076b4f, SSH Manager f876d37. Старые execution-broker/execution-prism MCP и broker-инструкция удалены из активного конфига; broker plugin отключён без удаления его файлов/ревизий. Оригинальные prism и prism-callee включены.
Codex работает с workspace-write и дополнительным writable root только для grants получателя. После точного согласия владельца активированы отдельные Docker seccomp/AppArmor profiles для bubblewrap; privileged/SYS_ADMIN не включались. Root grants остаётся operator-owned; пустые защищённые metadata targets позволяют собрать sandbox без права создавать произвольные grants.
Реальная модель внутри рабочей Balda успешно вызвала workspace_folders, ssh_hosts, ssh_identity, ssh_config, ssh_registrations, записала файл в /workspace/work и в настоящую динамически подключённую RW fixture. Запись вне workspace отвергнута (EROFS), permission requests: 0. Подготовка identity/config перенесена в запуск SSH Manager, поэтому их MCP lookup действительно read-only. Подтверждения выдачи/продления доступа и SSH authorize/revoke сохранены. Тестовые маркеры убраны, synthetic grant отозван/отмонтирован. Приёмка: 01a14f89-d937-78a0-b93d-71d70ef48179, candidate/model-policy-acceptance.json, candidate/review-fixes.json. Повторяемый тест: tests/balda_policy_acceptance.py. Оба Go-проекта: race/vet/build — pass; HTTP health/login — 200. State/home/work тома и backup сохранены.
Workspace Manager (9e5066a) и SSH Manager (f876d37) реализованы, проверены и работают как user launchd services на loopback. Владелец явно подтвердил два новых SSH-ключа: настоящий вход из Balda к Mac через обязательный Seatbelt принят; relay shell отвергается. Native SMB backend отзывает открытые FD и истекает независимо от Manager. Все 14 оригинальных Prism Role runtimes прошли callee doctor через SSH в совпадающем workspace. Native Beads 1.3.1/Dolt 2.5.0 прошли общие параллельные записи/чтение и гонку claim; из SSH+Seatbelt тот же bd работает через точный Unix socket без wildcard loopback.
Production переключение завершено с явного разрешения владельца на перезапуск. Balda и Web UI перезапущены 2026-10-18 в 20:13:46 Asia/Bishkek (14:13:46 UTC); активен штатный ask, сохранён прежний pool. Из настоящего рабочего контейнера прошли authenticated MCP initialize/list/read вызовы обоих Manager (4 и 6 tools) и SSH-команда через обязательный Seatbelt. /backoffice/healthz и /backoffice/login — HTTP 200; Mattermost websocket подключился. Сохранены все 49 sessions, 1926 events, 2 users и 87 execution jobs, прежние state/home/work тома. До переключения сделан consistent SQLite backup и копии compose/config в ~/.local/share/balda-workspace/backups/20261018T141324Z; отчёт candidate/activation.json. Коммит приёмки 51a63af, SSH Manager d9c19ee.
Полная модельная приёмка остаётся открытой. Ожидаются два отдельных решения: использование существующих CLI credentials на Mac и OpenCode v2 localhost binding. Автоматическая проверка отклонила эти действия без отдельного согласия; разрешение перезапуска их не заменяет. Manager-токены remote Mac агентам не передаются. Реальные project Beads databases не мигрировались.
Подробная приёмка: /Users/admin/Developer/workspace-gateway/docs/acceptance-2026-10-18.md; закрытый кандидат: ~/.local/share/balda-workspace/candidate. Исторический план и промежуточные неуспешные проверки ниже сохранены как журнал.
Принятая граница
Максимально использовать штатный стек Balda: провайдеры ACP, сессии, управление задачами, MCP, skills и подтверждения. Prism, Prism Callee, Callee и Beads — оригинальные, с сохранением их собственных контрактов.
Balda → штатный generic_acp → ssh -T → штатный ACP-агент в другой среде
Единый способ связи — SSH: контейнер, VM или физический хост отличаются окружением, а не протоколом запуска. macOS-окружения предоставляет Virfield через его MCP. Штатный агент выполняет работу в выданном workspace; Balda сохраняет управление беседой и сессией.
Что проверено
- Штатная фабрика Balda запускает
sshчерезgeneric_acp.cmdи передаёт ACP. - Реальный OpenCode создаёт и возобновляет сессию после повторного SSH.
- Контрольный ACP-агент получает штатное решение Balda разрешить или отклонить действие.
- Контрольный удалённый агент вызывает настоящий MCP-инструмент.
- Штатные тесты Balda подтверждают Mattermost review, защиту от чужого ответа и timeout.
- Воспроизведены локальная проверка cwd и требования к достижимости MCP.
Для передачи ACP новая реализация broker-acp не требуется: базовый путь уже проверен.
Дополнительный код допустим только для конкретного воспроизведённого пробела интеграции; прикладные сценарии и учёт фаз Prism остаются в штатном стеке.
Следующие конкретные действия
- Я реализую и приму Workspace Manager (проект
workspace-gateway) в отдельном проекте: настраиваемые именованные корни (developer,downloadsи другие), листинг и поиск папок по имени без файлов, подключение после подтверждения владельца, отключение и временный лизинг; сетевая файловая система обеспечит одни и те же исходные файлы Balda и агентам без перезапуска Balda при каждой выдаче. Указание корня в конфиге разрешает обнаружение папок, но не выдаёт доступ ко всем его файлам. - Я настрою авторизованный SSH из контейнера в реальные среды, проверку host key, ограниченные credentials и штатный
generic_acpс командой SSH; доступность порта и проверка протокола уже подтверждены, рабочая авторизация ещё не принята. - Я настрою запуск агентов и обычных команд на Mac под Seatbelt, начиная со штатных sandbox и готового
anthropics/sandbox-runtime, и проверю запрет доступа к соседним проектам, секретам и обхода через другой SSH command. - Я настрою согласованные пути workspace, достижимые MCP, оригинальные skills/tools и единое состояние Beads для Balda и одновременных агентов, затем включу запросы разрешений у агентов и штатный
askBalda. - Я проведу реальную приёмку выбранных Codex/Claude/OpenCode и оригинального Prism: статус проекта, подтверждение и отказ, выполнение, отмена, продолжение сессии и прекращение доступа после отзыва или истечения лизинга.
Это оставшаяся работа, а не уже выполненный deployment. SSH/Seatbelt/ACP и настройка Beads не расширяют четыре функции Workspace Gateway.
Что подтверждено дополнительно
- Docker работает через Colima, а не Docker Desktop.
- Из основного контейнера получены SSH banners Mac и внешнего GitHub на TCP/22; логин и команды при этом не выполнялись.
- Seatbelt на Mac 26.7.1 реально заблокировал чтение и запись в контрольную папку, в том числе дочерним shell; это не готовый production профиль.
- Документация Beads описывает Dolt server mode для нескольких одновременных записывающих агентов: первичный источник.
- Политика файлов и сети для реальных агентов, native approvals и полная работа Prism остаются открытыми.
Права и репозитории
Подтверждение подключения репозитория, подтверждение действия агента и файловая изоляция — три отдельные проверки.
Агент не получает полномочий самостоятельно выдавать себе доступ к новому проекту.
Весь каталог Developer не передаётся Balda или исполнителю.
Исходная БД Beads соответствующего проекта остаётся источником статусов; Git-клон сам по себе не доказывает наличие актуального состояния Beads.
Механизм выдачи доступа к реальным проектам и их БД ещё требует настройки и приёмки.
Текущее состояние и границы
Основная Balda получила оригинальные Prism/Prism Callee, bd, Callee и прямой Virfield MCP; это установка инструментов, а не приёмка удалённого исполнения.
В рабочем конфиге остаётся permissions.mode: allow_all; SSH-проверка production-конфиг, историю и авторизацию не меняла.
Полный Prism lifecycle с моделью и реальные удалённые Claude/Codex этой проверкой не приняты.
Новый сервис создаётся в отдельном проекте workspace-gateway; его объём ограничен четырьмя функциями доступа к папкам.
Прежняя ветка broker-rebuild в /Users/admin/.codex/worktrees/broker-rebuild/execution-broker — оставшийся каркас предыдущего обсуждения, а не место реализации Workspace Gateway.
Старые execution-broker, execution-prism и plugin остаются в действующей Balda; очистка новой ветки не удаляла их из deployment.
Историческая приёмка прежнего брокера: personal/plans/balda-callee-prism-plan.
Выполнение 2026-10-18 — промежуточный журнал
- Создан отдельный Git-проект
/Users/admin/Developer/ssh-manager, исходники и README записаны. Учёт настроенных оператором хостов/пользователей/проверенных public host keys, отдельная Ed25519-идентичность,ssh_config/known_hosts, ProxyJump, подтверждение регистрации/удаления управляемой строки authorized_keys через штатный MCP elicitation. Private key не возвращается инструментами; bootstrap credentials остаются у оператора. - Relay-ключ ограничен штатными OpenSSH options,
/usr/bin/falseзапрещает shell,permitopenограничивает переход заданными адресами. Execution до принятой файловой изоляции отвергается. Это каркас подготовки доступа; production Mac/VM ещё не авторизованы и удалённые реальные агенты не приняты. - Существующие пользовательские SSH-ключи и authorized_keys не менялись. Отдельный sshd на loopback-порту с fixture-файлом подтвердил вход по закреплённому ключу, отказ при подмене host key и отказ нового входа после удаления fixture-ключа. Полный ProxyJump и production SSH/ACP остаются открытыми.
- SSH Manager:
go test -race ./...,go vet ./..., сборка — успешно. Настоящий stdio MCP отдал 6 инструментов; отказ через elicitation остановил регистрацию. Локальная HTTP-авторизация и Host allowlist приняты; Colima получила 401 без токена. HTTP-порт подготовки17796; 7796 занят прежним Broker. - Готовый
@anthropic-ai/sandbox-runtime@0.0.80установлен только в тестовый каталог. Проверка на Mac прошла: разрешённая папка читается/пишется, соседняя закрыта, открытие SSH private key блокируется без чтения его содержимого, ограничения наследуются дочерним shell, SSH-обход блокируется. Это тестовый профиль, не приёмка Codex/Claude/OpenCode с реальными авторизациями и сетью. - Подготовлена отдельная копия конфига Balda:
permissions.mode: ask, MCP Workspace/SSH Manager, отдельный профильworkspace-setupна штатном Codex, существующий pool не изменён.balda --profile workspace-setup validateв новом одноразовом контейнере завершился exit 0; provider runtime/модели/каналы не запускались. Это проверка конфигурации, не preflight или сквозной Prism. - Копия конфига, приватный env новых manager-токенов, оригинальный backup и отчёты находятся в
/Users/admin/Docker/balda-mm-mac/state/workspace-setup-20261018. Внешние сообщения не отправлялись. Рабочая Balda не переключалась; перезапуск остаётся отдельным подтверждаемым действием после реальной приёмки. - При автоматической проверке был отклонён тест с передачей manager-токенов в отдельный Python Docker-образ. Его заменили безопасной проверкой: токены остаются в локальных Mac-процессах; контейнер проверяет только достижимость/401 без авторизации. Аутентифицированный вызов из Balda ещё открыт.
- Ближайшая зависимость: полный fixture-тест штатного NFS (
sudo /opt/homebrew/bin/python3 /private/tmp/workspace-setup-20261018/nfs-admin.py test). Файловый backend, реальный отзыв открытых дескрипторов, согласованные mounts, общий Beads/Dolt и полный Prism/удалённые агенты не заявляются выполненными.
Дополнительная приёмка SSH Manager: реальный ProxyJump
/private/tmp/workspace-setup-20261018/ssh-jump-acceptance.py запустил два настоящих локальных sshd, получил отдельный public key и клиентский конфиг через настоящий stdio MCP SSH Manager и проверил SSH roundtrip через ProxyJump. Четыре проверки успешны: roundtrip; отказ shell на relay; отказ forwarding к незаданному адресу (подтверждён журналом sshd); отклонение подменённого host key конечного сервера через jump. Менеджер использовал обычный OpenSSH, без нового транспортного launcher. Пользовательский .ssh и системный sshd не менялись, тестовые sshd остановлены. Это приёмка транспорта/конфига на локальных fixture-серверах, не production авторизация Mac/VM и не ACP с моделями. Отчёт: /private/tmp/workspace-setup-20261018/ssh-jump-acceptance.json.
Фактическое продолжение 2026-10-18
- Workspace Manager закоммичен:
00b7e13; SSH Manager:d6323b5. Оба прошлиgo test -race ./...,go vet ./..., build. Это реальные отдельные проекты, не изменения execution-broker. - Финальный файловый backend — готовые Samba SMB3, native
mount.cifsв Colima иmount_smbfsна Mac. Постоянного privileged Docker helper нет. Linux recipient — обычный контейнер сrslaveтолько своего пустого mount root. Приняты новые grants без его рестарта, общие оригинальные файлы, RW, server RO, продление, отзыв уже открытых read/write FD обоих native клиентов, независимое от Manager истечение и запрет продления истёкшего share. Go→встроенный backend и реальный отзыв при перезапуске Manager также прошли. - Два Manager установлены как user launchd jobs, слушают только
127.0.0.1:17795и:17796. Из одноразового доверенногоbalda-prism:20261018, UID node, read-only/cap-drop=ALL реально прошли authenticated initialize, 4/6 tools/list и readonly tool calls. Новые bearer tokens находятся вне Balda/state:~/.local/share/balda-workspace/managers.env(0600). - Владелец явно подтвердил два новых SSH fingerprints и передачу только Balda. Они установлены через SSH Manager с сохранением прочих authorized_keys; private identities находятся в отдельном Docker volume
balda-ssh-manager(UID 1000), а не в общем host .ssh. Native SSH из доверенного контейнера к Mac реально выполнил команду через обязательный SRT; relay shell реально отвергнут. Альтернативная SSH команда открыть личный SSH ключ Mac получила PermissionError без чтения содержимого. - Исправлен конфликт relay/execution на одном хосте: отдельные identity names. Native ProxyJump, ограниченный permitopen, отказ relay shell и подменённому target key повторно прошли. Kraken есть в inventory по существующему known_hosts, его execution остаётся закрытым до отдельной принятой изоляции.
- Подготовлены закрытые candidate config/compose:
~/.local/share/balda-workspace/candidate;docker-compose ... config --quietпрошёл. В нёмask, два Manager MCP, одинаковые абсолютные workspace пути и native generic_acp профили Mac Codex/Claude/OpenCode черезssh -T. Рабочая Balda пока не перезапущена. - Реальные Codex и Claude ACP на Mac под SRT уже проходят initialize и session/new через этот SSH. Это ещё не подтверждение вызова модели: CLI authorizations запрошены у владельца отдельным native input после отказа автоматической проверки доступа к credentials. OpenCode v2 падает при готовности standalone server; его узкий IPC runtime диагностируется без открытия общего loopback.
- Оригинальный Callee с правильным
--agent-root /home/node/.config/calleeуспешно отдал весь native Prism graph. Полный модельный Prism lifecycle и общее состояние Beads/Dolt пока не заявляются принятыми.
Итог текущей выполненной части
- Workspace HEAD
e99f043, SSH HEADd9c19ee; оба Git working tree чистые. Исходники, tests, scripts и точная приёмка закоммичены. Полная модельная работа не помечена выполненной. - User jobs
local.balda.workspace-manager,local.balda.ssh-manager,local.balda.beads-doltреально running. Manager listeners только 127.0.0.1:17795/17796, native Dolt только 127.0.0.1:13307 плюс точный Unix socket в agent-home. - Original Beads/Dolt: Mac и trusted Balda одновременно создали разные задачи в одной fixture DB, оба прочли оба ID; при одновременном claim exit codes 1/0 — ровно один победитель. Metadata — один и тот же оригинальный файл через SMB. Native bd внутри реального SSH+Seatbelt прочитал ту же БД через Unix socket и explicit native credentials file. Свои fixture credentials не дают доступа к реальным проектам; их БД не переинициализировались.
- Broad localhost binding по-прежнему выключен. OpenCode требует отдельного решения владельца. Уже работающие Codex/Claude ACP initialize/session-new не считаются модельной приёмкой; Claude на prompt вернул Authentication required при закрытых существующих CLI credentials.
- Передача Manager bearer tokens Mac была отклонена автоматической проверкой и исключена из схемы. Manager MCP подключены управляющей Balda; remote executors получают approved filesystem и native Beads. Для необходимых Balda HTTP callbacks штатный SRT proxy работает с очищенным NO_PROXY; unauthenticated Mac→Manager probe получил ожидаемый HTTP 401 без раскрытия токенов.
- Собственный synthetic ACP grant после проверок отозван и снят. Привилегированных постоянных mount helpers нет. Исходный Docker Dolt volume сохранён как резерв fixture; рабочий server теперь native Mac, чтобы Beads использовал Unix socket внутри sandbox.
- Кандидат включает original Prism assets с неизменёнными workflow bodies; изменены только native provider settings, убран отвергавшийся runtime pin gpt-5.4, включён ask. Полный runtime doctor всех 14 ролей exit 0. Production restart остаётся финальным отдельным подтверждением после model acceptance.