Backup & Restore Mechanism
Relevant source files
The following files were used as context for generating this wiki page:
- app/src/main/java/io/github/mojri/hesabyar/domain/usecase/ManageBackupUseCase.kt
- app/src/main/java/io/github/mojri/hesabyar/data/BackupModels.kt
- app/src/main/java/io/github/mojri/hesabyar/ui/BackupViewModel.kt
- app/src/main/java/io/github/mojri/hesabyar/ui/screens/SettingsScreen.kt
- rust/hesabyar-core/src/lib.rs
- rust/hesabyar-core/src/models/mod.rs
- README.md
The Backup & Restore Mechanism in Hesabyar provides a robust offline-first system for securing user financial data. It allows users to export their entire application state—including transactions, loans, installments, and categories—into a structured JSON format. This system supports both full data replacement and merging data from a backup file into the existing local database.
Sources: README.md:58-61, app/src/main/java/io/github/mojri/hesabyar/data/BackupModels.kt:8-19
System Architecture
The mechanism employs a hybrid architecture utilizing a Kotlin/Android UI and Domain layer interfaced with a high-performance Rust Core (hesabyar-core) via UniFFI. While the UI handles file selection and state management, the Rust core provides critical services for JSON parsing, structural validation, and cryptographic security.
Core Components
| Component | Responsibility |
|---|---|
SettingsScreen | Provides UI triggers for importing/exporting files. |
BackupViewModel | Manages UI state (Idle, Importing, Exporting) and stages pending restores. |
ManageBackupUseCase | Orchestrates logic between the Repository and Rust/Kotlin parsers. |
HesabyarRepository | Executes the final database operations (Insert, Merge, Replace). |
hesabyar-core (Rust) | High-performance JSON serialization, validation, and AES-256-GCM encryption. |
Sources: app/src/main/java/io/github/mojri/hesabyar/ui/BackupViewModel.kt:28-36, rust/hesabyar-core/README.md:12-22, app/src/main/java/io/github/mojri/hesabyar/ui/screens/SettingsScreen.kt:472-506
Data Flow Overview
This diagram illustrates the flow of data during a restore operation, starting from file selection to database commitment.
Data Models
The system centers around the BackupPayload, a comprehensive container for all portable user data.
BackupPayload Structure
The payload is designed for cross-platform compatibility, using CamelCase in Kotlin and supporting Snake_Case aliases in Rust for seamless serialization.
| Field | Type | Description |
|---|---|---|
version | Int | Schema version of the backup file (Current: 1). |
timestamp | Long | UTC Epoch milliseconds when the backup was created. |
appVersion | String | The version of the app that generated the backup. |
transactions | List<Transaction> | All recorded income and expense entries. |
loans | List<Loan> | Debt and credit tracking records. |
installments | List<Installment> | Payment schedules and reminders. |
categories | List<Category> | User-defined or default classification buckets. |
Sources: app/src/main/java/io/github/mojri/hesabyar/data/BackupModels.kt:8-19, rust/hesabyar-core/src/models/mod.rs:253-267
Implementation Details
Parsing and Validation
The system implements a multi-tier parsing strategy. It primary attempts to use the Rust core for high-performance parsing. If the Rust library is unavailable or encounters malformed enum strings from older versions, it falls back to a Kotlin-based JSONObject parser.
Restore Modes
Users are offered two distinct modes when restoring data:
- REPLACE: Clears all existing data in the local database and inserts the backup content. This is a destructive operation.
- MERGE: Appends backup data to the existing database. Logic within the Repository handles conflict resolution (e.g., matching categories by name/key).
Sources: app/src/main/java/io/github/mojri/hesabyar/data/RestoreMode.kt:3-6, app/src/main/java/io/github/mojri/hesabyar/domain/usecase/ManageBackupUseCase.kt:218-223
Validation Logic
Before any data is written to the database, it undergoes structural validation. The Rust core performs deep checks, such as:
- Ensuring
amountis positive. - Verifying
dateis valid (> 0). - Checking referential integrity (e.g.,
categoryIdin transactions must exist in thecategorieslist).
Sources: rust/hesabyar-core/src/lib.rs:114-162, app/src/main/java/io/github/mojri/hesabyar/domain/usecase/ManageBackupUseCase.kt:180-216
Security and Encryption
The project supports AES-256-GCM encryption for backups. Encrypted files follow a specific format:
- Header:
HESABYAR_BACKUP_V1\n - Checksum: 64-character SHA-256 hex string.
- Payload: Binary data containing the
[12-byte nonce][ciphertext + auth tag].
The Rust hesabyar-core handles these operations to ensure memory safety and high-speed cryptographic throughput.
Sources: rust/hesabyar-core/src/lib.rs:175-182, rust/uniffi/hesabyar_core/uniffi/hesabyar_core/hesabyar_core.kt:1056-1070
Conclusion
The Backup & Restore Mechanism is a critical feature for Hesabyar's offline-first philosophy. By leveraging a Rust core for parsing and validation, the system ensures data integrity and security while providing the Kotlin UI with a simple, high-level API to manage complex data migrations. This architecture allows the app to maintain high performance even with large datasets containing thousands of transactions.
Sources: README.md:14-19, app/src/main/java/io/github/mojri/hesabyar/ui/BackupViewModel.kt:28-43