-
Notifications
You must be signed in to change notification settings - Fork 0
05. Database
DIRD+ stores all clinical data in a local SQLite database, encrypted at rest with SQLCipher (AES-256). The encryption key is derived from the application password with Argon2id (OWASP 2025 parameters) and passed to SQLCipher as a raw key (PRAGMA key = x'…'), bypassing SQLCipher's internal PBKDF2.
-
Rust side:
src-tauri/src/db.rs(viarusqlite, featurebundled-sqlcipher-vendored-openssl). -
Frontend access layer:
src/lib/db-sql/— a thinTableShimper table, column ↔ objectmappers, and a one-timemigrator. -
Schema:
src-tauri/migrations/0001_init.sql.
| Table | Key fields | Purpose |
|---|---|---|
| patients | patientId, name, diabetes (type/duration), HTN, dyslipidemia, medications | Demographics & clinical data |
| sessions | patientId, date, modelVersions, locked, type (normal/combined) | Clinical visits |
| images | sessionId, eyeType (OD/OI), originalBlob, order | Fundus images |
| detections | imageId, type (ai/manual), bbox, class, confidence | Lesion bounding boxes |
| segmentations | imageId, type (ai/manual), maskData, class, opacity | Segmentation masks |
| imageClassifications | imageId, severity, guideline, treatments[], followupDays, urgency, rationale, manuallyModified | Per-guideline DR classification |
| reports | sessionId, type (preview/final), pdfBlob, evaluatorNotes, conclusionEdited | Generated PDF reports |
| measurements | imageId, origin, destination, distancePixels, distanceDD | Calibrated measurements |
(8 tables. The former pending_contributions table was removed with the data-sharing subsystem.)
Installations created before the SQLite swap used Dexie / IndexedDB (src/lib/db/schema.ts). On upgrade, a one-time migration:
- Backs up the existing data to a
.dirdcontainer first. - Copies every table from IndexedDB into the SQLite database (
src/lib/db-sql/migrator.ts). - Marks completion idempotently via
meta.migrated_from, so it never runs twice.
The legacy Dexie schema is kept only for this migration path; new installs go straight to SQLite.
The frontend reads the database through a useLiveQuery shim (src/lib/db-sql) that re-runs queries when the underlying tables change, keeping the UI in sync without manual refresh.