Event Contract: pin.support.ticket-created (TicketCreatedKafkaEvent)
Версионируемый контракт интеграционного события «обращение (тикет) заведено». Consumer-документы ссылаются
сюда, не переописывая payload. Событие фиксирует факт создания TicketEntity
(ticket.md) — из веб-формы заявителя (create-ticket) или оператором
(create-ticket-on-behalf) — и несёт минимальный маршрутный snapshot: очередь, категория, приоритет,
канал, заявитель. Единственный потребитель — notifications (оповестить дежурных операторов очереди).
Назначение
Даёт notifications факт нового обращения, чтобы оповестить дежурных операторов очереди (QueueId) без
синхронного запроса в support: маршрутизация уже вычислена producer-ом (INV-Q-5,
ticket-queue.md), поэтому событие несёт готовый QueueId/Category/Priority,
а не заставляет консюмера повторять правила. ФИО/телефон заявителя в payload не входят — потребитель
берёт их из собственной реплики identity (pin.identity.users.v1); событие несёт только
RequesterUserId/RequesterCompanyId. Публичное в границах платформы (m2m ACL Kafka), т.к. служит
внутренней маршрутизации обращений.
Metadata
| Поле | Значение |
|---|---|
| Event type | pin.support.ticket-created |
| Topic | pin.support.ticket-created.v1 |
| Partitions / key | 3 (низкий объём, ADR-0056) / ключ = TicketId (= AggregateId; per-ticket порядок) |
| ContractVersion | 1 |
| Producer | support: create-ticket (веб-форма, ../api/public/create-ticket.md) и create-ticket-on-behalf (../api/support/create-ticket-on-behalf.md) |
| Статус | draft |
Событие публикуется атомарно с созданием обращения в статусе
New: пока изменение не зафиксировано, событие не отправляется потребителям; после фиксации — доставляется гарантированно (at-least-once). Метаданные события:MessageId(Guid v7, для дедупликации),AggregateId = TicketId(= Kafka key, per-ticket порядок),AggregateType = "Ticket".
Payload TicketCreatedKafkaEvent
Дом полей — entity: TicketEntity (раздел «Доменные и интеграционные события»);
здесь перечислено только то, что реально в событии. Все поля — скаляры/enum-строки; вложенных моделей нет.
| Поле | Тип | Обязательность | Источник (TicketEntity) | Compatibility | Описание |
|---|---|---|---|---|---|
TicketId | Guid | Да | Id | Immutable | Ключ агрегата (= AggregateId, Kafka key). |
Number | long | Да | Number | Immutable | Человекочитаемый номер (SUP-NNN) для текста уведомления/диплинка. |
TenantId | Guid | Да | TenantId | Immutable | PIN CompanyId (единый tenant платформы, ADR-0052). |
QueueId | Guid | Да | QueueId | Immutable | Очередь маршрутизации — адресат оповещения дежурных операторов. |
Category | string (enum TicketCategory) | Да | Category | Additive only (новые значения) | Тематика обращения (Account/Deal/Booking/Payment/Content/Technical/Complaint/Other). |
Priority | string (enum TicketPriority) | Да | Priority | Additive only | Приоритет (Low/Normal/High/Urgent) — влияет на срочность оповещения. |
Status | string (enum TicketStatus) | Да | Status | Additive only | Всегда New в момент создания (INV-TKT-1); включён для единообразия с ticket-status-changed. |
Channel | string (enum TicketChannel) | Да | Channel | Additive only | Канал (WebForm/Operator/ExternalDesk). |
RequesterUserId | Guid | Да | RequesterUserId | Immutable | Заявитель (id, не PII); ФИО/телефон — из реплики identity у потребителя. |
RequesterCompanyId | Guid? | Нет | RequesterCompanyId | Additive only | Компания заявителя (контекст оповещения); null — инвестор. |
RelatedDealId | Guid? | Нет | RelatedDealId | Additive only | Связанная сделка (crm), если указана при создании. |
CreatedAt | DateTimeOffset | Да | CreatedAt | Immutable | Момент создания обращения. |
Enum-значения не дублируются — дом ticket.md → «Enum TicketCategory/TicketPriority/TicketStatus/TicketChannel». Subject, тело первого сообщения, AssigneeUserId (при создании null), SLA-дедлайны и ФИО/телефон/email заявителя в payload не входят — потребителю (notifications) не нужны; текст обращения читается по API тикета, display-подпись — из реплики identity.
Когда публикуется
| Условие | Переход состояния | Публикация |
|---|---|---|
create-ticket (веб-форма заявителя; Channel = WebForm, CreatedByUserId = null/заявитель) | [*] → New (INV-TKT-1; QueueId по маршрутизации) | атомарно со сменой состояния агрегата |
create-ticket-on-behalf (оператор от лица заявителя; Channel = Operator) | [*] → New | та же |
Взятие в работу/смена статуса публикуются отдельным событием
ticket-status-changed.md; публичный ответ оператора (reply-ticket,
Visibility = Public) порождает ticket-message-posted.md (уведомление заявителя
через notifications), а внутренняя переписка/заметки (Internal) и сообщения самого заявителя Kafka-события
не порождают (внутренний тред, ticket-message.md).
Потребители (consumers)
| Consumer-контекст | Side effects | Идемпотентность | Задержка (SLA) |
|---|---|---|---|
notifications | Оповещение дежурных операторов очереди QueueId о новом обращении (получатели — своя модель дежурств/подписок notifications) | first-seen по MessageId | < 1 мин |
Список получателей событие сознательно не несёт: сопоставление QueueId → дежурные операторы
инкапсулировано в notifications (собственная модель дежурств), support его не публикует.
Доставка и восстановление. At-least-once; потребитель дедуплицирует по MessageId (first-seen).
Транзиентный сбой обработки — ретраи, исчерпание попыток → DLQ с алертом (без блокировки партиции).
Порядок гарантирован только внутри этого топика (ключ TicketId); межтопикового порядка с
ticket-status-changed/ticket-message-posted того же тикета нет — при опережающем status-changed
консюмер обрабатывает событие как самодостаточное (Number/QueueId/Category уже в payload), см.
README.md («Гарантии доставки, порядка и восстановления»).
Версионирование и совместимость
ContractVersion = 1; приVersion != ContractVersionconsumer логирует warning и продолжает обработку. Топик кодирует версию суффиксом.v1по конвенции.- Additive-only для minor: новые optional-поля с безопасным default — без bump. Новые значения enum
TicketCategory/TicketPriority/TicketChannel— additive. - Breaking (удаление/переименование/смена типа/смысла) —
ContractVersion = 2+ новый топикpin.support.ticket-created.v2+ dual-publish на период миграции + deadline миграции consumers + sunset.v1. - Unknown enum (
Category/Priority/Channel) — fallback: сохранить строку как есть, warning, не падать (оповещение с нейтральной формулировкой/приоритетом).
Безопасность
Событие несёт только идентификаторы, enum-значения и метку времени — прямого PII нет по построению:
ФИО/телефон/email заявителя намеренно исключены (потребитель резолвит из своей реплики identity).
| Поле | Класс данных | Правило |
|---|---|---|
TicketId, Number, TenantId, QueueId, RequesterUserId, RequesterCompanyId, RelatedDealId | Internal | include (id/номер, не PII) |
Category, Priority, Status, Channel | Internal | include (enum-строки) |
CreatedAt | Internal | include |
Событие НЕ содержит secrets, tokens, raw credentials, ФИО/телефон/email, тела обращения, вложений.
Доступ к топику — m2m ACL Kafka (notifications).
Обратные ссылки
Автоссылки: где используется этот документ.
- Домен (CQRS) (1): Entity / Aggregate: TicketEntity
- API (2): POST /api/public/support/tickets — Подать обращение, POST /api/support/tickets — Создать обращение от имени пользователя
- Use Cases (1): UC-SUP-001. Приём обращения и назначение оператора
- События (4): События сервиса support: карта топиков и решения об интеграциях, Event Contract: pin.support.arbitrage-resolved (ArbitrageResolvedKafkaEvent), Event Contract: pin.support.ticket-message-posted (TicketMessagePostedKafkaEvent), Event Contract: pin.support.ticket-status-changed (TicketStatusChangedKafkaEvent)
- Консюмеры (10): Consumer: контроль смены телефона связанного инвестора (pin-investor-owner-identity-users), Consumer: Calendar Identity User Sync (calendar-identity-users), Consumer: CRM Identity User Sync (CrmUserUpsertedConsumer), Consumer: Identity Events → Notifications (notifications-identity-events), Consumer: identity-users-sync (ProfileUserUpsertedConsumer, ProfileUserBlockedConsumer), Consumer: identity.users.v1 → AuthorReplica (news-identity-users), Consumer: Messenger User Replica Sync (MessengerUserUpsertedConsumer), Consumer: ReferralUserUpsertedConsumer (pin.identity.users.v1), Consumer: Support Identity User Sync, Consumer: Wallet Identity Display Sync (wallet-identity-users)
- Дашборды (1): Панель Наблюдаемости: support-overview (эксплуатация)
- registries (1): Реестр событий PIN
- index.md (1): Support Service
Связанные документы
- Источник (операции): ../api/public/create-ticket.md, ../api/support/create-ticket-on-behalf.md; сущность — ticket.md (поля, enum, INV-TKT-1); очередь — ticket-queue.md.
- Соседние контракты топиков
support: ticket-status-changed.md, arbitrage-resolved.md; карта — README.md.