Files
HY2XS_flamy/docs/architecture/06-speed-limits-and-congestion.md
T
founder c0a43ae915 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 после
разнесения по каталогам совпадал бы ровно с одним файлом.
2026-09-01 07:27:15 +05:00

96 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 слой в этот документ не входит.