Skip to content

Conversation

@seshanthS
Copy link
Collaborator

@seshanthS seshanthS commented Jan 14, 2026

Description

Disables strongbox by default. Can be enabled optionally in DevSettingScreen

Tested

  • Tested StrongBox value is used correctly through adb logs
  • Tested by generating and disclosing a mock passport with strongbox enabled
  • Tested by generating and disclosing a mock passport with strongbox disabled

How to QA

  • Generate a mock passport
  • Disable strongbox from DevSettings screen
  • Disclose normally
  • Generate another mock passport
  • Check adb logs, it should log Generating regular security key for alias {...}
    adb logcat --pid=$(adb shell pidof -s com.proofofpassportapp)
  • Disclose both mock passports

Summary by CodeRabbit

  • New Features

    • Android StrongBox toggle added to developer settings (Android-only) with confirmation; preference is persisted and defaults to disabled.
  • Bug Fixes

    • Broadened detection of keychain crypto failures and user/biometric cancellations for more accurate error handling.
  • Chores

    • Android backups disabled for improved security.
    • Keychain options updated to honor the StrongBox preference.
    • App version bumped to 2.9.12 across Android and iOS.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 14, 2026

📝 Walkthrough

Walkthrough

Added an Android "Use StrongBox" persisted setting with Dev UI toggle, wired it into keychain options via a new ExtendedSetOptions.useStrongBox flag, disabled Android auto-backup in the manifest, expanded keychain error matching, and bumped app version metadata for Android/iOS/package.

Changes

Cohort / File(s) Summary
Android Manifest
app/android/app/src/main/AndroidManifest.xml
Added android:allowBackup="false" and included android:allowBackup in tools:replace.
Versioning & Release Metadata
app/android/app/build.gradle, app/ios/OpenPassport/Info.plist, app/ios/Self.xcodeproj/...project.pbxproj, app/package.json, app/version.json
Bumped Android versionCode/build and versionName, iOS MARKETING_VERSION/CFBundleShortVersionString, package.json version, and updated app/version.json android.build and timestamp.
Keychain types
app/src/types/react-native-keychain.d.ts
Added exported ExtendedSetOptions = SetOptions & { useStrongBox?: boolean }.
Settings store
app/src/stores/settingStore.ts
Added persisted useStrongBox: boolean (initialized to false) and setter setUseStrongBox(useStrongBox: boolean).
Keychain integration
app/src/integrations/keychain/index.ts
Introduced GetSecureOptions.useStrongBox, switched setOptions to ExtendedSetOptions, import useSettingStore, and pass useStrongBox into Keychain calls (casts to ExtendedSetOptions).
Developer UI (Android only)
app/src/screens/dev/DevSettingsScreen.tsx
New "Android Keystore" section with a "Use StrongBox" toggle; shows confirmation Alert and updates persisted setting on confirm.
Keychain error handling
app/src/utils/keychainErrors.ts
Expanded crypto-error detection ("Could not encrypt data", "Keystore operation failed") and broadened user-cancellation matches (additional messages and codes).

Sequence Diagram

sequenceDiagram
    actor User as User
    participant Dev as DevSettingsScreen
    participant Store as SettingStore
    participant Integration as KeychainIntegration
    participant Native as NativeKeychain
    participant StrongBox as AndroidStrongBox

    User->>Dev: Toggle "Use StrongBox"
    Dev->>User: Show confirmation Alert
    User-->>Dev: Confirm
    Dev->>Store: setUseStrongBox(boolean)
    Store->>Store: Persist flag

    Note over Integration,Store: On subsequent secure operations
    Integration->>Store: read useStrongBox
    Store-->>Integration: return boolean
    Integration->>Native: setGenericPassword(ExtendedSetOptions)
    Native->>StrongBox: create/keygen (useStrongBox flag)
    StrongBox-->>Native: key result
    Native-->>Integration: operation result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • transphorm
  • remicolin

Poem

🔐 Toggle the box, strong and small,

