Files
obsidian-vault/personal/plans/workspace-gateway.md
T

21 KiB
Raw Blame History

Workspace Gateway — план

Обновлено: 2026-10-18. Проект: /Users/admin/Developer/workspace-gateway. Git: main, реализация 00b7e13; актуальные deployment scripts и приёмка e99f043 (2026-10-18). Четыре MCP-функции реализованы; принят native SMB3 backend с фактическим отзывом открытых FD на Linux и Mac, независимым истечением срока и динамическим подключением без рестарта получателя. Сервис установлен как user launchd job на 127.0.0.1:17795; аутентифицированные вызовы из доверенного образа Balda прошли. Переключение production Balda и полная прикладная приёмка ещё не завершены. Общий setup Balda: personal/plans/balda-remote-agent.

Назначение и четыре функции

Сервис выдаёт Balda и удалённым агентам доступ к исходным папкам через сетевую файловую систему. Balda и агенты видят одни и те же файлы; копирование Git-репозитория не считается реализацией общего доступа.

  1. Папки: листинг и навигация по папкам внутри настроенных корней (developer, downloads и других), а также поиск папок по имени; без выдачи списка файлов и их содержимого.
  2. Подключение: выбранная папка появляется в work dir после подтверждения владельцем точного пути, получателя, режима доступа и срока.
  3. Отключение: фактический отзыв ранее выданного доступа.
  4. Лизинг: статус и срок действия, автоматический отзыв после истечения срока, продление с подтверждением владельца.

Четыре пользовательские функции — согласованный объём проекта. Обработка ответа владельца, журнал выданных разрешений и таймеры обслуживают эти функции, а не расширяют API прикладными сценариями.

Конфиг корней и поиск папок

Workspace Manager — пользовательское название сервиса; текущие путь проекта и имя этой заметки остаются workspace-gateway.

В конфиге задаются несколько именованных корней; список расширяется без изменения кода. Например:

roots:
  developer: /Users/admin/Developer
  downloads: /Users/admin/Downloads

Корень задаёт область обнаружения папок, а не автоматический доступ Balda или агентов ко всем его файлам. Сервис не монтирует целиком Developer или Downloads только потому, что они указаны в конфиге.

Поиск выполняется по имени папки (полное имя или подстрока, без учёта регистра), в выбранном корне либо во всех настроенных корнях. Результат содержит имя корня и относительный путь папки, чтобы различать одинаковые имена. Имена файлов и содержимое файлов в поиск не входят. Выход за корни через .. и символические ссылки не допускается. Подключение найденной папки по-прежнему требует подтверждения владельца точного пути, получателя, прав и срока.

Порядок реализации: загрузить и проверить roots из конфига; реализовать листинг/навигацию; добавить поиск по имени; включить операции в MCP; проверить поиск в нескольких корнях, одинаковые имена, отсутствующий/недоступный корень и запрет выхода за границы.

Границы

SSH-запуск, ACP-транспорт, исполнение команд на хосте и Seatbelt относятся к настройке Balda и среды, а не к Workspace Gateway. Prism, Callee, Beads, управление задачами и сессиями используются штатно. Сервис не реализует собственные Story workflows, собственный Prism и дублирующий scheduler.

Общий каталог Developer и домашний каталог не выдаются агентам. Листинг папок даёт возможность запросить конкретный путь, а не право читать его файлы. Ответ от модели или аргумент approved=true не является подтверждением владельца. Отзыв и истечение срока должны прекращать реальный доступ, включая существующие соединения и открытые файловые дескрипторы.

Конкретные шаги

  1. Я проверю готовую сетевую файловую систему на текущем Docker/Colima и целевых средах: исходные файлы видны обоим клиентам, добавление разрешённой папки обходится без перезапуска Balda, соседняя папка недоступна, отзыв закрывает уже выданный доступ.
  2. Я подключу постоянную точку сетевой файловой системы в work dir; это разовая настройка deployment, последующие выдачи и отзывы происходят в рантайме.
  3. Я реализую конфиг нескольких именованных корней (developer, downloads и других), листинг/навигацию и поиск папок по имени внутри этих корней; затем запрос подключения, связав подтверждение владельца с точным путём, получателем, правами и сроком. Сначала проверю пригодность штатных взаимодействий Balda. Приёмка поиска включает несколько корней, одинаковые имена папок, недоступный корень и запрет выхода через ссылки или ...
  4. Я реализую отключение и временный лизинг, сохранение состояния разрешений и обработку истечения срока после перезапуска сервиса; неполученное подтверждение оставляет доступ закрытым.
  5. Я проведу приёмку с двумя клиентами: общие файлы, RO/RW, запрет соседних путей и обхода через ссылки, отказ владельца, отзыв, истечение, продление и повторный запуск сервиса.

