Makes BackupPolicy.EXCLUDED_DATABASE_PATHS the true single source of truth by deriving it from DatabaseFiles rather than hand-listing paths, and fixes DatabaseFiles.clear to use context.deleteDatabase.
1. Backup exclusion set is now derived from DatabaseFiles (security-relevant)
New DatabaseFiles.fileNames(name) helper returns a DB file plus its statically-nameable SQLite sidecars (-wal/-shm/-journal) — the one place that knows which files make up a database.
BackupPolicy.EXCLUDED_DATABASE_PATHS is now fileNames(NAME) + fileNames(ACCOUNTS_NAME). This adds libremail-accounts.db (+ sidecars) — the accounts + encrypted-credentials DB that #118/#111 split out of libremail.db — to the never-back-up set, matching the field's stated intent. A newly added database can no longer silently fall out of the exclusions.
2. DatabaseFiles.clear fix
Now wipes the cache DB via context.deleteDatabase(NAME), which also removes the -mj* master-journal temp files the hand-rolled suffix list missed.
Still wipes only the cache DB (NAME) and never the accounts DB (ACCOUNTS_NAME) — the sign-in-survives-cache-wipe separation from #111 is preserved. The only caller (DatabaseModule.provideDatabase) already passes a Context, so no no-Context fallback is needed.
3. Doc + test updates
Updated the comments in data_extraction_rules.xml (API 31+) and backup_rules.xml (API 29-30) to note libremail-accounts.db is also kept off-device by the strict include-allowlist.
BackupPolicyTest: asserts the accounts DB (+ sidecars) is in the exclusion set and that the set is exactly the DatabaseFiles-derived list (lockstep, no drift).
DataExtractionRulesTest: the derived secretPaths now includes the accounts DB, so assertSafe checks it against every include section; added an explicit test pinning both DBs into the guarded set.
Security note
There is no active backup leak today. The backup XML is a strict include-allowlist (only datastore/libremail_settings.preferences_pb is backed up), so libremail-accounts.db was already excluded by omission. This PR closes the SoT drift #118 introduced (credentials changed DBs but the exclusion SoT did not) and the -mj* gap, so the security posture no longer depends on the allowlist staying strict by luck.
Scope
Strictly BackupPolicy.kt, DatabaseFiles.kt, the two backup XML resources, and their tests. Does not touch di/DatabaseModule.kt (#93), the migrator, or app-lock code.
Testing
Fast CI gate all green locally (JDK 21): assembleDebug, testDebugUnitTest, lintDebug, ktlintCheck, detekt, plus compileDebugAndroidTestKotlin.
## What
Closes #103.
Makes `BackupPolicy.EXCLUDED_DATABASE_PATHS` the true single source of truth by **deriving** it from `DatabaseFiles` rather than hand-listing paths, and fixes `DatabaseFiles.clear` to use `context.deleteDatabase`.
### 1. Backup exclusion set is now derived from `DatabaseFiles` (security-relevant)
- New `DatabaseFiles.fileNames(name)` helper returns a DB file plus its statically-nameable SQLite sidecars (`-wal`/`-shm`/`-journal`) — the one place that knows which files make up a database.
- `BackupPolicy.EXCLUDED_DATABASE_PATHS` is now `fileNames(NAME) + fileNames(ACCOUNTS_NAME)`. This **adds `libremail-accounts.db` (+ sidecars)** — the accounts + encrypted-credentials DB that #118/#111 split out of `libremail.db` — to the never-back-up set, matching the field's stated intent. A newly added database can no longer silently fall out of the exclusions.
### 2. `DatabaseFiles.clear` fix
- Now wipes the cache DB via `context.deleteDatabase(NAME)`, which also removes the `-mj*` master-journal temp files the hand-rolled suffix list missed.
- Still wipes **only** the cache DB (`NAME`) and **never** the accounts DB (`ACCOUNTS_NAME`) — the sign-in-survives-cache-wipe separation from #111 is preserved. The only caller (`DatabaseModule.provideDatabase`) already passes a `Context`, so no no-`Context` fallback is needed.
### 3. Doc + test updates
- Updated the comments in `data_extraction_rules.xml` (API 31+) and `backup_rules.xml` (API 29-30) to note `libremail-accounts.db` is also kept off-device by the strict include-allowlist.
- `BackupPolicyTest`: asserts the accounts DB (+ sidecars) is in the exclusion set and that the set is exactly the `DatabaseFiles`-derived list (lockstep, no drift).
- `DataExtractionRulesTest`: the derived `secretPaths` now includes the accounts DB, so `assertSafe` checks it against every include section; added an explicit test pinning both DBs into the guarded set.
## Security note
**There is no active backup leak today.** The backup XML is a strict include-*allowlist* (only `datastore/libremail_settings.preferences_pb` is backed up), so `libremail-accounts.db` was already excluded by omission. This PR closes the SoT drift #118 introduced (credentials changed DBs but the exclusion SoT did not) and the `-mj*` gap, so the security posture no longer depends on the allowlist staying strict by luck.
## Scope
Strictly `BackupPolicy.kt`, `DatabaseFiles.kt`, the two backup XML resources, and their tests. Does not touch `di/DatabaseModule.kt` (#93), the migrator, or app-lock code.
## Testing
Fast CI gate all green locally (JDK 21): `assembleDebug`, `testDebugUnitTest`, `lintDebug`, `ktlintCheck`, `detekt`, plus `compileDebugAndroidTestKotlin`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
Closes #103.
Makes
BackupPolicy.EXCLUDED_DATABASE_PATHSthe true single source of truth by deriving it fromDatabaseFilesrather than hand-listing paths, and fixesDatabaseFiles.clearto usecontext.deleteDatabase.1. Backup exclusion set is now derived from
DatabaseFiles(security-relevant)DatabaseFiles.fileNames(name)helper returns a DB file plus its statically-nameable SQLite sidecars (-wal/-shm/-journal) — the one place that knows which files make up a database.BackupPolicy.EXCLUDED_DATABASE_PATHSis nowfileNames(NAME) + fileNames(ACCOUNTS_NAME). This addslibremail-accounts.db(+ sidecars) — the accounts + encrypted-credentials DB that #118/#111 split out oflibremail.db— to the never-back-up set, matching the field's stated intent. A newly added database can no longer silently fall out of the exclusions.2.
DatabaseFiles.clearfixcontext.deleteDatabase(NAME), which also removes the-mj*master-journal temp files the hand-rolled suffix list missed.NAME) and never the accounts DB (ACCOUNTS_NAME) — the sign-in-survives-cache-wipe separation from #111 is preserved. The only caller (DatabaseModule.provideDatabase) already passes aContext, so no no-Contextfallback is needed.3. Doc + test updates
data_extraction_rules.xml(API 31+) andbackup_rules.xml(API 29-30) to notelibremail-accounts.dbis also kept off-device by the strict include-allowlist.BackupPolicyTest: asserts the accounts DB (+ sidecars) is in the exclusion set and that the set is exactly theDatabaseFiles-derived list (lockstep, no drift).DataExtractionRulesTest: the derivedsecretPathsnow includes the accounts DB, soassertSafechecks it against every include section; added an explicit test pinning both DBs into the guarded set.Security note
There is no active backup leak today. The backup XML is a strict include-allowlist (only
datastore/libremail_settings.preferences_pbis backed up), solibremail-accounts.dbwas already excluded by omission. This PR closes the SoT drift #118 introduced (credentials changed DBs but the exclusion SoT did not) and the-mj*gap, so the security posture no longer depends on the allowlist staying strict by luck.Scope
Strictly
BackupPolicy.kt,DatabaseFiles.kt, the two backup XML resources, and their tests. Does not touchdi/DatabaseModule.kt(#93), the migrator, or app-lock code.Testing
Fast CI gate all green locally (JDK 21):
assembleDebug,testDebugUnitTest,lintDebug,ktlintCheck,detekt, pluscompileDebugAndroidTestKotlin.🤖 Generated with Claude Code