Files
han-app/support&notes/backlog.md
T
2026-08-26 11:05:32 +03:00

28 KiB
Raw Blame History

Закрыто 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, §18 DoR/DoD и cutover gates module-10-vm2: - 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 схлапывание контактов. Подробности реализации ниже (на подумать) 36. #INFRASTRUCTURE положить в облако секреты ВМ

Критично для релиза:

1. Разработка message-safety 2. Разработка sync-service 3. Пользовательское соглашение 4. Подключить OTLP-провайдер 5. Починить UI баги 6. Второй контур для продакшн

  1. details Комплексный алгоритм:

  2. Нормализовать номер приложения P.

  3. Если active mapping существует:

    • Contact принадлежит текущему user_id — обновить служебные поля и app-телефон;
    • user_id пуст — восстановить служебные поля;
    • указан чужой user_id — ничего не перезаписывать, создать alert mapping_identity_mismatch;
    • Contact отсутствует — пометить mapping broken и создать alert.
  4. Если mapping отсутствует, собрать объединённый список Contact:

    • найденные по текущему user_id;
    • найденные по новому полю app-телефона P;
    • найденные через duplicate.findbycomm по стандартному PHONE.
  5. Загрузить все карточки и классифицировать:

    • принадлежат текущему пользователю;
    • свободны — 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 создаётся только после успешной записи служебных полей.
  • Все конфликтные ветки должны иметь отдельные регрессионные тесты до реализации.
  1. 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 не становится небезопасным источником истины для номера авторизации.

  1. 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-процедура наподобие:

request_account_merge(
  canonical_user_id,
  absorbed_user_id,
  canonical_contact_id,
  absorbed_contact_id,
  reason,
  operator_id,
  compliance_case_id
)

Операция должна быть идемпотентной, поэтапной и восстанавливаемой после сбоя. Для финансовых или юридически значимых данных автоматический перенос без отдельных правил недопустим.