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

Событие «Запрошена карточка лида»: pin.referral.lead-attach-requested

Контракт интеграционного события «нужна карточка лида по реферальному приходу». Consumer-документы ссылаются сюда, не переописывая payload. Состав payload зафиксирован домом процесса привязки — attach-rules.md (шаг 6 нормативного алгоритма); здесь — полный контракт.

Назначение

Запрос контексту crm создать карточку лида «агент ↔ инвестор»: инвестор пришёл по реферальной ссылке агента/застройщика («ЛИД … появляется в CRM-системе застройщика или агентства»). Публикуется правилами привязки R1–R4 при выполнении INV-REF-002 (владелец ссылки — Agent или DeveloperManager, активный) — в том числе без создания реферальной связи (правила R3/R4: пользователь зарегистрировался сам либо просто открыл ссылку). Событие — запрос, а не факт: единственность активной пары «инвестор + агент» и жизненный цикл карточки — зона crm (глоссарий «Лид»; дедупликация на стороне потребителя). Контекст referral след лида не хранит (кроме флага LeadRequested журнала).

Metadata

ПолеЗначение
Имя событияpin.referral.lead-attach-requested (ReferralLeadAttachRequestedKafkaEvent)
Topicpin.referral.lead-attachments.v1
Partitions / key6 (ADR-0056) / key = InvestorUserId (порядок запросов per-инвестор)
ContractVersion1
Producerreferral: consumer T1 (user-upserted.md, R1), consumer T2 (user-signed-in.md, R2/R3), операция T3 (validate-referral-link.md, R4, за флагом Referral:LinkOpenAttachEnabled)
Статусdraft

Событие публикуется транзакционно (через outbox) вместе с изменениями процесса привязки: для R1/R2 — согласованно со связью и журналом; для R3/R4 мутаций в referral может не быть — запись всё равно согласована с отметкой идемпотентности потребителя / инкрементом VisitsCount. Собственного агрегата у запроса нет — это событие-запрос процесса привязки; ключ агрегирования — InvestorUserId. Корреляция/actor переносятся в служебном трейсе, не в payload.

Payload

Поля собираются процессом привязки из резолвнутой ссылки (referral-link.md) и созданной связи (referral-bond.md); дом состава — attach-rules.md, шаг 6.

ПолеТипОбязательностьИсточник (поле агрегата)CompatibilityОписание
InvestorUserIdGuidДаUserId триггер-события / актор T3ImmutableИнвестор-лид (= Kafka key, = ключ агрегирования); guard G2 гарантирует Type = Investor.
AgentUserIdGuidДаReferralLinkEntity.OwnerUserIdImmutableАгент/менеджер застройщика — владелец ссылки, которому создаётся карточка лида (INV-REF-002: только Agent/DeveloperManager).
AgentCompanyIdGuid?НетReferralLinkEntity.TenantIdImmutableКомпания агента (агентство/застройщик) — tenant карточки лида в CRM (ADR-0052); null не встречается при выполнении INV-REF-002, но тип nullable — как у источника.
ReferralLinkIdGuidДаReferralLinkEntity.IdImmutableСсылка-источник лида (атрибуция в карточке).
Channelstring (enum ReferralChannel)ДаReferralLinkEntity.ChannelAdditive only (новые значения)Канал привлечения (Direct/Telegram/…; дом enum — referral-link.md) — источник лида в CRM-аналитике.
AppliedRulestring (enum ReferralAttachRule)Даправило матрицы привязкиAdditive only (новые значения)Как пришёл лид: R1 (регистрация), R2 (авторизация в окне), R3 (авторизация самостоятельно зарегистрировавшегося), R4 (открытие ссылки). R6 не публикуется — admin-коррекция лида не создаёт. Дом enum — attach-rules.md.
BondIdGuid?НетReferralBondEntity.IdImmutableСозданная этим же срабатыванием реферальная связь; null — правила R3/R4 и повторные срабатывания при уже существующей активной связи (guard G5: лид без новой связи).
RequestedAtDateTimeOffsetДамомент публикации процесса привязкиImmutableКогда запрошен лид (дублирует время события для удобства потребителя).

Вложенных моделей нет — все поля скалярные. ФИО/телефон инвестора в payload не входят: crm заполняет карточку из собственной реплики пользователей (топик pin.identity.users.v1, user-upserted.md).

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

