Реализованы сервисы ВМ2 - проверка сообщений и синхронизация с Б24 (деплой еще без перевода в боевой режим)

This commit is contained in:
mi
2026-08-13 18:52:42 +03:00
parent 5100ba9fc3
commit 99605b1c77
144 changed files with 15295 additions and 1120 deletions
+6 -6
View File
@@ -90,7 +90,7 @@ Resend запускает новое Keycloak action, блокирует double
- сообщения сортируются по `created_at asc`, дубли объединяются по `message_id`;
- `waiting_for_company`, `waiting_for_client`, `closed` отображаются русскими подписями;
- завершённая беседа readonly; CTA «Продолжить общение» повторно открывает текущий чат через `POST /dialogs`;
- промежуточный safety `203` клиенту не показывается: send request остаётся в progress до финального ответа.
- internal safety `202` клиенту не показывается: send request остаётся in progress до финального ответа.
### 5.4. Профиль
@@ -146,7 +146,7 @@ Bootstrap повторяем безопасно после неопределё
3. `POST /dialogs` с idempotency key, сохранить `dialog_id` и перейти на экран чата до отправки.
4. Экран чата выполняет `POST /dialogs/{id}/messages` с отдельным стабильным key.
5. Блокировать повторный click только для того же intent; другие действия не замораживать.
6. На `201` merge `MessageResponse`; на `422 message_blocked` не показывать красную техническую ошибку, а обновить историю с сохранённой backend `company`-репликой; на `503/504` предложить retry с тем же key.
6. На `201` merge `MessageResponse`; на `422 message_blocked` не показывать internal reason/rule и не строить собственный текст: получить/merge backend `company`-реплику (`message.new`) с контентом мнемоники `safety.chat.blocked`; на `503/504` предложить retry с тем же key.
7. Composer показывает счётчик `n/max`, где `max` приходит как `messages.max_text_length` из public app-config; сверх лимита отправка блокируется без обрезки ввода.
## 11. Файловый flow
@@ -156,11 +156,11 @@ MVP допускает ровно один файл, только allow-list ext
1. Локальная prevalidation.
2. Создать/reuse dialog.
3. `POST .../attachments/init` с filename, MIME, size.
4. Выполнить прямой `PUT upload_url` с точно выданными `upload_headers`; API domain при этом не используется.
5. Вычислить SHA-256, вызвать `complete`.
4. Вычислить SHA-256 до upload и выполнить прямой `PUT upload_url` с **точно** выданными `upload_headers`, включая `If-None-Match: *` и checksum; заголовки являются частью подписи.
5. Вызвать `complete` с тем же checksum; backend фиксирует authoritative S3 version/ETag/checksum.
6. Отправить file message с `attachment_id` и `sha256:<hex>`.
Presigned URL не сохраняется и редактируется из диагностик. Abort позволяет отменить PUT; orphan очищает backend. При expiry init выполняется повторно в рамках согласованного состояния. CORS S3 должен разрешать origin сайта, PUT и необходимые headers.
Presigned URL не сохраняется и редактируется из диагностик. `412` означает, что immutable key уже записан: frontend не повторяет PUT в тот же key, а запрашивает новый init. Abort позволяет отменить PUT; orphan очищает backend через 48 ч. При expiry init выполняется повторно в рамках согласованного состояния. CORS S3 разрешает origin сайта, PUT и только необходимые signed headers.
## 12. Realtime и polling
@@ -292,4 +292,4 @@ Browsers: Chromium, Firefox, WebKit; viewport desktop/mobile. В CI исполь
- F3: web storage policy refresh token перед production security review;
- F4: окончательный DTO app-config (G10);
- F5: WS `event_id`/protocol version (TBD module-01/G11);
- F6: продуктовые тексты всех error states по мнемоникам.
- F6 для Safety закрыт: generic deny использует `safety.chat.blocked`; остальные error-state мнемоники остаются в frontend content backlog.