Appearance
Канал обратной связи (Feedback FAB + RUM)
Обновлено: 17.05.2026 Статус: wave K-FB1 live с 13.05. Floating Feedback Button виден на каждой странице AntRoute. Backend feedback_reports + rum_events принимает submission'ы; первый реальный feedback от Андрея получен 16.05 13:36. Адресат: Андрей (главный pilot tester), технолог-заказчик, диспетчер — все, кто видит несоответствия в продукте и хочет их зафиксировать без выхода в почту/Telegram.
Описывает канал обратной связи AntRoute: глобальный FAB-виджет на каждой странице (text/voice/screenshot), RUM-телеметрия (JS errors / UX metrics), как админ читает поток.
1. Зачем это нужно
Андрей и пилотные пользователи находят расхождения «инструкция — реальный интерфейс» в реальном времени. Email / Telegram теряют контекст: какая страница, какой role, какой timestamp. Feedback FAB решает это:
- кнопка на каждой странице, доступна одним кликом;
- автоматически фиксирует URL, role, timestamp, viewport, browser;
- сохраняет screenshot + audio + текст (опционально);
- доступен и анонимно (anti-bot токен публичный), и под auth;
- backend хранит в
feedback_reports, новые записи доступны админу через Django shell или будущий admin UI.
Параллельно RUM (rum_events) собирает performance + UX-метрики: route_change, long_task (>50ms), inp, lcp, fcp, cls, nav_timing, click_latency — для последующего поиска hotspot'ов.
2. FAB-виджет
Кнопка живёт в правом нижнем углу любой страницы. На скриншоте — кнопка свёрнута, видна как небольшой floating button:

Клик открывает modal с тремя секциями: текст, voice, screenshot:

