# Codex: дать Control доступ к состоянию mesh

Небольшое задание, но блокирующее: без него эндпоинт выдачи кодов регистрации, сделанный Antigravity в PR #53, на настоящем Hub не работает.

## Репозиторий

- https://github.com/ochenstarik-ui/server-monitor-manager
- База: `main` @ `5fd9def` или новее
- Ветка: `codex/mesh-state-permissions`
- `main` защищён: PR обязателен, обязательны статусы `build-and-test` и `build`, force-push запрещён
- один PR — одна тема; описание PR заполняется **после** завершения CI

## Дефект

`NodeEnrollmentService` в Control читает и дописывает `/var/lib/ochenstarik-server-monitor-manager/mesh/nodes.tsv` — тот же файл и тот же формат из четырёх колонок, что использует `reserve_node_address` в `deploy/ochenstarik-server-monitor-manager.sh`. Разделяемое состояние выбрано верно: два источника истины были бы хуже.

Но доступа к этому файлу у Control нет:

- `deploy/ochenstarik-server-monitor-manager.sh:723` и `:764` — `install -d -m 0700 "$MESH_DIR"`, каталог создаётся от root и остаётся root-овым;
- `:740` и `:766` — `chmod 0600 "$MESH_DIR/nodes.tsv"`;
- `:574` — `chown -R "$CONTROL_USER:$CONTROL_USER" "$STATE_DIR/control"`. Права выдаются только подкаталогу `control`. Подкаталог `mesh` не упомянут нигде;
- `deploy/ochenstarik-smm-control.service:8` — `User=ochenstarik-smm-control`.

Итог: на настоящем Hub запрос кода упрётся в отказ доступа. В CI это не проявляется — тесты подставляют `Control:MeshNodesPath` во временный каталог, поэтому проверяется логика, но не права.

## Что сделать

Дать пользователю Control право читать и изменять состояние mesh, не отдавая ему лишнего:

- каталог `$MESH_DIR` — `root:$CONTROL_USER`, режим `0770`;
- `$MESH_DIR/nodes.tsv` — `root:$CONTROL_USER`, режим `0660`;
- применить это во всех местах, где каталог и файл создаются, а не в одном: сейчас это `mesh_init` и `reserve_node_address`;
- существующие установки чинятся при обновлении: если каталог уже есть с прежними правами, они приводятся к новым.

Приватные ключи WireGuard в `$WG_DIR` остаются недоступными Control. Проверьте, что `$WG_DIR` и `$MESH_DIR` — разные каталоги, и что расширение прав не задевает ключи.

## Что проверить тестами

- после `mesh-init` каталог и файл имеют ожидаемых владельца, группу и режим;
- пользователь Control может прочитать и дописать `nodes.tsv`;
- пользователь Control **не** может прочитать приватный ключ Hub;
- обновление поверх установки со старыми правами приводит их к новым.

## Замечание про гонку

Ни bash, ни Control не берут блокировку на `nodes.tsv`. Внутри Control выдача сериализована семафором процесса, но с bash-путём `node-code` он не согласован, а Control ещё и перезаписывает файл целиком, а не дописывает: одновременная запись из bash будет потеряна.

Пока код выдаётся из одного места, это теоретическая гонка. Но два пути к одному файлу уже существуют. Разумно ввести общую блокировку `flock` на `nodes.tsv` и использовать её с обеих сторон. Bash-сторона — ваша; если сделаете, отметьте в отчёте, чтобы Antigravity подхватил то же соглашение в Control.

## Критерий приёмки

- Control читает и дописывает `nodes.tsv` под своим пользователем;
- приватные ключи WireGuard Control недоступны;
- права выставляются во всех местах создания и чинятся при обновлении;
- перечисленные проверки присутствуют и проходят;
- PR, CI зелёный, PR не смержен до зелёного.

## Отчёт

Раздельно: что проверено локально, что в CI со ссылками на прогоны, что не проверялось и почему.
