Files
dotfiles/.scratch/proxy-client/issues/06-simplification-pass.md
T
ddadmin 6e431d875e refactor(proxy-client): переименован интерфейс прокси
- Зачем:
  - прежнее имя выпячивало Xray, хотя клиент поддерживает также внешний прокси, а два каталога конфигурации были неочевидны.
- Что:
  - пакет, CLI, конфигурация, состояние, тесты и документация переименованы в proxy-client.
  - машинный конфиг, профиль и два явных примера собраны в одном пользовательском каталоге.
  - свежая установка защищена от сворачивания каталога конфигурации внутрь репозитория.
- Проверка:
  - bash tests/test_proxy_client_full.sh.
  - bash tests/test_install.sh.
  - ручные start, status и xray run -test; незавершённая сетевая приёмка записана в handoff.
2026-07-21 09:31:21 -04:00

181 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 06 — Упрощение: срез accidental-сложности спеки и кода
**What to build:** Один проход упрощения по готовым issue 01–02 и спеке:
убрать поддержку второй версии Xray, избыточные защитные проверки вне
принятой модели угроз («доверенные пользователи машины», единственный
пользователь редактирует свои файлы сам) и церемонии, не нужные личному
foreground-инструменту. Поведенческие контракты из раздела «Не трогать»
сохраняются без изменений.
**Blocked by:** 02 — Управляемый Xray: полный штатный путь.
**Status:** done
**Резолюция (2026-07-20):** реализовано и принято. Дельта: CLI 1123→976,
shell.bash 116→91, тесты 1357→1236 строк; сьюты: 34 unittest OK + 8 shell
PASS. Ревью: 1 MAJOR (scoped IPv6 в упрощённом валидаторе — починен с
регрессионным тестом под Python 3.8), 1 NIT отклонён аргументированно.
Non-gating замечания ревью приняты как риски модели угроз.
**Сначала прочитать:**
1. Этот файл целиком, затем `/tmp/xray-simplify-Zeo5/06-simplify/sweep.md` —
там точный line-level blast radius каждого пункта (секция 2 — срезы A/B,
секция 3 — SIMP-N). Номера строк — ориентир, сверяй с фактическим кодом.
2. `docs/specs/2026-07-15-proxy-client-design.md` — исходная спека.
3. `proxy-client/.local/bin/proxy-client`, `proxy-client/.config/proxy-client/shell.bash`,
`tests/test_proxy_client.py`, `tests/test_proxy_client_managed.py`.
Команды проверки (обе обязательны):
- `python3 -m unittest discover -s tests` — baseline до изменений: 38
тестов, OK, ~60 с;
- `bash tests/test_proxy_launchers.sh` — baseline: 9 проверок PASS.
После изменений тестов станет меньше (удаляются тесты срезанных фич); все
оставшиеся зелёные, новые счётчики указать в отчёте.
## A. Срез dual-version: остаётся только Xray 26.3.27
- [x] `VERSION_LINE` принимает только `26.3.27`; параметр `version` убран из
сигнатур `parse_vless`, `build_xray_config`, `safe_summary`, `warn_legacy`
и их вызовов; `xray_version` остаётся воротами «поддержанная версия или
отказ» и по-прежнему показывает фактическую версию в сводке.
- [x] Ветка эмиссии `allowInsecure` для 25.12.8 и запрет `pcs`/`vcn` для
25.12.8 удалены. `parse_boolean_fields` (валидация точных `true`/`false`,
требование согласованности обоих полей, предупреждение при истинном
значении) сохраняется; `allowInsecure` никогда не попадает в JSON.
- [x] Тестовая ось версий схлопнута: lifecycle-тест гоняет один прогон
26.3.27 (обе локации профиля — default и `-f` — сохраняются);
`test_old_version_preserves_explicit_legacy_insecure` и все
25.12.8-строки табличных тестов удалены.
## B. Срез проверки владения сокетом через /proc/net/tcp
- [x] `process_owns_listener`, `process_socket_inodes`, `decode_proc_address`
и их вызовы (в `verify_managed_state` и readiness-цикле `command_start`)
удалены. Сохраняются: сверка PID/идентичности процесса, сверка
адрес/порт машинного конфига со state и `check_endpoint`-проверка
доступности порта.
- [x] `test_verified_child_must_own_configured_listener` удалён вместе с
веткой `FAKE_XRAY_LISTEN_PORT` в фейковом xray;
`test_substituted_machine_port_fails_closed...` сохраняется и зелёный.
- [x] Диагностические сообщения, упоминающие проверку владения слушателем
(в `verify_managed_state` и readiness-цикле `command_start`), обновлены:
после среза они описывают фактические проверки (идентичность процесса,
сверка адрес/порт, доступность порта), а не владение сокетом.
## C. Диета входной валидации (файлы пишет сам пользователь)
- [x] `validate_address`: сначала `ipaddress.ip_address`, иначе минимальная
проверка «непустое ASCII-имя без пробелов, схемы `://`, `@`, `/` и
квадратных скобок». RFC-строгость по меткам DNS, лимит 253 и
сопутствующие тесты удалены. Оборачивание IPv6 в `[]` при сборке URL
сохраняется.
- [x] `load_config`: сохраняется отказ на неизвестной секции/ключе и на
отсутствии обязательного ключа (ловит реальные опечатки) и диапазон
порта. Удалены: скан NUL, guard UTF-8-декодирования, отдельный запрет
`[DEFAULT]`, запрет CR/многострочных значений, case-sensitive
`optionxform`; соответствующие подкейсы тестов удалены.
- [x] `read_profile`: сохраняются разрешение симлинка, проверка прав
(group/other → ошибка с подсказкой `chmod 600`) и правило «ровно одна
непустая строка». Удалены скан NUL и guard UTF-8.
- [x] `parse_query`: сохраняются отказ на неизвестном и на повторном
query-параметре. Удалены regex на сырые `%`-последовательности и
посимвольный запрет управляющих символов.
## D. Диета церемоний
- [x] `write_private_json`: простая запись файла с правами 0600 внутри
уже-0700 каталога; O_EXCL/fsync/`os.replace`/PID-суффиксы удалены.
- [x] Валидация `PROXY_PREFLIGHT_TIMEOUT` и `PROXY_CLIENT_STOP_TIMEOUT` — один
guard «`float()` успешен и > 0, иначе понятная ошибка»; `math` не
импортируется; тесты экстремальных значений (nan/inf/1e-7/1e308)
удалены. Для `PROXY_PREFLIGHT_TIMEOUT` оставить один тест «плохое
значение → понятный отказ»; для `PROXY_CLIENT_STOP_TIMEOUT` отдельного
теста нет и добавлять его не нужно — достаточно guard'а.
- [x] `check_reachable` использует `socket.create_connection(timeout=...)`
без SIGALRM/setitimer-машинерии. Принятый риск (записан здесь):
зависший DNS-резолв на external-пути не ограничен таймаутом — для
личного инструмента пользователь прерывает вручную.
- [x] `extra` и `alpn` разбираются один раз в `parse_vless`, результат
сохраняется в профиле и переиспользуется в `build_xray_config` без
повторного разбора. `parse_json_object` сохраняет оба отказа —
на повторах ключей и на JSON-константах (`reject_constant` остаётся):
существующий тест требует отказ на уровне разбора с диагностикой про
`extra` и без запуска `run -test`, и это дешевле, чем переносить
ответственность на сериализацию.
- [x] `process_alive` — только `os.kill(pid, 0)`; чтение
`/proc/PID/stat` ради zombie-состояния удалено.
- [x] Отпечаток профиля (`profile_fingerprint`) удалён из state и кода:
он не участвует ни в одном решении. Смена профиля по-прежнему
блокируется существованием state. Вместе с ним обновлены `STATE_KEYS` и
все тестовые фикстуры state (включая точную сверку набора ключей в
managed-тестах): устаревший ключ в фикстуре не должен ронять сверку
ключей раньше, чем тест дойдёт до проверяемой идентичности процесса.
## E. shell.bash: средняя форма приёма `env`
- [x] `_proxy_apply_env_file`: при ненулевом коде возврата CLI окружение не
меняется вовсе; успешный вывод разбирается построчно по первому `=`;
применяются (через `printf -v`, без `eval`) только восемь известных
ключей, прочие строки — ошибка без частичного экспорта. Удалены сканы
NUL/CR, отдельный детектор повторов и проверка «ровно восемь строк».
Свойство «нет частичного изменения окружения при ошибке» сохраняется и
остаётся покрыто тестом.
- [x] `tests/test_proxy_launchers.sh` приведён к средней форме: проверки
повторов/CR/NUL/счётчика строк, соответствующие удалённой машинерии,
убраны или переписаны; проверки «ненулевой код возврата CLI → окружение
не тронуто», «неизвестная строка → ошибка без частичного экспорта» и
владения функциями остаются зелёными.
## F. Спека и соседние issue приведены к новому объёму
- [x] Из спеки удалены: ветка 25.12.8 (все места из секции 2 sweep-файла),
флаги `-v`/`--debug` (не реализованы), упоминание отпечатка профиля в
state; описания валидации/атомарности смягчены до фактического
поведения после этого issue. Формулировка идентичности процессов
(«PID + время старта + исполняемый файл») в спеке не меняется.
- [x] Issue 03: добавлен явный мандат «идентичность = PID + время старта
(`/proc/PID/stat`) + исполняемый файл ребёнка / путь скрипта
супервизора; текущий argv-обход заменить этим механизмом»; убраны
унаследованные упоминания срезанных фич, если есть; строка Blocked by
дополнена: «06 — Упрощение».
- [x] Issue 05: приёмка сведена к одной версии Xray 26.3.27; упоминания
25.12.8 удалены. Пункты про РЕД ОС сохранены (решение пользователя
2026-07-20: целевые системы шире Ubuntu — РЕД ОС, возможно Astra Linux
и Alt Linux; инструмент могут использовать коллеги).
- [x] В спеке в раздел ручной проверки добавлены Astra Linux и Alt Linux
как кандидаты «по мере доступности» с тем же правилом, что для РЕД ОС:
недоступная среда явно записывается как неподтверждённая, поддержка не
заявляется без фактической проверки версии Python и прогона.
- [x] В issue 01 и 02 добавлена одна строка после Status: «Часть
требований пересмотрена в 06 — см. 06-simplification-pass.md»; чекбоксы
01 и 02 не редактируются (issue 01 описывает строгую приёмку `env`,
которую этот issue смягчает, — без пометки он противоречил бы коду).
## G. Не трогать (границы)
- Строгий отказ на неизвестном/повторном query-параметре VLESS.
- Точечный `stop` только по проверенному PID; никакого pkill.
- Foreground-супервизор, проброс сигналов, очистка state.
- Изоляция окружения `run` (proxy-переменные только у ребёнка), сохранение
argv и кода возврата, `--`-разделитель.
- Fail-fast `pclaude`/`pcodex`, обратная совместимость: без машинного
конфига — внешний `hproxy.local:12334`.
- Проверка прав файла профиля (chmod 600) и loopback-only вход.
- Авто-диагностика внешнего IP на старте (несмертельная) — остаётся.
- Секреты: полная VLESS-ссылка, UUID, ключи не появляются в stdout/stderr/
argv — все существующие тесты на это остаются зелёными.
- `bash/.bash_functions`, установщик, README — не входят в этот issue.
- Никаких коммитов.
## Отчёт исполнителя
1. Изменённые файлы со строкой «зачем» на каждый.
2. Команда тестов и счётчик (все зелёные, указать новое число).
3. Чекбоксы: закрыт / не закрыт и почему.
4. Итоговая дельта `wc -l` по CLI, shell.bash и обоим тест-файлам
против baseline (1123 / 116 / 467 / 890).
5. Сомнения, если есть.