Files
HY2XS_flamy/docs
founder b22b4b0d99 fix(v1): сделать read-only свойством doctor, а sentinel-ошибки — решением
Два свойства были описаны в документации, но не обеспечены кодом.

1. doctor «не изменяет диагностируемую систему».

   Принудительный skipServiceStart закрывал ровно одну ИЗВЕСТНУЮ мутацию —
   рестарт сервисов. Всё остальное в smoke держалось на том, что автор правки
   выбрал правильный раннер: `test -s`, `grep -q`, `stat`, `sudo -u ... test`
   и `nft -c` шли через мутирующий namespace, хотя ничего не меняют. Ожидание
   между попытками выполнялось подпроцессом `sleep` через runMutatingHidden,
   то есть пауза между двумя чтениями объявлялась изменением системы.

   Следствие: настоящая мутация, случайно добавленная в smoke, ничем бы от них
   не отличалась и была бы разрешена в doctor молча — а включить guard было
   нельзя, он отказал бы на первой же читающей команде.

   Команды классифицированы честно, `sleep` заменён таймером, и doctor целиком
   выполняется под тем же read-only guard, что и PHASE 0 установки. Guard
   снимается в finally. Диагностика при этом не сузилась: слушатели, healthz,
   права, machine auth, trafficStats, версия бинаря, семантика конфига и
   синтаксис nft проверяются полностью.

2. reset-admin различает «администратора нет» и «база не ответила».

   Слой данных специально возвращает разные sentinel'ы, но команда склеивала их
   обычным `if err != nil { создать } else { обновить }`. Опасен здесь не
   только нарушенный смысл: при транзиентном отказе чтения («database is
   locked») ветка создания отрабатывала успешно, и в таблице оказывались ДВЕ
   учётные записи администратора. GetAdminUser берёт First() и о второй строке
   не сообщает — на сервере оставалась вторая рабочая учётка с паролем, уже
   напечатанным на экран, и ни один запрос об этом не говорил.

   Заодно исправлено проглатывание ошибки хеширования: в ветке обновления
   стояло `hash, _ := util.HashPassword(password)` внутри литерала map. При
   отказе bcrypt в password_hash уезжала пустая строка, а на экран печатался
   пароль, которым войти уже невозможно — VerifyPassword отклоняет всё, что не
   bcrypt. Команда восстановления доступа умела молча его отобрать.

Тесты: doctor-readonly.test.ts дополнен поведенческой проверкой guard и
контролем набора раннеров в smoke; apps/cmd/reset_test.go проверяет обе ветки
на настоящей SQLite и отказ чтения при полностью работоспособной базе — ровно
тот случай, который прежний код превращал во второго администратора. Добавлена
dao.CountAdminUsers: до неё появление дубликата было ненаблюдаемым.
2026-08-30 18:28:39 +05:00
..

HY2XS baseline docs

Этот набор документов фиксирует актуальную baseline-модель HY2XS под следующие ограничения:

  • серверный транспорт: ванильная Hysteria2
  • UI: HY2XS admin, штатный компонент проекта, поставляется вместе с пакетом
  • target OS: только чистый Debian 13
  • оркестратор: install-only, только первичная установка и базовая настройка
  • стек оркестратора: Bun + TypeScript
  • target-side build: запрещён
  • standalone update / rollback / uninstall subcommands: вне scope
  • сборка и упаковка: отдельный локальный build layer
  • post-install state: /etc/hysteria/post-install.env
  • установка: только на чистый хост, миграция с 0.x не поддерживается
  • контракт версий продукта/платформы/toolchain: корневой versions.env
  • клиентский delivery/access layer: вне baseline этого пакета docs

Главная архитектурная схема

В этой редакции зафиксированы два слоя:

  1. Builder layer — работает на отдельном Debian 13 amd64 build host. Он собирает итоговый пакет, собирает HY2XS admin, компилирует Bun/TypeScript оркестратор в install-артефакт, упаковывает шаблоны, unit-файлы и примеры конфигов.

  2. Runtime / target layer — работает на чистом Debian 13. Здесь нет сборщика. Здесь запускается только итоговый install package / orchestrator, который:

    • ставит системные зависимости
    • разворачивает встроенный HY2XS admin
    • забирает закреплённую в пакете Hysteria2 из официального upstream и сверяет её по SHA-256 и версии
    • создаёт конфиги, systemd unit-файлы и post-install.env
    • выполняет базовую настройку сервера

Версия Hysteria2 выбирается на builder layer: последняя стабильная разрешается при сборке и замораживается в metadata пакета. Target layer никогда не обращается к moving latest.

Базовые правила

  1. Hysteria2 не вендорится и не собирается как часть HY2XS.
  2. HY2XS admin — штатный компонент проекта и поставляется вместе с пакетом.
  3. Оркестратор пишется на Bun + TypeScript.
  4. На target нет npm / pnpm / yarn / bun install / transpile step.
  5. На target нет standalone логики update / rollback / uninstall.
  6. В install/reconfigure есть bounded rollback для failure-сценариев firewall/systemd/config/smoke. Rollback опирается на то, что операция реально успела применить: сервисы, которые она не разворачивала, не останавливаются никогда.
  7. Установка двухфазная: PHASE 0 — read only, PHASE 1 — mutation. До успешного clean-host preflight на сервере не изменяется ни один persistent path. У мутирующей фазы ровно один владелец — оркестратор: install.sh проверяет и передаёт управление, не изменяя ничего сам. Очистка предыдущей установки — отдельная явная операция оператора, см. 14-legacy-cleanup.md.
  8. Выдача доступа пользователям, Telegram-бот, billing, backend профилей и похожие контуры не входят в этот baseline.

Состав документов

  1. 01-architecture-baseline.md
  2. 02-build-layer-and-package.md
  3. 03-server-hysteria2.md
  4. 04-admin-panel.md
  5. 05-client-and-access-scope.md
  6. 06-speed-limits-and-congestion.md
  7. 07-systemd-and-firewall.md
  8. 08-orchestrator-spec.md
  9. 09-post-install-env.md
  10. 10-access-layer-out-of-scope.md
  11. 11-testing-and-acceptance.md
  12. 12-operations-and-troubleshooting.md
  13. 13-production-runbook.md
  14. 14-legacy-cleanup.md

История изменений проекта — в CHANGELOG.md.

Жёсткие рамки baseline

Не делаем:

  • upgrade manager
  • rollback manager
  • uninstall
  • reconcile engine
  • target-side build pipeline
  • Docker baseline
  • multi-node
  • port hopping
  • Telegram-бот
  • backend выдачи remote profiles
  • «умную» миграцию сломанных старых инсталляций

Одной фразой

Правильная baseline-модель теперь такая:

Локальный builder разрешает последнюю стабильную Hysteria2, проверяет её на совместимость с конфигом HY2XS и собирает install package с HY2XS admin и Bun/TypeScript оркестратором; серверный install-only orchestrator ставит этот пакет на чистый Debian 13, скачивает ровно закреплённую Hysteria2, разворачивает HY2XS admin, создаёт systemd + nftables + post-install env и подготавливает рабочее серверное окружение.