WellNuo/CLAUDE.md
Sergei 8af7a11cd9 Fix WiFi credentials cache implementation in SecureStore
- Fix saveWiFiPassword to use encrypted passwords map instead of decrypted
- Fix getWiFiPassword to decrypt from encrypted storage
- Fix test expectations for migration and encryption functions
- Remove unused error variables to fix linting warnings
- All 27 tests now passing with proper encryption/decryption flow

The WiFi credentials cache feature was already implemented but had bugs
where encrypted and decrypted password maps were being mixed. This commit
ensures proper encryption is maintained throughout the storage lifecycle.
2026-01-31 15:55:24 -08:00

12 KiB
Raw Permalink Blame History

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

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)

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

# 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.)
  • Делать изменения "вслепую" без понимания текущей логики