# WellNuo - Project Architecture ## API-First Architecture **IMPORTANT: This project uses an API-first approach. NO local storage for business data!** ### Key Principles 1. **All beneficiary data comes from the remote API only** - No AsyncStorage for beneficiaries - No local caching of beneficiary lists - Every CRUD operation goes through the WellNuo API 2. **Single Source of Truth: WellNuo Backend** - All beneficiary data is stored in PostgreSQL (hosted on eluxnetworks.net) - Changes are immediately persisted to the server - App always fetches fresh data on screen focus ### API Endpoints #### WellNuo API (Primary) Base URL: `https://wellnuo.smartlaunchhub.com/api` | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/me/beneficiaries` | List all beneficiaries for current user | | GET | `/me/beneficiaries/:id` | Get single beneficiary details | | POST | `/me/beneficiaries` | Create new beneficiary | | PATCH | `/me/beneficiaries/:id` | Update beneficiary | | DELETE | `/me/beneficiaries/:id` | Remove beneficiary access | | POST | `/me/beneficiaries/:id/activate` | Activate device for beneficiary | | GET | `/auth/me` | Get current user profile with beneficiaries | | PATCH | `/auth/profile` | Update user profile (firstName, lastName, phone) | Authentication: Bearer token (JWT from `/auth/verify-otp`) #### Legacy API (WebView Dashboard) Base URL: `https://eluxnetworks.net/function/well-api/api` Used only for: - Developer Mode / WebView dashboard - Real sensor data visualization (from NDK devices) ### Data Flow ``` ┌─────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ React App │ ──▶ │ WellNuo Backend │ ──▶ │ PostgreSQL │ │ (Expo) │ ◀── │ (Express.js) │ ◀── │ (eluxnetworks.net)│ └─────────────┘ └──────────────────┘ └──────────────────┘ ``` ### Database Schema - `users` - User accounts (email, password hash) - `person_details` - Beneficiary profiles (firstName, lastName, avatar, etc.) - `user_access` - Links accessor_id → beneficiary_id with role (owner/viewer) - `subscriptions` - Subscription status for beneficiaries - `devices` - IoT devices linked to beneficiaries ### What NOT to do - ❌ Don't use `localBeneficiaries` from BeneficiaryContext for actual data - ❌ Don't save beneficiary data to AsyncStorage - ❌ Don't cache API responses locally for offline use - ❌ Don't assume data is available without API call - ❌ Don't save user profile data (name, phone) to SecureStore - ❌ Don't use `userName` from SecureStore - it's legacy! ### What TO do - ✅ Always fetch fresh data via `api.getAllBeneficiaries()` or `api.getWellNuoBeneficiary(id)` - ✅ Get user profile via `api.getMe()`, update via `api.updateProfile()` (calls `/auth/profile`) - ✅ Use `useFocusEffect` to reload data when screen gains focus - ✅ Handle loading and error states for all API calls - ✅ Show appropriate feedback on successful operations - ✅ Only store in SecureStore: `accessToken`, `userId`, `userEmail` (technical auth data) ## Navigation Controller (Centralized Routing) All navigation decisions are centralized in `services/NavigationController.ts`. **IMPORTANT: NavigationController is NOT automatic middleware!** - It does NOT intercept or control all navigation automatically - It's a utility that must be EXPLICITLY called at specific points in the app - You must manually call `nav.navigateAfterLogin()`, `nav.navigateAfterAddBeneficiary()`, etc. - Regular navigation (e.g., `router.push('/profile')`) works independently ### When to use NavigationController: - ✅ After OTP verification (login flow) - ✅ After creating a new beneficiary - ✅ After completing purchase/demo selection - ✅ When you need to determine the "correct next screen" based on user state ### When NOT needed: - ❌ Simple screen-to-screen navigation (just use `router.push()`) - ❌ Tab navigation (handled by Expo Router) - ❌ Back navigation (handled automatically) ### Key Files - `services/NavigationController.ts` - All routing logic and conditions - `hooks/useNavigationFlow.ts` - React hook for easy usage in components ### Navigation Flow After Login ``` User enters OTP code ↓ Has firstName in profile? │ NO → /(auth)/enter-name │ YES → Has beneficiaries? │ NO → /(auth)/add-loved-one │ YES → Check equipment status of first beneficiary ├── none → /(auth)/purchase ├── ordered/shipped → /(tabs)/beneficiaries/:id/equipment ├── delivered → /(auth)/activate └── active/demo → /(tabs)/dashboard ``` ### Navigation After Adding Beneficiary ``` Beneficiary created in DB ↓ User already has WellNuo devices? │ NO → /(auth)/purchase (buy equipment) │ YES → /(auth)/activate (connect existing device) ``` ### Navigation After Purchase ``` Payment completed / Demo selected ↓ Demo mode? │ YES → /(auth)/activate (immediate activation) │ NO → /(tabs)/beneficiaries/:id/equipment (track delivery) ``` ### Usage Example ```typescript import { useNavigationFlow } from '@/hooks/useNavigationFlow'; function MyScreen() { const nav = useNavigationFlow(); // After login - automatically determines correct screen nav.navigateAfterLogin(profile, beneficiaries); // After adding beneficiary nav.navigateAfterAddBeneficiary(42, hasExistingDevices); // After purchase nav.navigateAfterPurchase(42, { demo: true }); // Quick shortcuts nav.goToDashboard(); nav.goToPurchase(beneficiaryId); nav.goToActivate(beneficiaryId); } ``` ### Available Routes (ROUTES constant) ```typescript ROUTES.AUTH.LOGIN // /(auth)/login ROUTES.AUTH.VERIFY_OTP // /(auth)/verify-otp ROUTES.AUTH.ENTER_NAME // /(auth)/enter-name ROUTES.AUTH.ADD_LOVED_ONE // /(auth)/add-loved-one ROUTES.AUTH.PURCHASE // /(auth)/purchase ROUTES.AUTH.ACTIVATE // /(auth)/activate ROUTES.TABS.DASHBOARD // /(tabs)/dashboard ROUTES.TABS.BENEFICIARIES // /(tabs)/beneficiaries ROUTES.TABS.CHAT // /(tabs)/chat ROUTES.TABS.VOICE // /(tabs)/voice ROUTES.TABS.PROFILE // /(tabs)/profile ROUTES.BENEFICIARY.DETAIL(id) // /(tabs)/beneficiaries/:id ROUTES.BENEFICIARY.SUBSCRIPTION(id) // /(tabs)/beneficiaries/:id/subscription ROUTES.BENEFICIARY.EQUIPMENT(id) // /(tabs)/beneficiaries/:id/equipment ROUTES.BENEFICIARY.SHARE(id) // /(tabs)/beneficiaries/:id/share ``` ## Development ### Server Location - Production: `root@91.98.205.156:/var/www/wellnuo-api/` - PM2 process: `wellnuo-api` ### Key Files - `services/api.ts` - All API methods - `services/NavigationController.ts` - Centralized routing logic - `hooks/useNavigationFlow.ts` - Navigation hook for components - `contexts/BeneficiaryContext.tsx` - Beneficiary state management (current selection only) - `app/(tabs)/beneficiaries/` - Beneficiary screens ### Running Locally ```bash # Start Expo on port 8081 with iPhone 16 Pro Max IOS_SIMULATOR_UDID=6BB240A2-0F2F-41E4-B568-9FFAF9B7FBA2 npx expo start --port 8081 --ios ``` ## Specs (Спецификации задач) **Структурированные спецификации для планирования и отслеживания задач.** ### Структура ``` specs/ ├── wellnuo/ # Основное приложение ├── wellnuo-lite/ # Lite версия ├── shared/ # Общие задачи (backend, API) └── templates/ # Шаблоны ``` ### Типы спек - `FEATURE-XXX` — новая функциональность - `BUG-XXX` — исправление бага - `TASK-XXX` — техническая задача ### Как работать со спеками **Создать спеку:** ``` Создай спеку для фичи "название" в specs/wellnuo/ ``` **Начать работу:** ``` Прочитай specs/wellnuo/FEATURE-001-voice-integration.md и начни реализацию ``` **Продолжить:** ``` Продолжи по спеке FEATURE-001 с шага 3 ``` **Обновить статус:** ``` Отметь шаги 1-3 как выполненные в FEATURE-001 ``` ### Важно - Спека = план работы. Claude следует шагам из Implementation Steps - Статусы: 🔴 Not Started | 🟡 In Progress | 🟢 Done - Подробности в `specs/README.md` --- ## Правила разработки (Development Approach) **Методология и подход к качеству кода и тестированию.** ### ГЛАВНОЕ ПРАВИЛО: НЕ ДОБАВЛЯЙ НИЧЕГО БЕЗ СОГЛАСОВАНИЯ **ЗАПРЕЩЕНО без явного согласования с юзером:** - ❌ Добавлять новые UI элементы (бейджи, кнопки, тексты) - ❌ Менять поведение которое юзер не просил менять - ❌ "Улучшать" что-то по своей инициативе - ❌ Интерпретировать данные API и решать как их показывать **Если видишь что-то непонятное (например `equipmentStatus: "demo"`):** 1. СПРОСИ юзера: "Что это значит? Как это должно отображаться?" 2. НЕ ПРИДУМЫВАЙ сам UI решения 3. НЕ ДОБАВЛЯЙ бейджи/тексты которые юзер не просил **Твоя задача — делать ТОЛЬКО то что просят, не больше.** --- ### Правило: ЧИТАЙ КОД ПЕРЕД ИЗМЕНЕНИЯМИ 1. **Всегда читай существующий код компонента перед изменением** - Понять текущую логику, state machine, conditional rendering - Не добавлять логику которая уже есть - Не ломать существующее поведение 2. **Проследи весь user flow, не только один экран** - Если фиксишь список — проверь как это влияет на detail page - Если фиксишь backend — проверь как UI отображает новые данные - Backend fix без проверки UI — это НЕ завершённый fix ### Правило edge cases: ПРОВЕРЯЙ ВСЕ СОСТОЯНИЯ Перед тем как сказать "готово", проверь UI для ВСЕХ возможных состояний: - Happy path (всё работает) - Пустое состояние (нет данных) - Ошибка (API недоступен) - Специальные режимы (demo mode, trial, expired и т.д.) ### Не проси юзера тестить пока сам не проверил 1. Сначала проверь API ответ (curl) 2. Потом проверь что UI правильно отображает этот ответ 3. Потом сделай скриншот и убедись 4. Только потом говори юзеру "готово, проверь" ### Частые ошибки которых НЕЛЬЗЯ допускать - ❌ Фиксить backend и НЕ проверять frontend - ❌ Проверить только один сценарий и сказать "готово" - ❌ Не читать существующий код и добавлять дублирующую логику - ❌ Игнорировать edge cases (demo mode, expired subscription, etc.) - ❌ Делать изменения "вслепую" без понимания текущей логики --- ## Julia AI Voice Agent (LiveKit) ### Расположение скрипта **Python Agent для голосового ассистента Julia находится здесь:** ``` /Users/sergei/Desktop/WellNuo/WellNuoLite/julia-agent/julia-ai/src/agent.py ``` ### Архитектура Voice Assistant ``` ┌─────────────┐ ┌────────────────────────┐ ┌─────────────────┐ ┌──────────────────┐ │ Mobile App │ ──▶ │ Julia Token Server │ ──▶ │ LiveKit Cloud │ ──▶ │ Python Agent │ │ (Expo) │ │ wellnuo.smartlaunchhub │ │ (Agents Cloud) │ │ (agent.py) │ └─────────────┘ └────────────────────────┘ └─────────────────┘ └──────────────────┘ │ │ │ │ │ metadata: {deploymentId, beneficiaryNamesDict} │ │ └──────────────────────────────────────────────────────┘ │ │ │ ▼ │ ┌──────────────────┐ │ │ WellNuo API │ └─────────────────────────────────────────────────────────────────│ eluxnetworks.net│ text chat goes directly here └──────────────────┘ ``` ### SINGLE_DEPLOYMENT_MODE Флаг `SINGLE_DEPLOYMENT_MODE` контролирует отправку `beneficiary_names_dict`: | Режим | `SINGLE_DEPLOYMENT_MODE` | Что отправляется | |-------|--------------------------|------------------| | Lite | `true` | только `deployment_id` | | Full | `false` | `deployment_id` + `beneficiary_names_dict` | Файлы с флагом: - `WellNuoLite/app/(tabs)/chat.tsx` — текстовый чат - `WellNuoLite/services/livekitService.ts` — голосовой ассистент ### Ключевые файлы | Файл | Назначение | |------|------------| | `julia-agent/julia-ai/src/agent.py` | Python агент для LiveKit Cloud | | `services/livekitService.ts` | Клиент для получения токена | | `components/VoiceCall.tsx` | UI голосового звонка | ### Серверы | Сервис | URL | Расположение | |--------|-----|--------------| | Julia Token Server | `https://wellnuo.smartlaunchhub.com/julia` | `root@91.98.205.156:/var/www/julia-token-server/` | | WellNuo API | `https://eluxnetworks.net/function/well-api/api` | Внешний сервис | | Debug Console | `https://wellnuo.smartlaunchhub.com/debug/` | `root@91.98.205.156:/var/www/wellnuo-debug/` | ### Деплой Python агента на LiveKit Cloud **Путь к агенту (локально):** ``` /Users/sergei/Desktop/WellNuo/WellNuoLite/julia-agent/julia-ai/ ``` **Структура директории:** ``` julia-ai/ ├── src/ │ └── agent.py # Основной Python агент ├── livekit.toml # Конфигурация LiveKit Cloud ├── Dockerfile # Для сборки на LiveKit Cloud ├── pyproject.toml # Python зависимости └── AGENTS.md # Документация LiveKit ``` **Текущий Agent ID:** `CA_Yd3qcuYEVKKE` **LiveKit Project:** `live-kit-demo-70txlh6a` **Region:** `eu-central` #### Редактирование агента ```bash # Открыть код агента code /Users/sergei/Desktop/WellNuo/WellNuoLite/julia-agent/julia-ai/src/agent.py ``` Основные места в agent.py: - **Инструкции Julia** — строка ~50-100 (system prompt) - **Обработка metadata** — функция `_build_request_data()` - **Вызов API** — метод `send_to_wellnuo_api()` - **agent_name** — строка 435: `agent_name="julia-ai"` #### Деплой изменений ```bash cd /Users/sergei/Desktop/WellNuo/WellNuoLite/julia-agent/julia-ai # 1. Проверить что работает локально (опционально) uv run python src/agent.py console # 2. Задеплоить на LiveKit Cloud lk agent deploy # Это: # - Соберёт Docker образ # - Запушит в LiveKit Cloud registry # - Развернёт новую версию агента ``` #### Полезные команды ```bash # Список агентов в проекте lk agent list # Логи агента (в реальном времени) lk agent logs # Логи определённого агента lk agent logs --id CA_Yd3qcuYEVKKE # Статус агента lk agent list --verbose ``` #### Связка Agent ↔ Token Server Token Server использует имя `julia-ai` для диспетчеризации агента: ```javascript // /var/www/julia-token-server/server.js const AGENT_NAME = 'julia-ai'; // Должно совпадать с agent_name в agent.py ``` При создании нового агента: 1. Измени `agent_name` в `agent.py` 2. Обнови `AGENT_NAME` в Token Server 3. Перезапусти Token Server: `pm2 restart julia-token-server`