Files
dotfiles/.scratch/headless-xray-proxy/issues/01-external-proxy-and-portable-shell.md
T
ddadminandClaude Fable 5 98bfd6338a refactor(xray-proxy): срезана accidental-сложность CLI, тестов и спеки
- Зачем:
  - CLI и спека были переусложнены относительно принятой модели угроз
    (один пользователь, доверенная машина): лишняя ось версий Xray и
    защита от входов, которые не возникают при ручном редактировании.
- Что:
  - убрана поддержка Xray 25.12.8 — поддерживается только 26.3.27;
    allowInsecure валидируется, но никогда не эмитится в JSON.
  - удалена проверка владения сокетом через /proc/net/tcp; идентичность
    процесса и сверка адрес/порт со state сохранены.
  - валидация INI/профиля/адреса/query сведена к отказам на реальные
    опечатки; scoped IPv6 отклоняется одинаково на Python 3.8 и 3.9+.
  - удалены fsync/O_EXCL-церемония, SIGALRM-таймер, zombie-инспекция,
    мёртвый отпечаток профиля и двойной разбор extra/alpn.
  - shell.bash принимает вывод env без ре-валидации, сохранив атомарность;
    спека и issue 01–05 приведены к новому объёму (тикет 06, леджер).
- Проверка:
  - python3 -m unittest discover -s tests — 34 теста OK.
  - bash tests/test_proxy_launchers.sh — 8 проверок PASS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 04:13:54 -04:00

71 lines
6.3 KiB
Markdown

# 01 — Внешний прокси и переносимый Bash-интерфейс
**What to build:** Самостоятельный пользовательский пакет прокси, через который
можно безопасно запускать команды с уже работающим внешним прокси, например
Hiddify. Привычные Bash-команды переходят на единый CLI-контракт, но прежний
сценарий без машинного конфига продолжает работать.
**Blocked by:** None — can start immediately.
**Status:** done
Часть требований пересмотрена в 06 — см. 06-simplification-pass.md.
- [x] CLI работает на Python 3.8+ без сторонних библиотек, ничего не устанавливает
и не запускает без явной подкоманды и выдаёт понятную ошибку на более старом
Python.
- [x] Машинный INI явно различает типы `external` и `xray`, проверяет имя, адрес,
порт и добавку к `NO_PROXY`; отсутствие файла сохраняет внешний прокси
`hproxy.local:12334` без неявного переключения на другой тип.
- [x] Канонический машинный INI содержит единственную секцию `[proxy]` и ровно
по одному ключу `type`, `name`, `address`, `port`, `no_proxy_extra`:
```ini
[proxy]
type = external
name = Hiddify
address = hproxy.local
port = 12334
no_proxy_extra = .example.internal,git.example.internal
```
Все ключи обязательны при наличии файла; `no_proxy_extra` может быть пустым.
Неизвестные секции и ключи, повторы, пропуски, многострочные или содержащие
NUL значения, пустые имя или адрес и порт вне диапазона 1–65535 отклоняются.
Добавки к `NO_PROXY` задаются через запятую, окружающие пробелы удаляются,
пустые элементы отклоняются.
- [x] `address` принимает IPv4, IPv6 без квадратных скобок либо ASCII DNS-имя
из корректных непустых меток; схема URL, встроенный порт, скобки, zone ID,
пробелы, `/`, `@` и другие URL-разделители отклоняются. При формировании
proxy-URL CLI сам заключает IPv6-литерал в квадратные скобки.
- [x] Для типа `external` команды `status`, `env` и `run -- COMMAND ARG...`
проверяют только настроенный адрес и порт; недоступный прокси запрещает запуск
дочерней команды с понятным сообщением.
- [x] До реализации управляемого процесса конфиг с `type=xray` обрабатывается
безопасным отказом: `status`, `env`, `run` и `start` не считают один открытый
порт доказательством управляемого Xray и не запускают дочернюю команду.
- [x] `env` при успехе печатает только восемь разрешённых proxy-переменных в двух
регистрах, а при ошибке не печатает частичный результат; базовый `NO_PROXY`
включает loopback и узел прокси, затем дополняется машинной настройкой.
- [x] Документированный `PROXY_PREFLIGHT_TIMEOUT` сохраняется как положительное
число секунд с прежним значением по умолчанию `2` для проверок доступности из
`status`, `env` и `run`; ошибочное значение даёт понятный отказ.
- [x] `run` без искажений сохраняет аргументы и код возврата команды, передаёт
proxy-переменные только дочернему процессу и возвращает отдельную понятную
ошибку, если команда отсутствует в `PATH`.
- [x] Переносимый Bash-модуль становится единственным владельцем `proxy_on`,
`proxy_off`, `pclaude`, `pcodex`, `myip` и внутренних proxy-помощников;
WSL-функция обновления `hproxy.local` остаётся независимой.
- [x] Обычный запуск dotfiles подключает общий Bash-файл и переносимый
proxy-модуль независимо: после установки доступны все пять proxy-команд и
`update_hproxy`; подключение одного переносимого модуля без остальных
dotfiles также предоставляет все пять proxy-команд.
- [x] Bash-модуль принимает вывод `env` атомарно, проверяет белый список и
наличие каждого из восьми ключей ровно один раз, не использует `eval` и при
любом неверном выводе оставляет прежние восемь переменных без изменений;
`proxy_on` и `proxy_off` больше не делают автоматический запрос внешнего IP.
- [x] Автоматические тесты подтверждают прежний внешний Hiddify-сценарий,
fail-fast, оба регистра переменных, настраиваемый `NO_PROXY`, отсутствие
протечки окружения, обычное и самостоятельное подключение Bash-модуля,
безопасный отказ для `type=xray` и атомарный разбор полного вывода `env`.