Kyc operator flow
Рецепт: полный KYC review flow через Admin Panel.
Предусловия¶
- Пользователь должен быть в статусе
pending_operator_review - Администратор должен иметь роль
operatorилиsuperadminвadmin_roles - Admin Panel подключена к Auth Center через Serverpod client
Статус pending_operator_review устанавливается автоматически KYC Service после успешной OCR-проверки (переход из ocr_processing).
Flow¶
sequenceDiagram
participant Op as Оператор
participant AP as Admin Panel
participant AC as Auth Center
Op->>AP: найти пользователя (getQueue / поиск)
AP->>AC: adminKyc.getQueue() → список pending_operator_review
Op->>AP: открыть карточку пользователя
AP->>AC: adminKyc.getDetail(userId)
AC-->>AP: KYC карточка + presigned URLs документов
Op->>AP: просмотреть документы (фото ID + селфи)
AP->>AC: adminKyc.revealOcrResult(userId, reason)
AC-->>AP: KycOcrResult (расшифрованные поля)
alt Одобрить
Op->>AP: нажать "Approve"
AP->>AC: adminKyc.approve(userId)
Note over AC: kyc_verification.status = 'approved'<br/>kyc_verification.approvedAt = now<br/>kyc_verification.operatorReviewedAt = now
AP->>AC: adminKyc.finalize(userId)
Note over AC: Транзакция:<br/>kyc_verification.status = 'fully_verified'<br/>user.status = 'active'<br/>user_profile заблокирован от изменений
else Отклонить
Op->>AP: нажать "Reject" + указать причину
AP->>AC: adminKyc.reject(userId, reason)
Note over AC: kyc_verification.status = 'pending'<br/>kyc_verification.reviewedAt = now
Note over AC: Пользователь получает Push-уведомление
end
Результат при approve + finalize¶
adminKyc.approve() → adminKyc.finalize() выполняется в одной DB транзакции внутри KycService.finalizeVerification():
| Таблица | Поле | До | После |
|---|---|---|---|
kyc_verification |
status |
approved |
fully_verified |
kyc_verification |
operatorReviewedAt |
null | now |
user |
status |
kyc_pending |
active |
user_profile |
(блокируется от изменений) | изменяемый | locked |
После финализации пользователю отправляется Push-уведомление «KYC подтверждён» (fire-and-forget, ошибка уведомления не откатывает транзакцию).
Результат при reject¶
adminKyc.reject(userId, reason) → KycService.operatorReject():
| Таблица | Поле | После |
|---|---|---|
kyc_verification |
status |
pending |
kyc_verification |
reviewedAt |
now |
Пользователь возвращается в статус pending и может повторно подать документы.
Откат ошибочного approve¶
Если approve() вызван, но finalize() ещё не вызван — статус kyc_verification = 'approved', user.status ещё не изменён.
Для отката через Admin Panel:
1. Вызвать adminKyc.reject(userId, reason) — сбросит статус в pending
2. Пользователь сможет повторно пройти KYC
Если finalize() уже вызван (user.status = 'active') — прямого пути откат нет. Используйте adminUser.blockUser(userId, reason) для блокировки аккаунта до ручного разбирательства.