Выбран и принят SMB3 backend: native Samba, mount.cifs Colima и mount_smbfs macOS. Приняты оригинальные файлы, RO/RW, динамические grants, отзыв открытых FD, независимый expiry и реальный отзыв после перезапуска Manager. Подробности — в актуальном журнале ниже. До выбора backend сохраняется ровно этот объём; общая копия всех репозиториев и ослабление изоляции не являются заменой выдаче доступа.

Что уже проверено и что остаётся

  • Создан отдельный Git-проект с зафиксированной границей четырёх функций.
  • Проверена независимая возможность штатного ACP Balda поверх SSH: personal/projects/balda/ssh-acp-verification-2026-10-18.
  • Выбрана и испытана сетевая файловая система: native SMB3, Linux и Mac.
  • Реализованы четыре функции, native подтверждения, реальный отзыв открытых FD и независимый срок доступа.
  • Настроено общее состояние Beads и принята работа реальных агентов через полученный workspace.

Доступ к исходникам и доступ к состоянию Beads — связанные, но отдельные пункты общей установки. Для одновременной работы Balda и нескольких агентов Beads описывает server mode Dolt: официальная архитектура. Сетевой mount сам по себе не считается приёмкой конкурентной работы БД.

Выполнение 2026-10-18 — промежуточный журнал

  • Исходники находятся в /Users/admin/Developer/workspace-gateway: конфиг именованных корней, навигация и поиск только папок; запрет .., выхода через ссылки и выдачи целого корня.
  • Ровно четыре MCP-инструмента: workspace_folders, workspace_connect, workspace_disconnect, workspace_lease. Подтверждение через MCP elicitation; путь, получатель, RO/RW и точный срок перечисляются в запросе владельцу.
  • Написано ядро лизинга: атомарный журнал с fsync, отдельно подтверждаемое продление, видимый отказ отзыва и повторные попытки, закрытие незавершённых/активных разрешений после перезапуска. Это проверено тестовым backend; реальные mounts и отзыв файлового доступа ещё не приняты. В исполняемом сервисе подключение закрыто до выбора проверенного backend.
  • В реальном проекте прошли go test -race ./..., go vet ./..., сборка. Настоящий stdio MCP: initialize, tools/list (4 инструмента), листинг без имён файлов, отказ на traversal и неподтверждённом backend.
  • HTTP MCP: авторизация проверена локально на Mac, host.docker.internal разрешён, чужой Host отвергается. Из отдельного контейнера Colima проверены достижимость и HTTP 401 без токена; аутентифицированный MCP из контейнера не проверялся. Рабочий порт для подготовки: 17795 (7795 занят прежним Broker).
  • Подготовлены /private/tmp/workspace-setup-20261018/nfs-admin.py и nfs-acceptance.py. Полный запуск: sudo /opt/homebrew/bin/python3 /private/tmp/workspace-setup-20261018/nfs-admin.py test. Он предназначен только для fixture /private/tmp/workspace-setup-20261018/nfs/source/allowed, клиентов Colima и восстановления исходного состояния после теста.
  • Первый ручной start остановился до изменения системы из-за неверной обработки штатного exit 1 у nfsd status; проверка исправлена на наличие самого процесса nfsd и проверена с mock. Полная NFS-приёмка ещё ожидает ручного sudo. На момент этой записи /etc/exports отсутствует, nfsd не запущен.
  • Закрытые отчёты/резервные копии: /Users/admin/Docker/balda-mm-mac/state/workspace-setup-20261018. Production Balda не переключалась.

NFS: ручной запуск и диагностика сетевого пути

Пользователь выполнил nfs-admin.py start: штатный nfsd реально запущен, RPC NFSv3/2049 и mountd зарегистрированы, showmount -e localhost показывает только fixture. Полный test этим выводом ещё не подтверждён.

Первое подключение обоих контейнеров получило Permission denied. Причина в исходной настройке fixture, не доказательство непригодности NFS: TCP-измерение показало, что Mac видит клиента Colima как 127.0.0.1, тогда как экспорт разрешал 192.168.5.1. Отдельно проверено преобразование reserved port: контейнер привязал исходящий порт 900, на Mac наблюдался 127.0.0.1:64152. Артефакт: /private/tmp/workspace-setup-20261018/nfs/colima-source-address.json.

