Files
han-app/architectory/arch-00-glossary.md
T

180 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# arch-00. Глоссарий и единый словарь терминов
## Назначение
Канонические **имена** сущностей, полей, идентификаторов, enum-значений, бакетов S3, env-переменных и терминов проекта.
При расхождении имён приоритет у настоящего словаря.
## Bucket Selectel S3
| Логическое имя | env-переменная | Пример физического бакета |
|---|---|---|
| **S3-quarantine** | `SELECTEL_S3_BUCKET_QUARANTINE` | `han-chat-quarantine` |
| **S3-data** (attachments) | `SELECTEL_S3_BUCKET_ATTACHMENTS` | `han-chat-attachments` |
| **S3-data** (documents) | `SELECTEL_S3_BUCKET_DOCUMENTS` | `han-chat-documents` |
В тексте: **S3-quarantine** — временное хранилище до вердикта Message Safety; **S3-data** — проверенные файлы (attachments и documents — два физических бакета).
## Сущности App DB (основные)
| Имя | Схема | Назначение (кратко) |
|---|---|---|
| `UserIdentity` | `han_app` | Локальный пользователь, связь с Keycloak |
| `UxSession` | `han_app` | Аналитическая UX-сессия (период активности пользователя) |
| `UserConsent` | `han_app` | Запись о принятии согласий (после OTP, привязка к `user_id`) |
| `ClientProfile` | `han_app` | Кэш профиля для UI |
| `Dialog` | `han_app` | Диалог клиента с Open Lines |
| `Message` | `han_app` | Сообщение в диалоге |
| `MessageAttachment` | `han_app` | Вложение к сообщению |
| `sync_queue` | `han_app` | Очередь sync App → Bitrix24 |
| `safety_tasks` | `han_app` | Checkpoint sync-wait Message Safety (`task_id`) для recovery |
| `entity_external_mapping` | `han_app` | Маппинг App entity ↔ Bitrix entity |
| `app_settings` | `han_app` | Бизнес-настройки |
| `text_resources` | `han_app` | Тексты UI по мнемоникам |
| `popular_questions` | `han_app` | Популярные вопросы главного экрана |
| `dialog_sessions` | `bitrix_local` | Маппинг чата Open Lines |
| `sms_template` | `sms` | Версионируемый согласованный SMS-шаблон; active-версия уникальна для `code`+`channel`+`locale` |
| `sms_setting` | `sms` | Технические runtime-настройки `sms-service`, не секреты и не OTP product settings |
| `sms_outbound_message` | `sms` | Бессрочный журнал заказа, отправки и доставки SMS; источник истины provider status |
## Идентификаторы
| Имя | Где используется |
|---|---|
| `dialog_id` | UUID диалога в приложении; **равен** `external_chat_id` в Open Lines |
| `external_chat_id` | Идентификатор чата для `bitrix-local-app` / `imconnector` |
| `keycloak_sub` | Subject JWT Keycloak (`sub`); ключ `UserIdentity` |
| `phone_number` | Auth-телефон пользователя; master — Keycloak; в App DB пишется из JWT claims при `bootstrap`, не из body клиента |
| `guest_session_id` | Опциональный локальный UUID на устройстве (UI); **не** auth и **не** открывает write API |
| `ux_session_id` | UUID **аналитической UX-сессии**; заголовок `X-Ux-Session-Id` |
| `bitrix_contact_id` | ID Contact в Bitrix24 CRM |
| `bitrix_chat_id` | ID чата Open Lines в Bitrix24 |
| `session_id` | ID сессии Open Lines (поле `dialog_sessions`; не путать с `ux_session_id`) |
| `task_id` | ID async-проверки Message Safety |
| `request_id` | Корреляция HTTP-запроса (заголовок `X-Request-ID`) |
| `sms_message_id` | UUID `sms.sms_outbound_message.id`; логическая ссылка из Keycloak challenge/event, межсхемного FK нет |
| `provider_message_id` | `messageUuid` i-Digital Direct; хранится только в `sms-service` |
| `provider_external_id` | `externalMessageId`; в v1 равен `sms_message_id` и является корреляцией, а не доказанной идемпотентностью Direct |
Публичные id сущностей — **UUID**.
## `UxSession` (аналитическая UX-сессия)
### Определение
**`UxSession`** — период **непрерывной активности** пользователя в приложении (web / iOS / Android) для **аналитики** и **сквозной корреляции** логов и событий.
- Идентификатор периода — **`ux_session_id`** (UUID).
- Начало периода фиксируется событием **`session_start`** (**ровно один раз** на период).
- Запись создаётся в App DB при `POST /api/v1/analytics/session-start` (**только с JWT**, см. arch-02).
- Frontend передаёт **`X-Ux-Session-Id`** во всех JWT-запросах к backend, пока сессия активна.
**`UxSession` не является механизмом авторизации.** Отсутствие или неизвестный `ux_session_id` **не** блокирует API (кроме endpoint, где id обязателен по контракту). Сам endpoint `session-start` без JWT недоступен.
### Когда начинается **новая** `UxSession`
Новый **`ux_session_id`** + событие **`session_start`** — **только** если:
1. **`first_launch`** — приложение открыто, в памяти **нет** `ux_session_id`.
2. **`cold_start`** — после kill app или закрытия вкладки браузера (память очищена).
3. **`idle_timeout`** — возврат спустя **более N минут** (`ux.session.idle_timeout_minutes` в `app_settings`, default **30**).
### Когда **та же** `UxSession` продолжается
- возврат из фона **в пределах** idle timeout (напр. через 5 минут — **без** нового `session_start`);
- успешный refresh access token, если `ux_session_id` уже создан и idle timeout не превышен;
- успешный OTP внутри уже активной UX-сессии, если повторная авторизация не очистила память приложения;
- навигация между экранами внутри приложения.
При первом JWT-входе после гостевого режима или после cold start, когда в памяти нет активного `ux_session_id`, frontend создаёт новую UX-сессию через `POST /api/v1/analytics/session-start`.
## `Dialog.status`
| Значение | Смысл |
|---|---|
| `open` | Диалог создан, сообщений ещё нет (сразу после `POST /dialogs`) |
| `waiting_for_company` | Последнее значимое событие — исходящее от клиента; ждём оператора |
| `waiting_for_client` | Последнее значимое событие — входящее от оператора; ждём клиента |
| `closed` | Диалог закрыт в Open Lines (`dialog.closed` / `ONIMCONNECTORDIALOGFINISH`) |
Переходы задаёт `api-backend` (см. arch-01, потоки чата). Значения — **строковые enum** в API и App DB (не sequence-справочник).
## `Message` — enum и поля
| Имя | Допустимые значения |
|---|---|
| `Message.sender_type` | `client`, `company` |
| `Message.safety_status` | `pending`, `allowed`, `blocked` (`needs_review` — зарезервирован, MVP не используется) |
| `Message.delivery_status` | `accepted`, `processing`, `delivered`, `rejected`, `failed` |
| `Message.text` | текст сообщения; пустая строка для файлового сообщения |
| `content_kind` (логическое) | `text`, `file` — тип исходящего сообщения клиента (MVP) |
Семантика `allow` / `deny` / `pending` в `message-safety` и HTTP-коды — [`arch-02-api-contracts.md`](arch-02-api-contracts.md).
### `Message.delivery_status` (смысл)
| Значение | Когда |
|---|---|
| `accepted` | Сообщение принято API, safety ещё не завершена или только начата |
| `processing` | Внутренний/transient на время sync-wait safety; клиенту на `POST .../messages` не отдаётся как финальный ответ |
| `delivered` | Финальный `allow`, сообщение ушло в Open Lines (или входящее от оператора сохранено) |
| `rejected` | Финальный `deny` от Message Safety |
| `failed` | Инфраструктурная ошибка доставки (Bitrix/S3), не safety-deny |
Realtime-событие `message.status` передаёт актуальные `safety_status` и/или `delivery_status`.
## `MessageAttachment.scan_status`
| Значение | Смысл |
|---|---|
| `pending` | Файл в S3-quarantine, проверка не завершена |
| `clean` | Проверка завершена, allow |
| `infected` | Проверка завершена, deny |
| `failed` | Ошибка инфраструктуры проверки |
## Строковые enum vs справочники
- **Строковые enum** (значения в API/контрактах): `Dialog.status`, `Message.sender_type`, `Message.safety_status`, `Message.delivery_status`, `MessageAttachment.scan_status`, `content_kind`, `start_reason`, SMS `send_status`, SMS `delivery_status`, OTP `challenge_status`.
- **Справочники (sequence ID)** — для больших/изменяемых списков UI и доменных классификаторов (типы документов post-MVP, причины и т.п.); правило — [`arch-05-agent-development-process.md`](arch-05-agent-development-process.md).
### SMS и OTP статусы
- `sms_outbound_message.send_status`: `pending`, `accepted`, `rejected`, `failed`, `uncertain`, `skipped`.
- `sms_outbound_message.delivery_status`: `unknown`, `sent`, `delivered`, `undelivered`, `unsent`.
- `han_otp_challenge.challenge_status`: `ordering`, `active`, `consumed`, `superseded`, `expired`, `limited`, `order_failed`.
- Provider statuses принадлежат только `sms-service`: Keycloak не читает их и не использует для verify.
## Мнемоники internal API
Префикс: **`/internal/{service_mnemonic}/v1/`**. Health: **`/health/*`**.
| `{service_mnemonic}` | Сервис |
|---|---|
| `safety` | `message-safety` |
| `openlines` | `bitrix-local-app`, приёмник inbox на `api-backend` |
| `sync` | `bitrix-sync` |
| `settings` | internal settings bridge на `api-backend` для Keycloak SPI |
| `sms` | `sms-service`; durable order/read API во внутренней сети |
## SMS-конфигурация
- Product OTP settings: `otp.phone.code_length`, `otp.phone.ttl_seconds`, `otp.phone.sms_order_timeout_ms` и лимиты — `han_app.app_settings`, выдаются Keycloak через settings bridge.
- Runtime SMS settings: `provider.idgtl.*` и `worker.*``sms.sms_setting`.
- Infra/secrets env: `KEYCLOAK_SMS_SERVICE_URL`, `SMS_DATABASE_URL`, парные `KEYCLOAK_SMS_SERVICE_TOKEN`/`SMS_SERVICE_TOKEN`, `IDGTL_SMS_BASE_URL`, `IDGTL_SMS_API_KEY`, `IDGTL_SMS_CALLBACK_PUBLIC_URL`, `IDGTL_SMS_CALLBACK_USERNAME`, `IDGTL_SMS_CALLBACK_PASSWORD`.
- Текст, placeholders и sender template не хранятся в env: они принадлежат `sms_template`; default sender — `sms_setting`.
## Bitrix24 Open Lines
| Имя | Значение |
|---|---|
| `BITRIX_CONNECTOR_ID` / connector | `han_mobile_app` |
| `BITRIX_OPEN_LINE_ID` | `8` |
| Канонический URL коннектора | `https://han0107.bitrix24.ru/contact_center/connector/?ID=han_mobile_app&LINE=8` |
## Термины чата
| Термин | `Message.sender_type` / направление |
|---|---|
| клиент | `client`; исходящее сообщение |
| оператор | `company`; входящее сообщение |
| сообщение пользователя | исходящее; проверяет Message Safety |