Поток Выводов¶
Вывод средств требует явного запроса пользователя, backend-проверок, прохождения защиты вывода и операционной обработки Saga.
Основной Поток¶
- Пользователь создаёт withdrawal request.
- Backend проверяет JWT, баланс, валюту, сеть, адрес и настройки защиты вывода.
- Backend создаёт заявку с
protection_state. - Если включена задержка, пользователь получает email со ссылкой отмены.
- Scheduler переводит заявку из
queued_delayвreadyпослеrelease_at. - Администратор видит готовую заявку в admin app.
- Администратор подтверждает или отклоняет заявку.
- Исполнение фиксируется через manual/Fordefi workflow.
- Backend создаёт append-only transaction и обновляет статус заявки.
Режимы Защиты¶
| Режим | Новые заявки | Адрес назначения | Влияние на существующие заявки |
|---|---|---|---|
standard |
Разрешены | Любой валидный адрес | Не меняет существующие заявки |
whitelist_only |
Разрешены | Только активный подтверждённый адрес | Не меняет существующие заявки |
disabled |
Заблокированы | Не применимо | Не меняет существующие заявки |
emergency_lock |
Заблокированы | Не применимо | Ожидающие заявки переводятся в blocked |
emergency_lock хранится отдельно от пользовательского режима и сильнее disabled. Пользователь может включить аварийную блокировку, но снять её может только оператор после проверки восстановления доступа.
Состояния защиты заявки¶
| State | Когда ставится | Следующий допустимый переход |
|---|---|---|
queued_delay |
Заявка создана и ждёт защитную задержку | ready, cancelled, blocked |
ready |
Задержка прошла или равна нулю | Обычный admin approval/rejection flow |
cancelled |
Пользователь подтвердил отмену по email | Финальное состояние для защиты |
blocked |
Включён emergency lock или оператор заблокировал заявку | Только operator recovery в ready |
ready не означает выплату. Это только разрешение передать заявку в обычную операционную обработку.
Изменение Настроек¶
Усиление защиты применяется сразу:
standard→whitelist_onlystandard→disabledwhitelist_only→disabled- увеличение
min_delay_hours - включение
emergency_lock
Ослабление защиты применяется только через delayed change и email-подтверждение:
whitelist_only→standarddisabled→whitelist_onlydisabled→standard- уменьшение
min_delay_hours
Пока pending change существует, новый запрос на ослабление не должен перетирать текущий. Включение emergency_lock очищает pending weakening, чтобы после восстановления не применилось устаревшее ослабление.
Email-Cancel¶
При создании заявки с ожиданием backend генерирует одноразовый cancel token.
Инварианты:
- Открытие ссылки показывает страницу подтверждения, но не отменяет заявку само по себе.
- Cancel endpoint не требует JWT, только валидный token.
- Token одноразовый и ограничен сроком действия.
- Отмена доступна только для
queued_delay. - После отмены заявка получает
protection_state = cancelled.
Операторское Восстановление¶
Admin app управляет защитой вывода в карточке клиента, а не на странице операций вывода.
Оператор может:
- снять
emergency_lockс обязательными причиной и evidence/support ID; - выбрать целевой режим после восстановления;
- восстановить отдельную заявку из
blockedвready.
Оператор не должен:
- снимать аварийную блокировку из таблицы выводов без контекста клиента;
- восстанавливать все blocked-заявки автоматически;
- считать
blocked→readyодобрением вывода.
Инварианты¶
- Недостаточный баланс возвращает явную ошибку.
- Неподтверждённый адрес в
whitelist_onlyвозвращает явную ошибку. disabledиemergency_lockблокируют создание новых заявок явной ошибкой.- Отмена, отклонение, блокировка и исполнение не удаляют историю.
- Частичный сбой не должен оставлять заявку в неоднозначном состоянии.
- Frontend не принимает финансовые решения самостоятельно.
- Сумма заявки не должна выбирать отдельный путь защиты.
Проверки¶
- Только user JWT может создать пользовательскую заявку.
- Только admin JWT с нужными правами может менять operator state.
- Повторное подтверждение не создаёт дубль операции.
- Все переходы статусов логируются.
- External custody failure виден оператору.
make analyzeне должен находить fallback/default masking вокруг protection planner.