c0a43ae915
Девятый проход, по итогам приёмки v1.0.0-rc1 на живом Debian 13. Общая тема:
интерфейс обещал оператору то, что продукт умел, но до чего не доходило
управление.
Секрет пира. Подпись под полем предлагала оставить его пустым, сервер умел его
сгенерировать, и генерация была недостижима: в go-playground/validator тег
omitempty НЕ пропускает правило, если поле объявлено указателем и указатель не
nil — hasValue считает указатель на пустую строку «значением». Правило min=6
применялось к пустой строке и отказывало. Ловушка закрыта общим шагом
нормализации DTO, а не тегом на одном поле: та же ловушка ломала фильтр списка
пиров, где очищенный крестиком el-input отправляет `?name=`. Граница проходит по
каждому полю отдельно — у remark пустая строка означает «убрать пометку», у
disabled ноль означает «включён».
Отказы. Любая ошибка любого поля превращалась в слово `invalid`, а слой vo
определял код ответа СРАВНЕНИЕМ текста сообщения — тот же антипаттерн, который
запрещён панели, только на сервере. Ответ несёт errors[{code, field, message,
params}]; панель выбирает фразу по коду и подставляет причины под поля.
Сессия. Ветка «войдите заново» была недостижима дважды: сервер отвечает HTTP 200
на любой отказ, поэтому обработчик ошибок axios не вызывался, а условие в нём
проверяло code === "A0230" и поле msg, которых в этом API никогда не было.
Истёкший токен вдобавок уезжал с кодом системной ошибки.
Иконки. Контракт currentColor был объявлен в двух местах и не действовал: восемь
ассетов несли литеральный fill="#000000" на <path>, а атрибут представления
перебивает унаследованное CSS-свойство. Под это попадали все семь иконок
бокового меню на фоне #181818.
Имя пира. Два правила на одном поле противоречили друг другу (min=1 против
6-32), а копия набора символов в слое контроллеров несла неэкранированный дефис
и впускала `, - . / : ; <` — через панель проходило имя peer/name, которое
импорт того же пира отклонял. Набор символов ЛОГИНА сознательно не сужен и
закреплён тестом: он приходит из HY2XS_ADMIN_USER и оркестратором не
ограничивается.
Добавлены подпись «Разработано во Flamy» с адресом, принадлежащим приложению, и
контрактные тесты панели как обязательный шаг сборки. Их исполняет Bun, а не
vitest: jsdom не вычисляет currentColor и визуальной корректности не доказал бы,
зато vitest привёл бы в граф pnpm audit сотню транзитивных зависимостей.
docs/ разложена по слоям, 11-testing-and-acceptance.md (117 КБ) разбит на пять
частей, добавлен docs/acceptance/ с отчётом о прогоне rc1 и перечнем дефектов.
Обход документации в приёмке стал рекурсивным: плоский docs/*.md после
разнесения по каталогам совпадал бы ровно с одним файлом.
116 lines
8.1 KiB
Markdown
116 lines
8.1 KiB
Markdown
# 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` проверяет и передаёт управление, не изменяя ничего сам.
|
||
Очистка предыдущей установки — отдельная явная операция оператора,
|
||
см. [operations/14-legacy-cleanup.md](operations/14-legacy-cleanup.md).
|
||
8. Выдача доступа пользователям, Telegram-бот, billing, backend профилей и похожие контуры **не входят** в этот baseline.
|
||
|
||
## Состав документов
|
||
|
||
Документы разложены по слою, к которому относятся. Двузначный префикс в имени —
|
||
стабильный идентификатор документа: под ним на него ссылаются CHANGELOG,
|
||
релизные гейты и сообщения оркестратора, поэтому при переносе в каталоги он
|
||
сохранён.
|
||
|
||
### Архитектура и рамки
|
||
|
||
- [architecture/01-architecture-baseline.md](architecture/01-architecture-baseline.md) — baseline-модель двух слоёв
|
||
- [architecture/03-server-hysteria2.md](architecture/03-server-hysteria2.md) — серверный транспорт
|
||
- [architecture/05-client-and-access-scope.md](architecture/05-client-and-access-scope.md) — граница клиента
|
||
- [architecture/06-speed-limits-and-congestion.md](architecture/06-speed-limits-and-congestion.md) — ограничения скорости
|
||
- [architecture/10-access-layer-out-of-scope.md](architecture/10-access-layer-out-of-scope.md) — что вне baseline
|
||
|
||
### Сборка
|
||
|
||
- [build/02-build-layer-and-package.md](build/02-build-layer-and-package.md) — builder layer, состав пакета, требования к сборочной машине
|
||
|
||
### Runtime на target
|
||
|
||
- [runtime/08-orchestrator-spec.md](runtime/08-orchestrator-spec.md) — спецификация оркестратора
|
||
- [runtime/07-systemd-and-firewall.md](runtime/07-systemd-and-firewall.md) — systemd и nftables
|
||
- [runtime/09-post-install-env.md](runtime/09-post-install-env.md) — post-install состояние
|
||
|
||
### Панель
|
||
|
||
- [admin/04-admin-panel.md](admin/04-admin-panel.md) — HY2XS admin
|
||
- [admin/15-ui-contracts.md](admin/15-ui-contracts.md) — контракты панели: иконки, структурированные ошибки, необязательные поля, атрибуция
|
||
|
||
### Эксплуатация
|
||
|
||
- [operations/13-production-runbook.md](operations/13-production-runbook.md) — production runbook
|
||
- [operations/12-operations-and-troubleshooting.md](operations/12-operations-and-troubleshooting.md) — операции и разбор отказов
|
||
- [operations/14-legacy-cleanup.md](operations/14-legacy-cleanup.md) — очистка установки предыдущего поколения
|
||
|
||
### Проверки
|
||
|
||
- [testing/](testing/README.md) — набор проверок по слоям (бывший `11-testing-and-acceptance.md`)
|
||
- [acceptance/](acceptance/README.md) — отчёты о фактических прогонах приёмки
|
||
|
||
История изменений проекта — в [CHANGELOG.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 и подготавливает рабочее серверное окружение.**
|