[versions] agp = "9.2.0" kotlin = "2.4.0" ksp = "2.3.9" hilt = "2.60" hiltNavigationCompose = "1.3.0" coreKtx = "1.17.0" lifecycle = "2.9.4" activityCompose = "1.12.4" navigationCompose = "2.9.8" webkit = "1.12.1" biometric = "1.1.0" composeBom = "2026.06.00" room = "2.8.4" paging = "3.3.6" sqlcipher = "4.16.0" datastore = "1.2.1" work = "2.11.2" coroutines = "1.10.2" # Forced above androidx.savedstate's transitive 1.7.3 (shared with the androidTest classpath via # AGP 9 consistent resolution); Room's schema-bundle serializers need >= 1.8.0 or MigrationTestHelper # throws AbstractMethodError on GeneratedSerializer.typeParametersSerializers(). kotlinxSerialization = "1.8.1" appauth = "0.11.1" angusMail = "2.0.5" junit = "4.13.2" androidxJunit = "1.2.1" espresso = "3.7.0" androidxTestRules = "1.7.0" turbine = "1.2.1" mockk = "1.14.11" greenmail = "2.1.9" errorprone = "2.50.0" # Lint/format. ktlint owns formatting; detekt owns static analysis (formatting ruleset off). # detekt 2.0 is the only line with Gradle 9 support (stable 1.23.x tops out at Gradle 8.12). ktlint = "14.2.0" detekt = "2.0.0-alpha.5" # JaCoCo coverage agent/report tool (issue #192). Pinned above Gradle's bundled default so the # coverage agent understands Kotlin 2.4.0 bytecode on JDK 21. jacoco = "0.8.13" [libraries] # AndroidX core / lifecycle / activity / navigation androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" } androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" } androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" } androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } androidx-webkit = { group = "androidx.webkit", name = "webkit", version.ref = "webkit" } # Biometric / device-credential auth for the opt-in app-lock + encrypted-cache unlock. androidx-biometric = { group = "androidx.biometric", name = "biometric", version.ref = "biometric" } # Compose (versions managed by the BOM) androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" } androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } androidx-compose-material-icons-core = { group = "androidx.compose.material", name = "material-icons-core" } # Hilt (DI) hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } # Pulled onto the compile classpath because Hilt/Dagger generated code references it. error-prone-annotations = { group = "com.google.errorprone", name = "error_prone_annotations", version.ref = "errorprone" } hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" } androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" } androidx-hilt-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hiltNavigationCompose" } androidx-hilt-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltNavigationCompose" } # Room (local cache) androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" } androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" } androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" } # Room MigrationTestHelper (instrumented migration tests). androidx-room-testing = { group = "androidx.room", name = "room-testing", version.ref = "room" } # Room PagingSource support — lets @Query methods return androidx.paging.PagingSource. androidx-room-paging = { group = "androidx.room", name = "room-paging", version.ref = "room" } # SQLCipher — opt-in at-rest encryption of the Room cache. sqlcipher-android = { group = "net.zetetic", name = "sqlcipher-android", version.ref = "sqlcipher" } # Paging 3 — pages the unified "All inboxes" list so its query/recomposition cost scales with the # visible window, not the whole cache (issue #124). runtime = Pager/PagingData; compose = # collectAsLazyPagingItems; testing = asSnapshot for JVM unit tests. androidx-paging-runtime = { group = "androidx.paging", name = "paging-runtime", version.ref = "paging" } androidx-paging-compose = { group = "androidx.paging", name = "paging-compose", version.ref = "paging" } androidx-paging-testing = { group = "androidx.paging", name = "paging-testing", version.ref = "paging" } # DataStore (settings) / WorkManager (sync) — wired in later increments androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastore" } androidx-work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work" } # TestListenableWorkerBuilder for instrumented CoroutineWorker tests (issue #226). androidx-work-testing = { group = "androidx.work", name = "work-testing", version.ref = "work" } # Coroutines kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" } kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "coroutines" } # Serialization BOM — imported as a platform (not used directly) to raise the transitive # kotlinx-serialization runtime to the version Room's schema bundles were compiled against. kotlinx-serialization-bom = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-bom", version.ref = "kotlinxSerialization" } # Email transport / OAuth — wired in later increments appauth = { group = "net.openid", name = "appauth", version.ref = "appauth" } angus-mail = { group = "org.eclipse.angus", name = "angus-mail", version.ref = "angusMail" } # Test junit = { group = "junit", name = "junit", version.ref = "junit" } kotlin-test = { group = "org.jetbrains.kotlin", name = "kotlin-test", version.ref = "kotlin" } turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine" } mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } # mockk's Android artifact for instrumented tests (dexmaker/byte-buddy-android backed). mockk-android = { group = "io.mockk", name = "mockk-android", version.ref = "mockk" } greenmail = { group = "com.icegreen", name = "greenmail", version.ref = "greenmail" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxJunit" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" } androidx-espresso-intents = { group = "androidx.test.espresso", name = "espresso-intents", version.ref = "espresso" } androidx-test-rules = { group = "androidx.test", name = "rules", version.ref = "androidxTestRules" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" } detekt = { id = "dev.detekt", version.ref = "detekt" }