| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
SDK Size
|
Sorry, something went wrong.
## 🎯 Goal This is a port of [this feature](#3780) to V8. ## 🛠 Implementation details <!-- Provide a description of the implementation --> ## 🎨 UI Changes <!-- Add relevant screenshots --> <details> <summary>iOS</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> <details> <summary>Android</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> ## 🧪 Testing <!-- Explain how this change can be tested (or why it can't be tested) --> ## ☑️ Checklist - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [ ] PR targets the `develop` branch - [ ] Documentation is updated - [ ] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - [ ] Expo iOS and Android
|
🎉 This PR is included in version 9.8.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
🎯 Goal
Let integrators encrypt the offline database at rest. The offline cache stores channels, messages, members, drafts and reminders, and right now we write all of it as plaintext SQLite.
It's opt-in. Apps that don't pass the new prop behave exactly as they do today.
One thing to know up front, since it shapes the rest of the PR: op-sqlite accepts an encryptionKey on a build without SQLCipher and then ignores it. You get a plaintext database and no error at any layer. So part of this change is detecting that and refusing to open the database, instead of passing the key along and assuming it was used.
Accompanying docs PR: https://github.com/GetStream/docs-content/pull/1521
🛠 Implementation details
API
Chat takes one new prop:
getEncryptionKey?: () => Promise<string | undefined> runs once per database open, so once per launch and again after a sign-out. Its result is passed to SQLCipher through op-sqlite. SqliteClientError and SqliteClientErrorCode are exported too.
We throw instead of recovering
When the database can't be opened with the encryption that was asked for, Chat throws a SqliteClientError from render and the integrator's error boundary handles it. We don't fall back to plaintext, we don't switch offline support off, and we don't delete anything.
The reason is that all of those recoveries have a security consequence and there's no default that's right for everyone. Falling back to plaintext defeats the point of the feature and nothing tells you it happened. Dropping the cache decides a compliance question for the integrator. Deleting the file throws away offline actions that are still queued. We also can't tell "the Keystore isn't unlocked yet, try again shortly" from "something is wrong here, sign this device out". So we detect the failure and classify it, and the app decides what to do about it.
Scenarios
Two of those rows need a closer look in review.
OFFLINE_DB_UNREADABLE is not gated on getEncryptionKey being set, and that's on purpose, because of the "turning encryption off again" row. If we only threw it when a key was supplied, an integrator removing the prop would get a blank screen instead of an error they can recover from. I hit that on device.
The last row is why the boundary is useful even for apps that never use encryption. A corrupted database gives you the same code, so anything using enableOfflineSupport can end up there.
Where the error comes from
AbstractOfflineDB.init in the LLC catches whatever initializeDB throws and doesn't re-throw it, so a caller can't find out why initialisation failed. I left that alone, because changing it would tie this PR to an LLC release. OfflineDB stores the reason on the instance on the way out instead, and the new hook reads it back once init has settled. No LLC changes needed for this.
🎨 UI Changes
🧪 Testing
☑️ Checklist