A guarded key behind the wall,
Manifest locked, versions climb high,
Settings saved with a mindful sigh,
Secure nights beneath the app sky.

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'SELF-1497: add keychain patch' is vague and generic. While it references a ticket number and mentions 'keychain patch', it does not clearly convey the main purpose of the changes: adding an option to disable StrongBox for Android keystore security. Revise title to be more descriptive, such as: 'Add option to disable StrongBox in Android keystore settings' or 'SELF-1497: Allow disabling StrongBox for Android keychain operations'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description covers all required sections: a clear description of the feature, comprehensive testing explanation, and specific QA steps with adb commands.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@seshanthS seshanthS marked this pull request as ready for review January 15, 2026 10:45
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@app/src/integrations/keychain/index.ts`:
- Around line 94-101: createKeychainOptions reads
useSettingStore.getState().useStrongBox synchronously which can return a default
value before AsyncStorage rehydration; guard this by checking store hydration
before falling back to getState (e.g., use useSettingStore.persist.hasHydrated()
and only read getState() if hydrated, or subscribe to onRehydrateStorage to
defer resolving useStrongBox), and update the logic around useStrongBox (the
options.useStrongBox ?? ...) so it prefers the explicit option, then the
persisted value only when persist.hasHydrated() is true, otherwise use a safe
fallback until rehydration completes.
🧹 Nitpick comments (1)
app/src/screens/dev/DevSettingsScreen.tsx (1)

759-785: LGTM! Platform-specific rendering correctly implemented.

The Platform.OS === 'android' guard ensures this section only renders on Android devices. The confirmation alert with clear messaging about the impact on new vs. existing keys is a nice UX touch.

One minor observation: TopicToggleButton is semantically named for notification topics. Consider extracting a more generically-named ToggleButton component if this pattern is reused elsewhere.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d08ca4 and 195e019.

📒 Files selected for processing (6)
  • app/android/app/src/main/AndroidManifest.xml
  • app/src/integrations/keychain/index.ts
  • app/src/screens/dev/DevSettingsScreen.tsx
  • app/src/stores/settingStore.ts
  • app/src/types/react-native-keychain.d.ts
  • patches/react-native-keychain+10.0.0.patch
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{js,jsx,ts,tsx}: NEVER log sensitive data including PII (names, DOB, passport numbers, addresses), credentials, tokens, API keys, private keys, or session identifiers.
ALWAYS redact/mask sensitive fields in logs using consistent patterns (e.g., ***-***-1234 for passport numbers, J*** D*** for names).

Files:

  • app/src/types/react-native-keychain.d.ts
  • app/src/stores/settingStore.ts
  • app/src/screens/dev/DevSettingsScreen.tsx
  • app/src/integrations/keychain/index.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Use React Navigation with createStaticNavigation for type-safe navigation in React Native applications.
Implement platform-specific handling with Platform.OS === 'ios' ? 'iOS' : 'Android' checks before platform-specific code in React Native.
Initialize native modules with initializeNativeModules() before any native operations in React Native.
Implement lazy loading for screens using React.lazy() in React Native applications.
Implement custom modal system with useModal hook and callback registry in React Native.
Integrate haptic feedback using useHapticNavigation hook in React Native navigation.
Use platform-specific initial routes: web uses 'Home', mobile uses 'Splash' in React Navigation.
Use Zustand for global state management in React Native applications.
Use custom hooks for complex state (useModal, useHapticNavigation) instead of inline logic.
Use AsyncStorage for simple data, SQLite for complex data, and Keychain for sensitive data in React Native.
Use @/ alias for src imports and @tests/ alias for test imports in TypeScript/JavaScript files.
Use conditional rendering with Platform.OS for platform-specific code in React Native.
Use Tamagui for UI components in React Native applications.
Do not log sensitive data in production, including identity verification and passport information.
Use Keychain for secure storage of sensitive data in React Native.
Implement proper cleanup of sensitive data after use.
Implement certificate validation for passport data verification.
Always use try-catch for async operations in React Native and TypeScript code.
Implement graceful degradation when native modules fail in React Native.
Provide user-friendly error messages in UI and error handlers.
Lazy load screens and components to optimize bundle size in React Native.
Prevent memory leaks in native modules in React Native.

Files:

  • app/src/types/react-native-keychain.d.ts
  • app/src/stores/settingStore.ts
  • app/src/screens/dev/DevSettingsScreen.tsx
  • app/src/integrations/keychain/index.ts
**/*.{tsx,jsx,ts,js}

📄 CodeRabbit inference engine (.cursorrules)

Implement proper cleanup in useEffect and component unmount hooks in React.

Files:

  • app/src/types/react-native-keychain.d.ts
  • app/src/stores/settingStore.ts
  • app/src/screens/dev/DevSettingsScreen.tsx
  • app/src/integrations/keychain/index.ts
**/{mobile,client,app,time,verification}/**/*.{ts,tsx,js,swift,kt}

📄 CodeRabbit inference engine (.cursor/rules/compliance-verification.mdc)

Use server-signed time tokens or chain block timestamps for trusted time in mobile clients, do not trust device wall-clock alone

Files:

  • app/src/types/react-native-keychain.d.ts
  • app/src/stores/settingStore.ts
  • app/src/screens/dev/DevSettingsScreen.tsx
  • app/src/integrations/keychain/index.ts
**/{mobile,client,app,proof,zk}/**/*.{ts,tsx,js,swift,kt}

📄 CodeRabbit inference engine (.cursor/rules/compliance-verification.mdc)

**/{mobile,client,app,proof,zk}/**/*.{ts,tsx,js,swift,kt}: Include trusted time anchor in proof generation and verify time anchor authenticity before proof generation in mobile implementations
Achieve proof generation in <60 seconds on mid-tier mobile devices

Files:

  • app/src/types/react-native-keychain.d.ts
  • app/src/stores/settingStore.ts
  • app/src/screens/dev/DevSettingsScreen.tsx
  • app/src/integrations/keychain/index.ts
app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (app/AGENTS.md)

Ensure yarn types passes (TypeScript validation) before creating a PR

Files:

  • app/src/types/react-native-keychain.d.ts
  • app/src/stores/settingStore.ts
  • app/src/screens/dev/DevSettingsScreen.tsx
  • app/src/integrations/keychain/index.ts
app/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (app/AGENTS.md)

app/**/*.{ts,tsx,js,jsx}: Ensure web build succeeds with yarn web before creating a PR
Do not include sensitive data in logs - avoid logging PII, credentials, and tokens
Use react-native-dotenv for environment configuration via @env import
Confirm no sensitive data exposed before PR merge

Files:

  • app/src/types/react-native-keychain.d.ts
  • app/src/stores/settingStore.ts
  • app/src/screens/dev/DevSettingsScreen.tsx
  • app/src/integrations/keychain/index.ts
app/src/**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

app/src/**/*.{ts,tsx,js,jsx}: Review React Native TypeScript code for:

  • Component architecture and reusability
  • State management patterns
  • Performance optimizations
  • TypeScript type safety
  • React hooks usage and dependencies
  • Navigation patterns

Files:

  • app/src/types/react-native-keychain.d.ts
  • app/src/stores/settingStore.ts
  • app/src/screens/dev/DevSettingsScreen.tsx
  • app/src/integrations/keychain/index.ts
app/android/**/*

📄 CodeRabbit inference engine (app/AGENTS.md)

Ensure Android build succeeds with yarn android before creating a PR

Files:

  • app/android/app/src/main/AndroidManifest.xml

⚙️ CodeRabbit configuration file

app/android/**/*: Review Android-specific code for:

  • Platform-specific implementations
  • Performance considerations
  • Security best practices for mobile

Files:

  • app/android/app/src/main/AndroidManifest.xml
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursorrules)

Implement comprehensive error boundaries in React components.

Files:

  • app/src/screens/dev/DevSettingsScreen.tsx
🧠 Learnings (16)
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Keychain for secure storage of sensitive data in React Native.

Applied to files:

  • app/src/types/react-native-keychain.d.ts
  • app/src/screens/dev/DevSettingsScreen.tsx
  • app/src/integrations/keychain/index.ts
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Prevent memory leaks in native modules in React Native.

Applied to files:

  • app/src/types/react-native-keychain.d.ts
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Implement platform-specific handling with `Platform.OS === 'ios' ? 'iOS' : 'Android'` checks before platform-specific code in React Native.

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-12-25T19:19:35.354Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: packages/mobile-sdk-alpha/AGENTS.md:0-0
Timestamp: 2025-12-25T19:19:35.354Z
Learning: Applies to packages/mobile-sdk-alpha/**/*.{ts,tsx} : Verify cross-platform compatibility for both React Native and Web environments

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-12-25T19:19:35.354Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: packages/mobile-sdk-alpha/AGENTS.md:0-0
Timestamp: 2025-12-25T19:19:35.354Z
Learning: Applies to packages/mobile-sdk-alpha/**/*.{ts,tsx} : Ensure no breaking changes to public API or document them properly

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Tamagui for UI components in React Native applications.

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Implement custom modal system with `useModal` hook and callback registry in React Native.

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use React Navigation with `createStaticNavigation` for type-safe navigation in React Native applications.

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Integrate haptic feedback using `useHapticNavigation` hook in React Native navigation.

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Zustand for global state management in React Native applications.

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use custom hooks for complex state (`useModal`, `useHapticNavigation`) instead of inline logic.

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use conditional rendering with Platform.OS for platform-specific code in React Native.

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-08-26T14:41:41.821Z
Learnt from: shazarre
Repo: selfxyz/self PR: 936
File: app/src/screens/aesop/PassportOnboardingScreen.tsx:0-0
Timestamp: 2025-08-26T14:41:41.821Z
Learning: When verifying provider hierarchies in React Native apps, always check the main App.tsx file at the app root, not just navigation/index.tsx and layout files, as providers are often configured at the top-level App component.

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-12-25T19:19:04.954Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: app/AGENTS.md:0-0
Timestamp: 2025-12-25T19:19:04.954Z
Learning: Applies to app/**/*.test.{ts,tsx,js,jsx} : Avoid nested `require('react')` or `require('react-native')` calls in test files - use ES6 import statements instead

Applied to files:

  • app/src/screens/dev/DevSettingsScreen.tsx
📚 Learning: 2025-11-25T14:07:28.188Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursor/rules/compliance-verification.mdc:0-0
Timestamp: 2025-11-25T14:07:28.188Z
Learning: Applies to **/{compliance,crypto,key,security,auth}/**/*.{ts,tsx,js,py} : Implement proper key rotation and secure storage for compliance verification keys

Applied to files:

  • app/src/integrations/keychain/index.ts
📚 Learning: 2025-11-25T14:06:55.970Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use AsyncStorage for simple data, SQLite for complex data, and Keychain for sensitive data in React Native.

Applied to files:

  • app/src/integrations/keychain/index.ts
🧬 Code graph analysis (2)
app/src/screens/dev/DevSettingsScreen.tsx (2)
app/src/stores/settingStore.ts (1)
  • useSettingStore (60-174)
packages/mobile-sdk-demo/tests/mocks/react-native.ts (2)
  • Platform (14-25)
  • Alert (6-6)
app/src/integrations/keychain/index.ts (2)
app/src/types/react-native-keychain.d.ts (1)
  • ExtendedSetOptions (11-21)
app/src/stores/settingStore.ts (1)
  • useSettingStore (60-174)
⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: android-build-test
🔇 Additional comments (7)
app/android/app/src/main/AndroidManifest.xml (1)

28-29: LGTM! Solid security hardening.

Disabling android:allowBackup prevents the Android backup system from exfiltrating sensitive keystore data to cloud storage. This is the right call for an app managing cryptographic secrets and passport data.

app/src/stores/settingStore.ts (2)

41-47: LGTM! Clean addition to the persisted settings.

The useStrongBox setting follows the established store patterns with proper typing. Defaulting to true is the right security-first choice.


152-155: LGTM! Implementation is consistent with other settings.

The setter and initial value follow the existing conventions in this store.

app/src/integrations/keychain/index.ts (2)

65-69: Good defensive choice for the passcode check.

Hardcoding useStrongBox: false for the test entry ensures the passcode availability check won't fail on devices with StrongBox issues. The type assertion to ExtendedSetOptions is necessary here.


13-14: Imports are correctly structured.

The store import and custom type import align with the codebase's @/ alias pattern.

app/src/screens/dev/DevSettingsScreen.tsx (1)

402-403: Store bindings look good.

The hook usage follows the Zustand selector pattern correctly.

app/src/types/react-native-keychain.d.ts (1)

1-21: Patch is properly implemented and integrated end-to-end.

The react-native-keychain+10.0.0.patch exists and is applied via patch-package during postinstall. The native Kotlin implementation correctly handles useStrongBox with proper fallback logic (if (useStrongBox && supportsSecureHardware)), and the type definition accurately reflects this. Integration is complete: the keychain integration layer, Zustand store, and dev UI all properly use the setting. No issues identified.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +94 to +101
const useStrongBox =
options.useStrongBox ?? useSettingStore.getState().useStrongBox;

const setOptions: ExtendedSetOptions = {
accessible: config.accessible,
...(config.securityLevel && { securityLevel: config.securityLevel }),
...(config.accessControl && { accessControl: config.accessControl }),
useStrongBox,
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential race condition with store rehydration.

useSettingStore.getState().useStrongBox accesses the persisted store synchronously. If createKeychainOptions is called early during app startup before AsyncStorage rehydration completes, it may read the default true instead of the user's persisted preference.

Consider checking useSettingStore.persist.hasHydrated() or subscribing to onRehydrateStorage if this function can be invoked during initial app boot.

🛠️ Potential safeguard
  const useStrongBox =
-   options.useStrongBox ?? useSettingStore.getState().useStrongBox;
+   options.useStrongBox ??
+   (useSettingStore.persist.hasHydrated()
+     ? useSettingStore.getState().useStrongBox
+     : true);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const useStrongBox =
options.useStrongBox ?? useSettingStore.getState().useStrongBox;
const setOptions: ExtendedSetOptions = {
accessible: config.accessible,
...(config.securityLevel && { securityLevel: config.securityLevel }),
...(config.accessControl && { accessControl: config.accessControl }),
useStrongBox,
const useStrongBox =
options.useStrongBox ??
(useSettingStore.persist.hasHydrated()
? useSettingStore.getState().useStrongBox
: true);
const setOptions: ExtendedSetOptions = {
accessible: config.accessible,
...(config.securityLevel && { securityLevel: config.securityLevel }),
...(config.accessControl && { accessControl: config.accessControl }),
useStrongBox,
🤖 Prompt for AI Agents
In `@app/src/integrations/keychain/index.ts` around lines 94 - 101,
createKeychainOptions reads useSettingStore.getState().useStrongBox
synchronously which can return a default value before AsyncStorage rehydration;
guard this by checking store hydration before falling back to getState (e.g.,
use useSettingStore.persist.hasHydrated() and only read getState() if hydrated,
or subscribe to onRehydrateStorage to defer resolving useStrongBox), and update
the logic around useStrongBox (the options.useStrongBox ?? ...) so it prefers
the explicit option, then the persisted value only when persist.hasHydrated() is
true, otherwise use a safe fallback until rehydration completes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That’s acceptable

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seshanthS, understood. I've noted your decision. The implementation will proceed with the current approach.


🧠 Learnings used
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Keychain for secure storage of sensitive data in React Native.

Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T14:06:55.970Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use AsyncStorage for simple data, SQLite for complex data, and Keychain for sensitive data in React Native.

Learnt from: transphorm
Repo: selfxyz/self PR: 1516
File: app/src/screens/account/recovery/RecoverWithPhraseScreen.tsx:51-52
Timestamp: 2025-12-17T15:27:42.298Z
Learning: In app/src/screens/account/recovery/RecoverWithPhraseScreen.tsx, ethers.Mnemonic.isValidMnemonic should not be used as a gate for pasting recovery phrases because it produces false negatives and rejects valid mnemonics. Allow users to paste any clipboard content; validation should only occur when the user attempts to restore the account.

@seshanthS seshanthS requested a review from transphorm January 15, 2026 12:14
@seshanthS seshanthS changed the title add keychain patch - wip add keychain patch - DO NOT MERGE YET Jan 15, 2026
@cursor
Copy link

cursor bot commented Jan 15, 2026

You have run out of free Bugbot PR reviews for this billing cycle. This will reset on January 17.

To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

@transphorm transphorm changed the title add keychain patch - DO NOT MERGE YET add keychain patch (2.9.12) - DO NOT MERGE YET Jan 15, 2026
@transphorm transphorm changed the title add keychain patch (2.9.12) - DO NOT MERGE YET SELF-1497: add keychain patch - DO NOT MERGE YET Jan 16, 2026
@seshanthS seshanthS changed the title SELF-1497: add keychain patch - DO NOT MERGE YET SELF-1497: add keychain patch Jan 20, 2026
@seshanthS seshanthS merged commit d5b843d into dev Jan 20, 2026
24 checks passed
@seshanthS seshanthS deleted the hotfix/keychain branch January 20, 2026 18:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants