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

6.3 KiB

01 — Внешний прокси и переносимый Bash-интерфейс

What to build: Самостоятельный пользовательский пакет прокси, через который можно безопасно запускать команды с уже работающим внешним прокси, например Hiddify. Привычные Bash-команды переходят на единый CLI-контракт, но прежний сценарий без машинного конфига продолжает работать.

Blocked by: None — can start immediately.

Status: done

Часть требований пересмотрена в 06 — см. 06-simplification-pass.md.

  • CLI работает на Python 3.8+ без сторонних библиотек, ничего не устанавливает и не запускает без явной подкоманды и выдаёт понятную ошибку на более старом Python.

  • Машинный INI явно различает типы external и xray, проверяет имя, адрес, порт и добавку к NO_PROXY; отсутствие файла сохраняет внешний прокси hproxy.local:12334 без неявного переключения на другой тип.

  • Канонический машинный INI содержит единственную секцию [proxy] и ровно по одному ключу type, name, address, port, no_proxy_extra:

    [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 задаются через запятую, окружающие пробелы удаляются, пустые элементы отклоняются.

  • address принимает IPv4, IPv6 без квадратных скобок либо ASCII DNS-имя из корректных непустых меток; схема URL, встроенный порт, скобки, zone ID, пробелы, /, @ и другие URL-разделители отклоняются. При формировании proxy-URL CLI сам заключает IPv6-литерал в квадратные скобки.

  • Для типа external команды status, env и run -- COMMAND ARG... проверяют только настроенный адрес и порт; недоступный прокси запрещает запуск дочерней команды с понятным сообщением.

  • До реализации управляемого процесса конфиг с type=xray обрабатывается безопасным отказом: status, env, run и start не считают один открытый порт доказательством управляемого Xray и не запускают дочернюю команду.

  • env при успехе печатает только восемь разрешённых proxy-переменных в двух регистрах, а при ошибке не печатает частичный результат; базовый NO_PROXY включает loopback и узел прокси, затем дополняется машинной настройкой.

  • Документированный PROXY_PREFLIGHT_TIMEOUT сохраняется как положительное число секунд с прежним значением по умолчанию 2 для проверок доступности из status, env и run; ошибочное значение даёт понятный отказ.

  • run без искажений сохраняет аргументы и код возврата команды, передаёт proxy-переменные только дочернему процессу и возвращает отдельную понятную ошибку, если команда отсутствует в PATH.

  • Переносимый Bash-модуль становится единственным владельцем proxy_on, proxy_off, pclaude, pcodex, myip и внутренних proxy-помощников; WSL-функция обновления hproxy.local остаётся независимой.

  • Обычный запуск dotfiles подключает общий Bash-файл и переносимый proxy-модуль независимо: после установки доступны все пять proxy-команд и update_hproxy; подключение одного переносимого модуля без остальных dotfiles также предоставляет все пять proxy-команд.

  • Bash-модуль принимает вывод env атомарно, проверяет белый список и наличие каждого из восьми ключей ровно один раз, не использует eval и при любом неверном выводе оставляет прежние восемь переменных без изменений; proxy_on и proxy_off больше не делают автоматический запрос внешнего IP.

  • Автоматические тесты подтверждают прежний внешний Hiddify-сценарий, fail-fast, оба регистра переменных, настраиваемый NO_PROXY, отсутствие протечки окружения, обычное и самостоятельное подключение Bash-модуля, безопасный отказ для type=xray и атомарный разбор полного вывода env.