Skip to main content

Local Data Storage & Privacy

Everything lives locally, by default

All application data — profiles, user_roles, test content, and user_test_sessions (including in-progress answers and AI feedback) — is stored in a single local SQLite file, imh.db, in the OS-specific Tauri app data directory (see Running the App in Development for exact paths per OS). There is no cloud sync by default and no remote database.

Uploaded media (writing task images, listening audio) is stored under $HOME/.imh/<domain>/<user_id>/ (src/core/src/commands/storage.rs), matching the assetProtocol.scope configured in src/core/tauri.conf.json:

"assetProtocol": {
"enable": true,
"scope": ["$HOME/.imh/**"]
}

The one outbound network call

The only network request the app makes is the AI grading call in grade_writing (src/core/src/commands/grade_writing.rs), which sends the Writing prompt and the candidate's response text to whichever AI provider is currently marked active in the ai_configurations table — configured from Admin → AI Configurations (src/ui/pages/admin/AiConfigurations.tsx). Credentials for each provider are encrypted (AES-256-GCM) before being stored; there are no VITE_-prefixed environment variables involved. See Writing Module & AI Grading for the per-provider request/response shape.

:::warning Writing submissions leave the device for AI grading Because Writing responses and prompts are sent to an external AI provider for grading, admins configuring a provider in AI Configurations should ensure its endpoint and credentials are trusted and kept private — anyone with the credentials can send requests through that account, and the provider sees the raw text of every graded submission. Credentials are encrypted at rest, but the encryption key file lives alongside imh.db, so this isn't a substitute for not sharing the machine or its data directory. This is the one place candidate-authored content is not fully local. :::

Anonymous identity, not accounts

There is no login/signup flow; getAnonId() (src/ui/lib/anonId.ts) generates a random UUID on first run and persists it in localStorage, used as the user_id for all local data scoping. See Frontend Architecture for the implications of this for the Admin CMS's lack of route-level access control.