This guide details how credentials, API keys, plugin configuration, and device permissions are managed securely within Chattree.
When users configure cloud providers (OpenAI, Google Gemini, Anthropic Claude), credentials must be protected against malicious apps, physical extraction, and inadvertent leaks.
┌─────────────────────────────────────────────────────────────┐
│ User Input │
│ Settings → AI Providers → Enter API Key │
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ SecureCredentialStore │
│ - Strips leading/trailing whitespace │
│ - Validates key format (e.g. sk-..., AIza...) │
│ - Disallows logging (debugPrint strips values) │
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Hardware-Backed Operating System Keystore │
│ Android: EncryptedSharedPreferences (AES-256 GCM) │
│ iOS: Apple Keychain Services │
└─────────────────────────────────────────────────────────────┘
SecureCredentialStore guarantees that API keys and authentication tokens are never written to disk logs, crash reports, or debug outputs.allowBackup="false" to prevent unencrypted cloud sync via Google Drive or iCloud device backups.The plugin manifest schema accepts an optional settings array with declarative fields (key, label, type, defaultValue, options, and isSecret) rendered in Settings → Plugins → [Plugin]. When a field is marked with isSecret: true (or uses a secret/token/password/api_key key identifier), PluginStateStore encrypts its value at rest in FlutterSecureStorage (EncryptedSharedPreferences on Android / Keychain on iOS) and writes only a __SECURE_STORED__ sentinel in SharedPreferences. See the manifest reference for full details.
Chattree's own user preferences (theme, language, inference parameters, local model optimization, RAG controls, provider credentials, and history deletion) are managed in the app's Settings screens. See Chattree App Features.
Chattree categorizes capabilities into three danger tiers:
| Level | Badge | Permissions Included | User Consent Mechanism |
|---|---|---|---|
| Normal | 🟢 | storage.private, share.text, open.url, clipboard.write | Granted automatically upon installation (core sandbox capabilities). |
| Sensitive | 🟡 | network.http, network.webhook_inbound, network.webhook_outbound, files.pick, files.read, files.write, chattree.notes.*, chattree.reminders.*, notifications.send, clipboard.read, share.file, open.app, contacts.create, contacts.update, calendar.*, chattree.context.read, chat.history.read, ai.context, ai.embeddings | Explicit confirmation dialog presented during installation or first invocation. |
| Critical | 🔴 | location.current, camera.capture, contacts.read, network.local, email.read, email.send | Explicit confirmation prompt AND operating system runtime permission prompt. |
User runs: /plugin-command
│
▼
Does plugin declare required capability in plugin.json?
├─► NO ──► Host API returns permissionDenied
▼ YES
Has user granted permission in Chattree?
├─► NO ──► Chattree presents PermissionDialog
│ ├─► Denied ──► Execution halts
│ └─► Granted
▼
Does operation require OS-level permission (Camera/Location/Contacts)?
├─► NO ──► Operation executes
▼ YES
Is Android runtime permission granted?
├─► NO ──► System permission prompt shown
│ ├─► Denied ──► Error returned to plugin
│ └─► Granted
▼
Operation executes successfully
Users can review and revoke permissions at any time: