# Roadmap Sources Источники задач для фазы DECOMPOSITION. Собрано при проходе по репозиторию 2026-10-05, ответы владельца учтены. Полный Q&A-источник (с разделами «Вопрос», «Факт», «Риск», «Кандидат») восстановим из git-истории: `git log -p docs/arch/invariants.md | less` (последний коммит, где Q&A был полным). Пометки: `[!]` — найденный дефект, не вопрос. `[?]` — не смог определить по коду. `[✓]` — отвечено владельцем 2026-10-05. ## Статус ответов (2026-10-05) Отвечено: **2.1, 5.2, 6.1, 6.3, 6.5, 7.1, 7.2** (7 пунктов). Остальные ждут ответа (таблица ниже). Ключевое из ответов: - **6.5** — `100.64.0.0` не «сетевой адрес вместо интерфейса»: Tailscale-адрес sapphira, назначен вручную. См. ADR R1.4. - **6.3** — `firewall.enable = false` на sapphira не недосмотр: граница на роутере (5 портов). См. ADR R1.3 + задачу D1. - **7.2** — 3x-ui рабочий, откат осознанный. Состояние «заморожено», не сломано. См. ADR R1.5 + задачи C1–C5. - **5.2** — подтверждённая дыра в защите данных → задача B1. ## Сводка подтверждённых инвариантов См. `.agent/rules/project-rules.md` (R1.1–R1.7) — закреплено в `AGENTS.md` §«Подтверждённые инварианты» до мерджа. | # | Пункт | Краткая формулировка | Задача | |---|---|---|---| | 1 | Все `outputs` флейка вычисляются | A1: правка `lib/xlib.nix` → `lib/xlib`; закрепить через `nix flake check` | A1 | | 2 | External-диск монтируется до сервисов | mkServiceStorage + bind без guard'а → сервис стартует на пустой БД | B1 | | 3 | Сетевая граница sapphira = роутер | 5 портов: 22, 80, 443, 8443, 22000; `firewall.enable = false` намеренно | D1 | | 4 | `100.64.0.0` = Tailscale sapphira | Назначен вручную; в 4 файлах | D2 | | 5 | 3x-ui заморожен | Панель на latest; ядро Xray на 26.7.x; миграция 26.9 провалена | C1–C5 | | 6 | nftables на VDS — явная финальная политика | Сейчас ruleset без финального правила + конфликт с `firewall.*` | A3 | | 7 | sops-пути — через `config.sops.secrets..path` | Любой `path =` override на sops-блоке делает хардкод-потребителя молча сломанным | ADR-0001 | ## Открытые вопросы (слои 0–8) Самые важные — выделены. Источник для новых задач в `.agent/tasks/manifest.json`. | ID | Вопрос | Что блокирует | |---|---|---| | 0.1 | Восстанавливать ли migration notes, удалённые в `22a19be`? | C1: реконструкция заметки 3x-ui | | 0.2 | Комментарий-density 38/120 файлов без комментариев — нормально? | Стиль модулей | | 0.3 | 15 закомментированных модулей: удалить или хранить как референс? | E3: чистота кода | | 0.4 | README пустой, todo.md нет — норма? | E1: AGENTS.md/README | | 1.3 | Лишние inputs в flake (`justray`, `nix-minecraft`, `proxy-suite`)? | Чистота flake | | 1.5 | `nix-systems` через `follows` — оптимизация размера lock | Документация | | **2.2** | **`vetymae` / `lamet` / `therima` / `soptur` — те же машины или хосты вне реестра?** | **DNS/nginx/identity** | | 2.3 | sapphira uid=1001: блокер ли использование `/mnt/archive`/`/mnt/mobile`? | Миграция ФС | | **2.5** | **stateVersion 24.05 / 24.11 / 25.05 / 26.05 — намеренный дрейф?** | **Миграции** | | 2.6 | Есть ли escape hatch для per-host отличий в xlib? | Архитектура | | 2.7 | `devices.termux` без NixOS-хоста — закрытый список | Документация | | 3.2 | `any.nix` (minimal) нужны home-manager + sops + disko? | Минималка | | **4.1** | **Как root получает доступ по SSH — authorizedKeys в коде нет** | **deploy, безопасность** | | **4.2** | **Как разрешается цикл «ключ в секрете, а нужен для расшифровки»?** | **bootstrap, recovery** | | 4.3 | Все файлы в `secrets/` покрыты `path_regex`? | sops | | 4.4 | Как подключается вторая машина / второй человек при одном age-ключе? | sops, scale | | 4.5 | `users.nix:87` — личный ключ или общий «ключ от деплоя»? | Безопасность | | 5.1 | `/mnt/services` mode 0777 — осознанно? | Безопасность | | 5.3 | NFS выключен, Samba работает — миграция? | Сетевые сервисы | | 5.4 | NTFS-том `lamet-drive` `mask=0000` — что на нём? | Семантика | | 5.5 | `therima` / `vetymae` / `soptur` в dirs.nix — реально смонтированы? | Семантика | | 5.6 | Где бэкапы БД и 3x-ui? | B2 | | 6.6 | `192.168.1.20` зашит в 30 мест — константа? | Рефакторинг | | 6.7 | DNS ↔ сервисы — как ловим рассинхрон? | Документация, CI | | **6.8** | **Публичные IP + SSH-алиасы в `home/termux.nix` — карта «хост → адреса» нужна?** | **Архитектура** | | 6.9 | Какой путь REALITY правильный сейчас? | C5 | | 7.4 | Почему не публиковать весь диапазон 14380-15379? | 3x-ui | | 8.2 | `lamet.opencodes` → `:6061` (порт miniflux) — ошибка? | nginx | | 8.4 | `onlyoffice` после трёх регрессов — работает? | Статус сервиса | | 8.5 | Что слушает `:3002` (`/whiteboard` nextcloud)? | Карта сервисов | | 8.6 | Бэкапы вне Nix — записать | Документация | ## Слой 9. home-manager **9.1** `home/home.nix:52-57` — для пользователя импортируется `home/${xlib.device.type}.nix`; для `root` — без профиля (строка 51). **Вопрос:** почему у `root` нет home-профиля — сознательно? **Кандидат:** `home/.nix` = единственный источник «что есть на этом хосте» для пользователя; добавление пакета в новый тип = правильный файл, а не `home/default.nix`. **9.2 [!]** `home/home.nix:28-43` для headless-хостов: `xdg.userDirs.* = null` и `createDirectories = false`, при этом `lib/xlib/dirs.nix:26` обещает `music-library = "${user-home}/Music"`. **Вопрос:** кто создаёт `~/Music` и `~/Storage`? `createDirectories = false` означает, что home-manager их не создаст, а `dirs.nix` на них ссылается. **Риск:** на headless-хосте путь в конфиге есть, а каталога нет → тихий сбой сервиса, который туда пишет. **9.3 [!]** `home/modules/opencode.nix:339-350` (`c73a698`): в home-manager нельзя писать `serviceConfig = { ... }` — рендерится литеральная секция `[serviceConfig]`, которую systemd молча игнорирует. Закреплено в R2. **9.4** `linger = true` добавлен ради `opencode-web` (`users.nix:71-75`) и включён **для всех** хостов. **Кандидат:** «user-сервисы переживают logout на всех хостах» — закрепить, потому что это неочевидное поведение, влияющее на ресурсы и на безопасность. **9.5** `home/modules/opencode.nix:286-303` — `opencode.web` слушает `0.0.0.0:4096` (комментарий: nginx проксирует `127.0.0.1:4096`), и nginx на sapphira ходит туда же по Tailscale у двух других хостов (см. 8.3). **Кандидат:** `0.0.0.0` в `opencode.web` — обязательное условие для внешнего доступа через `opencodes.*`; пароль приходит из sops-секрета `opencode_server`. **9.6** Секреты opencode приходят в `~/.config/opencode/server.env` (dotenv), `~/.local/share/opencode/auth.json` и `account.json` (json, `key = ""`). **Кандидат:** эти три файла перезаписываются sops при каждой активации — ручные правки в них теряются. ## Слой 10. deploy и проверка **10.1** `deploy/default.nix:20-24` — цели: `sapphira` (server), `otrecа` (vds), `rydiwo` (ноутбук). **Нет** `atoridu` (основной десктоп), `wsl`, `epral`. **Вопрос:** почему не деплоится десктоп? И безопасно ли пересобирать ноутбук `rydiwo` по SSH (он может быть выключен/на другом Wi-Fi)? **Кандидат:** `deploy-rs` = только серверы + ноутбук; десктоп и WSL обновляются вручную. **10.2** `deploy/default.nix:18-19` — `sshUser = "oqyude"`, `user = "root"`. См. 4.1: root-доход по SSH не описан в конфигурации. **10.3** `deploy/default.nix:27-29` — `checks = builtins.mapAttrs (... deployChecks)`. **Вопрос:** `nix flake check` реально проходит сейчас? **10.4** CI нет, `flake check` не запускается автоматически. **Кандидат:** минимальный локальный набор перед коммитом: `nix flake check && nix build .#nixosConfigurations.<хост>.config.system.build.toplevel --dry-run`. ## Слой 11. Формат **11.1** Где будет жить итог: `AGENTS.md` в корне (читается агентом всегда), `docs/arch/map.md` (карта хостов/сервисов), `docs/arch/invariants.md` (этот файл). **Кандидат:** этот файл после ответов превращается в `.agent/roadmap/sources.md` с колонкой «ответ» и становится источником для `.agent/context/project-state.md`; `.agent/context/project-state.md` — сжатая выжимка, без подробностей. (Сделано.) **11.2** Какие инварианты можно превратить в автоматическую проверку (тогда они перестанут «забываться»): 7 кандидатов в `analysis-report.md §5`. **Вопрос:** какие из этих проверок ты хочешь, а какие — лишний CI? ## Шаблон инварианта Этот шаблон — для добавления новых инвариантов в `.agent/rules/project-rules.md` (и для зеркалирования в `AGENTS.md`). Та же 4-осевая структура используется, чтобы вытащить «невидимое знание владельца» из существующего кода в явное утверждение. 1. **Утверждение** — что именно верно и нельзя менять без осознанного решения. Один-два абзаца, никаких «может быть». 2. **Где** — конкретные файлы и строки. Агент не должен угадывать. 3. **Почему** — что происходит при нарушении. Лучше всего — сценарий (rebuild / рантайм), а не абстрактный риск. 4. **Действие** — task id в `manifest.json`, ссылка на коммит, или явное «закреплено автоматической проверкой (см. analysis-report.md §5)». Дополнительные поля по необходимости: «ловушка» (выглядит сломанным, намеренно), «обратное» (где это уже было сломано раньше), «как проверить» (grep / CI).