Entity / Aggregate: FixationRequestEntity
Дом полей агрегата «Заявка на фиксацию клиента» контекста crm (глоссарий «Заявка на фиксацию»,
«Фиксация»). Все проекции (списки фиксаций агента/агентства/застройщика, страница фиксации, payload
pin.crm.fixation-approved.v1) ссылаются сюда и описывают только дельту.
Назначение
FixationRequestEntity — запрос агента застройщику закрепить клиента (ФИО + телефон) за агентом до сделки.
Создаётся только на основе лида (lead.md); у одного лида может быть много одновременных
фиксаций к одному и разным застройщикам. Заявка несёт snapshot ФИО/телефона клиента и опциональный
override хотелок («шапка» остаётся в лиде; override — для UI/UX, если что-то поменялось, например
срочность).
Застройщик при рассмотрении видит подсветку дублей по ФИО/телефону (полнотекстовый поиск) и решает: одобрить как уникальную (дублей нет) или не уникальную (клиент уже есть в базе застройщика), либо отклонить.
Застройщик подтверждает право агента вести этого клиента по своим объектам (пара «клиент × застройщик»), но сделку не создаёт. Одна одобренная фиксация авторизует агенту создать сколько угодно сделок по объектам этого застройщика (связь фиксация → сделки — 1:N, ведётся со стороны сделки, см. deal.md). Инвестор о фиксациях не знает.
В отличие от лида и сделки (единая модель ParticipantRole, ADR-0071), заявка на фиксацию проще и
описывается тремя скалярными сторонами: иммутабельная атрибуция (OriginAgencyCompanyId/OriginAgentUserId)
- текущий исполнитель (
ExecutorAgentUserId, получатель комиссии) + инвестор (InvestorUserId). Смена исполнителя выполняется переназначением скаляраExecutorAgentUserId(reassign), Origin при этом не трогается.
Классификация
| Поле | Значение |
|---|---|
| Контекст | crm |
| Kind | AggregateRoot |
| Source of truth | crm |
| Таблица | crm.fixation_requests |
| Tenant isolation | TenantId = DeveloperCompanyId (владелец решения по заявке — застройщик, ADR-0052); сторона агентства — иммутабельная атрибуция OriginAgencyCompanyId/OriginAgentUserId + текущий исполнитель ExecutorAgentUserId; видимость — по членству, а не по скаляру (ADR-0071) |
Поля
| Поле | Тип | Обязательность | Ограничения (PK/FK/index/constraint) | Источник | Описание |
|---|---|---|---|---|---|
Id | Guid | Да | PK | app | Идентификатор заявки на фиксацию. |
TenantId | Guid | Да | index ix_fixation_requests_tenant_id | app (выбранный застройщик) | DeveloperCompanyId — застройщик-адресат. |
OriginAgencyCompanyId | Guid | Да | index ix_fixation_requests_origin_agency_company_id | из лида (active-agency claim на момент создания, ADR-0070) | Агентство агента-инициатора на момент подачи: историческая атрибуция, воронка агентства, основание комиссии. Origin-снапшот, иммутабелен (ADR-0061 п.4, ADR-0071, INV-FIX-7) — не переписывается при смене агентом активного агентства. |
OriginAgentUserId | Guid | Да | index; часть ux_fixation_active_triple | из лида | Агент-инициатор на момент подачи: историческая атрибуция и антифрод. Origin-снапшот, иммутабелен (ADR-0061 п.4, ADR-0071, INV-FIX-7) — не переписывается при передаче ведения/смене агентства. |
ExecutorAgentUserId | Guid | Да | index ix_fixation_requests_executor_agent_user_id | производное (текущий исполнитель) | Текущий агент-исполнитель фиксации и получатель комиссии при одобрении. При создании совпадает с OriginAgentUserId; мутабельно — руководитель агентства/Менеджер ПИН может переназначить ведение (reassign) без переписывания Origin. Единственный источник истины исполнителя (ADR-0071); скаляр-«владелец» упразднён. |
InvestorUserId | Guid | Да | index; часть ux_fixation_active_triple | из лида | Инвестор (клиент). |
LeadId | Guid | Да | FK fk_fixation_requests_lead_id → crm.leads(id), index | app | Лид-основание. |
ClientId | Guid | Да | FK fk_fixation_requests_client_id → crm.clients(id), index | из лида | Карточка клиента агентства. |
Status | FixationStatus | Да | enum как text, varchar(32), index ix_fixation_requests_status; unique partial ux_fixation_active_triple on (OriginAgentUserId,InvestorUserId,TenantId) where status in ('Pending','FixedUnique','FixedNonUnique') | app | См. enum и INV-FIX-001. |
ClientName | FullName (owned) | Да | контракт VO — client.md | snapshot из ClientEntity на момент подачи | ФИО клиента в заявке (иммутабельный snapshot: застройщик видит то, что подал агент). |
ClientPhoneNumber | string | Да | varchar(32), E.164 | snapshot из ClientEntity | Телефон клиента в заявке (ключ дубль-проверки). |
WishesOverride | LeadWishes? (owned) | Нет | контракт VO — lead.md, префикс колонок wishes_override_ | app (форма отправки фиксации) | Override «шапки хотелок» для этой заявки; null — застройщику показываются актуальные Lead.Wishes через агентскую проекцию. Лид не изменяется. |
Uniqueness | FixationUniqueness | Да | enum как text, varchar(32), default Unknown | app (авто-проверка) / решение застройщика | Результат дубль-проверки (см. enum). |
DuplicateOfFixationId | Guid? | Нет | FK self fk_fixation_requests_duplicate_of → crm.fixation_requests(id) | авто-проверка | Активная фиксация-дубль у этого застройщика, на которую сработала подсветка (лучшее совпадение). |
DuplicateMatchKind | DuplicateMatchKind? | Нет | enum как text, varchar(32) | авто-проверка | Чем совпало: телефон/ФИО/оба. |
DecidedByUserId | Guid? | Нет | — | app (менеджер застройщика) | Кто одобрил/отклонил. null — решения ещё нет. |
DecidedAt | DateTimeOffset? | Нет | — | app | Момент решения. |
RejectReason | string? | Нет | varchar(1000); обязателен при Status = Rejected (check ck_fixation_reject_reason) | app | Причина отклонения. |
CancelledAt | DateTimeOffset? | Нет | — | app (агент) | Момент отмены агентом. |
CreatedAt | DateTimeOffset | Да | index ix_fixation_requests_created_at desc | app | Подача заявки. |
CreatedByUserId | Guid? | Нет | — | app | Агент-инициатор (совпадает с OriginAgentUserId; Менеджер ПИН может подать от имени агента). |
UpdatedAt | DateTimeOffset | Да | — | app | Дата последнего изменения. |
UpdatedByUserId | Guid? | Нет | — | app | Последний изменивший. |
DeletedAt | DateTimeOffset? | Нет | — | app | Soft-delete (административно). |
DeletedByUserId | Guid? | Нет | — | app | Кто скрыл. |
Enum FixationStatus («ожидает, зафиксирован, отклонён; зафиксирован уникальный / не уникальный»)
| Значение | Описание |
|---|---|
Pending | Ожидает решения застройщика. |
FixedUnique | Зафиксирован как уникальный клиент (дублей в базе застройщика нет). Даёт право на комиссию. |
FixedNonUnique | Зафиксирован как не уникальный (дубль есть; условия комиссии решает застройщик/rewards). |
Rejected | Отклонён застройщиком (RejectReason обязателен). |
Cancelled | Отозван агентом до решения. |
Enum FixationUniqueness
| Значение | Описание |
|---|---|
Unknown | Проверка не выполнялась (черновой момент до сохранения; в БД практически не встречается). |
NoDuplicates | Авто-проверка не нашла активных совпадений у застройщика. |
HasDuplicates | Найдены совпадения; заполнены DuplicateOfFixationId/DuplicateMatchKind, UI подсвечивает дубль. |
Enum DuplicateMatchKind
| Значение | Описание |
|---|---|
Phone | Точное совпадение нормализованного телефона. |
Name | Fuzzy-совпадение ФИО (полнотекстовый поиск, порог score — конфигурация). |
PhoneAndName | Совпали оба признака. |
Дубль-детект (правило)
При создании заявки и при открытии карточки застройщиком выполняется проверка по активным фиксациям того
же TenantId через поисковую проекцию FixationRequestSearchDocument (область
поиска: TenantId = DeveloperCompanyId, IsActive = true; исключая текущую заявку):
- точное совпадение телефона — точный поиск по
ClientPhoneNumber→Phone; - fuzzy-совпадение ФИО — нечёткий поиск по
ClientNameс порогом score (конфигурация) →Name; - лучшее совпадение пишется в
DuplicateOfFixationId+DuplicateMatchKind,Uniqueness = HasDuplicates; иначеNoDuplicates. Решение «уникальный/не уникальный» принимает менеджер застройщика — авто-проверка только подсвечивает («автоматически с проверкой дублей по номеру / ФИО»).
Value objects
FullName(owned, snapshot) — контракт в client.md; колонкиclient_name_*.LeadWishes(owned, nullable override) — контракт в lead.md; колонкиwishes_override_*- флаг наличия
wishes_override_is_set boolean not null default false.
- флаг наличия
Модели JSONB (versioned)
JSONB-модели не используются.
Связи
| Связь | Тип | Ключ | Правило загрузки | Delete behavior |
|---|---|---|---|---|
LeadEntity | reference (основание) | LeadId | загрузка при создании (проверка Status = Active) | restrict |
ClientEntity | reference | ClientId | загрузка при создании (snapshot ФИО/телефона) | restrict |
DealEntity | inverse (1:N, авторизованные сделки) | DealEntity.FixationRequestId → crm.fixation_requests(id) | связь ведётся со стороны сделки; одна одобренная фиксация авторизует много сделок (deal.md) | restrict (нельзя удалить фиксацию-основание при живых сделках) |
FixationRequestEntity (дубль) | self-reference | DuplicateOfFixationId | загрузка при показе карточки | set null |
Инварианты и переходы состояний
| Инвариант | Условие | Когда проверяется | Ошибка |
|---|---|---|---|
| INV-FIX-001 | На тройку (OriginAgentUserId,InvestorUserId,DeveloperCompanyId) — не более одной активной фиксации (Pending/FixedUnique/FixedNonUnique). Тройка строится на иммутабельном OriginAgentUserId (агент-инициатор), не на мутабельном исполнителе — переназначение ведения не создаёт/не ломает уникальность | при создании заявки (unique partial ux_fixation_active_triple) | CRM_FIXATION_ACTIVE_EXISTS |
| INV-FIX-2 | Создание — только из лида Status = Active, агентом-владельцем лида (или Менеджером ПИН) | при создании заявки | CRM_LEAD_NOT_ACTIVE / CRM_LEAD_FORBIDDEN |
| INV-FIX-3 | Решение (Approve/Reject) — только из Pending, менеджером компании TenantId | при решении по заявке | CRM_FIXATION_INVALID_STATE |
| INV-FIX-4 | Отмена (Cancel) — только из Pending, агентом-инициатором (или руководителем его агентства, Менеджером ПИН) | при отмене заявки | CRM_FIXATION_INVALID_STATE / CRM_FIXATION_FORBIDDEN |
| INV-FIX-5 | Rejected требует RejectReason; FixedUnique допустим только при Uniqueness = NoDuplicates (иначе менеджер обязан выбрать FixedNonUnique или подтвердить уникальность вручную флагом команды forceUnique — фиксируется в audit) | при решении по заявке (check ck_fixation_reject_reason) | CRM_FIXATION_REASON_REQUIRED / CRM_FIXATION_DUPLICATE_CONFLICT |
| INV-FIX-6 | Одобрение — только авторизация: перевод в FixedUnique/FixedNonUnique подтверждает право агента вести клиента по объектам застройщика. Сделка при одобрении не создаётся; фиксация не хранит ссылку на сделку. Одна одобренная фиксация авторизует много сделок (пара «клиент × застройщик») — связь 1:N ведётся со стороны сделки (DealEntity.FixationRequestId, deal.md) | при одобрении заявки | — |
| INV-FIX-7 | Иммутабельна только атрибуция OriginAgencyCompanyId/OriginAgentUserId — snapshot на момент подачи (set-once): не пересчитывается/не back-fill-ится при смене агентом агентства или передаче ведения (ADR-0061 п.4, ADR-0071). Переписывание исказило бы историческую воронку, антифрод и основание начислений rewards. Текущий исполнитель ExecutorAgentUserId мутабелен — может быть переназначен (reassign) руководителем агентства/Менеджером ПИН; при одобрении событие несёт актуального Executor (получателя комиссии) | Origin — при создании (правки нет); ExecutorAgentUserId — при reassign (актор ∈ полномочные) | CRM_FIXATION_SNAPSHOT_IMMUTABLE / CRM_FIXATION_REASSIGN_FORBIDDEN |
Доменные и интеграционные события
| Событие | Тип | Когда | Snapshot/поля |
|---|---|---|---|
FixationRequested | доменное | Создание заявки | Id, TenantId, LeadId, OriginAgentUserId, ExecutorAgentUserId |
FixationDecided | доменное | Approve/Reject/Cancel | Id, Status, DecidedByUserId |
FixationApprovedEvent | интеграционное, topic pin.crm.fixation-approved.v1, ContractVersion = 1 | Pending → FixedUnique/FixedNonUnique | FixationRequestId, TenantId (застройщик), OriginAgencyCompanyId, OriginAgentUserId, ExecutorAgentUserId, CommissionRecipientUserId (= ExecutorAgentUserId на момент одобрения — получатель комиссии, ADR-0071), InvestorUserId, Status, DecidedAt (сделки нет — событие авторизации, DealId не передаётся); консюмеры: rewards (право/eligibility исполнителя; комиссия — при завершении сделки), notifications; контракт — ../events/fixation-approved.md |
FixationRejectedEvent | интеграционное, topic pin.crm.fixation-rejected.v1, ContractVersion = 1 | Pending → Rejected | FixationRequestId, TenantId, OriginAgentUserId, ExecutorAgentUserId, RejectReason, DecidedAt; консюмер: notifications; контракт — ../events/fixation-rejected.md |
Интеграционные события публикуются атомарно с переходом статуса.
Индексы, хранение, безопасность
| Аспект | Значение |
|---|---|
| Индексы | PK; ix_fixation_requests_tenant_id; ix_fixation_requests_origin_agency_company_id; btree (origin_agent_user_id), ix_fixation_requests_executor_agent_user_id, (investor_user_id), (lead_id), (client_id); ux_fixation_active_triple unique partial (origin_agent_user_id,investor_user_id,tenant_id); ix_fixation_requests_status; ix_fixation_requests_created_at desc |
| Полнотекстовый поиск | Elasticsearch-проекция FixationRequestSearchDocument (../search/fixations.md, ADR-0059) — поиск списков агента/застройщика + дубль-детект (fuzzy ФИО + точный телефон); PostgreSQL-FTS (tsvector/GIN) не используется |
| Партиционирование / retention | none (объём мал; история хранится бессрочно как основание комиссий) |
| Concurrency | оптимистическая блокировка: одновременные Approve/Cancel — проигравший получает конфликт и перечитывает состояние |
| Permissions / PII | crm.fixations.view / crm.fixations.manage (агентская сторона), crm.fixations.decide (застройщик). Видимость по членству/полномочию (ADR-0071), не по скаляру-владельцу: доступ имеет актор, который является текущим исполнителем (ExecutorAgentUserId) или админ/руководитель компании-владельца агентской стороны (по OriginAgencyCompanyId, в рамках scope-иерархии ADR-0025) или Менеджер ПИН (platform-scope). Сторона застройщика — заявки своего TenantId; инвестор доступа не имеет. PII: ClientName/ClientPhoneNumber — маскирование телефона в списках застройщика до решения не требуется (данные переданы для фиксации осознанно), в логи — только Id. |
| Audit | отметки создания/изменения/удаления (кто и когда); решения (DecidedByUserId,DecidedAt,RejectReason) — иммутабельные факты |
Межсервисные последовательности и промежуточные состояния
Дубль-детект и поисковая реплика. Проверка дублей выполняется по поисковой проекции
FixationRequestSearchDocument (Elasticsearch), которая наполняется асинхронно из
изменений фиксаций. Проекция — eventually consistent: только что поданная соседняя заявка может не
попасть в индекс мгновенно, поэтому авто-подсветка HasDuplicates — вспомогательная, а решение
уникальности всегда за менеджером застройщика (INV-FIX-5). Дубль-детект запускается дважды: при подаче
заявки (первичная отметка Uniqueness) и при открытии карточки застройщиком (пересчёт по свежему индексу).
Одобрение (авторизация, без сделки). В одном согласованном изменении: заявка → FixedUnique/FixedNonUnique,
проставляются DecidedByUserId/DecidedAt (INV-FIX-6) — сделка не создаётся, фиксация ссылки на сделку
не хранит. Далее асинхронно публикуется FixationApprovedEvent (→ rewards: право/eligibility текущего
исполнителя по CommissionRecipientUserId, основание — по иммутабельному Origin; комиссия материализуется
позже — при завершении сделки; notifications — агенту «фиксация одобрена»). Инвестор о факте фиксации
не уведомляется (о фиксациях не знает). Сделки по объектам застройщика агент создаёт отдельно —
одобренная фиксация авторизует их сколько угодно (связь 1:N со стороны сделки, deal.md).
- Что видит агент/застройщик. Заявка сразу переходит в одобренный статус (данные
crm); в списке застройщика —FixedUnique/FixedNonUnique. Право (eligibility) вrewards— с задержкой (eventual); сделок в этот момент нет.
Отклонение/отмена. → Rejected → FixationRejectedEvent (→ notifications агенту с причиной); → Cancelled (агентом) закрывает активную тройку без внешних эффектов, кроме снятия блокировки INV-FIX-001.
Отказы, идемпотентность и конкуренция
- Единственность активной тройки. Структурная защита — unique partial
ux_fixation_active_tripleна (AgentUserId,InvestorUserId,DeveloperCompanyId); повтор подачи в активной фазе →CRM_FIXATION_ACTIVE_EXISTS. Гонка двух одновременных подач на одну тройку → ровно однаPending. - Гонка «одобрение ↔ отмена».
Approveменеджера иCancelагента конкурируют заPending; оптимистическая блокировка по версии: побеждает первый коммит, проигравший перечитывает состояние и видитCRM_FIXATION_INVALID_STATE(заявка уже неPending). Если одобрение выиграло — отмена невозможна (заявка уже решена); если отмена выиграла — менеджер видитCancelled. - Устаревший дубль-детект. Если между подсветкой и решением индекс изменился (появился/ушёл дубль),
менеджер всё равно решает вручную; при
Uniqueness = HasDuplicatesвыборFixedUniqueтребует явного флагаforceUnique(фиксируется в audit) — иначеCRM_FIXATION_DUPLICATE_CONFLICT(INV-FIX-5). - Идемпотентность одобрения. Переход возможен только из
Pending— повтор команды одобрения над уже решённой заявкой отклоняется (CRM_FIXATION_INVALID_STATE);FixationApprovedEventпубликуется ровно один раз (при первом одобрении). Сделка при одобрении не создаётся, поэтому двойной сделки быть не может. - Иммутабельная атрибуция vs мутабельный исполнитель.
OriginAgencyCompanyId/OriginAgentUserId— set-once (INV-FIX-7); смена агентом агентства или передача ведения после подачи не переписывают Origin (основание/атрибуциюrewards). Текущий исполнительExecutorAgentUserIdможет быть переназначен (reassign); при одобрении получатель комиссии (CommissionRecipientUserId) снимается с актуальногоExecutorAgentUserIdна момент решения.
Acceptance-критерии
- Happy (одобрение уникального). Дано: заявка
Pending,Uniqueness = NoDuplicates. Когда менеджер застройщика одобряет как уникальную. Тогда заявкаFixedUnique, сделка не создаётся (фиксация ссылки на сделку не хранит), опубликованFixationApprovedEventбезDealIdсCommissionRecipientUserId = ExecutorAgentUserId(→rewardsфиксирует право/eligibility текущего исполнителя; комиссия — при завершении будущей сделки). - Переназначение исполнителя перед одобрением. Дано: заявка
Pending, руководитель агентства сменилExecutorAgentUserIdна другого агента (reassign). Когда застройщик одобряет. ТогдаOrigin*не изменён,FixationApprovedEvent.CommissionRecipientUserIdравен новомуExecutorAgentUserId. - Дубль при подаче. Дано: активная фиксация с тем же телефоном у застройщика. Когда агент открывает
карточку. Тогда
Uniqueness = HasDuplicates, заполненыDuplicateOfFixationId/DuplicateMatchKind. - Уникальный при наличии дубля. Дано:
Uniqueness = HasDuplicates. Когда менеджер выбираетFixedUniqueбезforceUnique. Тогда отказCRM_FIXATION_DUPLICATE_CONFLICT. - Отклонение без причины. Дано: заявка
Pending. Когда менеджер отклоняет безRejectReason. Тогда отказCRM_FIXATION_REASON_REQUIRED. - Повторная активная тройка. Дано: активная фиксация на (агент, инвестор, застройщик). Когда подаётся
вторая. Тогда отказ
CRM_FIXATION_ACTIVE_EXISTS. - Лид не активен. Дано: лид
Expired/Archived. Когда агент подаёт фиксацию. ТогдаCRM_LEAD_NOT_ACTIVE. - Гонка одобрение/отмена. Дано:
Pending, менеджер одобряет и агент отменяет одновременно. Когда оба выполняются. Тогда применяется один переход; проигравший получаетCRM_FIXATION_INVALID_STATE.
Обратные ссылки
Автоссылки: где используется этот документ.
- Домен (CQRS) (3): Entity / Aggregate: ClientEntity, Entity / Aggregate: DealEntity, Entity / Aggregate: LeadEntity
- API (18): GET /api/agent/crm/clients/{clientId} — Карточка клиента, GET /api/agent/crm/fixations — Список фиксаций агентства (+ поиск), GET /api/agent/crm/fixations/{fixationId} — Карточка фиксации (агент), GET /api/agent/crm/leads/{leadId} — Карточка лида, GET /api/agent/crm/statistics — Статистика агентства/агента, GET /api/developer/crm/fixations — Список фиксаций застройщика (+ FTS), GET /api/investor/crm/leads — Мои лиды (инвестор), GET /api/pin-manager/crm/fixations — Сквозной список всех фиксаций платформы, GET /api/pin-manager/crm/fixations/{fixationId} — Карточка любой фиксации (Менеджер ПИН), GET /api/pin-manager/crm/leads/{leadId} — Карточка любого лида (Менеджер ПИН), POST /api/agent/crm/clients/{clientId}/archive — Архивировать клиента, POST /api/agent/crm/deals — Создать сделку из лида по объекту (+6)
- Use Cases (8): UC-CRM-002. Агент создаёт сделку из лида (выбор объекта, гейт вовлечения застройщика), UC-CRM-013. Увольнение агента: каскад отвязки от процессов CRM, UC-CRM-017. Flow B: агент предлагает объект → Draft-сделка → подтверждение инвестором → вовлечение застройщика, UC-CRM-018. Несколько сделок из одной одобренной фиксации (по разным объектам застройщика), UC-FIX-001. Агент отправляет заявку на фиксацию, UC-FIX-002. Застройщик одобряет фиксацию (авторизация работы с клиентом, без создания сделки), UC-FIX-003. Застройщик отклоняет фиксацию, US-реестр «Участники и владение процессами» (US-CRM-PART / US-AG-ADMIN / US-AGT-MULTI / US-INV-CO)
- События (3): Event Contract: pin.crm.deal-created (DealCreatedEvent), Event Contract: pin.crm.fixation-approved (FixationApprovedEvent), Event Contract: pin.crm.fixation-rejected (FixationRejectedEvent)
- Консюмеры (2): Consumer: CRM Agent Offboarding (CrmAgentOffboardingConsumer), Consumer: CRM Fixation Approved
- Поиск (1): FixationRequestSearchDocument
- adr (4): ADR-0061: Независимый агент, отвязка от агентства и приглашения по номеру телефона, ADR-0070: Мульти-агентство и контекст активного агентства, ADR-0071: Владение процессами CRM компанией и единая модель участников, ADR-0072: Увольнение/исключение агента и каскад доступа
- index.md (1): CRM Service
- registries (2): Реестр инвариантов PIN, Реестр сущностей PIN
Связанные документы
- lead.md (основание, VO
LeadWishes), client.md (VOFullName), deal.md (сделки, авторизованные фиксацией; связь 1:N черезDealEntity.FixationRequestId, составParticipantRole). - Комиссия по фиксации —
docs/06-services/rewards/README.md(будущий путь по конвенции); получатель —CommissionRecipientUserIdсобытия одобрения (= текущийExecutor), основание — по Origin. - ADR-0052 (tenancy двухсторонних сущностей); ADR-0070 (мульти-агентство:
AgencyCompanyIdиз active-agency claim на момент создания); ADR-0071 (Origin-атрибуция ⟂Executor, видимость по членству,CommissionRecipientUserId); ADR-0061 п.4 (запрет back-fill Origin). Поиск списков и дубль-детект — Elasticsearch-проекция ../search/fixations.md (ADR-0059), PostgreSQL-FTS не используется.