Privacy & security
Keys in secure device storage, conversations local-only, prompts only to your chosen provider, no telemetry, and one-tap erase of every local boundary.
Cordy for Mobile is designed so that your keys and conversations stay yours. There is no Cordy backend: the app talks directly from your device to the provider you choose. This page is the complete data-handling story, including an honest note on platform status.
Principles
- No backend. Cordy operates no server. Nothing you type is sent to, stored by, or routed through Cordy.
- Local-first. Conversations and settings live on the device; API keys live in the platform secure store.
- Direct to the provider. Prompts go only to the endpoint you selected, using that provider's authentication header. Built-in and public custom endpoints require HTTPS; explicitly local custom endpoints may use HTTP.
- No account, no sync, no telemetry. You never sign in, nothing is mirrored to a server, and there is no analytics or payload capture.
- Erasable. One action wipes every local boundary the app owns.
The data flow
When you send a message:
You → CordyAI (on device) → the provider you selected
That's the entire path. The provider receives your prompt (and processes it under their privacy policy and data-retention terms — worth reading for whichever provider you use). Cordy is not a party to the request.
Where your data lives
| Data | Location | Notes |
|---|---|---|
| API keys | Android Keystore / iOS Keychain source | Per-provider secure-storage entries, never in the conversation DB or application logs. The repository records no completed iOS runtime verification. |
| Conversations & messages | On-device SQLDelight (SQLite) database | Never leave the device except as prompt content you send. |
| Attachments (images) | On-device file storage, referenced by messages | Released when their message/conversation is deleted. |
| Settings & preferences | On-device app preferences | Non-sensitive (active provider/model, temperature, etc.). |
| Model catalog & pricing cache | On-device database | Fetched per provider; safe to clear/refresh. |
Key storage, in detail
API keys get the strongest local protection each platform offers:
- Android — a key held in the Android Keystore performs AES-256-GCM encryption of each value, stored as Base64(IV ‖ ciphertext ‖ GCM tag) in a private preferences file. If the Keystore key is permanently invalidated (for example by a device restore or lock-screen reset), the affected value is dropped rather than returned corrupt. Values written by the older
EncryptedSharedPreferencesare transparently migrated to this scheme on first read. - iOS source — uses the Keychain with
AfterFirstUnlockThisDeviceOnlyaccessibility, intended to make each key device-bound and non-syncable. The repository records no completed iOS binary link, execution, or smoke, so this protection has not been verified at runtime.
Keys are scoped per provider, so each provider has an independent entry. Saving a blank key is treated as deletion.
What leaves the device — and what doesn't
- Leaves: the prompt content of messages you send, to the provider you chose, plus your key in that request's auth header.
- Does not leave through Cordy sync: the on-device conversation database, settings, usage summaries, and stored keys. A request necessarily sends the selected context and authentication material to your chosen provider, whose own retention policy applies.
Logging
Cordy does not capture analytics or telemetry. In release builds, logging severity is capped so that verbose/debug/info logs — which can carry prompt or request detail — never reach the device console. Error messages shown in the UI are deliberately safe: raw provider response bodies, API keys, and auth headers are never displayed.
One-tap erase
Settings → Erase all local data wipes every local boundary the app owns. The confirm dialog is explicit: "This permanently deletes every local conversation, every preference, and every API key on this device. This cannot be undone."
Erase clears, in order:
| Boundary | What's removed |
|---|---|
| Database | Conversations, messages, and generation runs (plus user-defined providers and the model catalog) |
| Preferences | The whole preferences store |
| Secure storage | All stored API keys |
| Attachments | Image attachment files |
| Image caches | Platform image memory + disk caches |
| Temp files | Camera / capture temporary files |
Erase attempts every boundary even if one fails (so a locked keychain can't leave the database full of conversations), collects any failures, and then verifies the app is actually empty. It reports honestly if any part could not be cleared.
What erase does not touch: the app binary, OS-level backups, and anything outside CordyAI's own storage. It only removes data the app itself persisted.
In-app disclosures
Cordy states its data flow inside the app, not just in these docs. Settings includes a Privacy and data flow section: "Conversations stay on this device. API keys use secure storage. This version has no cloud sync, account, or analytics." When a provider is selected, it also shows "Your prompts go to (provider) when you send them. CordyAI doesn't send them anywhere else."
Honest platform note
Android: the v0.5.0 baseline includes shared tests, an Android debug build, real-device launch, chat smoke, and gallery image send. Manual camera, share-in, microphone, and TalkBack checks remained open. The implementation and automated coverage do not establish a fully verified platform claim.
iOS: the repository records no completed binary link, execution, or simulator/device smoke. A Windows-host klib compile from May 2026 is stale because iOS sources changed afterward. Current source contains Keychain, database, attachment, export, and erase implementations, but image picking, camera, and voice are disabled and every runtime claim remains unverified.