Add handoff task document for PWA, chats, and connections

This commit is contained in:
ai5590 2026-04-05 12:12:59 +03:00
parent 09566fdfde
commit ad323d17a2

181
TASKS/CHAT_PWA_HANDOFF.md Normal file
View File

@ -0,0 +1,181 @@
# Анонс для исполнителя (кратко)
Ниже описан текущий статус ветки по функциям:
- PWA + FCM уведомления
- личные сообщения (вторая слева вкладка, "Личные сообщения")
- связи / близкие друзья (центральная вкладка)
- server-push события (в том числе закрытие сессии)
## Что нужно проверить и довести до рабочего состояния
1. **PWA/FCM**: регистрация service worker, получение FCM token, отправка token на сервер, получение foreground/background уведомлений.
2. **Личные сообщения**: отправка первого сообщения любому пользователю, входящие по WS, ACK, fallback в FCM, дедупликация на клиенте.
3. **Связи / близкие друзья**: поиск пользователя, добавление в близкие, обновление графа связей сразу после добавления.
4. **SessionRevoked**: если сессию закрыли с другого устройства, клиент должен корректно завершить локальную сессию и показать понятное состояние.
## Главная цель handoff
Сделать так, чтобы все описанные сценарии стабильно работали end-to-end без ручных "подпинок".
---
# Подробное ТЗ и технические детали
## 1) Архитектура протокола и общие принципы
### 1.1 Формат обмена
Используется JSON-over-WebSocket.
- Для запрос-ответ: `op + requestId + payload`
- Для server-push событий: те же поля, но `event=true`, `requestId` используется как eventId.
### 1.2 ID сообщений/событий
ID генерируются в формате:
- `prefix-yyyyMMdd-HHmmss-SSS-random10`
Реализация: `NetIdGenerator`.
### 1.3 Роли каналов доставки
- **WS** — приоритетная доставка в активные сессии.
- **FCM** — fallback, если ACK по WS не получен или WS-сессия отсутствует.
---
## 2) PWA + FCM
## 2.1 Что уже добавлено
### Клиент
- `shine-UI/manifest.webmanifest`
- `shine-UI/firebase-messaging-sw.js`
- `shine-UI/js/services/pwa-push-service.js`
- `shine-UI/index.html` содержит placeholders:
- `window.__SHINE_FIREBASE_CONFIG__`
- `window.__SHINE_FIREBASE_VAPID_KEY__`
### Сервер
- API `UpsertPushToken`
- Таблица `user_push_tokens`
- Серверный FCM sender (legacy HTTP): `FcmPushSender`
- Конфиг: `fcm.server.key` в `application.properties`
## 2.2 Как должно работать (целевое поведение)
1. Клиент после авторизации регистрирует SW.
2. Просит permission на notifications.
3. Получает FCM token.
4. Если token новый/изменился — отправляет `UpsertPushToken`.
5. Сервер сохраняет token за конкретной сессией.
## 2.3 Что проверить/доделать
- Синхронизация Firebase config между `index.html` и `firebase-messaging-sw.js`.
- Работа iOS Safari (PWA через Home Screen).
- Поведение при смене token.
- Надёжность `FcmPushSender` (таймауты, логирование ошибок ответа).
---
## 3) Вторая слева вкладка: Личные сообщения / Чаты
## 3.1 Продуктовая логика (как должно быть)
1. Открытие списка диалогов на вкладке "Личные сообщения".
2. Кнопка `+` открывает поиск пользователя по префиксу логина (`SearchUsers`).
3. **Первое сообщение можно отправить любому пользователю**, даже если он не контакт.
4. Если пользователь не в контактах — в чате показывается действие "Добавить в контакты".
5. Входящее сообщение может прийти:
- напрямую по WS (`IncomingDirectMessage`)
- через FCM (fallback)
6. На клиенте дедупликация должна быть по `messageId`.
## 3.2 Что уже сделано технически
### Сервер
- `SendDirectMessage`
- `AckIncomingMessage`
- `direct_messages` таблица + DAO
- доставка по активным WS-сессиям + ожидание ACK + fallback в FCM
### Клиент
- `authService.sendDirectMessage(...)`
- `authService.ackIncomingMessage(...)`
- WS client поддерживает server events (`onEvent`)
- В `app.js` обработка `IncomingDirectMessage`
- В `state.js` добавлены `incomingDedup`, `addIncomingMessage`
## 3.3 Что глючит/что проверить
- Стабильность отображения новых чатов, если сообщение пришло от неизвестного пользователя.
- Согласованность списка диалогов и фактических сообщений.
- Поведение при быстрых дубликатах WS + FCM.
- Поведение при сетевых обрывах/повторном коннекте.
---
## 4) Центральная вкладка: Связи / Близкие друзья
## 4.1 Целевое поведение
1. Экран "Связи" загружает граф друзей (`GetUserConnectionsGraph`).
2. Кнопка "Добавить близкого друга" открывает модалку:
- поле логина/префикса
- кнопка "Поиск"
- кнопка "Назад"
3. Поиск идёт через `SearchUsers`.
4. По клику на найденного — подтверждение "Добавить? Да/Нет".
5. При "Да" вызывается `AddCloseFriend`, после успеха:
- закрыть модалку
- вернуться на экран связей
- обновить граф.
## 4.2 Что уже сделано
- UI-flow модалки реализован на `network-view.js`.
- API `AddCloseFriend` добавлен на сервере.
- `ConnectionsStateDAO.upsertRelation(...)` добавлен для upsert связи FRIEND.
## 4.3 Что проверить/доделать
- Валидация edge-cases (добавление самого себя, несуществующий логин).
- Корректность отрисовки графа после добавления.
- Согласованность данных с будущей "настоящей" записью в blockchain (сейчас MVP upsert в `connections_state`).
---
## 5) SessionRevoked и мультисессии
## 5.1 Целевое поведение
Если с другой сессии закрыли текущую сессию:
1. сервер шлёт событие `SessionRevoked`
2. клиент чистит локальную авторизацию
3. клиент возвращается в состояние неавторизованного входа.
## 5.2 Что проверить
- Что событие приходит до закрытия socket.
- Что UX не "зависает" на промежуточном экране.
---
## 6) API-операции (быстрый список)
### Уже используемые/добавленные в ветке
- `SearchUsers`
- `ListContacts`
- `GetUserConnectionsGraph`
- `AddCloseFriend`
- `UpsertPushToken`
- `SendDirectMessage`
- `AckIncomingMessage`
- `CloseActiveSession` (с server event `SessionRevoked`)
---
## 7) Минимальный чек-лист тестирования для нового исполнителя
1. Авторизация пользователя A и B в разных браузерах/устройствах.
2. A отправляет первое сообщение B (без контактов) — должно уйти.
3. B получает по WS, отправляется ACK, fallback FCM не должен дублировать.
4. Выключить WS у B и проверить fallback FCM.
5. Вкладка "Связи": добавить близкого друга через поиск, проверить обновление графа.
6. Закрыть сессию B с другого устройства и проверить `SessionRevoked` UX.
7. Перезапуск клиента: проверка повторной регистрации push-токена только при изменении.
---
## 8) Важное ограничение текущей реализации
Некоторые части реализованы как MVP и требуют стабилизации:
- местами UI/состояние могут рассинхронизироваться;
- fallback WS->FCM может требовать донастройки таймингов и ретраев;
- `AddCloseFriend` сейчас пишет прямое состояние связи (upsert), а не полный blockchain-поток создания блоков.
Это ожидаемо для handoff: задача следующего исполнителя — довести до production-стабильности.