Перейти к основному содержимому

Event Contract: pin.identity.user-blocked (UserBlockedKafkaEvent)

Версионируемый контракт интеграционного события «пользователь заблокирован». Consumer-документы ссылаются сюда, не переописывая payload.

Назначение

Сигнальное событие перехода UserEntity Active|Invited → Blocked: потребители немедленно ограничивают активность пользователя (отклонение действий по кэшированным токенам на gateway, скрытие из контактов, остановка уведомлений), не дожидаясь снапшота. Обратный переход (Blocked → Active) отдельного события не имеет — публикуется user-upserted со Status = Active.

Metadata

ПолеЗначение
Event typepin.identity.user-blocked
Topicpin.identity.users.v1 — общий с user-upserted; общий key (UserId) обеспечивает строгий порядок per-user
Partitions / key6 / key = UserId
ContractVersion1
Produceridentity: блокировка через admin API (block-user), синхронизация из Talent (блокировка в Talent)
Статусdraft
Атомарность публикации

Событие публикуется атомарно с переходом статуса пользователя и отзывом сессий (INV-S7 user-session.md): до фиксации перехода событие не отправляется, после — доставляется гарантированно (at-least-once).

Payload UserBlockedKafkaEvent

Дом полей — entity: UserEntity (Id, BlockedAt, причина).

ПолеТипОбязательностьИсточник (поле агрегата)CompatibilityОписание
UserIdGuidДаUserEntity.IdImmutableКлюч агрегата (= Kafka key).
CompanyIdGuid?НетUserEntity.CompanyIdAdditive onlyКомпания пользователя (null — инвестор); экономит потребителям lookup.
BlockedAtDateTimeOffsetДамомент блокировкиImmutableКогда заблокирован.
Reasonstring (enum UserBlockReason)Дапричина, указанная при блокировкеAdditive only (новые значения)Причина: см. enum ниже.
VersionlongДаUserEntity.VersionImmutable semanticsДоменная версия после перехода; монотонный guard.

Enum UserBlockReason

ЗначениеИсточник
AdminDecisionРешение администратора через admin API (ADR-0053).
CareInterventionВмешательство Службы заботы (арбитраж/фрод-подозрение через admin API).
TalentBlockedБлокировка пользователя в Talent Identity (talent-identity-sync).
CompanyRequestБлокировка руководителем компании (identity.users.block в scope организации).

Вложенных моделей нет.

Когда публикуется

УсловиеПереход состоянияПубликация
Блокировка через admin API (block-user)`ActiveInvited → Blocked`
Блокировка руководителем компании (public API, permission identity.users.block)та жета же
Блокировка/снапшот со Status = Blocked из Talent (алгоритмы C/D talent-identity-sync)та же, Reason = TalentBlockedта же

Потребители (consumers)

Consumer-контекстЭффектИдемпотентностьЗадержка (SLA)
gateway (gateway-shared)Инвалидация кэша интроспекции: запросы с живым access-JWT заблокированного отклоняются до истечения токенаMessageId< 30 сек
crmПометка реплики Blocked: запрет назначения участником новых сделок/лидовMessageId + Version-guard< 1 мин
messengerСкрытие из поиска контактов; в существующих чатах — пометка «заблокирован»то же< 5 мин
notificationsОстановка всех рассылок пользователюто же< 5 мин
Разграничение ответственности

Отклонение входа заблокированного enforce-ится самим identity (IDENTITY_USER_BLOCKED, user.md), отзыв сессий — в транзакции блокировки; consumers нужны только для реплик/кэшей.

Порядок и согласованность

  • Общий топик и ключ с user-upserted. Блокировка и последующая разблокировка (Blocked → Active, публикуется как user-upserted со Status = Active) идут одним топиком с ключом UserId — строгий порядок per-user; потребитель применяет по Version-guard.
  • First-seen. Если блокировка — первое событие потребителя по пользователю (реплики нет), он создаёт реплику в состоянии Blocked (fail-closed) и досогласует поля при ближайшем user-upserted.
  • Окно эффекта и сессии. На gateway блокировка эффективна в пределах SLA (< 30 сек, инвалидация кэша интроспекции); ранее выданные RefreshSession отозваны в транзакции блокировки (INV-S7 user-session.md), поэтому продлить доступ ротацией refresh-токена нельзя. Повтор доставки — no-op (пользователь уже Blocked).

Версионирование и совместимость

  • ContractVersion = 1; несоответствие версии события — warn-and-proceed.
  • Additive-only без bump; breaking — ContractVersion = 2 + pin.identity.users.v2 + dual-publish + sunset.
  • Unknown enum Reason — fallback AdminDecision, warning.

Безопасность

ПолеКласс данныхПравило
UserId, CompanyId, BlockedAt, VersionInternalinclude
ReasonInternalinclude; конечному пользователю дословно не показывается (только «учётная запись заблокирована, обратитесь в поддержку»)
Без PII и секретов

Событие НЕ содержит PII (ФИО/телефон — в снапшоте user-upserted), secrets, комментария оператора (комментарий — в аудите identity).

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы