plugins { // AGP must apply before recipe.kotlin.multiplatform — the latter calls androidTarget(), // which requires the Android Gradle Plugin to already be on the project. alias(libs.plugins.androidApplication) id("recipe.kotlin.multiplatform") alias(libs.plugins.composeMultiplatform) alias(libs.plugins.composeCompiler) alias(libs.plugins.composeHotReload) alias(libs.plugins.kotlinSerialization) id("recipe.quality") } // `group` is referenced by Compose Resources package naming — the // `compose.resources { packageOfResClass }` block below pins the historical package // regardless, but keep `group` set explicitly. Gradle artifact metadata only. group = "dev.ulfrx.recipe" version = "1.0.0" android { namespace = "dev.ulfrx.recipe" compileSdk = libs.versions.android.compileSdk .get() .toInt() defaultConfig { applicationId = "dev.ulfrx.recipe" minSdk = libs.versions.android.minSdk .get() .toInt() targetSdk = libs.versions.android.targetSdk .get() .toInt() versionCode = 1 versionName = "1.0" // AppAuth-Android (D-01) bundles a manifest entry for its // `RedirectUriReceiverActivity` that requires `${appAuthRedirectScheme}` to be // resolved at merge time. Pin it to the Phase 2 redirect scheme so simply // pulling AppAuth into the classpath (Plan 02-01) doesn't break AGP's manifest // merger before Plan 02-04 lands the full `` registration. // Must match `dev.ulfrx.recipe.shared.Constants.OIDC_REDIRECT_URI` byte-for-byte. manifestPlaceholders["appAuthRedirectScheme"] = "recipe" } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } } buildTypes { getByName("release") { isMinifyEnabled = false } } compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } } kotlin { sourceSets { commonMain.dependencies { implementation(project.dependencies.platform(libs.koin.bom)) implementation(libs.koin.core) implementation(libs.koin.compose) implementation(libs.koin.composeViewmodel) implementation(libs.kermit) implementation(libs.compose.runtime) implementation(libs.compose.foundation) implementation(libs.compose.material3) implementation(libs.compose.ui) implementation(libs.compose.components.resources) implementation(libs.compose.uiToolingPreview) implementation(libs.androidx.lifecycle.viewmodelCompose) implementation(libs.androidx.lifecycle.runtimeCompose) // `api` so `:shared` types (notably `Constants`) flow through to the // exported ObjC framework headers — the iOS Swift bridge needs them. api(projects.shared) // Phase 2: Ktor client + serialization + secure settings (D-13, D-16, D-17). // The MPP variant of `ktor-serialization-kotlinx-json` is required here; the // server module keeps the `-jvm` variant via `libs.ktor.serializationKotlinxJson`. implementation(libs.ktor.clientCore) implementation(libs.ktor.clientAuth) implementation(libs.ktor.clientContentNegotiation) implementation(libs.ktor.clientLogging) implementation(libs.ktor.serializationKotlinxJsonMpp) implementation(libs.kotlinx.serializationJson) implementation(libs.multiplatform.settings) implementation(libs.multiplatform.settings.coroutines) } commonTest.dependencies { // 02-07: kotlinx.coroutines.test.runTest is the multiplatform-safe // alternative to runBlocking (which is JVM/Native-only and breaks the // wasmJs test target). All commonTest coroutine tests use it. implementation(libs.kotlinx.coroutinesTest) } androidMain.dependencies { implementation(libs.compose.uiToolingPreview) implementation(libs.androidx.activity.compose) implementation(libs.koin.android) // Phase 2 Android: AppAuth-Android + AndroidX Security Crypto for the // SecureAuthStateStore actual (D-01, D-13). EncryptedSharedPreferences is // accepted technical debt per Open Question #1; the Keystore-backed // implementation can replace it without touching AuthSession. implementation(libs.appauth) implementation(libs.androidx.security.crypto) implementation(libs.ktor.clientOkhttp) } iosMain.dependencies { // Phase 2 iOS: Darwin engine for Ktor. AppAuth-iOS is delivered via // SwiftPM in iosApp.xcodeproj and consumed through a Swift bridge — // no Kotlin-side AppAuth dependency (DECISION-drop-cocoapods, 2026-04-28). implementation(libs.ktor.clientDarwin) } jvmMain.dependencies { implementation(compose.desktop.currentOs) implementation(libs.kotlinx.coroutinesSwing) // Phase 2 Desktop: CIO is the JVM Ktor engine for the dev-mode auth stub // (D-02). The full stub lives in Plan 02-04; this just makes the engine // available so `composeApp:run` still compiles in Phase 2. implementation(libs.ktor.clientCio) } } } dependencies { debugImplementation(libs.compose.uiTooling) } // `group = "dev.ulfrx.recipe"` shifts the Compose Resources `Res` class package from // `recipe.composeapp.generated.resources` to `dev.ulfrx.recipe.composeapp.generated.resources`, // breaking the Phase 1 `App.kt` import. Lock the historical package so module-naming // changes don't cascade into UI code. compose.resources { packageOfResClass = "recipe.composeapp.generated.resources" }