feat(v1): Gecko-обфускация, latest-stable Hysteria на сборке и forward-compatible admin

Сквозная миграция HY2XS на современную Hysteria (2.12.2) и переход на v1.

Build:
- версия Hysteria резолвится на этапе сборки из HyNetworks/hysteria и
  замораживается в metadata пакета (version + immutable url + sha256);
- compatibility gate: реальный бинарник должен принять канонический конфиг
  HY2XS для gecko и salamander до создания пакета;
- сборка прогоняет тесты оркестратора и админки.

Конфигурационный контракт:
- HY2XS_CONFIG_SCHEMA_VERSION=2, чужая схема отклоняется fail-fast;
- obfs стал настоящим union gecko|salamander, gecko — default;
- obfs-блок рендерится оркестратором целиком, два подтипа одновременно
  структурно невозможны;
- современный baseline: congestion bbr/standard, disableLossCompensation=false,
  disableStatelessReset=false, полный quic-блок.

Исправления:
- share URI для gecko: генератор был завязан на Obfs.Salamander.Password и
  выдавал нерабочую ссылку при любой другой обфускации;
- SNI брался только из ACME-блока и уходил пустым при HY2XS_TLS_MODE=file;
- экспорт конфига выносил trafficStats.secret, access_token и obfs-пароль;
- экспорт терял неизвестные upstream-поля при round-trip через типизированную
  модель;
- renderRuntimeEnv печатал тип обфускации литералом, расходясь с конфигом;
- namedotcom удалён из ACME-реестра (нет в Hysteria с 2.11.0).

Тесты:
- 95 тестов оркестратора: env, рендер, семантика профиля, резолвер, rollover;
- тесты URI и экспорта в Go;
- tools/test/e2e-hysteria.sh с реальным клиентом Hysteria.

UX:
- подсказки и примеры в форме создания пира.

