14 KiB
14 KiB
Этап 11А: пользователи и администрирование устройств
Статус: подготовка 2026-10-01. ReUI PRO/base-nova, существующие Frame, KpiStatGrid, Data Grid v9 и Sheet. Изменения последовательно, локальные коммиты без push.
Референсы и схемы
| Область | Референс | Схема |
|---|---|---|
| Обзор раздела | Settings 16 / Stats 12 | Источник → подтверждённая сводка → проблемы → действие |
| Таблицы | Data Grid Filtering 2 | Фильтры → объект → детали → результат API |
| Формы | Sheet 8 | Контекст → форма → проверка → подтверждённый результат / сохранённый черновик |
[Источник и права]
↓
[Каталоги + свежесть] → [Ошибка: последние данные, явный повтор]
↓
[Объект / детали] → [Форма с черновиком]
↓
[Подтверждение API / частичное выполнение]
↓
[Повторное чтение / восстановление контекста]
Карта реализации
| Порядок | Раздел / API | Исходная проблема | Точка завершения |
|---|---|---|---|
| 1 | Пользователи: /users, /servers | Live начинает с INIT_USERS; Promise.all связывает независимые отказы; нет свежести и защиты смены источника | Пустой/unknown/ошибка различаются, последний снимок и read-only права |
| 2 | Профиль и привязки: /users/:id, /bindings | Многошаговое сохранение, нет lock удаления, refresh ошибка проглатывается; Sheet эффект может сбросить форму | Частичное выполнение явно показано, повтор без дублей, успешный API отдельно от refresh |
| 3 | Interface catalog | Ошибка превращается в []; каталог может сохранять прежнее устройство; peer ошибки требуют проверки | Контекст и доступность, точный выбор, сохранение формы |
| 4 | Пользователи UI | «Пригласить» фактически создаёт профиль; icon actions без имён, raw colors, доступность формы | ПК/390/320, клавиатура, понятные подписи/токены |
| 5 | Контейнеры | Отказ очищает прошлые объекты, Promise.all и операции требуют защиты/валидации | Состояния снимка, реальные подтверждения действий, контекст/права |
| 6 | Сертификаты | Сводка, доступность экспорта/операций и конкретный сервер требуют аудита | Неизвестные статусы, действительный экспорт и ошибки API |
| 7 | Резервирование | Общий Promise.all четырёх источников, polling задач/интеграций и сохранение требуют аудита | Частичные сбои и состояние job без ложного завершения, форма сохранена |
| 8 | Приёмка 11А | Сквозные действия и общие компоненты | Профильная регрессия, production build, снимки, внешние ограничения |
Границы
- Права пользователя в профиле и Portal JWT авторизация приложения — разные существующие контракты; не менять правила выдачи доступа в UX исправлениях.
- Сохранение профиля и привязок сейчас несколько HTTP запросов. Не обещать атомарность и не повторять подтверждённое создание после частичного отказа.
- Серверный каталог — зависимость формы прав/привязок; отсутствие доступа или отказ не должен обнулять сохранённые разрешения.
- Backend/моки не подтверждают реальный Portal, PostgreSQL, RouterOS, выдачу сертификатов, восстановление backup или доступность S3. Реальную приёмку перечислять отдельно.
- Оповещения, сбор данных, интеграции, релизы, настройки и расписание диагностики — 11Б.
Блок 11А.2 — достоверная загрузка пользователей (2026-10-01)
- Live не содержит INIT_USERS/демо серверов до API. Пользователи и серверы читаются независимо: быстрый список появляется до медленного каталога; отказ одной зависимости сохраняет другую и последние подтверждённые данные. Unknown KPI — —, подтверждённый пустой список — отдельное состояние.
- Получение пользователей имеет время браузерного чтения и ручной повтор. Смена backend/mode размонтирует прежний контекст, читатели отменяются и поздние ответы не меняют новый экран. Схемы обязательны; дубли ID отклоняются.
- Права users read/write и server read проверены перед запросами/действиями. Без подтверждённых актуальных каталогов редактирование приостановлено; неизвестный общий серверный каталог не показывается числом 0. Icon действия получили имена; «Пригласить» заменено фактическим «Добавить пользователя».
- 12 data E2E + 4 context E2E, профильный lint и TypeScript прошли. Production frontend прошёл в приёмочной сборке после подготовки нового контекста; дальнейшие операции ещё не приняты. Mock ветка подписана как локальное демо.
- Далее 11А.3: lock удаления/сохранения, сохранение диалога/черновика при ошибке, поздние мутации и отдельное подтверждение API от refresh. Затем частичное сохранение привязок без дублей и interface catalog. Реальные Portal/БД ещё не проверены.
Блок 11А.3 — подтверждённое удаление пользователя (2026-10-01)
- DELETE имеет single-flight lock, AbortSignal/30s срок и защиту позднего ответа после размонтирования. Ожидание блокирует повтор/отмену диалога; ошибка остаётся в диалоге с возможностью повторить, target не теряется.
- Удаление требует существующий backend контракт HTTP 204; успешный 200 с произвольным телом не принимается. Подтверждённая строка удаляется сразу, а отказ последующего refresh не называется отказом удаления: API результат и необходимость повторного чтения показаны отдельно.
- 17 data/operations E2E + 6 context E2E, TypeScript и профильный lint прошли. Проверены 403/503/неверный ответ, двойной click, Escape, refresh error, поздний success/error прежнего backend. Созданы общие HTTP-фикстуры пользователей.
- Далее 11А.4: безопасное сохранение профиля/черновика и частичных привязок, без повторного создания при подтверждённом первом шаге. Сохранение ещё не принято; interface catalog и визуальная приёмка далее. Реальный Portal/БД не проверен.
Блок 11А.4 — многошаговое сохранение профиля и привязок (2026-10-01)
- Общий mutation lock, отмена/30s срок каждого запроса, защита прежнего источника; Sheet не сбрасывает черновик при изменении каталога/подтверждённом промежуточном шаге. Во время отправки поля/кнопки и закрытие блокируются.
- UserSaveCheckpoint сохраняет подтверждённый id профиля и каждую привязку. После частичного отказа повтор читает профиль/привязки, обновляет профиль по этому id и продолжает diff без второго POST пользователя/повторной подтверждённой привязки. Потерянный ответ DELETE/POST привязки сверяется чтением. Это несколько HTTP запросов, не атомарная транзакция.
- При неизвестном исходе POST профиля повтор заблокирован; доступно чтение списка, черновик сохранён. 4xx создания допускает исправление/повтор. UI не присваивает найденный по login чужой профиль автоматически. Подтверждённый профиль/привязки отделены от отказа refresh.
- Ответы проверяют userId/login, отправленные поля/права и контекст привязки. Wrong role/sections/servers не подтверждают сохранение. IDs в URL кодируются. Техническая многострочная ошибка схемы заменена понятной краткой ошибкой — иначе footer выходил за экран; обнаружено E2E, исправлено и повторено без ослабления теста.
- 5 fault-injection unit, 27 различных data/operations E2E и 8 context E2E прошли; TypeScript, профильный lint и production frontend прошли. В UserSheet остаётся одна исходная catalog set-state-in-effect ошибка; она входит в следующий блок, suppressions нет.
- Далее 11А.5: строгий interface catalog, loading/error/empty, точный сервер и поздние ответы/peer сбои; затем форма/таблица, клавиатура и ПК/телефон. Реальная БД/Portal не проверены.
Блок 11А.5 — каталог интерфейсов формы (2026-10-01)
- Каталог привязан к serverId/host; ожидание, error и подтверждённое empty различаются. Поздний ответ другого устройства отменяется. При повторе сохраняются прошлые строки/время получения, выбор блокируется до успешного чтения; черновик формы не сбрасывается.
- API схемы отклоняют дубли интерфейсов/пиров, отсутствующий peer snapshot и пустые ключи. Ошибка peers показана явно, не выдаётся за пустой список; выбор неподтверждённого пира блокируется. Перед привязкой выбранные объекты сверяются с текущим каталогом.
- IPsec теперь выбирает конкретного клиента/CN как требует backend; раньше весь ipsec-vpn отправлялся с пустым ключом. WireGuard остаётся выбором public-key. Время handshake/активности не называется текущим подключением.
- Frame scroll имеет высоту родителя и min-h-0 flex цепочку. Демо каталог вычисляется при рендере; последняя исходная UserSheet set-state-in-effect ошибка устранена без suppressions.
- 25 catalog/operations E2E, TypeScript и профильный lint прошли. Проверены API/malformed/дубли/неполные peer данные, empty/loading, поздний success/error другого сервера, WG failure/retry, IPsec CN payload и прежние операции.
- Далее 11А.6: backend достоверность interface catalog (сейчас snapshot/история без метаданных, неизвестные флаги и скрытый IPsec failure); затем UI/доступность и локальная приёмка пользователей. Реальные RouterOS/DB/Portal не проверены.