257 lines
28 KiB
Markdown
257 lines
28 KiB
Markdown
# Закрыто 21.07-27.07
|
||
## MVP frontend: один чат с компанией без истории диалогов; пункт «Чат» открывает текущий активный диалог или создаёт его при отсутствии
|
||
## При создании пользователя номер телефона копировать в профиль Russian_Phone
|
||
## Убрать хеширование устройства клиента в devise_json - хочу видеть его параметры.
|
||
## Добавить параметр, ограничивающих кол-во неуспешных попыток ввода смс.
|
||
## Поправить чтение сообщений от Битрикса. Сейчас они выглядят так: "[b]Антон Пичугин:[/b] [br]опять ты?" Надо убрать из текста сообщения Отправителя в битриксе
|
||
## Если неавторизованный пользователь вводит сообщение, после отправки идет на регистрацию, после окончания регистрации его сообщение пропадает. Надо чтобы сохранялось и отправлялось (по аналогии с нажатием на кнопку из раздела "Популярные вопросы")
|
||
## Изменение в БД по аудитам (заполнение IP, сквозное заполнение UserSession)
|
||
## Яндекс.капчу добавить
|
||
## Формы согласий поправить (Согласие на обработку ПД + Политика, Пользовательское соглашение, Реклама)
|
||
## При повторном запросе OTP кода при авторизации не нужно указывать ошибку "Новый код заказан. Предыдущий код больше не действует."
|
||
## Интеграция с СМС-провайдером — спецификация и план rollout зафиксированы в `modules/module-11-idgtl-sms.md`; пункт не закрыт до реализации `sms-service`/worker, Keycloak lifecycle, schema `sms`, callback/nginx, env validation, observability и общего DoD. Production prerequisites: согласованные sender/template, Direct `TOKEN_1`, callback credentials/подтверждённый source IP и статический egress IP.
|
||
## Моделирование уведомлений — постановка v6 синхронизирована с `functional_blocks (business logic)/notification-requirements.md`, arch-00…05 и module-01/03/07. Зафиксированы: instruction только в новой вкладке; TTL только при отсутствии `date_expired`; первое скачивание любого связанного документа скрывает; `producer_test` только для smoke, secret/hash раздельно.
|
||
## Кнопка "Позвонить оператору" (ссылка tel:+74999591007)
|
||
## На главном экране две кнопки: чат и звонок оператору. На кнопке с чатом уведомление при наличии непрочитанных сообщений.
|
||
|
||
# Закрыто 28.07-03.08
|
||
## #MONITORING Подключить OTLP-провайдер (Signoz)
|
||
## #UI Отправлять на UI информацию разные ошибки при попытках авторизации в зависимости от события: код неверен, истёк или уже использован; превышен лимит попыток авторизации, попробуйте через 24 часа (в случаях превышения otp.phone.max_send_attempts_per_24h); превышен лимит неуспешных авторизаций, начните процедуру заново (в случае превышения otp.phone.max_verify_attempts).
|
||
## #UI При отрицательном результате проверки сообщения через message-safety, если сообщение отправлялось с главного экрана, то пользователь не переводится в чат, ему под окном главного экрана выпадает сообщение об ошибке. Не на всех устройствах это видно. Воспринимается как UX-дефект. Как надо: вне зависимости от решения message-safety, если пользователь отправил сообщение, то он переводится на экран с чатом. Далее, сейчас отрицательный результат message-safety выводится пользователю как техническая ошибка (красным цветом под полем ввода сообщения) и опять же воспринимается не как бизнес-логика, а как техническая ошибка. Это поведение нужно поменять. Если сообщение пользователя не прошло проверку, нужно ему в окне чата прислать ответ: Для сообщений: К сожалению, ваше сообщение не соответствует правилам данного чата и не может быть отправлено. Попробуйте переформулировать. Для документов: К сожалению, ваш документ не прошел проверку и не может быть доставлен.
|
||
## UX-дефект: frontend показывает «Не удалось завершить вход» при ошибке отправки отложенного сообщения, хотя вход завершён. Это следует исправить: завершать экран авторизации после bootstrap, а ошибку Bitrix показывать уже в чате (если сообщение отклонено сервисом message-safety, учесть реализацию предыдущего пункта)
|
||
## #UI Ограничить кол-во символов в сообщении на фронте. Показывать в моменте счетчик: n/max, где n сколько символов уже напечатано, max сколько может быть отправлено. Максимальное кол-во символов - положить в app_settings.
|
||
## #UI Убрать с экрана ввода номера телефона тексты согласий внизу экрана: Нажимая «Получить код», вы соглашаетесь с условиями использования и политикой конфиденциальности. Согласия пользователь дает ранее на отдельном экране.
|
||
## #BACK_SECURE Перенести секреты из .env в KM Selectel.
|
||
## #BACK_SECURE Провести аудит безопасности вм
|
||
## #UI Унифицированы гостевые экраны Центра уведомлений, Профиля и Чата: единый стиль сообщения о необходимости входа и кнопка «Авторизоваться».
|
||
## #BACK_BUSINESS Архитектурное решение принято: `message-safety` и `bitrix-sync` выносятся на самостоятельную ВМ2 с одним root Compose/nginx; Message Safety доступен privately, CRM webhook приходит напрямую на отдельный public host ВМ2; реализация/cutover остаются в задачах 16–17.
|
||
## #BACK_SECURE Разработан архитектурный стандарт по безопасному деплою и размещению сервисов на ВМ.
|
||
|
||
# Закрыто 04.08-10.08
|
||
## #BACK_DEFECT Исправлены дублирующиеся триггеры на создание контакта для сервиса синхронизации. Исправлено создание в БД лишних задач на обновление контакта (каждый бустрап пользователя вызывал задачу на обновление контакта)
|
||
|
||
# Закрыто 18.08-24.08
|
||
## #BACK_DEFECT Автопродление TLS падает при перезагрузке nginx; сертификат действует до 14.10.2026. (Исправить reload внутри контейнера и проверить systemctl start an-chat-ssl-renew.service до успешного завершения.)
|
||
|
||
# В разработку:
|
||
|
||
1 #BACK_SECURE После интеграции с смс провайдером, реализовать debounce механизм при авторизации - каждая след. смс можно отправить через все большее окно. (сейчас есть Фиксированный cooldownmin_seconds_between_attempts)
|
||
2. #MONITORING Настроить мониторинг в Signoz
|
||
3. #BACK_BUSINESS Хранить историю устройств, с которых пользователь входил в ЛК (Ид юзера, идентификатор устройства, дата последнего входа, способ входа - веб\приложение)
|
||
4. #BACK_BUSINESS Веб-пуши для PWA
|
||
5. #UI На кнопке Чат отображать значок наличия непрочитанных уведомлений. Требуется синхронизация между устройствами (решение, например через Dialog.client_last_opened_at)
|
||
6. #BACK_BUSINESS Описание бизнес сущностей: Пользователь
|
||
7. #BACK_BUSINESS Описание бизнес сущностей: Сообщение
|
||
8. #UI Сделать страницу с инструкцией по установке приложения
|
||
9. #LEGAL Написать пользовательское соглашение.
|
||
10. #BACK_BUSINESS Разработка Message Safety v2 по [`module-05`](modules/module-05-message-safety.md), §18 DoR/DoD и cutover gates [`module-10-vm2`](modules/module-10-deployment-vm2.md):
|
||
- API/OpenAPI v2, versioned `message_safety.config_versions`, configuration activation/validation и schema migrations;
|
||
- PostgreSQL queue/lease/fencing/deadline + Redis hot cache/rate/wakeup;
|
||
- Unicode normalization и versioned text rule bundle/corpus;
|
||
- local-only URL parser/IDNA/DNS/IP policy и cache split;
|
||
- immutable S3 version flow, file detectors и technical matrix;
|
||
- ClamAV/freshclam, signature rollback и EICAR tests;
|
||
- api-backend integration: `202` polling, M8, `safety.chat.blocked`, conditional promote;
|
||
- VM2 internal nginx/TLS/egress/collector/dashboards + root-owned emergency MOCK helper/alert;
|
||
- contract/security/failure/load acceptance и S3 negative gate;
|
||
- controlled v1→v2 cutover, rollback rehearsal и удаление stub references.
|
||
11. #BACK_BUSINESS Разработка sync-service
|
||
12. #INFRASTRUCTURE Перераскатить сервисы от деплоя
|
||
13. #INFRASTRUCTURE Поднять второй контур для продакшн
|
||
14. #INFRASTRUCTURE Спрятать сеть за балансировщиком нагрузки
|
||
15. #UI Добавить подсказку по разрешенным типам файлов
|
||
16. #INFRASTRUCTURE WireGuard-only SSH.
|
||
17. #LEGAL Обновить документы по ПД - модель угроз и меры защиты.
|
||
18. #LEGAL Уведомление в РКН по БД обработки ПД.
|
||
19. #MONITORING Добавить логи (Для Python-сервисов добавить OTLP Log Exporter: api-backend; sms-service; sms-worker. Подключить LoggerProvider, BatchLogRecordProcessor и bounded queue. Передавать resource attributes: service.name; service.version; deployment.environment; service.namespace=han-chat.) Экспортировать структурированные поля request_id, trace_id, span_id, severity и event name. Оставить stdout как аварийный локальный журнал. Добавить canary-тесты, запрещающие экспорт токенов, cookie, телефонов, email, текстов сообщений, SQL и object keys.).
|
||
20. #MONITORING Nginx metrics/tracing в signoz
|
||
21. #BACK_SECURE Сформулировать требования для обработки персональных данных
|
||
22. #UI Скрыть раздел диагностики в профиле пользователя (наличие этого раздела в енв передать, как часть наследования продуктовой среды?)
|
||
23. #BACK_BUSINESS Разработка notification-service
|
||
24. #BACK_BUSINESS Store-review вход: точечный bypass в Keycloak OTP SPI по номеру из `.env` (`STORE_REVIEW_ENABLED` / `STORE_REVIEW_PHONE` / `STORE_REVIEW_OTP`) — для этого телефона SMS не шлётся, verify принимает фиксированный OTP; остальные номера идут обычным OTP/SMS. Не путать с глобальным `KEYCLOAK_OTP_MOCK_*`. Учётные данные только в Review Notes стора (не в бинарнике/UI); пользователь с демо-контентом; в production включать только на время ревью.
|
||
25. #UI Реализация мнемоник: Определение итогового перечня мнемоник, перевод фронтенда на мнемоники, seed заливка мнемоник в БД (?)
|
||
26. #INFRASTRUCTURE Развернуть Гит в облаке
|
||
27. #BACK_BUSINESS Синхронизация документов из битрикс24 в Приложение.
|
||
28. #INFRASTRUCTURE Зарегистрировать Conteiner registry Selectel
|
||
29. #BACK_BUSINESS Определить пул тестовых номеров, чтобы их было легко в Б24 отслеживать.
|
||
30. #INFRASTRUCTURE перевести взаимодействие с signoz на TLS (сейчас OTEL_REMOTE_TLS_INSECURE=true)
|
||
31. #BACK_BUSINESS VM1 -> VM2: `curl -sS --cacert /etc/han/ca/vm2-internal-ca.crt "https://processing.internal:8443/internal/safety/status" | python3 -m json.tool` В коде захардкожен Redis в components = "degraded". Надо реализовать реальную проверку вместо костыля.
|
||
32. #BACK_BUSINESS Решить проблему с обновлением сигнатур CLAMAV.
|
||
33. #BACK_BUSINESS Создать поле "Номер телефона в приложении". Подробности реализации ниже (на подумать)
|
||
34. #BACK_BUSINESS реализация смены номера телефона. Подробности реализации ниже (на подумать)
|
||
35. #BACK_BUSINESS схлапывание контактов. Подробности реализации ниже (на подумать)
|
||
|
||
# Критично для релиза:
|
||
~~1. Разработка message-safety~~
|
||
~~2. Разработка sync-service~~
|
||
3. Пользовательское соглашение
|
||
~~4. Подключить OTLP-провайдер~~
|
||
~~5. Починить UI баги~~
|
||
6. Второй контур для продакшн
|
||
|
||
|
||
33. details
|
||
Комплексный алгоритм:
|
||
|
||
1. Нормализовать номер приложения `P`.
|
||
2. Если active mapping существует:
|
||
- Contact принадлежит текущему `user_id` — обновить служебные поля и app-телефон;
|
||
- `user_id` пуст — восстановить служебные поля;
|
||
- указан чужой `user_id` — ничего не перезаписывать, создать alert `mapping_identity_mismatch`;
|
||
- Contact отсутствует — пометить mapping broken и создать alert.
|
||
3. Если mapping отсутствует, собрать объединённый список Contact:
|
||
- найденные по текущему `user_id`;
|
||
- найденные по новому полю app-телефона `P`;
|
||
- найденные через `duplicate.findbycomm` по стандартному `PHONE`.
|
||
4. Загрузить все карточки и классифицировать:
|
||
- принадлежат текущему пользователю;
|
||
- свободны — `user_id` пуст;
|
||
- принадлежат другому пользователю;
|
||
- app-телефон равен `P`;
|
||
- app-телефон пуст — legacy-контакт;
|
||
- app-телефон отличается от `P`.
|
||
|
||
Дальнейшие ветки:
|
||
|
||
- Найден Contact с тем же `user_id`:
|
||
- выбрать самый новый среди таких Contact;
|
||
- восстановить mapping;
|
||
- записать `P` в app-телефон;
|
||
- если таких Contact несколько или есть другие совпадения — создать duplicate alert со всеми ID.
|
||
|
||
- Контактов с тем же `user_id` нет:
|
||
- кандидатами считаются Contact с app-телефоном `P`;
|
||
- также допускаются legacy-контакты с пустым app-телефоном, найденные по стандартному `PHONE`;
|
||
- Contact с другим непустым app-телефоном нельзя автоматически привязывать.
|
||
|
||
- Один кандидат свободен:
|
||
- записать `user_id`, registration flag и app-телефон;
|
||
- создать mapping.
|
||
|
||
- Несколько кандидатов:
|
||
- выбрать самый новый по `CREATED_TIME`, затем по числовому ID;
|
||
- если выбранный свободен — привязать его и создать `duplicate_contacts`;
|
||
- если выбранный принадлежит другому пользователю — создать новый Contact и alert `contact_owned_by_other_user`;
|
||
- в `contactIds` alert передать все старые ID и ID нового Contact.
|
||
|
||
- Совпадения есть только по стандартному `PHONE`, но у них указан другой app-телефон:
|
||
- не считать их Contact текущего пользователя;
|
||
- создать новый Contact;
|
||
- создать alert о совпадении общего номера.
|
||
|
||
- Совпадений нет:
|
||
- создать новый Contact без alert.
|
||
|
||
Дополнительные правила:
|
||
|
||
- app-телефон — App-master: изменения этого поля в Б24 не меняют номер авторизации.
|
||
- При смене номера приложение обновляет app-телефон и гарантирует наличие нового номера в стандартном `PHONE`, но не удаляет остальные номера Contact.
|
||
- Перед повторным `contact.add` после timeout необходимо повторно искать по `user_id` и app-телефону, чтобы не создать дубль.
|
||
- Mapping создаётся только после успешной записи служебных полей.
|
||
- Все конфликтные ветки должны иметь отдельные регрессионные тесты до реализации.
|
||
|
||
|
||
34. details
|
||
Изменение стандартного `PHONE` в Битрикс24 не должно автоматически менять номер авторизации в приложении. Иначе сотрудник с доступом к CRM сможет случайно или намеренно передать чужой аккаунт другому номеру.
|
||
|
||
Рекомендуемый процесс:
|
||
|
||
1. Сотрудник меняет стандартный номер в карточке.
|
||
2. Webhook фиксирует расхождение с полем «Номер телефона в приложении».
|
||
3. Система создаёт отдельный запрос/смарт-процесс «Смена номера приложения».
|
||
4. Сотрудник явно выбирает, какой из номеров Contact является новым номером приложения.
|
||
5. Выполняются проверки:
|
||
- нормализация E.164;
|
||
- новый номер не занят другим пользователем;
|
||
- Contact действительно связан с нужным `user_id`;
|
||
- нет другого активного запроса.
|
||
6. Клиент подтверждает смену:
|
||
- OTP на новый номер;
|
||
- подтверждение в активной сессии приложения;
|
||
- желательно OTP на старый номер, если он доступен.
|
||
7. Если старый номер недоступен — отдельный усиленный сценарий идентификации сотрудником с обязательным аудитом и, желательно, дополнительным согласованием.
|
||
8. После подтверждения App меняет номер в своём источнике истины — БД приложения/Keycloak.
|
||
9. Через outbox создаётся задача синхронизации.
|
||
10. Bitrix Sync обновляет:
|
||
- поле «Номер телефона в приложении»;
|
||
- служебные поля связи;
|
||
- при необходимости добавляет новый номер в стандартный `PHONE`;
|
||
- закрывает запрос на смену номера.
|
||
|
||
Важные правила:
|
||
|
||
- Обычное редактирование `PHONE` только создаёт предложение на смену, но не меняет логин.
|
||
- Поле «Номер телефона в приложении» остаётся read-only для сотрудников.
|
||
- Старые дополнительные номера Contact автоматически не удаляются.
|
||
- Нужны срок действия запроса, ограничение попыток OTP, журнал сотрудника и времени операции.
|
||
- Повторный запрос должен быть идемпотентным.
|
||
|
||
Так сохраняется удобство работы через Б24, но CRM не становится небезопасным источником истины для номера авторизации.
|
||
|
||
35. details
|
||
Здесь нужно объединять не только карточки Битрикс24, но прежде всего два аккаунта приложения. Простое слияние Contact оставит данные личного кабинета привязанными к старому `user_id`.
|
||
|
||
Рекомендуемый сценарий account merge.
|
||
|
||
1. Создать заявку на объединение:
|
||
- старый `user_id` и старый Contact;
|
||
- новый `user_id` и новый Contact;
|
||
- результат комплайенса;
|
||
- оператор и подтверждающий сотрудник;
|
||
- причина и audit trail.
|
||
|
||
2. Выбрать канонический аккаунт. Обычно это старый аккаунт, содержащий историю и данные. Новый пустой аккаунт становится поглощаемым.
|
||
|
||
3. На время операции заблокировать изменения обоих аккаунтов и повторные merge-заявки.
|
||
|
||
4. Проверить конфликты:
|
||
- заказы, документы, согласия;
|
||
- бонусы, баланс и другие финансовые данные;
|
||
- активные процессы;
|
||
- наличие данных в новом аккаунте;
|
||
- отсутствие третьего аккаунта с новым номером.
|
||
|
||
5. На стороне приложения:
|
||
- привязать новый номер к каноническому старому аккаунту;
|
||
- старый номер сделать неактивным либо историческим;
|
||
- перенести допустимые данные нового аккаунта;
|
||
- отметить новый `user_id` как `merged_into=<canonical_user_id>`;
|
||
- запретить дальнейшее использование поглощённого аккаунта;
|
||
- обновить Keycloak/механизм авторизации;
|
||
- отозвать старые сессии и потребовать повторный вход.
|
||
|
||
6. Только после успешного App merge обработать Битрикс:
|
||
- старый Contact выбрать каноническим;
|
||
- записать в него канонический `user_id`;
|
||
- поле «Номер телефона в приложении» установить в новый номер;
|
||
- объединить стандартные номера обоих Contact;
|
||
- создать active mapping канонического пользователя на канонический Contact;
|
||
- у второго Contact очистить app-телефон, `user_id` и registration flag;
|
||
- затем объединить его с каноническим Contact штатным механизмом Б24 либо архивировать как поглощённый.
|
||
|
||
7. Закрыть старые mapping со специальной причиной `account_merge`, но сохранить историю.
|
||
|
||
8. Завершить заявку только после проверок:
|
||
- вход по новому номеру открывает старый личный кабинет;
|
||
- существует один active App user;
|
||
- существует один active mapping;
|
||
- только один Contact содержит app-телефон и registration flag;
|
||
- поглощённый аккаунт больше не создаёт задачи синхронизации.
|
||
|
||
Ключевой принцип: сначала объединение аккаунтов приложения, затем CRM. Если сначала слить карточки Б24, это не вернёт пользователю данные.
|
||
|
||
Для устойчивой реализации потребуется отдельная audited-процедура наподобие:
|
||
|
||
```text
|
||
request_account_merge(
|
||
canonical_user_id,
|
||
absorbed_user_id,
|
||
canonical_contact_id,
|
||
absorbed_contact_id,
|
||
reason,
|
||
operator_id,
|
||
compliance_case_id
|
||
)
|
||
```
|
||
|
||
Операция должна быть идемпотентной, поэтапной и восстанавливаемой после сбоя. Для финансовых или юридически значимых данных автоматический перенос без отдельных правил недопустим. |