Условие всех строк — guard-ы G1–G4 пройдены и выполнен INV-REF-002: владелец ссылки Type ∈ {Agent, DeveloperManager} и Status = Active (модификатор R5 отсекает остальных — attach-rules.md).

УсловиеПереход состоянияСогласованность
R1 — регистрация с реф-ссылкой (T1, user-upserted.md)вместе с ReferralBondEntity: [*] → Active (BondId заполнен)связь + журнал Initial + оба события — в одном согласованном изменении
R2 — авторизация в окне lazy-регистрации (T2, user-signed-in.md)та же (BondId заполнен); при существующей активной связи (G5) — без перехода, BondId = nullто же
R3 — авторизация самостоятельно зарегистрировавшегося (T2)переходов нет — связь не создаётся (INV-REF-003), BondId = nullсобытие + отметка идемпотентности — согласованно
R4 — открытие ссылки авторизованным инвестором (T3, validate-referral-link.md; флаг Referral:LinkOpenAttachEnabled)переходов нет, BondId = nullсобытие + инкремент VisitsCount — согласованно

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

Consumer-контекстПотребительЭффектИдемпотентностьЗадержка (SLA)
crmreferral-lead-attach-requested.mdСоздание карточки лида «инвестор + агент» в CRM компании AgentCompanyId с атрибуцией (ReferralLinkId, Channel, AppliedRule, BondId)MessageId + бизнес-ключ (InvestorUserId, AgentUserId): у пары одновременно только один активный лид — дубль/повтор → no-op (правило дедупа — глоссарий «Лид», attach-rules.md)< 5 мин

Единственный потребитель. referral шлёт запрос идемпотентно и повторно (несколько агентов могут одновременно отслеживать одного инвестора — пары различаются AgentUserId); решение «создать новую карточку / оставить существующую активную» принимает crm.

BondId может быть null (правила R3/R4) либо ссылаться на только что созданную связь; даже при заполненном BondId crm не должен предполагать синхронную доступность связи в других контекстах — реплика в rewards асинхронна, межтопикового порядка с pin.referral.bonds.v1 нет (лид способен дойти до CRM раньше, чем rewards увидит связь). Окно согласованности: карточка лида появляется в CRM в пределах SLA (< 5 мин) после срабатывания правила; в этот интервал у пары «инвестор+агент» карточки ещё нет.

Гарантии и порядок для crm:

  • Запросы по одному инвестору упорядочены ключом InvestorUserId; по разным агентам различаются AgentUserId (несколько агентов ведут одного инвестора — пары независимы, дедуп по паре).
  • Лид-запрос может прийти раньше, чем crm увидит пользователя в собственной реплике pin.identity.users.v1 (ФИО/телефон): crm заполняет карточку из своей реплики и обязан выдержать её лаг (retry/дозаполнение), а не отклонять запрос.
  • Событие — запрос-факт: version-guard не нужен, только дедуп по идентификатору сообщения и бизнес-ключу пары (InvestorUserId, AgentUserId); повтор при живой активной паре — no-op.

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

  • Версия — один ContractVersion = 1; при несовпадении версии события потребитель логирует warning и продолжает (upcasting не предусмотрен).
  • Additive-only для minor: новые optional-поля с безопасным default — без bump.
  • BreakingContractVersion = 2 + новый топик pin.referral.lead-attachments.v2 + dual-publish + deadline миграции crm + sunset .v1.
  • Unknown enum: Channel → fallback Other + warning; AppliedRule → warning + обработка как R1 (консервативно — карточка всё равно создаётся).
  • Событие — запрос-факт (append-only, не снапшот): version-guard потребителю не нужен, только дедупликация по MessageId + бизнес-ключу пары.

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

ПолеКласс данныхПравило
InvestorUserId, AgentUserId, AgentCompanyId, ReferralLinkId, BondIdInternalinclude
Channel, AppliedRule, RequestedAtInternalinclude

Событие НЕ содержит PII (ФИО/телефон — реплики потребителя из pin.identity.users.v1), secrets, slug ссылки, сумм/коммерческих условий. Доступ к топику — m2m ACL Kafka (только crm). Tenant-правило: карточка создаётся в scope AgentCompanyId (ADR-0052) — crm не должен раскрывать лид другим компаниям.

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

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

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