mirror of
https://github.com/stablyai/orca.git
synced 2026-09-24 08:02:33 +00:00
* fix(mobile): recover pairing save when the Android keystore alias is unusable Orca Mobile could reach a state where pairing succeeded but the host could never be saved, with every attempt failing identically: Could not encrypt the value for key 'orca.host-token.host-...' under keychain 'key_v1'. Caused by: unknown expo-secure-store derives ONE Android keystore alias from the keychain service (`<service>:unauthenticated`) and shares it across every host token, so a single unusable alias rejects all writes. Its built-in self-heal only covers KeyPermanentlyInvalidatedException, and a null-message GeneralSecurityException takes the unrecoverable branch instead — leaving onboarding permanently blocked, which a reinstall does not clear. Route host-token persistence through a keychain generation that rotates to a fresh service (and therefore a fresh alias) only after a write has already failed. Generation 0 keeps expo's default service so tokens written by earlier builds stay readable, reads walk back through retired services, and deletes clear every generation so a rotation cannot strand a live credential. Refs #6600 * fix(mobile): record a keychain rotation before storing the token under it Greptile flagged that a token could be stored under a generation the generation record never captured. `commitGeneration` swallowed the AsyncStorage failure and cached the new generation in memory, so the write succeeded for the rest of the session — but the next launch re-read the old record, and because reads only walk back from the recorded generation they never probed the newer service. The host silently vanished and the user had to re-pair, which is the same class of loss this change set out to fix. Record the rotation first and let a storage failure propagate, so a token is never written under a generation reads won't reach. Advancing the record before the write is safe because reads walk back through every older service; the worst case is one spent generation and one extra probe per miss. * fix(mobile): harden pairing keychain recovery * fix(mobile): harden pairing keychain recovery state * fix(mobile): fail closed on unreadable pairing credentials