fix(install): предотвращено сворачивание каталога .local

- Зачем:
  - свежая установка могла превратить ~/.local в ссылку на пакет и записать Xray в репозиторий.
- Что:
  - перед Stow теперь гарантируются настоящие ~/.local/bin и ~/.config/proxy-client без раскрытия посторонних ссылок.
  - добавлены регрессионные проверки свежего HOME и посторонней ссылки ~/.local.
  - README перестроены вокруг установки, выбора режима и ежедневного использования.
- Проверка:
  - bash tests/test_install.sh.
  - bash tests/test_proxy_launchers.sh.
  - bash -n install.sh tests/test_install.sh.
  - git diff --cached --check.
This commit is contained in:
ddadmin committed 2026-07-21 11:15:27 -04:00
1 parent bca90c1d21
commit 9c2e134fc1
5 files changed
+341 -201

No files matched your search

@@ -1,6 +1,6 @@
# Handoff: `proxy-client` переименован, Ubuntu-приёмка пройдена
Обновлён: 2026-07-21 10:08 EDT.
Обновлён: 2026-07-21 11:13 EDT.
## Состояние задачи 05
@@ -79,6 +79,14 @@ CONNECT- и SOCKS5h-соединений без ошибок; две однов
200. Известный сбой первых соединений из XTLS/Xray-core#3673 не воспроизвёлся.
Это не заменяет длительное наблюдение под обычной нагрузкой.
## Документация и установка
Корневой README сокращён до обзора, а `proxy-client/README.md` перестроен по
пути читателя: установка, выбор режима, настройка, ежедневная работа,
диагностика и справочник. Установщик заранее создаёт настоящие `~/.local/bin` и
`~/.config/proxy-client`, чтобы Stow не сворачивал изменяемые каталоги в ссылки
на репозиторий. Это покрыто свежим HOME и посторонней ссылкой `~/.local`.
## Следующий шаг
Решить, обязательна ли ручная проверка на доступной системе из семейства РЕД ОС,
@@ -87,6 +95,6 @@ Astra Linux или Alt Linux. Если нет, привести статус и
## Git
Переименование зафиксировано коммитом `6e431d8`. Обновления тикета и handoff после
успешной H3-приёмки ещё не закоммичены. Не включать посторонние неотслеживаемые
Переименование зафиксировано коммитом `6e431d8`, успешная H3-приёмка —
`bca90c1`. Не включать посторонние неотслеживаемые
`agents/.agents/.skill-lock.json` и `scripts/setup-xray-proxy.sh`.
+7 -60
View File
@@ -97,67 +97,14 @@ export ZAI_API_KEY="..." # https://z.ai
### Прокси (`proxy-client`)
Linux/Bash-команды `proxy_on/off`, `pclaude`, `pcodex` и `myip` находятся в
самостоятельном пакете [`proxy-client`](proxy-client/README.md). Он поддерживает
явно выбранный внешний Hiddify или управляемый пользовательский Xray 26.3.27 с
профилями VLESS TCP/RAW + REALITY и XHTTP + TLS. Для отдельного подключения
сначала выполните `mkdir -p ~/.config/proxy-client`, затем
`stow proxy-client`. Команды `proxy-client install/start/stop/status`
работают без systemd, автозапуска и автоматического перехода между прокси. Без
конфига сохраняется внешний Hiddify `hproxy.local:12334`.
Linux/Bash-интерфейс `proxy-client` поддерживает внешний прокси и управляемый
пользовательский Xray. Без машинного конфига используется прежний Hiddify на
`hproxy.local:12334`; автоматического запуска Xray и переключения между режимами
нет.
Имя `hproxy.local` — прежний алиас хоста с внешним прокси. Windows и VS Code
Server продолжают использовать его напрямую.
**Порты:** HTTP/HTTPS — `hproxy.local:12334`, SOCKS5 — `socks5://hproxy.local:12334`.
**WSL NAT mode** (IP шлюза меняется при каждом запуске):
```bash
# Через install.sh (интерактивно, ответить "y" на вопрос про wsl.conf)
./install.sh
# Или вручную:
sudo tee -a /etc/wsl.conf <<'EOF'
[boot]
command = "/path/to/dotfiles/scripts/setup-hproxy.sh"
EOF
```
После изменения `wsl.conf` — `wsl --shutdown`. Обновить без перезапуска: `sudo scripts/setup-hproxy.sh` или `update_hproxy`.
**WSL mirrored mode** (`networkingMode=mirrored`) — имя резолвится из WSL через DNS/hosts хоста. Достаточно записи на стороне Windows:
```
# C:\Windows\System32\drivers\etc\hosts
192.168.1.100 hproxy.local
```
Проверка: `getent hosts hproxy.local` (запись в Linux `/etc/hosts` не обязательна).
**Native Linux** — прокси на localhost, нужна запись в `/etc/hosts`:
```bash
echo '127.0.0.1 hproxy.local' | sudo tee -a /etc/hosts
```
**VS Code Server** — `vscode/.vscode-server/server-env-setup` автоматически подхватывает `hproxy.local` и выставляет все proxy-переменные (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY и lowercase-варианты). Если `hproxy.local` не резолвится — прокси не включается, запуск не блокируется.
**Windows pwsh** — `proxy_on` / `proxy_off` / `myip` работают аналогично bash-версиям.
**`pclaude` / `pcodex`** — явный запуск Claude/Codex CLI через прокси (bash и pwsh). Bash-версия делегирует проверку и запуск `proxy-client run`; Windows-версия сохраняет прежний адрес `hproxy.local:12334`. Таймаут — `PROXY_PREFLIGHT_TIMEOUT`, по умолчанию 2 c. Если прокси недоступен, клиент не запускается. Proxy-переменные видны только дочернему процессу и не остаются в сессии. Голые `claude`/`codex` не перекрываются и идут напрямую — для прокси нужен явный `p`-префикс.
**Codex GUI на Windows** — chezmoi создает Start Menu ярлык `Codex Proxy`, который запускает Codex Windows App с proxy-переменными:
```powershell
HTTP_PROXY=http://hproxy.local:12334
HTTPS_PROXY=http://hproxy.local:12334
ALL_PROXY=socks5://hproxy.local:12334
NO_PROXY=hproxy.local,localhost,127.0.0.1,::1,[::1],.concept-software.ru
```
Ярлык вызывает `~/.local/bin/start-codex-proxy.ps1`. Скрипт также добавляет эти переменные в `WSLENV` с флагом `/u`: это штатный мост Windows → WSL, чтобы дочерние WSL-сессии, запущенные из Codex GUI, получили тот же proxy environment.
[Установка, выбор режима, WSL и ежедневное использование](proxy-client/README.md)
описаны рядом с пакетом. Windows PowerShell и ярлык `Codex Proxy` сохраняют
прежнюю интеграцию с `hproxy.local:12334`.
### Git baseline
+8
View File
@@ -317,6 +317,14 @@ done
migrate_zed_config_stow_symlink
if [ ! -L "$HOME/.local" ]; then
mkdir -p "$HOME/.local"
fi
if [ -d "$HOME/.local" ] && [ ! -L "$HOME/.local" ] \
&& [ ! -L "$HOME/.local/bin" ]; then
mkdir -p "$HOME/.local/bin"
fi
if [ ! -L "$HOME/.config" ]; then
mkdir -p "$HOME/.config"
fi
+288 -138
View File
@@ -1,175 +1,325 @@
# proxy-client
Переносимый Linux/Bash-интерфейс для безопасного запуска команд через явно
настроенный внешний прокси или через управляемый пользовательский Xray.
`proxy-client` — переносимый Linux/Bash-интерфейс для запуска команд через
внешний прокси или через управляемый пользовательский Xray. Он добавляет команды
`proxy_on`, `proxy_off`, `pclaude` и `pcodex`, но не подменяет обычные `claude`
и `codex`.
CLI требует Python 3.8+ и использует только стандартную библиотеку. Он ничего не
устанавливает и не запускает без явной подкоманды. `start` использует первый
`xray` из `PATH`; скачивания и установки при запуске нет.
CLI требует Python 3.8+ и использует только стандартную библиотеку. Он не
запускает Xray и не переключает режим прокси без явной команды пользователя.
## Подключение
## Установка
В составе dotfiles:
### В составе dotfiles
Полная установка подключает пакет и автоматически загружает Bash-функции в
новых интерактивных сессиях:
```bash
cd ~/dotfiles
mkdir -p ~/.config/proxy-client
./install.sh
```
Установщик заранее создаёт `~/.local/bin` и `~/.config/proxy-client`, чтобы Stow
размещал ссылки внутри них, а не превращал сами каталоги в ссылки на
репозиторий.
После установки откройте новый Bash или выполните:
```bash
source ~/.bash_custom
```
### Только пакет `proxy-client`
```bash
cd ~/dotfiles
mkdir -p ~/.local/bin ~/.config/proxy-client
stow proxy-client
source ~/.config/proxy-client/shell.bash
```
Полный `./install.sh` выполняет тот же `stow` вместе с остальными пакетами, а
`.bash_custom` подключает модуль автоматически.
Если Bash-пакет dotfiles не установлен, добавьте подключение модуля в
`~/.bashrc`:
Без остальных dotfiles можно создать две ссылки:
```bash
printf '%s\n' 'source ~/.config/proxy-client/shell.bash' >> ~/.bashrc
```
## Как выбирается прокси
Режим определяется только машинным файлом
`~/.config/proxy-client/config`:
| Машинный конфиг | Используется | Что запускать |
|-----------------|-------------|---------------|
| Файла нет | Hiddify на `hproxy.local:12334` | Ничего |
| `type = external` | Указанный внешний прокси | Ничего |
| `type = xray` | Управляемый локальный Xray | `proxy-client start` |
Доступность процесса не меняет выбранный режим. Если в конфиге указан Xray, но
он не запущен, `status`, `env`, `run`, `proxy_on`, `pclaude` и `pcodex`
завершатся с ошибкой. Автоматического перехода на Hiddify или другой прокси нет.
Текущий выбор и доступность проверяет команда:
```bash
proxy-client status
```
## Настройка режима
### Hiddify в Windows, команды в WSL
Это режим по умолчанию. Если Hiddify доступен из WSL как
`hproxy.local:12334`, создавать `config` не нужно:
```bash
getent hosts hproxy.local
proxy-client status
pclaude --version
```
В WSL NAT mode IP Windows-шлюза меняется при перезапуске. Интерактивный
`./install.sh` предлагает добавить обновление `hproxy.local` в `/etc/wsl.conf`.
То же можно настроить вручную:
```ini
[boot]
command = "/path/to/dotfiles/scripts/setup-hproxy.sh"
```
После изменения выполните `wsl --shutdown` из Windows. Обновить адрес без
перезапуска WSL можно так:
```bash
sudo ~/dotfiles/scripts/setup-hproxy.sh
# или после загрузки Bash-функций:
update_hproxy
```
В NAT mode Hiddify должен слушать адрес, доступный через Windows-шлюз, а не
только `127.0.0.1`.
В [WSL mirrored mode](https://learn.microsoft.com/windows/wsl/networking#mirrored-mode-networking)
(`networkingMode=mirrored`) Windows-сервисы доступны из WSL через `127.0.0.1`.
Чтобы сохранить адрес по умолчанию, добавьте алиас в Windows hosts:
```text
# C:\Windows\System32\drivers\etc\hosts
127.0.0.1 hproxy.local
```
Альтернатива — создать `config.external` с `address = 127.0.0.1`. В обоих
случаях проверьте результат через `getent hosts hproxy.local` или
`proxy-client status`.
### Другой внешний прокси
Скопируйте пример и измените адрес, порт и локальные исключения:
```bash
cp ~/.config/proxy-client/examples/config.external \
~/.config/proxy-client/config
```
```ini
[proxy]
type = external
name = Office proxy
address = proxy.example.internal
port = 12334
no_proxy_extra = .example.internal,git.example.internal
```
Для внешнего прокси на той же Linux-машине можно указать `127.0.0.1` напрямую.
### Локальный Xray
Создайте машинный конфиг:
```bash
cp ~/.config/proxy-client/examples/config.xray \
~/.config/proxy-client/config
```
Закрытый профиль должен содержать ровно одну VLESS-ссылку:
```bash
cp ~/.config/proxy-client/examples/default.url \
~/.config/proxy-client/default.url
$EDITOR ~/.config/proxy-client/default.url
chmod 600 ~/.config/proxy-client/default.url
```
Установите проверенную версию Xray без root:
```bash
proxy-client install
```
Запустите Xray в отдельной панели tmux:
```bash
proxy-client start
```
Другой закрытый профиль можно выбрать без замены `default.url`:
```bash
proxy-client start -f ~/.config/proxy-client/work.url
```
Для переключения профиля сначала выполните `proxy-client stop`. Все файлы с
настоящими VLESS-ссылками должны иметь права `600` и не должны попадать в Git.
## Ежедневное использование
| Задача | Команда | Область действия |
|--------|---------|------------------|
| Запустить Claude через прокси | `pclaude [ARG...]` | Только дочерний процесс |
| Запустить Codex через прокси | `pcodex [ARG...]` | Только дочерний процесс |
| Запустить другую команду | `proxy-client run -- COMMAND ARG...` | Только дочерний процесс |
| Включить прокси | `proxy_on` | Текущая Bash-сессия |
| Выключить прокси | `proxy_off` | Текущая Bash-сессия |
| Проверить прокси | `proxy-client status` | Без изменения окружения |
| Получить proxy-переменные | `proxy-client env` | Машинный вывод в stdout |
| Показать внешний IP | `myip` | С учётом текущего окружения |
`run`, `pclaude` и `pcodex` передают дочернему процессу восемь вариантов
`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY` и `NO_PROXY`, включая имена в нижнем
регистре. После завершения команды переменные не остаются в оболочке.
`proxy_on` применяет те же переменные к текущей Bash-сессии только после
успешной проверки прокси. `proxy_off` удаляет их. Обычные `claude` и `codex` не
обёрнуты и не выполняют предварительную проверку, но после `proxy_on` наследуют
прокси-переменные, как и любой другой дочерний процесс.
### Жизненный цикл Xray
```bash
proxy-client install [--replace]
proxy-client start [-f PROFILE]
proxy-client status
proxy-client stop
```
`start` сначала проверяет версию и конфигурацию Xray, затем остаётся на переднем
плане. Systemd, фоновый автозапуск и скрытый запуск из `run` не используются.
Один loopback-порт принимает HTTP CONNECT и SOCKS5.
`stop` завершает управляемые процессы и удаляет созданные служебные файлы. Он
работает и после изменения машинного типа на `external`.
## Диагностика
Начните с проверки выбранного режима:
```bash
proxy-client status
```
Для внешнего Hiddify в WSL проверьте имя и порт:
```bash
getent hosts hproxy.local
curl --proxy http://hproxy.local:12334 https://example.com
curl --proxy socks5h://hproxy.local:12334 https://example.com
```
Для запущенного Xray можно дополнительно проверить созданный JSON:
```bash
xray run -test -c \
"${XDG_STATE_HOME:-$HOME/.local/state}/proxy-client/client.json"
```
Если выбран `type = xray`, но процесс не запущен, запустите его отдельно —
`proxy_on` и `run` этого не делают. Профиль XHTTP с ALPN `h3` требует доступного
UDP-маршрута до сервера; автоматического перехода на H2 нет.
Таймаут предварительной проверки по умолчанию равен двум секундам. Его можно
изменить положительным числом:
```bash
export PROXY_PREFLIGHT_TIMEOUT=5
```
## Справочник
### Ручное подключение без Stow
Можно создать ссылки на CLI, Bash-модуль и примеры либо скопировать те же файлы:
```bash
mkdir -p ~/.local/bin ~/.config/proxy-client
ln -s /path/to/proxy-client/.local/bin/proxy-client ~/.local/bin/proxy-client
ln -s /path/to/proxy-client/.config/proxy-client/shell.bash \
~/.config/proxy-client/shell.bash
printf '%s\n' 'source ~/.config/proxy-client/shell.bash' >> ~/.bashrc
ln -s /path/to/proxy-client/.config/proxy-client/examples \
~/.config/proxy-client/examples
```
Вместо ссылок файлы можно скопировать в те же пути. Исполняемому файлу нужен
режим `chmod 755`. Каталог `~/.local/bin` должен входить в `PATH`.
Исполняемому файлу нужен режим `755`, а `~/.local/bin` должен входить в `PATH`.
## Машинный конфиг
### Машинный конфиг
Скопируйте пример нужного режима и отредактируйте его:
Формат строгий: одна секция `[proxy]` и пять обязательных ключей без повторов и
неизвестных полей:
```bash
mkdir -p ~/.config/proxy-client
cp ~/.config/proxy-client/examples/config.xray ~/.config/proxy-client/config
# или для внешнего Hiddify:
cp ~/.config/proxy-client/examples/config.external ~/.config/proxy-client/config
```
- `type` — `external` или `xray`;
- `name` — имя для диагностики;
- `address` — IPv4, IPv6 без квадратных скобок или ASCII DNS-имя без схемы и
порта;
- `port` — TCP-порт локального входа;
- `no_proxy_extra` — дополнительные IP и домены через запятую, значение может
быть пустым.
Формат строгий: одна секция `[proxy]`, пять обязательных ключей без повторов и
неизвестных полей.
```ini
[proxy]
type = external
name = Hiddify
address = hproxy.local
port = 12334
no_proxy_extra = .example.internal,git.example.internal
```
`address` — IPv4, IPv6 без квадратных скобок или ASCII DNS-имя без схемы и
порта. `no_proxy_extra` — список через запятую; значение может быть пустым.
Поддержка CIDR в `NO_PROXY` различается между программами, поэтому надёжнее
указывать точные IP и домены.
указывать точные IP и домены. Без машинного файла внешний режим дополнительно
включает `.concept-software.ru` в `NO_PROXY`. Для `type = xray` адрес обязан
быть адресом обратной петли, например `127.0.0.1` или `::1`.
Если файла нет, используется прежний внешний Hiddify на
`hproxy.local:12334`, включая `.concept-software.ru` в `NO_PROXY`. Это не
переключает тип прокси автоматически.
### Поддерживаемые профили
Для управляемого Xray задайте явный тип, loopback IP и нужный локальный порт:
```ini
[proxy]
type = xray
name = Local Xray
address = 127.0.0.1
port = 12334
no_proxy_extra = .example.internal,git.example.internal
```
Секретный профиль хранится отдельно. Скопируйте синтетический пример, замените
его одной настоящей VLESS-ссылкой и закройте права конечного файла:
```bash
cp ~/.config/proxy-client/examples/default.url ~/.config/proxy-client/default.url
chmod 600 ~/.config/proxy-client/default.url
```
Файл должен содержать ровно одну непустую строку. Можно передать другой файл
через `proxy-client start -f /path/to/profile.url`. Если это симлинк, проверяются
права конечного файла.
## Команды
```bash
proxy-client install [--replace]
proxy-client status
proxy-client start [-f PROFILE]
proxy-client stop
proxy-client env
proxy-client run -- COMMAND ARG...
proxy_on
proxy_off
pclaude [ARG...]
pcodex [ARG...]
myip
```
`install` без root устанавливает единственную поддержанную версию Xray
`26.3.27` в `~/.local/bin/xray`. Для `x86_64`/`amd64` используется официальный
`Xray-linux-64.zip`, для `aarch64`/`arm64` — `Xray-linux-arm64-v8a.zip`.
Остальные архитектуры отклоняются. CLI скачивает рядом файл `.dgst`, проверяет
единственную запись `SHA2-256= <64 lowercase hex>` в официальном
четырёхстрочном формате, извлекает `xray` в закрытый временный каталог внутри
`~/.local/bin`, проверяет `xray version` и только затем атомарно меняет
назначение. Дубликаты, uppercase, пропущенные и лишние записи отклоняются.
Архив и извлечённый бинарник ограничены 64 MiB, `.dgst` — 4 KiB; объявленный
`Content-Length` должен точно совпадать с фактически прочитанным размером.
Существующая корректная версия `26.3.27` даёт успешный no-op без сети. Другой,
битый, неисполняемый файл или симлинк не заменяется без `--replace`; каталог не
заменяется никогда. Если после установки `PATH` выбирает не этот файл, команда
завершается с ошибкой и предлагает поставить `~/.local/bin` в начало `PATH`,
но проверенная установка сохраняется. Родительский симлинк принимается, только
если разрешённый каталог остаётся внутри `HOME`. Во время живого или
неподтверждённого managed-экземпляра установка запрещена: сначала выполните
`proxy-client stop`.
Для `external` команды `status`, `env` и `run` проверяют настроенный адрес и
порт. Для `xray` они дополнительно требуют закрытое состояние именно того
супервизора и дочернего Xray, который запустил CLI. Один открытый порт или чужой
PID не принимается. `run` никогда не запускает Xray скрыто.
`start` поддерживает только Xray `26.3.27`, сначала выполняет
`xray version` и `xray run -test`, затем остаётся на переднем плане. Используйте
отдельную панель tmux. После готовности один loopback-порт принимает HTTP и
SOCKS. `stop` ограниченно ждёт завершения супервизора и Xray, очищает служебные
файлы и возвращает исходный `start` в терминал. Команда `stop` работает и после
явного переключения машинного типа на `external`. CLI не создаёт systemd-службу,
не запускает Xray автоматически и не переключается между типами прокси.
`run` передаёт восемь proxy-переменных только дочернему процессу и сохраняет
аргументы и код возврата. `proxy_on` атомарно применяет те же восемь переменных
к текущей Bash-сессии; `proxy_off` удаляет их.
Таймаут проверки задаётся положительным числом секунд:
```bash
export PROXY_PREFLIGHT_TIMEOUT=2
```
Значение по умолчанию — 2 секунды. `env` при успехе печатает только восемь строк
`KEY=value`; для обычной диагностики используйте `status` или `myip`.
## Поддерживаемые профили
Поддерживаются только VLESS TCP/RAW с REALITY и VLESS XHTTP с TLS. Неизвестные,
Поддерживаются VLESS TCP/RAW с REALITY и VLESS XHTTP с TLS. Неизвестные,
повторные и несовместимые query-параметры отклоняются. XHTTP поддерживает ALPN
`http/1.1`, `h2` и `h3`; `extra` должен быть JSON-объектом без повторных ключей.
Xray 26.3.27 использует `pcs` и `vcn`, а устаревшие `allowInsecure` и
`insecure` не переносит. Истинное legacy-значение даёт предупреждение, но
обычная проверка сертификата остаётся включённой. Автоматического перехода
между версиями или типами прокси нет.
обычная проверка сертификата остаётся включённой.
Для справки при ручном конфигурировании: последняя версия Xray, где
`allowInsecure` ещё применяется, —
Последняя версия Xray, где `allowInsecure` ещё применяется, —
[25.12.8](https://github.com/XTLS/Xray-core/releases/tag/v25.12.8); опция
удалена в [26.2.6](https://github.com/XTLS/Xray-core/releases/tag/v26.2.6).
CLI такие версии не поддерживает и не устанавливает.
`proxy-client` эти версии не поддерживает и не устанавливает.
Сводка скрывает UUID и ключи. Содержимое XHTTP `path` не показывается — только
его длина. Сгенерированный JSON и состояние лежат в закрытом каталоге
`$XDG_STATE_HOME/proxy-client` либо `~/.local/state/proxy-client` и удаляются после
штатной остановки. Сбой диагностики внешнего IP через локальный HTTP-прокси
показывается как предупреждение и не останавливает уже готовый Xray.
### Проверяемая установка Xray
`proxy-client install` устанавливает Xray 26.3.27 в `~/.local/bin/xray`. Для
`x86_64`/`amd64` используется `Xray-linux-64.zip`, для `aarch64`/`arm64` —
`Xray-linux-arm64-v8a.zip`; остальные архитектуры отклоняются.
CLI скачивает официальный архив и файл `.dgst`, проверяет SHA-256, ограничения
размера и фактическую версию бинарника, а затем атомарно заменяет назначение.
Корректная уже установленная версия даёт no-op без сети. Другой файл или симлинк
не заменяется без `--replace`; каталог не заменяется никогда.
`start` использует первый `xray` из `PATH` и принимает только версию 26.3.27.
Если `PATH` выбирает другой бинарник, команда сообщает об ошибке. Во время
живого или неподтверждённого управляемого процесса установка запрещена.
### Файлы и безопасность
| Путь | Назначение |
|------|------------|
| `~/.config/proxy-client/config` | Несекретный машинный выбор режима |
| `~/.config/proxy-client/default.url` | Закрытая VLESS-ссылка, права `600` |
| `~/.config/proxy-client/examples/` | Синтетические примеры без секретов |
| `$XDG_STATE_HOME/proxy-client/` или `~/.local/state/proxy-client/` | Состояние и сгенерированный JSON |
Сводка скрывает UUID и ключи, а для XHTTP показывает только длину `path`.
Служебный каталог закрыт для других пользователей и очищается после штатной
остановки Xray. Сбой определения внешнего IP показывается как предупреждение и
не останавливает уже готовый процесс.
+27
View File
@@ -97,6 +97,10 @@ test_fresh_install_uses_home_target() {
run_install "$repo_root" "$home_dir" env WSL_DISTRO_NAME= INSTALL_INTERACTIVE_MODE=never >"$fixture/install.out"
[ -L "$home_dir/.bash_custom" ] || fail "Expected .bash_custom symlink in HOME"
[ -d "$home_dir/.local" ] || fail "Expected ~/.local directory"
[ ! -L "$home_dir/.local" ] || fail "Expected ~/.local to stay a real directory"
[ -d "$home_dir/.local/bin" ] || fail "Expected ~/.local/bin directory"
[ ! -L "$home_dir/.local/bin" ] || fail "Expected ~/.local/bin to stay a real directory"
[ -x "$home_dir/.local/bin/proxy-client" ] || fail "Expected executable proxy-client CLI in HOME"
[ -d "$home_dir/.config/proxy-client" ] || fail "Expected proxy-client config directory"
[ ! -L "$home_dir/.config/proxy-client" ] || fail "Expected proxy-client config to stay outside the repository"
@@ -221,6 +225,28 @@ test_does_not_migrate_unrelated_config_symlink() {
assert_not_exists "$unrelated_config/proxy-client"
}
test_does_not_follow_unrelated_local_symlink() {
local fixture repo_root home_dir unrelated_local target expected
fixture="$(setup_fixture)"
repo_root="$fixture/repo"
home_dir="$fixture/home"
unrelated_local="$fixture/unrelated-local"
mkdir -p "$home_dir" "$unrelated_local"
printf '%s\n' 'keep me' > "$unrelated_local/local.conf"
ln -s "$unrelated_local" "$home_dir/.local"
# Установщик не должен создавать bin через произвольную ссылку ~/.local.
run_install "$repo_root" "$home_dir" \
env WSL_DISTRO_NAME= INSTALL_INTERACTIVE_MODE=never >"$fixture/install.out" 2>&1 || true
[ -L "$home_dir/.local" ] || fail "Expected unrelated ~/.local symlink to be preserved"
target="$(readlink -f "$home_dir/.local")"
expected="$(readlink -f "$unrelated_local")"
[ "$target" = "$expected" ] || fail "Unrelated ~/.local target changed"
assert_file_contains "$unrelated_local/local.conf" "keep me"
assert_not_exists "$unrelated_local/bin"
}
test_settings_local_is_symlinked_to_repo() {
local fixture repo_root home_dir
fixture="$(setup_fixture)"
@@ -505,6 +531,7 @@ main() {
test_migrates_legacy_zed_config_symlink
test_stops_legacy_migration_when_listing_fails
test_does_not_migrate_unrelated_config_symlink
test_does_not_follow_unrelated_local_symlink
test_settings_local_is_symlinked_to_repo
test_settings_local_backup_on_existing_file
test_settings_local_dir_is_skipped