# 01 — BRD: Агенты пишут файлы под root в смонтированный хост-репо Work Item: **ORCH-040** Тип: инфра-фикс (runtime / docker-compose) Исполнение: через Dev напрямую (по решению Owner) ## 1. Бизнес-контекст и проблема Контейнер `orchestrator` (prod, 8500) работает под `uid=0 (root)`. Он монтирует хостовый каталог `/home/slin/repos` → `/repos` (rw). Claude-CLI агенты запускаются через `subprocess.Popen` **внутри контейнера**, то есть тоже под root. Они пишут: - в git worktree задач — `/repos/_wt///...`; - в прод-клон — `/repos//docs/work-items/...` (через коммит/пуш из worktree). В результате на **хосте** файлы создаются с владельцем `root:root`. ### Симптом При ребилде/деплое прода `git pull` / `git reset` под пользователем `slin` падает: ``` error: insufficient permission for adding an object to repository database .git/objects Permission denied (на docs/work-items/ORCH-016, владелец root:root) ``` Каждый будущий деплой будет ломаться, пока вручную не выполнить `chown`. ### Диагноз (живая разведка 05–06.06) - `docker exec orchestrator id` → `uid=0(root) gid=0(root) groups=0,999`. - Хост `slin` = `uid=1000 gid=1000`, группы: `sudo`, `docker(999)`. - `/home/slin/repos` → `/repos` (rw); на хосте `/repos` уже `1000:1000 rwxrwxr-x`. - `docs/work-items/*` на хосте — `root:root` (наследие прошлых прогонов). ## 2. Цель Агенты конвейера **не должны** создавать `root`-файлы в хостовом репозитории. После любого прогона конвейера `git pull/status/reset` под `slin` на хосте работает **без ручного chown**. ## 3. Объём (scope) В объёме: - Изменение runtime-режима контейнера так, чтобы артефакты создавались под `uid:gid` хоста (`1000:1000`). - Сохранение работоспособности: claude-auth (preflight), git/ssh, docker.sock (деплой), запуск конвейера. - Обновление документации (INFRA.md, CHANGELOG, ADR с обоснованием варианта). - Проверка на staging (8501) ДО прода. Вне объёма: - Массовое исправление прав уже существующих `root:root` файлов в истории (разовый `chown` на хосте делает Owner; в задаче — только описать команду). - Изменение логики конвейера, QG, схемы БД. - Смена модели/effort агентов, прочие фичи. ## 4. Заинтересованные стороны - Owner (Слава) — заказчик, владелец хоста mva154. - Стрим — разведка/контекст. - Проект enduro-trails — co-tenant того же прод-инстанса (групповой риск). ## 5. Ограничения и риски (off-limits) Self-hosting: прод-инстанс `orchestrator` ОДИН на все прод-проекты, общая БД и очередь. **Нельзя ломать**: запуск конвейера, доступ к Plane/Gitea/SSH из агентов, docker.sock. Любой рестарт контейнера под новым uid — **только в окно тишины** (нет активных задач). Тестировать на staging ПЕРЕД продом. ### Известные мины (подтверждены разведкой) - **МИНА 1 — docker.sock**: `/var/run/docker.sock` = `srw-rw---- root:999`. Доступ идёт через gid 999, не через root. При переходе на непривилегированный uid обязателен supplementary group `999`. *В текущем `docker-compose.yml` уже есть `group_add: ["999"]` для обоих сервисов — учесть, не сломать.* - **МИНА 2 — claude creds (БЛОКЕР)**: `/home/slin/.claude/.credentials.json` = `root:root 0600`. Сейчас читает контейнер-root. Под `uid=1000` без доступа → `claude-auth` ломается → весь конвейер умирает (preflight ORCH-044 заворачивает). Проверить ПЕРВЫМ. - **МИНА 3 — claude бинарь**: реальный бинарь `/opt/claude-code/bin/claude.exe` (root:root, `+x` для всех — ok). `ORCH_CLAUDE_BIN=/usr/bin/claude` в env не существует; launcher использует hardcode `CLAUDE_BIN=/opt/claude-code/bin/claude.exe`. Под uid 1000 исполним, но проверить запуск. - **SSH-маунт**: `/home/slin/.orchestrator-ssh` → `/root/.ssh:ro`. При смене uid HOME/домашний каталог меняется — путь к ключам нужно поправить (деплой по ssh). - **HOME**: launcher форсит `HOME=/home/slin` (две точки: env Popen и git_env). Креды читаются из `/home/slin/.claude`. Учесть при смене uid. ## 6. Бизнес-ценность Устранение постоянного ручного `chown` после каждого деплоя; деплой прода перестаёт ломаться на правах; снимается источник простоя конвейера всех проектов. ## 7. Допущения - Хост-каталоги `/app/data` и `/repos` уже `1000:1000` (запись под uid 1000 пройдёт). - Dockerfile уже содержит `git config --system --add safe.directory '*'`. - Окно тишины для рестарта контейнера согласуется с Owner. ## 8. Host-prerequisites (предусловия на стороне Owner) Часть фикса невозможно закрыть только кодом — есть действия на хосте mva154, которые выполняет Owner (в гит не коммитятся, фиксируются в ADR/INFRA). Это обязательные предусловия Варианта 1; без них переход на uid 1000 ломает конвейер: - **P-1 (блокер, МИНА 2):** обеспечить чтение `/home/slin/.claude/.credentials.json` под uid 1000 (рекомендация — `chown -R 1000:1000 /home/slin/.claude`). Способ выбирает ADR; анализ фиксирует факт предусловия. - **P-2:** ssh-ключи (`/home/slin/.orchestrator-ssh`) читаемы uid 1000. - **P-3:** подтверждение `slin = uid 1000 gid 1000` (подтверждено разведкой). - **P-4:** рестарт прод-self только в окно тишины (`GET /status` без активных задач). Детализация и команды — в `02-trz.md` §10.