fix(mobile): critical security and error handling improvements

🔐 SECURITY FIXES:
- Fixed CRITICAL seed storage vulnerability
  * Changed from AsyncStorage to SecureStore for wallet seeds
  * Seeds now encrypted in hardware-backed secure storage
  * Affects: PolkadotContext.tsx (lines 166, 189)

🛡️ ERROR HANDLING:
- Added global ErrorBoundary component
  * Catches unhandled React errors
  * Shows user-friendly error UI
  * Integrated into App.tsx provider hierarchy
  * Files: ErrorBoundary.tsx (new), App.tsx, components/index.ts

🧹 PRODUCTION READINESS:
- Protected all 47 console statements with __DEV__ checks
  * console.log: 12 statements
  * console.error: 32 statements
  * console.warn: 1 statement
  * Files affected: 16 files across contexts, screens, i18n
  * Production builds will strip these out

📦 PROVIDER HIERARCHY:
- Added BiometricAuthProvider to App.tsx
- Updated provider order:
  ErrorBoundary → Polkadot → Language → BiometricAuth → Navigator

Files modified: 18
New files: 1 (ErrorBoundary.tsx)

This commit resolves 3 P0 critical issues from production readiness audit.
This commit is contained in:
Claude
2025-11-21 22:18:11 +00:00
parent 15d6dc62c9
commit 6a86915549
18 changed files with 340 additions and 78 deletions
+10 -10
View File
@@ -85,7 +85,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
}
}
} catch (error) {
console.error('Biometric init error:', error);
if (__DEV__) console.error('Biometric init error:', error);
}
};
@@ -108,7 +108,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
// Check if app should be locked
await checkAutoLock();
} catch (error) {
console.error('Error loading settings:', error);
if (__DEV__) console.error('Error loading settings:', error);
}
};
@@ -136,7 +136,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
return false;
} catch (error) {
console.error('Authentication error:', error);
if (__DEV__) console.error('Authentication error:', error);
return false;
}
};
@@ -159,7 +159,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
return false;
} catch (error) {
console.error('Enable biometric error:', error);
if (__DEV__) console.error('Enable biometric error:', error);
return false;
}
};
@@ -173,7 +173,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
await AsyncStorage.setItem(BIOMETRIC_ENABLED_KEY, 'false');
setIsBiometricEnabled(false);
} catch (error) {
console.error('Disable biometric error:', error);
if (__DEV__) console.error('Disable biometric error:', error);
}
};
@@ -191,7 +191,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
// Store in SecureStore (encrypted on device)
await SecureStore.setItemAsync(PIN_CODE_KEY, hashedPin);
} catch (error) {
console.error('Set PIN error:', error);
if (__DEV__) console.error('Set PIN error:', error);
throw error;
}
};
@@ -220,7 +220,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
return false;
} catch (error) {
console.error('Verify PIN error:', error);
if (__DEV__) console.error('Verify PIN error:', error);
return false;
}
};
@@ -250,7 +250,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
await AsyncStorage.setItem(AUTO_LOCK_TIMER_KEY, minutes.toString());
setAutoLockTimerState(minutes);
} catch (error) {
console.error('Set auto-lock timer error:', error);
if (__DEV__) console.error('Set auto-lock timer error:', error);
}
};
@@ -273,7 +273,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
try {
await AsyncStorage.setItem(LAST_UNLOCK_TIME_KEY, Date.now().toString());
} catch (error) {
console.error('Save unlock time error:', error);
if (__DEV__) console.error('Save unlock time error:', error);
}
};
@@ -303,7 +303,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
setIsLocked(false);
}
} catch (error) {
console.error('Check auto-lock error:', error);
if (__DEV__) console.error('Check auto-lock error:', error);
// On error, lock for safety
setIsLocked(true);
}