Authentication & In-App Purchases
Authentication Flow
Auto-Login
On app start, UserProvider.initialize() triggers auto-login:
- Check for a cached Supabase session locally
- If found, restore session and navigate to HomeScreen
- If no network, enter offline mode with cached session
- If no session at all, show LoginScreen
Supported Auth Methods
| Method | Details |
|---|---|
| Email/password | Standard Supabase auth |
| Google Sign-In | OAuth via Supabase, detected via provider == 'google' in auth state |
| Magic links | Used for device removal confirmation |
| Password reset | Via deep links (lucidflow:// on mobile, web URL on browser) |
Offline Mode
- App checks for network on startup
- If offline but a local session exists, the user goes straight to HomeScreen
- Controlled by
AppConfig.enableOfflineModeflag - Sessions are cached using Supabase’s built-in local storage
Deep Links
- Mobile:
lucidflow://appscheme - Web:
Uri.base.origin(browser origin URL) - Password reset links are browser-specific (Supabase limitation)
In-App Purchases
Product ID Format
| Platform | Format | Example |
|---|---|---|
| Android | Lowercase course code | h01enb |
| iOS | Bundle prefix + lowercase code | me.hypnoelp.app.h01enb |
Course codes come from shop.json (e.g., H01ENB).
Purchase Flow
- User selects course and voice (M/F) in the shop
- Platform-specific product ID is generated from the course code
InAppPurchaseService.purchaseCourse()initiates native purchase- Purchase token/receipt sent to
/functions/v1/validate_purchase - Backend validates with Apple (verifyReceipt API) or Google Play
- On success, course added to user account
- Sync triggered to download the purchased course content
iOS-Specific Details
- Receipt retrieved via method channel (
app_receipt) fromBundle.main.appStoreReceiptURL - Binary receipt, base64-encoded for validation
- Backend uses production + sandbox fallback for Apple validation
- Non-consumable products may show as
PurchaseStatus.restoredafter first purchase — this is expected
Sandbox Mode
AppConfig.useSandboxIAP is automatically true in debug builds, false in release. In sandbox mode the backend skips store API validation.
Backend Endpoints
| Endpoint | Purpose |
|---|---|
/functions/v1/validate_purchase |
Course & subscription IAP validation |
/functions/v1/validate_purchase_ai_credits |
AI credit IAP validation |
/functions/v1/actions |
Course switch operations |