Files
sfera-new/2025-09-18/SMS_REGISTRATION_DEBUG_PLAN.md
Veronika Smirnova 24a6ff74b5 feat: migrate from useAuth to AuthContext for centralized auth state
• Полная миграция 64 компонентов с useAuth на AuthContext
• Исправлена race condition в SMS регистрации
• Улучшена SSR совместимость с таймаутами
• Удалена дублирующая система регистрации
• Обновлена документация архитектуры аутентификации

Технические изменения:
- AuthContext.tsx: централизованная система состояния
- auth-flow.tsx: убрана агрессивная логика logout
- confirmation-step.tsx: исправлена передача телефона
- page.tsx: добавлена синхронизация состояния
- 64 файла: миграция useAuth → useAuthContext

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-19 17:21:52 +03:00

250 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🔍 ПЛАН ИСПРАВЛЕНИЯ SMS РЕГИСТРАЦИИ - ДЕТАЛЬНЫЙ АНАЛИЗ ПРОБЛЕМЫ
> **Дата:** 2025-09-18
> **Проблема:** После SMS верификации пользователь перебрасывается на `/` вместо продолжения регистрации
---
## 🚨 ОПИСАНИЕ ПРОБЛЕМЫ
### 📱 Что должно происходить (правильная логика SFERA):
**ЕДИНЫЙ FLOW авторизации/регистрации:**
1. Пользователь вводит номер телефона → SMS отправляется
2. Пользователь вводит SMS код → код верифицируется
3. **Определяется сценарий:**
- **СЦЕНАРИЙ A:** Пользователь существует + есть организация → **Dashboard**
- **СЦЕНАРИЙ B:** Пользователь существует + НЕТ организации → **Cabinet-select** (выбор типа кабинета)
- **СЦЕНАРИЙ C:** Новый пользователь → **Cabinet-select** (выбор типа кабинета)
### ❌ Что происходит сейчас (баг):
```
1. Пользователь вводит телефон → ✅ SMS отправляется
2. Пользователь вводит SMS код → ✅ код верифицируется успешно
3. ❌ Пользователь перебрасывается на главную страницу `/`
4. ❌ AuthFlow сбрасывается на step: "phone"
5. ❌ Пользователь вынужден начинать регистрацию заново
```
### 🔍 Логи ошибки:
```javascript
// SMS verification прошла успешно:
🌐 GraphQL REQUEST: { operationName: 'VerifySmsCode', variables: { phone: '76657584949', code: '1234' } }
POST /api/graphql 200 in 1295ms
// Но после этого:
AppShell state: { pathname: '/', isAuthenticated: false, hasUser: false }
🎢 AuthFlow - useEffect triggered with: { isAuthenticated: false, hasUser: false, currentStep: "phone" }
🎢 AuthFlow - User not authenticated, setting step to phone
```
**КЛЮЧЕВАЯ ПРОБЛЕМА:** `isAuthenticated: false` после успешной SMS верификации!
---
## 🔍 КОРНЕВАЯ ПРИЧИНА
### 🎯 Диагноз:
**AuthContext не обновляется после SMS верификации**, поэтому:
1. SMS верификация успешна → токен сохраняется в localStorage
2. НО AuthContext остается `isAuthenticated: false, user: null`
3. app/page.tsx видит неавторизованного пользователя → redirect на `/login`
4. AuthFlow инициализируется заново → step: "phone"
### 🔧 Предполагаемые причины:
**1. Timing issue в AuthContext:**
- SMS-step сохраняет токен через `verifySmsCode()`
- AuthContext не успевает обновить состояние
- useEffect в AuthFlow срабатывает с устаревшими данными
**2. Конфликт между экземплярами AuthFlow:**
- AuthGuard на `/dashboard` может создавать второй AuthFlow
- Два AuthFlow конфликтуют между собой
**3. Проблема в app/page.tsx:**
- Слишком быстро перенаправляет до обновления AuthContext
- Не учитывает `isLoading` состояние
---
## 📋 ПЛАН ИСПРАВЛЕНИЯ
### **PHASE 1: ДИАГНОСТИКА И ЛОГИРОВАНИЕ**
#### 1.1 Добавить детальное логирование в AuthContext
```typescript
// В verifySmsCode после успешной верификации:
console.warn('🔑 AuthContext - BEFORE setState:', {
isAuthenticated: this.isAuthenticated,
hasUser: !!this.user
})
setUser(result.user)
setIsAuthenticated(true)
console.warn('🔑 AuthContext - AFTER setState:', {
isAuthenticated: true,
hasUser: !!result.user,
userOrganization: result.user.organization
})
```
#### 1.2 Добавить логирование в AuthFlow useEffect
```typescript
useEffect(() => {
console.warn('🎢 AuthFlow - useEffect DETAILED:', {
isAuthenticated,
hasUser: !!user,
hasOrganization: !!user?.organization,
userFromContext: user,
currentStep: step,
timestamp: new Date().toISOString()
})
// Существующая логика...
}, [isAuthenticated, user])
```
#### 1.3 Добавить логирование в app/page.tsx
```typescript
useEffect(() => {
console.warn('📍 app/page.tsx - routing decision:', {
isLoading,
hasUser: !!user,
hasOrganization: !!user?.organization,
currentPath: window.location.pathname
})
// Существующая логика...
}, [router, user, isLoading])
```
### **PHASE 2: ИСПРАВЛЕНИЕ TIMING ISSUES**
#### 2.1 Исправить AuthContext - добавить промисы
```typescript
const verifySmsCode = async (phone: string, code: string) => {
// ... существующий код ...
if (result.success && result.token && result.user) {
setAuthToken(result.token)
setUserData(result.user)
// Синхронно обновляем состояние
setUser(result.user)
setIsAuthenticated(true)
// ЖДЕМ обновления Apollo Client
await refreshApolloClient()
// Возвращаем промис когда все готово
return new Promise(resolve => {
setTimeout(() => {
resolve({ success: true, message: result.message, user: result.user })
}, 100) // Небольшая задержка для обновления состояния
})
}
}
```
#### 2.2 Добавить isLoading в app/page.tsx
```typescript
const { user, isLoading, isAuthenticated } = useAuthContext()
useEffect(() => {
// КРИТИЧНО: ждем завершения всех проверок
if (isLoading) {
console.warn('📍 app/page.tsx - still loading, waiting...')
return
}
// Только после isLoading: false делаем redirect
if (user?.organization) {
router.replace('/dashboard')
} else if (isAuthenticated) {
router.replace('/login') // Продолжить на странице регистрации
} else {
router.replace('/login')
}
}, [router, user, isLoading, isAuthenticated])
```
### **PHASE 3: УСТРАНЕНИЕ КОНФЛИКТОВ**
#### 3.1 Исправить AuthGuard
```typescript
// НЕ создавать новый AuthFlow на dashboard
if (!isAuthenticated || (isAuthenticated && user && !user.organization)) {
// Перенаправить вместо показа AuthFlow
const router = useRouter()
useEffect(() => {
router.replace('/login')
}, [])
return <div>Перенаправление...</div>
}
```
#### 3.2 Убрать window.location.href из AuthFlow
```typescript
// ЗАМЕНИТЬ:
window.location.href = '/dashboard'
// НА:
router.push('/dashboard')
```
### **PHASE 4: ТЕСТИРОВАНИЕ**
#### 4.1 Тест-сценарии:
1. **Новый пользователь:** phone → sms → cabinet-select → inn/api → complete → dashboard
2. **Существующий без организации:** phone → sms → cabinet-select → inn/api → complete → dashboard
3. **Существующий с организацией:** phone → sms → dashboard
4. **Партнерские коды:** все сценарии с параметрами
#### 4.2 Проверки:
- ✅ Нет перебросов на `/`
- ✅ AuthFlow не сбрасывается на phone
- ✅ Состояние AuthContext корректное
- ✅ Нет создания второго AuthFlow
---
## 🎯 ОЖИДАЕМЫЙ РЕЗУЛЬТАТ
### ✅ После исправления:
```
1. Пользователь вводит телефон → SMS отправляется
2. Пользователь вводит SMS код → код верифицируется
3. AuthContext обновляется → isAuthenticated: true, user: {...}
4. AuthFlow определяет сценарий:
- СЦЕНАРИЙ A: user.organization есть → step: 'complete' → dashboard
- СЦЕНАРИЙ B/C: user.organization нет → step: 'cabinet-select'
5. Пользователь продолжает регистрацию БЕЗ сброса
```
### 📊 Логи после исправления:
```javascript
🔑 AuthContext - SMS verification successful
🔑 AuthContext - State updated: isAuthenticated=true, user=...
🎢 AuthFlow - useEffect: { isAuthenticated: true, hasUser: true, hasOrganization: false }
🎢 AuthFlow - Setting step to cabinet-select
Пользователь видит страницу выбора типа кабинета
```
---
## 🚀 ГОТОВНОСТЬ К РЕАЛИЗАЦИИ
**✅ Проблема диагностирована:** Timing issue в AuthContext + конфликт AuthFlow экземпляров
**✅ План пошаговый:** 4 фазы с детальным логированием и тестированием
**✅ Минимальные изменения:** Фокус на исправлении, а не переписывании архитектуры
**🎯 Следующий шаг:** Начать PHASE 1 - добавить детальное логирование для подтверждения диагноза