Event Contract: pin.identity.user-blocked (UserBlockedKafkaEvent)
Версионируемый контракт интеграционного события «пользователь заблокирован». Consumer-документы ссылаются сюда, не переописывая payload.
Назначение
Сигнальное событие перехода UserEntity Active|Invited → Blocked: потребители немедленно
ограничивают активность пользователя (отклонение действий по кэшированным токенам на gateway,
скрытие из контактов, остановка уведомлений), не дожидаясь снапшота. Обратный переход
(Blocked → Active) отдельного события не имеет — публикуется
user-upserted со Status = Active.
Metadata
| Поле | Значение |
|---|---|
| Event type | pin.identity.user-blocked |
| Topic | pin.identity.users.v1 — общий с user-upserted; общий key (UserId) обеспечивает строгий порядок per-user |
| Partitions / key | 6 / key = UserId |
| ContractVersion | 1 |
| Producer | identity: блокировка через admin API (block-user), синхронизация из Talent (блокировка в Talent) |
| Статус | draft |
Событие публикуется атомарно с переходом статуса пользователя и отзывом сессий (INV-S7 user-session.md): до фиксации перехода событие не отправляется, после — доставляется гарантированно (at-least-once).
Payload UserBlockedKafkaEvent
Дом полей — entity: UserEntity (Id, BlockedAt, причина).
| Поле | Тип | Обязательность | Источник (поле агрегата) | Compatibility | Описание |
|---|---|---|---|---|---|
UserId | Guid | Да | UserEntity.Id | Immutable | Ключ агрегата (= Kafka key). |
CompanyId | Guid? | Нет | UserEntity.CompanyId | Additive only | Компания пользователя (null — инвестор); экономит потребителям lookup. |
BlockedAt | DateTimeOffset | Да | момент блокировки | Immutable | Когда заблокирован. |
Reason | string (enum UserBlockReason) | Да | причина, указанная при блокировке | Additive only (новые значения) | Причина: см. enum ниже. |
Version | long | Да | UserEntity.Version | Immutable 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) | `Active | Invited → 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— fallbackAdminDecision, warning.
Безопасность
| Поле | Класс данных | Правило |
|---|---|---|
UserId, CompanyId, BlockedAt, Version | Internal | include |
Reason | Internal | include; конечному пользователю дословно не показывается (только «учётная запись заблокирована, обратитесь в поддержку») |
Событие НЕ содержит PII (ФИО/телефон — в снапшоте user-upserted), secrets, комментария оператора (комментарий — в аудите identity).
Обратные ссылки
Автоссылки: где используется этот документ.
- Домен (CQRS) (3): Entity (Replica): UserDisplayReplicaEntity, Entity / Aggregate: ProfileEntity, Entity / Aggregate: RecipientContactEntity
- API (2): Identity Admin API — реестр методов и общие правила области, POST /api/admin/v1/users/{userId}/block — Блокировка пользователя (admin)
- События (3): События сервиса news: карта топиков и отклонённые события/консюмеры, Event Contract: pin.identity.user-access-changed (UserAccessChangedKafkaEvent), Event Contract: pin.identity.user-upserted (UserUpsertedKafkaEvent)
- Консюмеры (11): 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: Talent Identity Sync (pin-identity-talent-sync), Consumer: Wallet Identity Display Sync (wallet-identity-users)
- index.md (1): Identity Service (Pin.Identity)
- registries (1): Реестр событий PIN
Связанные документы
- Сущность: user.md (stateDiagram); сессии: user-session.md (INV-S7).
- Источники: block-user, talent-identity-sync.
- Соседний контракт топика: user-upserted.md.