UC-OVR-008. Агент выходит из агентства, сохраняя метрики
Назначение
Cross-service сценарий развязки членства (ADR-0061, аналогия «игрок меняет клан»): агент выходит из агентства
и становится независимым. Личные метрики/достижения (user-centric, агрегация по AgentUserId) сохраняются,
а исторические сделки/лиды/фиксации остаются у прежней компании (снапшоты иммутабельны, back-fill запрещён).
Оркестрирует identity (см. UC-IDN-010);
изменения доступа и ростера потребляют crm, rewards, catalog, chessboard.
Metadata
| Поле | Значение |
|---|---|
| Статус | draft |
| Owning team | identity |
| Primary capability | agent-membership-detach |
| Risk level | high |
Scope И Участники
| Участник | Роль |
|---|---|
| Агент (сам) / Руководитель агентства | Актор: инициирует выход / исключение |
identity | Владелец членства/ролей: AgentMembership → Left, роль Organization → Platform |
crm | Consumer: обновляет ростер и user-centric метрики; исторические снапшоты не пересчитывает |
rewards | Consumer: основания комиссий по AgentUserId (исторические — за прежней компанией) |
catalog / chessboard / gateway | Consumer user-access-changed: пересчёт эффективных прав |
notifications | Уведомление руководителю об убытии из ростера |
Preconditions
- У агента активное
AgentMembership(Status = Active);UserEntity.Type = Agent,Status = Active.
Основной Сценарий
- Агент жмёт «Выйти из агентства» (диалог: метрики сохранятся, доступ к клиентской базе агентства прекратится).
- Фронт →
POST /api/v1/me/agency-membership/leave(см. UC-IDN-010,leave-agency). identityв одном согласованном изменении: членство переходитActive → Left(проставляетсяLeftAt, история найма сохраняется); у пользователя обнуляется привязка к компании (CompanyId → null, тип остаётсяAgent); рольagentпереезжаетOrganization → Platform.- Публикуются интеграционные события:
pin.identity.agent-membership-changed.v1 (Left),pin.identity.users.v1 (CompanyId = null),pin.identity.access.v1 (Organization → Platform). crm(consumer): обновляет ростер и user-centric метрики поAgentUserId; исторические сделки/лиды/ фиксации не трогает (иммутабельные снапшотыAgencyCompanyId/AgentUserId, ADR-0061 п.4).rewardsпересчитывает основания текущих комиссий поAgentUserId; исторические комиссии остаются у прежней компании.catalog/chessboard/gateway пересчитывают эффективные права поuser-access-changed.- Агент видит статус «Независимый агент»; клиентская база агентства скрыта, личные метрики/достижения/лоты сохранены. Руководитель по membership-событию видит убытие из ростера.
Sequence
Постусловие
После успешной развязки гарантированно (в одном согласованном изменении в identity):
AgentMembershipпереведеноActive → Leftс проставленнымLeftAt; запись не удаляется (история найма сохраняется);- у
UserEntityобнулена привязка к компании (CompanyId → null), тип остаётсяAgent; рольagentпереехалаOrganization → Platform; - опубликованы три интеграционных события:
pin.identity.agent-membership-changed.v1(Status = Left, key =AgentUserId),pin.identity.users.v1(CompanyId = null),pin.identity.access.v1(Organization → Platform); - по обработке событий (eventual):
crmобновил ростер и user-centric метрики (< 1 мин),rewardsпрекратил основания текущих комиссий от имени компании (< 5 мин),catalog/chessboard/gateway пересчитали эффективные права (< 5 мин), руководитель уведомлён; - исторические сделки/лиды/фиксации не изменены — снапшоты
AgencyCompanyId/AgentUserIdиммутабельны, back-fill запрещён.
Наблюдаемое пользователем: агент сразу видит статус «Независимый агент», клиентская база агентства скрыта,
личные метрики/достижения/лоты сохранены; права к ресурсам агентства снимаются в пределах окна обработки
user-access-changed.
Альтернативные Сценарии И Отказы
| Ситуация | Поведение |
|---|---|
| Руководитель исключает агента | Тот же домен-метод с identity.users.manage; actor-stamping = руководитель (UC-IDN-010 A1) |
| Агент хочет полностью вернуться к инвестору | become-investor вместо leave (UC-IDN-010 A2); дополнительно снимается роль agent |
| Нет активного членства (уже независимый) | 404 IDENTITY_MEMBERSHIP_NOT_ACTIVE (идемпотентно для UI — повтор leave безопасен) |
| Гонка leave/accept (или leave/исключение) | 409 CONCURRENCY_CONFLICT (оптимистическая блокировка); побеждает первая зафиксированная, проигравший видит конфликт и перечитывает состояние |
agent-membership-changed доставлен потребителю повторно / с меньшей версией | Version-guard: событие с версией ≤ применённой игнорируется; повтор не удваивает пересчёт |
| Частичный отказ публикации событий | Единое согласованное изменение (членство + пользователь + роль + публикация) — либо всё зафиксировано и события уйдут, либо ничего |
Согласованность И Идемпотентность
- Атомарность. Переход членства, отвязка пользователя, переезд роли и постановка событий на публикацию — в одном согласованном изменении; при откате ничего из перечисленного не применяется.
- Порядок per-agent. Ключ
AgentUserId(неMembershipId) гарантирует последовательность join/leave по агенту — потребители видят единственное активное членство консистентно; держат монотонныйVersion-guard. - Идемпотентность. Повторный
leaveпри отсутствии активного членства →404 IDENTITY_MEMBERSHIP_NOT_ACTIVE(безопасно для UI); потребители дедуплицируют поMessageId. - Иммутабельность истории. Пересчёт исторических снапшотов
AgencyCompanyId/AgentUserId— запрещённая операция (ADR-0061 п.4); user-centric метрики/достижения агрегируются поAgentUserIdи переживают смену компании. - Окно eventual-consistency прав. Между
200агенту и фактическим снятием прав к ресурсам агентства — задержка обработкиuser-access-changed(< 5 мин); в окне агент уже «Независимый», но часть прав ещё может действовать до пересчёта.
Acceptance Criteria (Given/When/Then)
- Happy (выход, метрики сохранены). Дано: у агента активное членство (
Status = Active), типAgent. Когда: агент инициирует «Выйти из агентства». Тогда: членствоActive → Left(LeftAtпроставлен),CompanyId → null, роль →Platform; опубликованы три события; ростер/метрики/права пересчитаны; исторические сделки/лиды/фиксации не тронуты. - Исключение руководителем. Дано: руководитель с
identity.users.manage. Когда: исключает агента. Тогда: тот же результат, actor-stamping = руководитель. - Уже независимый. Дано: активного членства нет. Когда: повтор leave. Тогда:
404 IDENTITY_MEMBERSHIP_NOT_ACTIVE, состояние неизменно (идемпотентно). - Гонка. Дано: одновременно leave и accept/исключение. Когда: обе операции применяются. Тогда: одна
фиксируется, другая —
409 CONCURRENCY_CONFLICT. - Сохранность истории. Дано: у агента есть завершённые сделки прежней компании. Когда: агент вышел. Тогда:
снапшоты
AgencyCompanyId/AgentUserIdэтих сделок не изменились, метрики агента поAgentUserIdсохранены.
Source Of Truth И Данные
| Данные | Владелец | Consistency rule |
|---|---|---|
AgentMembership / роли | identity | Left не удаляет запись (история найма); роль переезжает на Platform |
| Исторические сделки/лиды/фиксации | crm | Снапшоты AgencyCompanyId/AgentUserId иммутабельны, back-fill запрещён |
| User-centric метрики/достижения | crm/rewards | Агрегация по AgentUserId (переживает смену компании) |
| Эффективные права | catalog/chessboard/gateway | Пересчитываются по user-access-changed (eventual) |
Контракты И Зависимости
- UC сервиса: UC-IDN-010.
- Events: agent-membership-changed.md
(
pin.identity.agent-membership-changed.v1),pin.identity.users.v1,pin.identity.access.v1. - Историческая привязка (reference): crm/domain/deal.md, get-statistics.md.
- ADR: 0061 independent-agent.
Наблюдаемость
- critical metrics: число выходов/исключений; консистентность user-centric метрик до/после.
- trace path:
identity(согласованное изменение) → шина событий →crm/rewards/catalog/chessboard. - alerts: рассинхрон прав после
access-события; пересчёт исторических снапшотов (запрещённая операция).
Риски И Guardrails
- Риск: потеря наработок агента при развязке. Control: user-centric агрегация по
AgentUserId, история найма сохраняется. - Риск: «утечка» исторических сделок к независимому агенту. Control: иммутабельные снапшоты компании, back-fill запрещён.
- Риск: частичное применение. Control: единое согласованное изменение (членство + пользователь + роль + публикация событий).
Обратные ссылки
Автоссылки: где используется этот документ.
- scenarios (2): Кросс-сервисные сценарии PIN (OVR), UC-OVR-004. От реферальной ссылки до объекта у собственника
- registries (1): Реестр use cases и user stories PIN