feat(logging): DB/keystore -> AppLog + breadcrumbs (#327) #337

Merged
JMR-dev merged 2 commits from feat-327-logging-dbkeystore into main 2026-07-05 02:33:41 +00:00
JMR-dev commented 2026-07-05 02:13:22 +00:00 (Migrated from github.com)

Summary

  • Migrates data/security/DatabaseKeyCipher (4 sites), data/local/DatabaseEncryption (1 site), and data/local/AccountDataMigrator (1 site) off raw android.util.Log onto AppLog (seam from #325), so these breadcrumbs reach the process RingLogBuffer (and a user-reviewed debug report) even in release builds, where Log.d is otherwise stripped from Logcat only.
  • Adds the new DatabaseEncryption.migrate start breadcrumb the ticket calls for: AppLog.i(TAG, "converting local cache database (targetEncrypted=...)"), alongside the existing "converted" completion line now routed through AppLog.d.
  • AccountDataMigrator's "moved account tables into the account database: $present" breadcrumb (table names only) now routed through AppLog.d.
  • DatabaseKeyCipher's 4 auth-bound-key decision points (encrypt's invalidated-key retry, and isInvalidated's three branches) now log via AppLog.d(tag, msg, e).
  • PII: none logged. Keystore exceptions, a set of table names, and a boolean flag only — never the passphrase, key material, or an account address/host.

Test plan

  • Extended DatabaseEncryptionTest (instrumented — loads the real SQLCipher native lib) with conversionEmitsNonPiiAppLogBreadcrumbs: installs a RingLogBuffer, round-trips a seeded DB (with a real email address) through ensureEncrypted/ensurePlaintext, and asserts the "converting…"/"converted" breadcrumbs land with the right levels (I/D) and never contain the passphrase, the db file path, or the seeded email.
  • Extended AccountDataMigratorTest with copyEmitsANonPiiAppLogBreadcrumbNamingOnlyTheMovedTables: installs a RingLogBuffer, runs copyAccountTables, and asserts the breadcrumb names every moved table and never contains the seeded email, secret, or passphrase.
  • DatabaseKeyCipher stays device-only and behavior-preserving (auth-bound Keystore keys/BiometricPrompt can't run off-device); its migration is compile-verified, and the breadcrumb-reaches-buffer guarantee at the AppLog.d(throwable) level is already unit-tested in the #325 seam.
  • :app:testDebugUnitTest :app:compileDebugAndroidTestKotlin :app:ktlintCheck :app:detekt all green locally.
  • The two new instrumented tests were not run on an emulator in this pass (dispatched as a unit-only validation to avoid concurrent local emulators); CI's full matrix will execute them before merge.

Closes #327
Part of #324

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

## Summary - Migrates `data/security/DatabaseKeyCipher` (4 sites), `data/local/DatabaseEncryption` (1 site), and `data/local/AccountDataMigrator` (1 site) off raw `android.util.Log` onto `AppLog` (seam from #325), so these breadcrumbs reach the process `RingLogBuffer` (and a user-reviewed debug report) even in release builds, where `Log.d` is otherwise stripped from Logcat only. - Adds the new `DatabaseEncryption.migrate` start breadcrumb the ticket calls for: `AppLog.i(TAG, "converting local cache database (targetEncrypted=...)")`, alongside the existing "converted" completion line now routed through `AppLog.d`. - `AccountDataMigrator`'s "moved account tables into the account database: $present" breadcrumb (table names only) now routed through `AppLog.d`. - `DatabaseKeyCipher`'s 4 auth-bound-key decision points (encrypt's invalidated-key retry, and `isInvalidated`'s three branches) now log via `AppLog.d(tag, msg, e)`. - PII: none logged. Keystore exceptions, a set of table names, and a boolean flag only — never the passphrase, key material, or an account address/host. ## Test plan - [x] Extended `DatabaseEncryptionTest` (instrumented — loads the real SQLCipher native lib) with `conversionEmitsNonPiiAppLogBreadcrumbs`: installs a `RingLogBuffer`, round-trips a seeded DB (with a real email address) through `ensureEncrypted`/`ensurePlaintext`, and asserts the "converting…"/"converted" breadcrumbs land with the right levels (`I`/`D`) and never contain the passphrase, the db file path, or the seeded email. - [x] Extended `AccountDataMigratorTest` with `copyEmitsANonPiiAppLogBreadcrumbNamingOnlyTheMovedTables`: installs a `RingLogBuffer`, runs `copyAccountTables`, and asserts the breadcrumb names every moved table and never contains the seeded email, secret, or passphrase. - [x] `DatabaseKeyCipher` stays device-only and behavior-preserving (auth-bound Keystore keys/BiometricPrompt can't run off-device); its migration is compile-verified, and the breadcrumb-reaches-buffer guarantee at the `AppLog.d(throwable)` level is already unit-tested in the #325 seam. - [x] `:app:testDebugUnitTest` `:app:compileDebugAndroidTestKotlin` `:app:ktlintCheck` `:app:detekt` all green locally. - [ ] The two new instrumented tests were not run on an emulator in this pass (dispatched as a unit-only validation to avoid concurrent local emulators); CI's full matrix will execute them before merge. Closes #327 Part of #324 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign in to join this conversation.