# 02 — ТЗ: agent-файлы под uid хоста (не root)

Work Item: **ORCH-040**

## 1. Суть требования
Артефакты конвейера (worktree + docs) должны создаваться на хосте под
`uid:gid = 1000:1000` (slin), а не `root:root`. При этом сохраняется работа
claude-auth, git, ssh-деплоя и docker.sock.

## 2. Задействованные модули и файлы

| Файл | Роль в задаче |
|------|----------------|
| `docker-compose.yml` | runtime-режим контейнера (prod `orchestrator` + `orchestrator-staging`). Основная точка изменения. |
| `Dockerfile` | возможные правки под непривилегированный запуск (safe.directory уже есть; при необходимости — создание пользователя/прав). |
| `src/agents/launcher.py` | `HOME=/home/slin` хардкод (env Popen ~стр.326 и git_env ~стр.513); путь `CLAUDE_BIN` (стр.187). Проверить совместимость при смене uid; править ТОЛЬКО при необходимости. |
| `docs/operations/INFRA.md` | блок «Тома (volumes)» (SSH-маунт `/root/.ssh`), карта рантайма — обновить. |
| `CHANGELOG.md` | запись об изменении. |
| `docs/work-items/ORCH-040/06-adr/` | ADR с выбором варианта + обоснованием (создаёт архитектор). |

## 3. Варианты решения (вход для ADR — выбор и обоснование за архитектором)

> Анализ фиксирует варианты как требование «выбрать и обосновать в ADR».
> Рекомендация разведки — Вариант 1.

1. **Вариант 1 (рекомендован): `user: "1000:1000"` в docker-compose.**
   Все файлы сразу `slin:slin`, git на хосте без chown. Обязательные довески:
   - сохранить/проверить `group_add: ["999"]` (docker.sock) — **уже присутствует**;
   - обеспечить доступ uid 1000 к claude creds (`/home/slin/.claude/.credentials.json`):
     `chown 1000:1000` на хосте ИЛИ права на чтение для 1000 (задокументировать);
   - поправить SSH-маунт: `/home/slin/.orchestrator-ssh` → домашний каталог uid 1000
     (`/home/slin/.ssh`), а не `/root/.ssh`; согласовать с `HOME` в launcher;
   - проверить запуск `claude.exe` + `git` + `ssh` под uid 1000.

2. **Вариант 2: subprocess агента под непривилегированным uid внутри контейнера**
   (`Popen preexec_fn setuid` / `gosu`). Точечно, но сложнее; контейнер остаётся root.

3. **Вариант 3 (fallback, костыль): chown-хук нормализации прав после стадии**
   (`chown -R 1000:1000` worktree/доки). Лечит симптом, не корень. Применять, только
   если В1 неустранимо рвёт creds/sock.

## 4. Требуемые изменения (при выбранном Варианте 1)

### 4.1 docker-compose.yml (оба сервиса: `orchestrator`, `orchestrator-staging`)
- Добавить `user: "1000:1000"`.
- Сохранить `group_add: ["999"]` (НЕ удалять).
- Изменить SSH-маунт: target `/root/.ssh` → каталог `.ssh` пользователя 1000,
  синхронно с `HOME`, который форсит launcher (`/home/slin`). То есть привести к
  единому HOME: маунт `/home/slin/.orchestrator-ssh` → `/home/slin/.ssh:ro`.
- Маунт `/home/slin/.claude` и `.claude.json` — оставить; проверить доступ uid 1000.

### 4.2 Доступ к claude creds
- Обеспечить, что `/home/slin/.claude/.credentials.json` читается uid 1000
  (на хосте — операция Owner; в ТЗ зафиксировать команду и проверку).

### 4.3 src/agents/launcher.py
- Проверить, что `HOME=/home/slin` остаётся валиден под uid 1000 (домашний каталог
  существует и доступен). Менять ТОЛЬКО при доказанной необходимости.
- Не менять CLAUDE_BIN, если запуск под 1000 подтверждён.

