fix(admin): закрыть обещания панели, которые продукт не выполнял
Девятый проход, по итогам приёмки 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 после
разнесения по каталогам совпадал бы ровно с одним файлом.
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# Speed limits and congestion policy
|
||||
|
||||
## Цель документа
|
||||
|
||||
Зафиксировать корректную speed policy без неточных упрощений.
|
||||
|
||||
## Что нельзя считать правильной схемой
|
||||
|
||||
Нельзя описывать baseline так:
|
||||
- на сервере включили host BBR
|
||||
- выдали какой-то URI
|
||||
- автоматически получили строгий лимит 50 Mbps на клиента
|
||||
|
||||
Это неверная модель.
|
||||
|
||||
## Три разные вещи, которые нельзя смешивать
|
||||
|
||||
Это главный источник путаницы в теме скоростей Hysteria.
|
||||
|
||||
| Механизм | Что это | Где задаётся |
|
||||
| --- | --- | --- |
|
||||
| **Политика HY2XS 50/50** | продуктовое решение проекта, сколько давать клиенту | `HY2XS_HYSTERIA_BANDWIDTH_UP` / `_DOWN` |
|
||||
| **Brutal bandwidth** | режим Hysteria, работающий по согласованным сторонами значениям полосы | `bandwidth.up` / `bandwidth.down` на сервере + hints на клиенте |
|
||||
| **Fallback congestion controller** | что делает Hysteria, когда Brutal не применяется | `congestion.type` / `congestion.bbrProfile` |
|
||||
|
||||
`50 mbps` здесь — **не** «оптимальная скорость Hysteria» и не свойство протокола. Это политика HY2XS.
|
||||
|
||||
## Что зафиксировано в baseline
|
||||
|
||||
### На сервере
|
||||
- `bandwidth.up = 50 mbps`
|
||||
- `bandwidth.down = 50 mbps`
|
||||
- `bandwidth.disableLossCompensation = false`
|
||||
- `ignoreClientBandwidth = false`
|
||||
- `congestion.type = bbr`
|
||||
- `congestion.bbrProfile = standard`
|
||||
|
||||
### На клиенте
|
||||
Совместимый клиентский конфиг должен задавать соответствующие bandwidth hints:
|
||||
- `up_mbps = 50`
|
||||
- `down_mbps = 50`
|
||||
|
||||
## Практический смысл
|
||||
|
||||
Ожидаемый 50/50 Mbps contract считается корректным только тогда, когда сервер и клиентская конфигурация согласованы.
|
||||
|
||||
Логика выбора внутри Hysteria:
|
||||
|
||||
- когда стороны согласовали Brutal bandwidth — используется Brutal;
|
||||
- когда это не применяется — используется выбранный fallback congestion controller.
|
||||
|
||||
Поэтому BBR тоже является частью явного baseline HY2XS, а не «настройкой по умолчанию, о которой можно не думать».
|
||||
|
||||
## Loss compensation
|
||||
|
||||
```yaml
|
||||
bandwidth:
|
||||
disableLossCompensation: false
|
||||
```
|
||||
|
||||
Компенсация потерь (появилась в Hysteria 2.10.0) позволяет отправлять быстрее заданной полосы, чтобы компенсировать потерю пакетов. В baseline HY2XS она **включена**, а значение фиксируется в конфиге явно — проект про воспроизводимое поведение, а не про молчаливое следование upstream-дефолтам.
|
||||
|
||||
## Что делать с host-level BBR
|
||||
|
||||
`net.ipv4.tcp_congestion_control=bbr` можно оставить как общий системный тюнинг, но:
|
||||
|
||||
- это не главный механизм speed policy Hysteria2;
|
||||
- это не замена клиентским bandwidth hints;
|
||||
- это **не то же самое**, что `congestion.type: bbr` в конфиге Hysteria — у Hysteria собственный congestion-control контур поверх QUIC;
|
||||
- это не центр документации по лимитам.
|
||||
|
||||
## Что фиксировать в `post-install.env`
|
||||
|
||||
Минимум:
|
||||
- `HY2_BANDWIDTH_UP`
|
||||
- `HY2_BANDWIDTH_DOWN`
|
||||
- `HY2_IGNORE_CLIENT_BANDWIDTH`
|
||||
- `HY2_DISABLE_LOSS_COMPENSATION`
|
||||
- `HY2_CONGESTION_TYPE`
|
||||
- `HY2_BBR_PROFILE`
|
||||
|
||||
Дополнительно фиксируется `HY2_VERSION` как фактически установленная версия Hysteria2 и `HY2_RESOLUTION` как способ её выбора при сборке пакета.
|
||||
|
||||
## Что нельзя писать в проектных доках
|
||||
|
||||
Не писать:
|
||||
- «лимит задаётся только на сервере, клиент не важен»
|
||||
- «любой URI достаточно для полной speed policy»
|
||||
- «host BBR и есть логика Hysteria»
|
||||
- «50 mbps — оптимальная скорость Hysteria» (это политика HY2XS, а не свойство протокола)
|
||||
- «Brutal и congestion controller — одно и то же»
|
||||
|
||||
## Правильная baseline-формулировка
|
||||
|
||||
Пер-клиентный лимит 50/50 Mbps обеспечивается согласованной серверной и клиентской конфигурацией. Install baseline отвечает за серверную часть этого контракта; конкретный delivery/access слой в этот документ не входит.
|
||||
Reference in New Issue
Block a user