nfs-admin.py test исправлен: разрешает только fixture для loopback, на время теста учитывает переписывание порта в MOUNT RPC, после проверки восстанавливает исходные байты /etc/nfs.conf, удаляет только собственный экспорт и останавливает тестовый сервер. Логика полного восстановления проверена с mock на успешном и ошибочном пути; реальное RO/RW/открытые FD пока ожидает ручного запуска test с sudo. Отказ обоим клиентам не считается успешной изоляцией получателей: результат теперь null до успешного доступа разрешённого клиента.

NFS: результат полного запуска и установленная причина отказа

Пользователь выполнил полный nfs-admin.py test. Оба клиента завершились на mount с Permission denied, поэтому RO/RW и отзыв FD не проверены. Система после сценария реально восстановлена: /etc/exports отсутствует, nfsd остановлен, /etc/nfs.conf содержит исходный текст.

Дальнейшая диагностика установила блокировку самой операции mount в тестовом клиенте; она не позволяет считать созданным NFS mount, независимо от возможных предварительных RPC: Docker использует AppArmor docker-default; с CAP_SYS_ADMIN обычный mount пустого tmpfs возвращает Permission denied (exit 255). Тот же контроль с apparmor=unconfined только у одноразового fixture-контейнера успешно монтирует tmpfs. Это пропуск в тестовом окружении, а не свидетельство непригодности NFS. Предыдущее объяснение одним адресом Colima было неполным; адрес/порт действительно переписываются, но исходные mount-пробы дополнительно блокировались AppArmor.

Подготовлен минимальный отдельный образ workspace-nfs-client:20261018 с официальным nfs-utils 2.6.4; image ID sha256:5468d8d0555b1658bd7626f0f840269203dac8bde49160261268c03aea8b75f4. Он не содержит пользовательских конфигов, токенов или ключей. Предварительная проверка клиента без Mac sudo реально прошла: стандартный mount.nfs существует, tmpfs монтируется. Исправлены fixture options и fail-fast: при неудачном initial тест больше не прогоняет RO/отзыв на остановленных контейнерах. Восстановление root-сценария снова проверено с mock для успеха и ошибки. Для реальной проверки NFS всё ещё требуется повторный ручной sudo ... nfs-admin.py test.

Принятый SMB backend — 2026-10-18

Финальная реализация закоммичена 00b7e13. Используются готовые Samba SMB3 и штатные клиенты macOS/Colima. На каждый lease выдаётся отдельный server/share с отдельным credential, точным bind только разрешённой папки и RO/RW на сервере. Истечение исполняет сам server supervisor, независимо от процесса Manager. Отзыв удаляет share, reload и close-share закрывают открытые FD, затем снимаются mounts; server ещё 60 секунд отвечает отказом старым клиентам и сам удаляется.

Приняты реальные проверки: динамическое подключение в уже работающий непривилегированный контейнер; чтение/запись оригинала с Linux и Mac; server RO; продление без смены mount; отзыв открытых read/write FD обоих клиентов; истечение без Manager; отказ продлению истёкшего share. Дополнительно Go→встроенный backend и фактический отзыв при перезапуске Manager прошли. Ранний протокольный тест также проверил отказ credentials другого получателя, symlink escape и сохранение другого share при отзыве первого. Сохранённая повторяемая приёмка: tests/smb_acceptance.py; отчёт ~/.local/share/workspace-manager-acceptance/report.json.

Постоянный privileged mount-helper был отклонён автоматической проверкой и исключён. Финальный вариант устанавливает cifs-utils в Colima и выполняет обычные разовые native mount/umount команды; привилегированный Docker daemon/helper не остаётся. Корни Developer/Downloads служат только обнаружению. В recipient монтируется только его mount root /var/lib/workspace-manager/balda, с rslave, по совпадающему абсолютному пути на Mac/в Balda. NFS больше не является зависимостью выбранного backend; повторный ручной sudo тест не требуется.

Сервис установлен на 127.0.0.1:17795, private config/state: ~/.local/share/balda-workspace/workspace; настоящее authenticated MCP initialize/tools/list/folders из доверенного образа Balda прошло. Production конфиг Balda ещё не переключался: candidate и финальная прикладная приёмка отслеживаются в personal/plans/balda-remote-agent.