### 4.4 Dockerfile
- Менять при необходимости (например, гарантировать существование `/home/slin` и
  права). `git config --system --add safe.directory '*'` уже есть — оставить.

## 5. Изменения API
Нет.

## 6. Изменения схемы БД
Нет.

## 7. Новые QG checks
Нет. Существующий staging-гейт (`check_staging_status`, ORCH-35) — обязательная
страховка перед прод-деплоем self (без изменений).

## 8. Артефакты pipeline, которые должны быть созданы/обновлены
- `06-adr/ADR-NNN-<slug>.md` — выбор варианта + обоснование (мины 1–3, SSH, HOME).
- `docs/operations/INFRA.md` — обновить блок volumes (SSH target) и, при изменении
  режима, упоминание uid рантайма.
- `CHANGELOG.md` — запись `fix:`/`refactor:` по Conventional Commits.
- `12-review.md`, `13-test-report.md`, `15-staging-log.md` — по ходу конвейера.

## 9. Порядок безопасного внедрения (требование)
1. Живая разведка прав creds/sock/ssh ДО кода.
2. Применить и проверить на **staging (8501)** end-to-end.
3. Прод-рестарт контейнера под новым uid — только в окно тишины (нет активных задач).
4. Регресс на хосте: новые tracked-артефакты `1000:1000`, `git pull` под slin без ошибок.

## 10. Зависимости и host-prerequisites (действия на хосте, вне кода)

Эти пункты — предусловия для Варианта 1; их выполняет Owner на хосте mva154 (в гит
не коммитятся, но фиксируются в ADR/INFRA как обязательная процедура). Без них
переход контейнера на uid 1000 ломает конвейер (МИНА 2 — блокер).

| # | Предусловие | Команда / проверка | Зачем |
|---|-------------|--------------------|-------|
| P-1 | Доступ uid 1000 к claude creds | `chown -R 1000:1000 /home/slin/.claude` (вкл. `.credentials.json`); проверка `sudo -u '#1000' test -r /home/slin/.claude/.credentials.json` | МИНА 2: без доступа preflight ORCH-044 завернёт весь конвейер |
| P-2 | SSH-ключи в HOME нового uid и читаемы | ключи в `/home/slin/.orchestrator-ssh` читаемы uid 1000; маунт ведёт в `/home/slin/.ssh` (см. §4.1) | деплой по ssh (DEPLOY_SSH_*) |
| P-3 | Подтверждение uid:gid рантайма | `id slin` → `uid=1000 gid=1000`; `/repos` и `/app/data` уже `1000:1000` (подтверждено разведкой) | целевые файлы создаются под slin |
| P-4 | Окно тишины для рестарта self | `GET /status` → нет активных задач перед рестартом прод-контейнера | self-hosting: общий инстанс с enduro-trails |

> **Открытый выбор для ADR (не решается анализом):** способ обеспечения P-1 —
> `chown` creds (рекомендация разведки) vs. ослабление read-прав vs. отказ от
> Варианта 1 в пользу Варианта 3 (chown-хук). Анализ фиксирует P-1 как
> обязательное предусловие при любом из вариантов 1/2; для Варианта 3 — неактуально.

## 11. Подтверждённые факты текущего рантайма (anchor для Dev)
Сверено с веткой `feature/ORCH-040-root-git` на 06.06:
- `docker-compose.yml`: оба сервиса имеют `group_add: ["999"]` (МИНА 1 — НЕ удалять);
  SSH-маунт обоих = `/home/slin/.orchestrator-ssh:/root/.ssh:ro` (требует правки target);
  claude-маунты = `/home/slin/.claude` и `/home/slin/.claude.json:ro`.
- `src/agents/launcher.py`: `HOME="/home/slin"` форсится в env Popen (стр. 326) и в
  git_env (стр. 513); `CLAUDE_BIN="/opt/claude-code/bin/claude.exe"` (стр. 187).
