127 lines
7.4 KiB
Markdown
127 lines
7.4 KiB
Markdown
# E4 UX-поток предупреждений: validate -> confirm -> apply
|
||
|
||
Дата: 2026-03-05
|
||
Статус: in-progress (E4.2 foundation реализован в GUI controller)
|
||
Владелец: Engineering
|
||
|
||
## 1) Цель
|
||
- Зафиксировать единый UX-флоу для безопасного применения multi-client policy.
|
||
- Исключить "тихие" конфликтные применения.
|
||
- Дать пользователю прозрачный diff, риски и явное подтверждение.
|
||
|
||
## 2) Базовый сценарий
|
||
1. Пользователь редактирует routing policy.
|
||
2. UI вызывает `POST /api/v1/transport/policies/validate`.
|
||
3. UI показывает результат валидации:
|
||
- `valid=true` и `block_count=0` -> можно применять.
|
||
- `valid=false` или `block_count>0` -> блокируем apply до подтверждения/исправления.
|
||
4. Если пользователь выбирает принудительное применение:
|
||
- UI показывает модал подтверждения риска,
|
||
- использует `confirm_token` из validate.
|
||
5. UI вызывает `POST /api/v1/transport/policies/apply`.
|
||
|
||
### 2.1 Сценарий Engine Switch / Connect
|
||
1. Пользователь выбирает целевой engine (`singbox|dnstt|phoenix`) или нажимает `Connect`.
|
||
2. UI формирует draft policy, где default ownership переходит к выбранному `client_id`.
|
||
3. Дальше используется тот же pipeline:
|
||
- `validate` -> (safe|risky) -> `confirm` -> `apply`.
|
||
4. После apply UI проверяет:
|
||
- `GET /api/v1/transport/clients/{id}/health`,
|
||
- расхождение `desired_engine` vs `active_engine`.
|
||
5. Если engine не поднялся, UI предлагает `rollback`.
|
||
|
||
## 3) Состояния UI
|
||
|
||
### 3.1 Draft
|
||
- Политика редактируется, но не проверена.
|
||
- Кнопка Apply отключена.
|
||
- Доступна кнопка Validate.
|
||
|
||
### 3.2 Validated (safe)
|
||
- `block_count=0`.
|
||
- Показываем diff (`added/changed/removed`).
|
||
- Apply активен без force режима.
|
||
|
||
### 3.3 Validated (risky)
|
||
- Есть блокирующие конфликты (`ownership`, `cidr_overlap`, `unknown_client`).
|
||
- Показываем список конфликтов и конкретные селекторы.
|
||
- Обычный Apply отключен.
|
||
- Доступен `Force apply` только через отдельный confirm-step.
|
||
|
||
### 3.4 Confirm required
|
||
- Модал с явным предупреждением:
|
||
- что будет перезаписано,
|
||
- какие flow могут быть прерваны,
|
||
- какие сайты/сети сменят client owner.
|
||
- Кнопка подтверждения вызывает `apply` с `force_override=true` + `confirm_token`.
|
||
|
||
### 3.5 Applied
|
||
- Показываем `policy_revision` и `apply_id`.
|
||
- Обновляем текущую policy в UI.
|
||
- Слушаем SSE `transport_policy_applied`.
|
||
|
||
### 3.6 Switching engine
|
||
- Идёт переключение активного engine.
|
||
- Кнопки mutating-действий блокируются до завершения.
|
||
- Отображается прогресс: `Validating`, `Applying`, `Waiting for health`.
|
||
|
||
### 3.7 Switch failed
|
||
- `apply` или `health` завершились ошибкой.
|
||
- Показываем `last_error` активного клиента и причину валидации/применения.
|
||
- Предлагаем быстрые действия:
|
||
- `Rollback`,
|
||
- `Switch back to previous engine`.
|
||
|
||
## 4) Тексты предупреждений (шаблоны)
|
||
- `ownership`:
|
||
- "Один и тот же селектор назначен разным клиентам. Это может вызвать нестабильную маршрутизацию."
|
||
- `cidr_overlap`:
|
||
- "CIDR-подсети пересекаются между клиентами. Пакеты могут идти не по ожидаемому интерфейсу."
|
||
- `unknown_client`:
|
||
- "Политика ссылается на несуществующий клиент. Сначала добавьте/включите клиент."
|
||
|
||
Force confirm warning:
|
||
- "Принудительное применение может вызвать кратковременный обрыв активных сессий и смену маршрута для части трафика."
|
||
|
||
## 5) UX-правила безопасности
|
||
- Без `validate` кнопка `apply` неактивна.
|
||
- `confirm_token` не хранится между сессиями UI и считается одноразовым.
|
||
- При смене `policy_revision` в фоне UI обязан повторно выполнить validate.
|
||
- При `POLICY_REVISION_MISMATCH` UI показывает "Конфигурация изменилась, нужно повторить проверку".
|
||
|
||
## 6) Web/iOS/Android паритет
|
||
- Один и тот же флоу и тексты рисков для всех клиентов.
|
||
- Разница только в визуальном представлении:
|
||
- web: side panel + modal,
|
||
- mobile: full-screen sheet.
|
||
- Логика decision-state остается одинаковой:
|
||
- draft -> validate -> (safe|risky) -> confirm -> apply.
|
||
|
||
## 7) Минимальный UI-чеклист внедрения
|
||
- Отображение `summary.block_count/warn_count`.
|
||
- Таблица `conflicts[]` с фильтром по severity/type.
|
||
- Видимый diff `added/changed/removed`.
|
||
- Модал force confirmation с явным перечислением рисков.
|
||
- Бейдж текущей ревизии policy (`policy_revision`).
|
||
- SSE-подписка на `transport_policy_validated`, `transport_policy_applied`, `transport_conflict_detected`.
|
||
- Для engine UX:
|
||
- индикатор `desired_engine / active_engine`,
|
||
- кнопки `Connect`/`Switch`,
|
||
- блокировка повторного switch, пока предыдущий не завершён,
|
||
- action `Rollback to previous engine` при неуспехе.
|
||
|
||
## 8) Статус внедрения (2026-03-07)
|
||
- E4.2 foundation в GUI controller реализован: `draft -> validate -> confirm -> apply`.
|
||
- E4.3.1 foundation в GUI реализован:
|
||
- на вкладке `AdGuardVPN` был добавлен foundation-блок `Transport engine`;
|
||
- доступен выбор client и действия `Prepare/Connect/Disconnect/Restart` через API `/api/v1/transport/clients/{id}/*`;
|
||
- отображается runtime-состояние выбранного engine (`status/iface/table/latency/last_error`);
|
||
- refresh блока привязан к transport SSE-событиям.
|
||
- E4.3.2 реализован:
|
||
- engine-блок вынесен в отдельную вкладку `SingBox`;
|
||
- `Connect/Switch` переведён на pipeline `validate -> confirm -> apply`, direct `start` для switch больше не используется;
|
||
- добавлен `Rollback policy` button.
|
||
- Следующий UX-этап:
|
||
- `desired_engine/active_engine` индикаторы и блокировка повторного switch;
|
||
- settings-переключатель видимости protocol tabs (`SingBox/DNSTT/Phoenix`).
|