OneWallet — Карта маршрутов¶
Переменные состояния (от провайдеров)¶
| Переменная | Источник | Значение |
|---|---|---|
isAuthenticated |
authProvider.status == authenticated |
Пользователь вошёл |
userStatus |
authProvider.userStatus |
null / registration_in_progress / kyc_pending / pending_operator_review / fully_verified |
kycStatus |
authProvider.kycStatus |
Статус KYC из таблицы kyc_verification (null / pending / in_review / pending_operator_review / approved / …) |
needsKyc |
userStatus == 'kyc_pending' |
Нужно пройти KYC (не начат) |
isPendingReview |
userStatus == 'pending_operator_review' или userStatus == 'registration_in_progress' && kycStatus != null && kycStatus != 'pending' |
KYC подан, ждёт проверки |
isInitialized |
pinProvider.isInitialized |
SecureStorage прочитан |
isPinSet |
pinProvider.isPinSet |
PIN задан |
isLocked |
pinProvider.isLocked |
Приложение заблокировано (после 5 мин) |
Все маршруты¶
/ → SplashScreen (начальный, ждёт инициализацию)
/welcome → WelcomeScreen (гость: выбор войти/регистрация)
/signin → SignInScreen
/register/email → RegisterEmailScreen
/register/otp → RegisterOtpScreen
/register/referral → RegisterReferralScreen
/register/password → RegisterPasswordScreen
/forgot-password → ForgotPasswordScreen
/forgot-password/otp → ForgotPasswordOtpScreen
/reset-password → ResetPasswordScreen
/setup-pin → SetupPinScreen (первичная установка PIN)
/setup-biometric → SetupBiometricScreen
/pin-unlock → PinUnlockScreen (разблокировка после auto-lock)
/kyc → KycIntroScreen
/kyc/upload → KycDocumentScreen (фото паспорта + селфи)
/kyc/processing → KycProcessingScreen (ожидание OCR)
/kyc/review → KycReviewScreen (проверка данных)
/kyc/terms → KycTermsScreen (согласие)
/kyc/pending → KycPendingScreen ("Verification Status" — только по тапу на баннер)
/home → HomeScreen ┐
/history → HistoryScreen ├─ StatefulShellRoute
/profile → ProfileScreen │ (GlassNavigationBar)
/profile/activity → ActivityScreen ┘
Логика редиректов (выполняется при КАЖДОЙ навигации)¶
redirect(path) {
┌─ Block 1 ─────────────────────────────────────────────────────────────
│ !isAuthenticated && !isAuthRoute && path ≠ '/'
│ → /welcome
└────────────────────────────────────────────────────────────────────────
┌─ Block 2 ─────────────────────────────────────────────────────────────
│ isAuthenticated && isLocked && !isPinUnlockRoute
│ → /pin-unlock
└────────────────────────────────────────────────────────────────────────
┌─ Block 2b ─────────────────────────────────────────────────────────────
│ isPinUnlockRoute && isAuthenticated && isInitialized && !isLocked
│ needsKyc → /kyc
│ else → /home ← isPendingReview НЕ редиректит на /kyc/pending
└────────────────────────────────────────────────────────────────────────
┌─ Block 3 ─────────────────────────────────────────────────────────────
│ isAuthenticated && isInitialized && !isPinSet
│ && !isPinSetupRoute && !isPinUnlockRoute
│ → /setup-pin
└────────────────────────────────────────────────────────────────────────
┌─ Block 4 ─────────────────────────────────────────────────────────────
│ isAuthenticated && (isAuthRoute || path == '/')
│ !isInitialized → null (остаёмся на сплэше)
│ needsKyc → /kyc
│ else → /home ← isPendingReview НЕ редиректит на /kyc/pending
│
│ ⚠️ isPendingReview НЕ вызывает авто-переход на /kyc/pending при холодном
│ запуске. Статус виден через баннер на /home, переход — по тапу.
└────────────────────────────────────────────────────────────────────────
┌─ Block 5 ─────────────────────────────────────────────────────────────
│ isAuthenticated && needsKyc
│ && !isKycRoute && !isPinSetupRoute && !isPinUnlockRoute
│ → /kyc
│ ⚠️ Без !isPinUnlockRoute: /pin-unlock→/kyc→/pin-unlock = redirect loop!
└────────────────────────────────────────────────────────────────────────
┌─ Block 6 ─────────────────────────────────────────────────────────────
│ isAuthenticated && isPendingReview
│ && path ∈ [/kyc/upload, /kyc/processing, /kyc/review, /kyc/terms]
│ → /kyc/pending
│ Защищает от повторной подачи документов пока идёт проверка.
└────────────────────────────────────────────────────────────────────────
→ null (навигация разрешена)
}
isPendingReview — расширенная логика¶
bool get isPendingReview =>
userStatus == 'pending_operator_review' ||
(userStatus == 'registration_in_progress' &&
kycStatus != null &&
kycStatus != 'pending');
| userStatus | kycStatus | isPendingReview | Результат |
|---|---|---|---|
registration_in_progress |
null |
false | Нужно пройти KYC → баннер _KycBanner (если needsKyc) |
registration_in_progress |
pending |
false | Нужно пройти KYC |
registration_in_progress |
in_review / pending_operator_review / … |
true | KYC подан → баннер _KycReviewBanner, переход по тапу |
pending_operator_review |
любой | true | KYC подан → баннер _KycReviewBanner |
fully_verified |
любой | false | Полный доступ, нет баннеров |
Баннеры на /home¶
| Условие | Баннер | Действие по тапу |
|---|---|---|
needsKyc |
_KycBanner — "Complete identity verification" |
context.go('/kyc') |
isPendingReview |
_KycReviewBanner — "Documents under review" |
context.go('/kyc/pending') |
| иначе | нет баннера | — |
/kyc/pendingоткрывается только по тапу на баннер. Автоматической навигации на этот экран при холодном запуске нет.
Схема переходов¶
Исходник: docs/diagrams/router-map.puml
Сценарии пользователей¶
A. Новый пользователь (регистрация → KYC)¶
RegisterPassword → context.go('/home')
└─ redirect Block3: !isPinSet → /setup-pin
└─ redirect Block5: needsKyc → /kyc ← пользователь здесь
└─ redirect: null (isKycRoute) → /kyc рендерится
B. Возврат в приложение (PIN заблокирован, needsKyc)¶
App start → / (SplashScreen)
└─ _init() completes: isLocked=true
└─ redirect Block2: isLocked → /pin-unlock
└─ User verifies PIN
└─ redirect Block2b: needsKyc → /kyc
C. Возврат в приложение (PIN разблокирован, KYC пройден)¶
App start → / (SplashScreen)
└─ _init() completes: isLocked=true
└─ redirect Block2 → /pin-unlock
└─ User verifies PIN
└─ redirect Block2b: !needsKyc → /home
D. KYC submitter (ждёт оператора) — холодный запуск¶
App start → / (SplashScreen)
└─ isAuthenticated + isInitialized + !needsKyc
└─ Block4 → /home
└─ _KycReviewBanner отображается на /home
└─ Пользователь тапает → context.go('/kyc/pending')
⚠️ До изменения (v1): Block 4/2b перенаправляли isPendingReview → /kyc/pending автоматически. Теперь
/kyc/pendingоткрывается только явным тапом.
E. registration_in_progress + kycStatus активный¶
userStatus='registration_in_progress', kycStatus='in_review'
isPendingReview = true
→ Block4: !needsKyc → /home
→ _KycReviewBanner отображается
→ Block6: если попытка зайти в /kyc/upload → /kyc/pending (защита)
F. Перелогон (pending_operator_review) — через /setup-biometric¶
signIn()
└─ clearPin() → isPinSet=false
└─ status: authenticated → Block3: !isPinSet → /setup-pin
└─ loadUserStatus() → userStatus='pending_operator_review'
└─ Пользователь ставит PIN → /setup-biometric
└─ Skip / Enable / Unavailable
└─ _postSetupRoute: !needsKyc → /home ✅
└─ _KycReviewBanner отображается на /home
⚠️ До исправления (issue #5):
SetupBiometricScreenвсегда делалcontext.go('/kyc'), из-за чего пользователь сpending_operator_reviewвидел экран "Start Verification".
Навигация внутри экранов (не GoRouter redirect)¶
Ряд экранов сами управляют навигацией после завершения действия. Это не покрывается логикой redirect — GoRouter проверяет маршрут только при переходе.
| Экран | Действие | Переход |
|---|---|---|
SetupPinScreen |
PIN подтверждён | context.go('/setup-biometric') |
SetupBiometricScreen |
Enable / Skip / Unavailable | context.go(_postSetupRoute) → /kyc если needsKyc, иначе /home |
HomeScreen — _KycBanner |
Тап | context.go('/kyc') |
HomeScreen — _KycReviewBanner |
Тап | context.go('/kyc/pending') |
KycIntroScreen |
"Start Verification" | context.go('/kyc/upload') |
Известные проблемы¶
| # | Статус | Проблема | Блок | Симптом |
|---|---|---|---|---|
| 1 | ✅ fixed | Block5 не исключал /pin-unlock |
Block 5 | /pin-unlock↔/kyc redirect loop → "Route not found" |
| 2 | ✅ fixed | Block5 не исключал /setup-pin, /setup-biometric |
Block 5 | Пользователь не попадает на PIN setup при needsKyc=true |
| 3 | ✅ fixed | Block4/2b авто-редиректили isPendingReview → /kyc/pending при холодном запуске |
Block 4, 2b | "Verification Status" показывался при каждом открытии для registration_in_progress пользователей |
| 4 | — | debugLogDiagnostics: true в production |
— | Лишние логи → теперь kDebugMode |
| 5 | ✅ fixed | SetupBiometricScreen жёстко вёл на /kyc после PIN setup |
Screen-level nav | Пользователь с pending_operator_review после перелогона видел "Start Verification" вместо /home |