Что в модальном диалоге:
- Текст — opional, multi-line input для описания проблемы;
- Voice — кнопка записи (MediaRecorder API), запись отправляется как audio blob, backend транскрибирует через Yandex SpeechKit (Mail.ru-Business credentials в
.env); - Screenshot — кнопка «Сделать скриншот» использует
html2canvasбиблиотеку, захватывает текущую страницу; - Submit — кнопка отправки; вызывает
useFeedback.submitFeedback()который:- ждёт
window.__antrouteRumFlush()(≤800 мс) — чтобы RUM breadcrumbs дошли до Feedback, - берёт anti-bot токен через
GET /anti-bot/token/, - POST
/feedback/report/с multipart form (text + audio_blob + screenshot_blob + metadata);
- ждёт
- Anonymous OK — если пользователь не залогинен, submit идёт без Authorization header (anti-bot токен публичный по дизайну).
3. RUM телеметрия
В отличие от FAB (явный click пользователя), RUM пассивный — собирает performance-метрики автоматически. Регистрируется в App.tsx через useEffect один раз на mount, использует PerformanceObserver + sendBeacon.
Что собирается:
| Метрика | Тип | Source |
|---|---|---|
route_change | navigation event | React Router navigation listener |
long_task | > 50ms main-thread blocks | PerformanceObserver longtask entries |
inp | input delay | Interaction-to-Next-Paint Web Vital |
lcp | Largest Contentful Paint | Web Vital |
fcp | First Contentful Paint | Web Vital |
cls | Cumulative Layout Shift | Web Vital |
nav_timing | server response timings | PerformanceNavigationTiming |
click_latency | click → next paint | manual measurement |
Особенность: user_id в rum_events всегда NULL — RUM-клиент по дизайну не пробрасывает user_id, только session_id. Это privacy-by-design choice.
4. Что админ видит сейчас
4.1. Полу-автоматический monitor
Скрипт scripts/feedback-monitor.sh (см. K-FB1 §Block 4) polling'ом раз в 20 сек проверяет feedback_reports и rum_events, при новой строке шлёт сигнал в tmux antroute_claude — Claude видит баг и фиксит за 15-20 мин. Реализация ситуативная, пока без admin UI.
4.2. SQL queries
Прямой доступ к таблицам через postgres docker:
sql
-- последние feedback за сутки
SELECT id, status, feedback_type, page_url, created_at
FROM feedback_reports
WHERE created_at > NOW() - INTERVAL '24 hours'
ORDER BY created_at DESC;
-- топ-URL по RUM events
SELECT url, count(*) FROM rum_events
WHERE created_at > NOW() - INTERVAL '24 hours'
GROUP BY url ORDER BY count(*) DESC LIMIT 20;
-- /login long_tasks performance check
SELECT count(*) FROM rum_events
WHERE metric = 'long_task' AND url = '/login'
AND created_at > NOW() - INTERVAL '24 hours';4.3. Пример живого feedback
Первый реальный feedback от Андрея (id=5, 16.05 13:36):
text
Page: /technology/operations/5db76ac4-7f0e-464e-aaf7-fc70df6c4888
Title: Технологическая операция — AntRoute
Type: bug
Browser: Chrome 148 on Windows
Screenshot: 83 KB attached
Message:
«Отсутствует подраздел "Операции" левой боковой панели раздела
Технология. В breadcrumbs он есть /Технология/Операции/ ... А в
панели его нет. Непорядок :)»Из этого admin узнал:
- Sidebar (
/components/layout/Sidebar.tsx:136) не содержит/technology/operations; - Breadcrumb labels (
/components/common/Breadcrumbs.tsx:44) показывают «Операции» → расхождение.
Это материал для следующего fix-wave'а.
5. Маршрут просмотра на 5 минут
- Войти под любым пользователем (например,
koc-4505016987-admin). - Открыть любую
/v/...страницу. - Увидеть FAB в правом нижнем углу.
- Кликнуть → открыть modal.
- (Опционально) записать короткое голосовое сообщение.
- (Опционально) сделать скриншот.
- Ввести текст «test feedback».
- Submit → toast «Отправлено».
- Открыть Django shell на сервере:
python manage.py shell -c "from feedback.models import FeedbackReport; print(FeedbackReport.objects.last())"— увидеть свою запись.
6. Что отложено
- Admin UI — пока чтение feedback через SQL / Django shell. Web-интерфейс для админа («Inbox feedback с фильтрами, threads, replies, status workflow») — отдельная задача.
- Notifications об ответе — пользователь отправил feedback, не знает что с ним. Email-уведомления «Ваш feedback принят / fixed» — будущая задача.
- Mobile FAB — Flutter mobile приложение пока не имеет FAB. Отдельный wave.
- Audio transcription readback — backend транскрибирует Voice через Yandex SpeechKit, но текст транскрипта не отдаётся обратно пользователю для проверки.
- Screenshot annotations — пользователь не может рисовать поверх скриншота (стрелки, обводки). Только raw capture.
7. Что искать в обратной связи о самом feedback'е
(Мета-фидбек: фидбек о канале фидбека.)
- FAB видимость. Заметна ли кнопка, или сливается с UI? Должна ли она быть более яркой или вызывающей?
- Modal flow. Удобно ли «текст + voice + screenshot» как три секции, или нужно «one-click submit text-only»?
- Anonymous OK. Является ли возможность отправлять без логина важной (например, для технологов-заказчиков с временным доступом)?
- Acknowledgment. Достаточно ли toast'а «Отправлено», или нужно явное «#5 принято, рассмотрим в течение N дней»?
- Permission model. Должен ли feedback модератор иметь возможность видеть screenshot/audio до текста (security review) или сразу всё?
8. Дисциплина обновления
- При появлении admin UI для чтения feedback — добавить раздел §4.3 с скриншотом интерфейса.
- При расширении набора RUM метрик — обновить §3 таблицу.
- При появлении mobile FAB — добавить §9 о mobile.
Приложение. Evidence в репозитории
docs/sprint_2026_may/active/K-FB1-feedback-fab-rum.md— task file со списком блоков (Block 1 backend done, Block 2-5 файл устарел — по факту FAB live с 13.05).antroute_backend/feedback/— Django app (models, serializers, views, services, tests).antroute_backend/monitoring/— Django app для RUM events.frontend/src/components/common/FeedbackFab.tsx— FAB виджет.frontend/src/hooks/useFeedback.ts— логика записи / submit.frontend/src/utils/rumClient.ts— RUM client.- Yandex SpeechKit credentials —
YANDEX_API_KEY+YANDEX_FOLDER_IDв.env(Mail.ru-Business). feedback_monitor_runbook.md— runbook armming / отключения agent-side Monitor'ов (см. memoryreference_k_fb1_monitor_runbook.md).