107 lines
7.3 KiB
Markdown
107 lines
7.3 KiB
Markdown
# 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/<repo>/<branch>/...`;
|
||
- в прод-клон — `/repos/<repo>/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.
|