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.
This commit is contained in:
1 parent
e5323284a8
commit
6e431d875e
25 files changed
+310
-227
No files matched your search
@@ -0,0 +1,180 @@
|
||||
# 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. Сомнения, если есть.
|
||||
Reference in new issue
Block a user