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

Event Contract: pin.identity.company-suspended (CompanySuspendedKafkaEvent)

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

Назначение

Сигнальное событие перехода CompanyEntity Active → Suspended: потребители должны немедленно ограничить операции компании (скрыть витрину, заблокировать создание фиксаций/сделок со стороны компании), не дожидаясь очередного snapshot-а. Выделено из company-upserted, потому что несёт причину блокировки и требует более жёсткого SLA реакции. Обратный переход (Suspended → Active) отдельного события не имеет — публикуется обычный CompanyUpsertedKafkaEvent со Status = Active.

Metadata

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

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

Payload CompanySuspendedKafkaEvent

Дом полей — entity: CompanyEntity (раздел «Доменные и интеграционные события»: Id, SuspendedAt, причина).

ПолеТипОбязательностьИсточник (поле агрегата)CompatibilityОписание
CompanyIdGuidДаCompanyEntity.IdImmutableКлюч агрегата (= Kafka key).
SuspendedAtDateTimeOffsetДамомент перехода в SuspendedImmutableКогда компания приостановлена.
Reasonstring (enum CompanySuspendReason)Дапричина, указанная при приостановкеAdditive only (новые значения)PinDecision (решение ПИН) / TalentBlocked (блокировка tenant-а в Talent) / Debt (задолженность).
VersionlongДаCompanyEntity.VersionImmutable semanticsДоменная версия после перехода; монотонный guard у потребителей.

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

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

УсловиеПереход состоянияПубликация
Администратор платформы приостанавливает компанию (admin API, ADR-0053)Active → Suspended (guard INV-8 company.md)атомарно с переходом статуса
Блокировка tenant-а в Talent (talent-identity-sync, алгоритм B)Active → Suspended, Reason = TalentBlockedта же

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

Consumer-контекстЭффектИдемпотентностьЗадержка (SLA)
catalogСкрытие бренд-страницы/пометка проектов застройщикаMessageId + Version-guard< 1 мин
crmБлокировка новых фиксаций/сделок со стороны компании; действующие сделки — предупреждение менеджеру ПИНто же< 1 мин
rewardsЗаморозка начислений/выплат компании до возобновлениято же< 5 мин
Вход пользователей

Вход пользователей приостановленной компании enforce-ится самим identity (INV-9 user.md) — отдельный consumer для этого не нужен.

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

  • Общий топик и ключ с company-upserted. Приостановка и последующее возобновление (Suspended → Active, публикуется как company-upserted) идут одним топиком с ключом CompanyId — строгий порядок per-company; потребитель применяет по Version-guard, поздний дубликат приостановки — skip.
  • First-seen. Если приостановка — первое событие потребителя по этой компании (реплики ещё нет), он создаёт запись в состоянии Suspended (fail-closed: витрина скрыта, операции компании заблокированы) и досогласует остальные поля при ближайшем company-upserted.
  • Идемпотентность и приоритет реакции. Повтор доставки — no-op (компания уже Suspended). Из-за более жёсткого SLA реакции (см. потребители) приостановка обрабатывается приоритетно относительно обычных snapshot-обновлений топика.

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

  • ContractVersion = 1; несоответствие версии события — warn-and-proceed.
  • Additive-only: новые optional-поля — без bump; breaking — ContractVersion = 2 + топик pin.identity.companies.v2 + dual-publish + sunset.
  • Unknown enum Reason — fallback: трактовать как PinDecision (наиболее общий), лог warning.
  • Deprecation — sunset через 2 релиза после миграции потребителей.

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

ПолеКласс данныхПравило
CompanyId, SuspendedAt, VersionPublicinclude
ReasonInternalinclude; в UI конечных пользователей причина не показывается дословно (только «компания временно недоступна»)

Событие НЕ содержит secrets, PII, комментариев оператора (комментарий admin-операции остаётся в аудите identity).

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

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

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