Прочее: CHANGELOG.md, .gitattributes (LF для target-side файлов),
документация на русском.
This commit is contained in:
2026-08-27 08:15:02 +05:00
parent 0205334cd8
commit ddf0ddf71e
53 changed files with 4827 additions and 291 deletions
+97 -34
View File
@@ -20,7 +20,10 @@ dist/hy2xs-install-<version>.tar.gz
- [`tools/build/lib/deps.sh`](lib/deps.sh) — проверка Debian/amd64, установка build dependencies, установка Go/Bun/Node.js/pnpm.
- [`tools/build/lib/package.sh`](lib/package.sh) — сборка orchestrator, сборка HY2XS admin, создание stage directory и tar.gz архива.
- [`tools/build/lib/verify.sh`](lib/verify.sh) — проверка структуры репозитория и итогового архива.
- [`tools/build/hysteria-lock.env`](hysteria-lock.env) — pinned версия, URL и SHA256 upstream Hysteria2 binary.
- [`tools/build/lib/acceptance.sh`](lib/acceptance.sh) — acceptance-проверки production-контракта.
- [`tools/build/lib/hysteria.sh`](lib/hysteria.sh) — разрешение upstream-версии Hysteria и compatibility gate.
- [`tools/build/hysteria-lock.env`](hysteria-lock.env) — fallback-значения для офлайн-сборки (`HYSTERIA_CHANNEL=pinned`).
- [`tools/test/e2e-hysteria.sh`](../test/e2e-hysteria.sh) — end-to-end проверка с реальным клиентом Hysteria.
- [`orchestrator`](../../orchestrator) — TypeScript/Bun install-only orchestrator.
- [`apps`](../../apps) — HY2XS admin: Go backend и Vue frontend.
- [`package`](../../package) — skeleton будущего install package: `install.sh`, templates, systemd units, default config.
@@ -58,13 +61,73 @@ Windows и macOS можно использовать для редактиров
- Bun `1.3.13`;
- Node.js `20.19.0`;
- pnpm `9.15.9`.
5. Собирает install-only orchestrator в standalone binary.
6. Собирает frontend HY2XS admin.
7. Собирает backend HY2XS admin в Linux amd64 binary.
5. Прогоняет тесты и типы оркестратора (`bun test`, `tsc --noEmit`).
6. Разрешает upstream-версию Hysteria, скачивает артефакт и считает SHA-256.
7. Проходит compatibility gate: реальный бинарник Hysteria должен принять канонический конфиг HY2XS.
8. Копирует package skeleton.
9. Записывает metadata и checksums.
10. Создаёт `dist/hy2xs-install-<version>.tar.gz`.
11. Проверяет, что архив содержит обязательные файлы.
9. Собирает install-only orchestrator в standalone binary.
10. Собирает frontend и backend HY2XS admin в Linux amd64 binary.
11. Прогоняет `go vet` и `go test` для HY2XS admin (после сборки frontend, потому что `go:embed all:dist` требует готовых ассетов).
12. Записывает metadata и checksums.
13. Создаёт `dist/hy2xs-install-<version>.tar.gz`.
14. Проверяет архив и прогоняет acceptance-проверки.
## Версия Hysteria: разрешение и compatibility gate
Builder не хранит версию Hysteria вручную. По умолчанию он определяет последнюю стабильную версию сам и замораживает её в пакете.
Правила разрешения:
1. канонический upstream — `HyNetworks/hysteria`;
2. принимаются только стабильные релизы, без draft и prerelease;
3. тег должен иметь вид `app/vX.Y.Z`;
4. берётся ровно один артефакт `hysteria-linux-amd64`;
5. URL используется в том виде, в каком его вернул upstream API, без пересборки строки;
6. SHA-256 считается локально от скачанного файла;
7. разрешённые значения попадают в metadata пакета.
Сравнение версий числовое, поэтому `v2.9.10` считается новее `v2.9.2`.
После разрешения обязателен compatibility gate:
```text
скачать бинарник
сверить SHA-256 и `hysteria version`
отрендерить канонический конфиг HY2XS тем же кодом, что и на target
запустить настоящий Hysteria с этим конфигом (gecko и salamander)
только после этого собирать release package
```
При несовместимости сборка останавливается:
```text
BUILD FAILED: unsupported Hysteria stable v2.13.0
```
Это осознанное решение: ошибка должна проявиться на build machine, а не на production-сервере.
Переменные:
| Переменная | По умолчанию | Назначение |
| --- | --- | --- |
| `HYSTERIA_CHANNEL` | `stable` | `stable` — разрешить последнюю стабильную через upstream API; `pinned` — офлайн-сборка по `hysteria-lock.env` |
| `HYSTERIA_VERSION_OVERRIDE` | пусто | Закрепить конкретную версию `vX.Y.Z` |
| `HYSTERIA_COMPAT_GATE` | `true` | Compatibility gate; для release-сборок обязателен |
| `HYSTERIA_WRITE_LOCK` | `false` | Записать разрешённые значения обратно в `hysteria-lock.env` |
| `HYSTERIA_GATE_PORT` | `34443` | UDP-порт для временного запуска Hysteria в gate |
| `HYSTERIA_GATE_STATS_PORT` | `34712` | TCP-порт trafficStats в gate |
| `GITHUB_TOKEN` | пусто | Опционально: снимает anonymous rate limit GitHub API |
| `SKIP_TESTS` | `false` | Аварийное отключение тестов; для release-сборок недопустимо |
Обновить lock-файл под текущий upstream:
```bash
HYSTERIA_WRITE_LOCK=true ./tools/build/build.sh
```
## Важное про Bun и старые CPU
@@ -111,7 +174,7 @@ BUN_FLAVOR=x64-baseline ./tools/build/build.sh
С явной версией и build id:
```bash
PACKAGE_VERSION=0.2.1 \
PACKAGE_VERSION=1.0.0 \
BUILD_ID=prod-$(date -u +%Y%m%dT%H%M%SZ) \
./tools/build/build.sh
```
@@ -121,59 +184,59 @@ BUILD_ID=prod-$(date -u +%Y%m%dT%H%M%SZ) \
Проверка архива:
```bash
ls -lh dist/hy2xs-install-0.2.1.tar.gz
sha256sum dist/hy2xs-install-0.2.1.tar.gz | tee dist/hy2xs-install-0.2.1.tar.gz.sha256
ls -lh dist/hy2xs-install-1.0.0.tar.gz
sha256sum dist/hy2xs-install-1.0.0.tar.gz | tee dist/hy2xs-install-1.0.0.tar.gz.sha256
```
Проверка обязательных файлов:
```bash
tar -tzf dist/hy2xs-install-0.2.1.tar.gz | grep -E '^(hy2xs-install/install.sh|hy2xs-install/orchestrator/hy2xs-orchestrator|hy2xs-install/ui/hy2xs-admin/hy2xs-admin|hy2xs-install/metadata/checksums.txt)$'
tar -tzf dist/hy2xs-install-1.0.0.tar.gz | grep -E '^(hy2xs-install/install.sh|hy2xs-install/orchestrator/hy2xs-orchestrator|hy2xs-install/ui/hy2xs-admin/hy2xs-admin|hy2xs-install/metadata/checksums.txt)$'
```
Проверка metadata:
```bash
tar -xOzf dist/hy2xs-install-0.2.1.tar.gz hy2xs-install/metadata/package.env
tar -xOzf dist/hy2xs-install-1.0.0.tar.gz hy2xs-install/metadata/package.env
```
## When to update orchestrator/bun.lock
## Когда обновлять orchestrator/bun.lock
Do not regenerate [`orchestrator/bun.lock`](../../orchestrator/bun.lock) during production builds.
Не перегенерируйте [`orchestrator/bun.lock`](../../orchestrator/bun.lock) во время production-сборки.
Update and commit [`orchestrator/bun.lock`](../../orchestrator/bun.lock) only when:
Обновлять и коммитить [`orchestrator/bun.lock`](../../orchestrator/bun.lock) следует только когда:
- [`orchestrator/package.json`](../../orchestrator/package.json) changes;
- `BUN_REQUIRED` changes in [`tools/build/lib/deps.sh`](lib/deps.sh);
- orchestrator dependencies are intentionally upgraded.
- изменился [`orchestrator/package.json`](../../orchestrator/package.json);
- изменился `BUN_REQUIRED` в [`tools/build/lib/deps.sh`](lib/deps.sh);
- зависимости оркестратора обновляются осознанно.
Production builder always runs:
Production builder всегда выполняет:
```bash
bun install --frozen-lockfile
```
If this command fails, fix and commit the lockfile in source control. Do not remove `--frozen-lockfile`.
Если команда падает, исправьте и закоммитьте lockfile в системе контроля версий. Не убирайте `--frozen-lockfile`.
## Frontend lockfile discipline
## Дисциплина lockfile для frontend
Do not regenerate frontend lock data during routine production builds.
Не перегенерируйте frontend lock data во время обычной production-сборки.
For frontend package management:
Правила управления пакетами frontend:
- [`apps/frontend/package.json`](../../apps/frontend/package.json) declares `"packageManager": "pnpm@9.15.9"`;
- builder uses pinned pnpm `9.15.9` from [`PNPM_REQUIRED`](lib/deps.sh);
- production frontend install path is always:
- [`apps/frontend/package.json`](../../apps/frontend/package.json) объявляет `"packageManager": "pnpm@9.15.9"`;
- builder использует закреплённый pnpm `9.15.9` из [`PNPM_REQUIRED`](lib/deps.sh);
- production-путь установки frontend всегда:
```bash
pnpm install --frozen-lockfile
```
If frozen install fails, update dependencies intentionally in source control and commit lockfile changes. Do not remove `--frozen-lockfile` from build flow.
Если frozen install падает, обновите зависимости осознанно в системе контроля версий и закоммитьте изменения lockfile. Не убирайте `--frozen-lockfile` из сборочного потока.
## Полезные переменные
- `PACKAGE_VERSION=0.2.1`
- `PACKAGE_VERSION=1.0.0`
- `BUILD_ID=prod-$(date -u +%Y%m%dT%H%M%SZ)`
- `BUN_FLAVOR=auto|x64|x64-baseline`
- `FRONTEND_NODE_OLD_SPACE_SIZE=2048` (default memory limit for frontend build step)
@@ -186,23 +249,23 @@ If frozen install fails, update dependencies intentionally in source control and
- `NODE_ARCHIVE_SHA256=<sha256>`
- `BUN_ARCHIVE_SHA256=<sha256>`
## Frontend memory policy
## Политика памяти при сборке frontend
Builder applies a safe default Node.js heap limit for frontend build inside [`bundle_ui()`](lib/package.sh):
Builder задаёт безопасный лимит heap для Node.js внутри [`bundle_ui()`](lib/package.sh):
```bash
--max-old-space-size=2048
```
Override options:
Способы переопределения:
- adjust default value for this policy:
- изменить значение по умолчанию для этой политики:
```bash
FRONTEND_NODE_OLD_SPACE_SIZE=3072 ./tools/build/build.sh
```
- or provide full custom Node options (if `--max-old-space-size` is already set there, builder will not append another one):
- или передать полный набор собственных Node-опций (если `--max-old-space-size` там уже задан, builder не добавит второй):
```bash
NODE_OPTIONS="--max-old-space-size=3072" ./tools/build/build.sh
@@ -229,7 +292,7 @@ echo "bun_exit=$?"
rm -rf .toolchain/bun .toolchain/bun-tmp
rm -f .toolchain/downloads/bun-linux-x64-*.zip
rm -f .toolchain/downloads/bun-linux-x64-baseline-*.zip
PACKAGE_VERSION=0.2.1 ./tools/build/build.sh
PACKAGE_VERSION=1.0.0 ./tools/build/build.sh
```
Проверить shell syntax: