diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/HttpClientFactory.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/HttpClientFactory.kt
deleted file mode 100644
index 4496d0d7de6169531a33e1305a7c692c93f288ab..0000000000000000000000000000000000000000
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/HttpClientFactory.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- *     Designed and developed in 2022-2024 by William Walker (wnwalker@ucsc.edu)
- *     Copyright 2022-2024 The Regents of the University of California. All rights reserved.
- *
- *     This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU Lesser General Public
- *     License as published by the Free Software Foundation; version 2.1 of the License.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *     Lesser General Public License for more details.
- *
- *     You should have received a copy of the GNU Lesser General Public
- *     License along with this library; if not, write to the Free Software
- *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-package edu.ucsc.its.temerity.core
-
-import edu.ucsc.its.temerity.TemClientConfig
-import edu.ucsc.its.temerity.core.Temerity.Companion.DEFAULT_WEB_TIMEOUT
-import io.ktor.client.HttpClient
-import io.ktor.client.HttpClientConfig
-import io.ktor.client.engine.HttpClientEngine
-import io.ktor.client.plugins.HttpTimeout
-import io.ktor.client.plugins.defaultRequest
-import io.ktor.client.plugins.logging.LogLevel
-import io.ktor.client.plugins.logging.Logging
-import io.ktor.client.request.header
-import io.ktor.http.URLProtocol
-import org.koin.core.context.GlobalContext.get
-import org.koin.core.parameter.parametersOf
-import kotlin.time.DurationUnit
-import co.touchlab.kermit.Logger as KermitLogger
-import io.ktor.client.plugins.logging.Logger as KtorLogger
-/**
- * Factory providing web request clients for the Temerity client.
- * Adapted from the tmdb-api project: https://github.com/MoviebaseApp/tmdb-kotlin/raw/refs/heads/main/tmdb-api/src/commonMain/kotlin/app/moviebase/tmdb/core/HttpClientFactory.kt
- */
-internal object HttpClientFactory {
-  /**
-   * Adapted from https://github.com/joreilly/FantasyPremierLeague/
-   * This function creates an HttpClient with the provided HttpClientEngine.
-   * The HttpClientEngine is injected by the Koin platformModule(), which as its name suggests provides an HttpClientEngine implementation that is platform-dependent.
-   * It configures the client to log all requests and responses if enableNetworkLogs is true. TODO: read this as a build setting
-   * It also sets a default request header with the provided authToken.
-   * @param httpClientEngine The HttpClientEngine to use for the HttpClient.
-   * @param config A block specifying the following options:
-   *  - Whether to log all requests and responses.
-   *  - Service URL to make requests to.
-   *  - Token to set as a default request header.
-   * @return The created HttpClient.
-   */
-  internal fun buildHttpClient(
-    httpClientEngine: HttpClientEngine,
-    config: TemClientConfig,
-  ): HttpClient {
-    val defaultConfig: HttpClientConfig<*>.() -> Unit = {
-      // Can't use install(ContentNegotiation){ json() } here because YuJa's API returns a 406 error if the Accept header is set to application/json
-      // This requires JSON transformations to be done via manually-called library functions
-
-      // Pass the stored authToken as a header in every request
-      defaultRequest {
-        header("authToken", config.serviceToken)
-        url {
-          protocol = URLProtocol.HTTPS
-        }
-      }
-
-      if (config.optDebugEnabled) {
-        when (config.httpClientLoggingBlock) {
-          null -> {
-            install(Logging) {
-              val kermit = get().get<KermitLogger> { parametersOf(null, config) }
-              logger = object : KtorLogger {
-                override fun log(message: String) {
-                  kermit.d(message)
-                }
-              }
-              level = LogLevel.ALL
-              sanitizeHeader { headerKey ->
-                headerKey == "authToken"
-              }
-            }
-          }
-          else -> {
-            config.httpClientLoggingBlock?.let {
-              Logging(it)
-            }
-          }
-        }
-      }
-
-      expectSuccess = config.expectSuccess
-
-      if (config.useWebTimeout) {
-        val defaultWebTimeout = DEFAULT_WEB_TIMEOUT.toLong(DurationUnit.MILLISECONDS)
-        val configuredWebTimeout = config.webTimeout?.toLong(DurationUnit.MILLISECONDS)
-        install(HttpTimeout) {
-          connectTimeoutMillis = configuredWebTimeout ?: defaultWebTimeout
-          requestTimeoutMillis = configuredWebTimeout ?: defaultWebTimeout
-          socketTimeoutMillis = configuredWebTimeout ?: defaultWebTimeout
-        }
-      }
-
-      config.httpClientConfigBlock?.invoke(this)
-    }
-    return config.httpClientBuilder?.invoke()?.config(defaultConfig) ?: HttpClient(httpClientEngine, defaultConfig)
-  }
-}
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/KoinAppFactory.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/KoinAppFactory.kt
deleted file mode 100644
index f0f4c01a323ffd8e4700c0e455044e8a50127db2..0000000000000000000000000000000000000000
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/KoinAppFactory.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *     Designed and developed in 2022-2024 by William Walker (wnwalker@ucsc.edu)
- *     Copyright 2022-2024 The Regents of the University of California. All rights reserved.
- *
- *     This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU Lesser General Public
- *     License as published by the Free Software Foundation; version 2.1 of the License.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *     Lesser General Public License for more details.
- *
- *     You should have received a copy of the GNU Lesser General Public
- *     License along with this library; if not, write to the Free Software
- *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-package edu.ucsc.its.temerity.core
-
-import edu.ucsc.its.temerity.di.libModule
-import edu.ucsc.its.temerity.di.loggerModule
-import edu.ucsc.its.temerity.platformModule
-import org.koin.core.Koin
-import org.koin.core.KoinApplication
-import org.koin.dsl.koinApplication
-
-/**
- * Factory providing a Koin application for the Temerity library.
- */
-internal object KoinAppFactory {
-  /**
-   * This function initializes the Koin dependency injection framework
-   */
-  internal fun createKoinApp() = object : TemerityKoinContext() {
-    override val koinApp = koinApplication {
-      modules(
-        loggerModule(),
-        platformModule(),
-        libModule,
-      )
-    }
-    override val koin: Koin = koinApp.koin
-  }
-}
-
-internal abstract class TemerityKoinContext {
-  abstract val koinApp: KoinApplication
-  abstract val koin: Koin
-}
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.kt
deleted file mode 100644
index 322862cb26f5553f052746e1f8c6770f4cf54fba..0000000000000000000000000000000000000000
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *     Designed and developed in 2022-2024 by William Walker (wnwalker@ucsc.edu)
- *     Copyright 2022-2024 The Regents of the University of California. All rights reserved.
- *
- *     This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU Lesser General Public
- *     License as published by the Free Software Foundation; version 2.1 of the License.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *     Lesser General Public License for more details.
- *
- *     You should have received a copy of the GNU Lesser General Public
- *     License along with this library; if not, write to the Free Software
- *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-package edu.ucsc.its.temerity.core
-
-import co.touchlab.kermit.CommonWriter
-import co.touchlab.kermit.Logger
-import co.touchlab.kermit.NoTagFormatter
-import co.touchlab.kermit.Severity
-import co.touchlab.kermit.loggerConfigInit
-import co.touchlab.kermit.platformLogWriter
-
-internal object LoggerFactory {
-
-  internal fun createLogger(tag: String?, supportKtxNotebook: Boolean): Logger = Logger(
-    config = loggerConfigInit(
-      if (supportKtxNotebook) CommonWriter(NoTagFormatter) else platformLogWriter(NoTagFormatter),
-      minSeverity = Severity.Debug,
-    ),
-    tag = tag ?: "TemerityLib",
-  )
-}
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt
index 71b6a69b02e3e5d28374df57b7db51c105122bd0..708245830dde61a447015132b5545dc7c7cad2fb 100644
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt
+++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt
@@ -17,19 +17,29 @@
  */
 package edu.ucsc.its.temerity.core
 
+import co.touchlab.kermit.CommonWriter
+import co.touchlab.kermit.NoTagFormatter
+import co.touchlab.kermit.Severity
+import co.touchlab.kermit.loggerConfigInit
+import co.touchlab.kermit.platformLogWriter
 import co.touchlab.stately.collections.ConcurrentMutableMap
 import com.skydoves.sandwich.ApiResponse
 import com.skydoves.sandwich.StatusCode
 import com.skydoves.sandwich.getOrThrow
 import com.skydoves.sandwich.ktor.executeApiResponse
 import com.skydoves.sandwich.ktor.statusCode
+import com.skydoves.sandwich.ktorfit.ApiResponseConverterFactory
 import com.skydoves.sandwich.onSuccess
+import de.jensklingenberg.ktorfit.ktorfit
 import edu.ucsc.its.temerity.AuditLogSortOrder
 import edu.ucsc.its.temerity.BuildConfig
 import edu.ucsc.its.temerity.TemClientConfig
 import edu.ucsc.its.temerity.TemerityApi
 import edu.ucsc.its.temerity.api.PlatformApi
+import edu.ucsc.its.temerity.api.createPlatformApi
+import edu.ucsc.its.temerity.core.DispatcherFactory.createLibraryScope
 import edu.ucsc.its.temerity.core.JsonFactory.buildJson
+import edu.ucsc.its.temerity.core.Temerity.Companion.DEFAULT_WEB_TIMEOUT
 import edu.ucsc.its.temerity.createJobScope
 import edu.ucsc.its.temerity.extensions.applyAuditLogFormat
 import edu.ucsc.its.temerity.extensions.applyScheduledSessionDateFormat
@@ -45,8 +55,18 @@ import edu.ucsc.its.temerity.model.User
 import edu.ucsc.its.temerity.model.UserGroup
 import edu.ucsc.its.temerity.model.UserRecordingSession
 import edu.ucsc.its.temerity.model.UserUpdate
+import edu.ucsc.its.temerity.platformModule
 import edu.ucsc.its.temerity.sortByCreationDate
+import io.ktor.client.HttpClient
+import io.ktor.client.HttpClientConfig
+import io.ktor.client.engine.HttpClientEngine
+import io.ktor.client.plugins.HttpTimeout
+import io.ktor.client.plugins.defaultRequest
+import io.ktor.client.plugins.logging.LogLevel
+import io.ktor.client.plugins.logging.Logging
+import io.ktor.client.request.header
 import io.ktor.client.statement.HttpResponse
+import io.ktor.http.URLProtocol
 import io.ktor.util.cio.toByteArray
 import io.ktor.utils.io.ByteReadChannel
 import kotlinx.coroutines.CoroutineScope
@@ -60,13 +80,25 @@ import kotlinx.serialization.SerializationException
 import kotlinx.serialization.encodeToString
 import kotlinx.serialization.json.Json
 import org.koin.core.Koin
+import org.koin.core.KoinApplication
 import org.koin.core.component.KoinComponent
 import org.koin.core.component.get
 import org.koin.core.context.GlobalContext.get
+import org.koin.core.logger.Level
+import org.koin.core.logger.Level.DEBUG
+import org.koin.core.logger.Level.ERROR
+import org.koin.core.logger.Level.INFO
+import org.koin.core.logger.Level.NONE
+import org.koin.core.logger.Level.WARNING
+import org.koin.core.logger.MESSAGE
 import org.koin.core.parameter.parametersOf
+import org.koin.dsl.koinApplication
+import org.koin.dsl.module
 import kotlin.time.Duration
 import kotlin.time.Duration.Companion.minutes
+import kotlin.time.DurationUnit
 import co.touchlab.kermit.Logger as KermitLogger
+import io.ktor.client.plugins.logging.Logger as KtorLogger
 
 /*
  * Adapted from https://github.com/santimattius/kmp-networking/blob/main/README.md
@@ -86,12 +118,77 @@ public class Temerity internal constructor(
     // TODO: Use this as cache4k expiration time
     public val DEFAULT_CACHE_EXPIRATION: Duration = 15.minutes
     internal const val DEFAULT_MINIMUM_THREAD_COUNT: Int = 2
+
+    internal fun createLogger(tag: String?, supportKtxNotebook: Boolean = false): co.touchlab.kermit.Logger =
+      co.touchlab.kermit.Logger(
+        config = loggerConfigInit(
+          if (supportKtxNotebook) CommonWriter(NoTagFormatter) else platformLogWriter(NoTagFormatter),
+          minSeverity = Severity.Debug,
+        ),
+        tag = tag ?: "TemerityLib",
+      )
+  }
+
+  /**
+   * This function provides the Koin module for the Temerity library.
+   * It includes the platform module and provides factories for [HttpClient] and [PlatformApi].
+   */
+  internal val libModule = module {
+    factory { (config: TemClientConfig, kermit: co.touchlab.kermit.Logger) ->
+      buildHttpClient(
+        httpClientEngine = get(),
+        config = config,
+        logger = kermit,
+      )
+    }
+    factory { (config: TemClientConfig) ->
+      val client: HttpClient = get { parametersOf(config) }
+      val ktorfit = ktorfit {
+        config.serviceUrl?.let { baseUrl(it) }
+        httpClient(client)
+        converterFactories(ApiResponseConverterFactory.create())
+      }
+      ktorfit.createPlatformApi()
+    }
+    single { (threadCount: Int) ->
+      createLibraryScope(threadCount)
+    }
+  }
+
+  /**
+   * This function initializes the Koin dependency injection framework
+   */
+  private fun createKoinApp() = object : TemerityKoinContext() {
+    val logger = createLogger("TemerityLib")
+    override val koinApp = koinApplication {
+      logger(object : org.koin.core.logger.Logger() {
+        override fun display(level: Level, msg: MESSAGE) {
+          when (level) {
+            DEBUG -> logger.d(msg)
+            INFO -> logger.i(msg)
+            ERROR -> logger.e(msg)
+            NONE -> logger.v(msg)
+            WARNING -> logger.w(msg)
+          }
+        }
+      })
+      modules(
+        platformModule(),
+        libModule,
+      )
+    }
+    override val koin: Koin = koinApp.koin
+  }
+
+  internal abstract class TemerityKoinContext {
+    abstract val koinApp: KoinApplication
+    abstract val koin: Koin
   }
 
   override fun version(): String = BuildConfig.LIB_VERSION
 
   private val json: Json = buildJson()
-  internal val koinContext = KoinAppFactory.createKoinApp()
+  internal val koinContext = createKoinApp()
   override fun getKoin(): Koin = koinContext.koin
 
   private var platformApi: PlatformApi
@@ -428,6 +525,77 @@ public class Temerity internal constructor(
     platformApi.getStorageAnalyticsReport(groupId).executeApiResponse<ByteReadChannel>().getOrThrow().toByteArray(limit = 2000000000) // Limit file downloads to 2 GB
 }
 
+/**
+ * Adapted from https://github.com/joreilly/FantasyPremierLeague/
+ * Adapted from the tmdb-api project: https://github.com/MoviebaseApp/tmdb-kotlin/raw/refs/heads/main/tmdb-api/src/commonMain/kotlin/app/moviebase/tmdb/core/HttpClientFactory.kt
+ * This function creates an HttpClient with the provided HttpClientEngine.
+ * The HttpClientEngine is injected by the Koin platformModule(), which as its name suggests provides an HttpClientEngine implementation that is platform-dependent.
+ * It configures the client to log all requests and responses if enableNetworkLogs is true. TODO: read this as a build setting
+ * It also sets a default request header with the provided authToken.
+ * @param httpClientEngine The HttpClientEngine to use for the HttpClient.
+ * @param config A block specifying the following options:
+ *  - Whether to log all requests and responses.
+ *  - Service URL to make requests to.
+ *  - Token to set as a default request header.
+ * @return The created HttpClient.
+ */
+internal fun buildHttpClient(
+  httpClientEngine: HttpClientEngine,
+  config: TemClientConfig,
+  logger: co.touchlab.kermit.Logger,
+): HttpClient {
+  val defaultConfig: HttpClientConfig<*>.() -> Unit = {
+    // Can't use install(ContentNegotiation){ json() } here because YuJa's API returns a 406 error if the Accept header is set to application/json
+    // This requires JSON transformations to be done via manually-called library functions
+
+    // Pass the stored authToken as a header in every request
+    defaultRequest {
+      header("authToken", config.serviceToken)
+      url {
+        protocol = URLProtocol.HTTPS
+      }
+    }
+
+    if (config.optDebugEnabled) {
+      when (config.httpClientLoggingBlock) {
+        null -> {
+          install(Logging) {
+            this.logger = object : KtorLogger {
+              override fun log(message: String) {
+                logger.d(message)
+              }
+            }
+            level = LogLevel.ALL
+            sanitizeHeader { headerKey ->
+              headerKey == "authToken"
+            }
+          }
+        }
+        else -> {
+          config.httpClientLoggingBlock?.let {
+            Logging(it)
+          }
+        }
+      }
+    }
+
+    expectSuccess = config.expectSuccess
+
+    if (config.useWebTimeout) {
+      val defaultWebTimeout = DEFAULT_WEB_TIMEOUT.toLong(DurationUnit.MILLISECONDS)
+      val configuredWebTimeout = config.webTimeout?.toLong(DurationUnit.MILLISECONDS)
+      install(HttpTimeout) {
+        connectTimeoutMillis = configuredWebTimeout ?: defaultWebTimeout
+        requestTimeoutMillis = configuredWebTimeout ?: defaultWebTimeout
+        socketTimeoutMillis = configuredWebTimeout ?: defaultWebTimeout
+      }
+    }
+
+    config.httpClientConfigBlock?.invoke(this)
+  }
+  return config.httpClientBuilder?.invoke()?.config(defaultConfig) ?: HttpClient(httpClientEngine, defaultConfig)
+}
+
 /**
  * Create a Temerity instance using Kotlin-DSL.
  */
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/Koin.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/Koin.kt
deleted file mode 100644
index 00a414a01fa210c10bcc3d12e6aaa42830fc014a..0000000000000000000000000000000000000000
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/Koin.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *     Designed and developed in 2022-2024 by William Walker (wnwalker@ucsc.edu)
- *     Copyright 2022-2024 The Regents of the University of California. All rights reserved.
- *
- *     This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU Lesser General Public
- *     License as published by the Free Software Foundation; version 2.1 of the License.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *     Lesser General Public License for more details.
- *
- *     You should have received a copy of the GNU Lesser General Public
- *     License along with this library; if not, write to the Free Software
- *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-package edu.ucsc.its.temerity.di
-
-import com.skydoves.sandwich.ktorfit.ApiResponseConverterFactory
-import de.jensklingenberg.ktorfit.ktorfit
-import edu.ucsc.its.temerity.TemClientConfig
-import edu.ucsc.its.temerity.api.PlatformApi
-import edu.ucsc.its.temerity.api.createPlatformApi
-import edu.ucsc.its.temerity.core.DispatcherFactory.createLibraryScope
-import edu.ucsc.its.temerity.core.HttpClientFactory.buildHttpClient
-import edu.ucsc.its.temerity.core.LoggerFactory.createLogger
-import io.ktor.client.HttpClient
-import org.koin.core.parameter.parametersOf
-import org.koin.dsl.module
-
-internal fun loggerModule() = module {
-  factory<co.touchlab.kermit.Logger> { (tag: String?, config: TemClientConfig) ->
-    createLogger(tag, config.supportKtxNotebook)
-  }
-}
-
-/**
- * This function provides the Koin module for the Temerity library.
- * It includes the platform module and provides factories for [HttpClient] and [PlatformApi].
- */
-internal val libModule = module {
-  factory { (config: TemClientConfig) ->
-    buildHttpClient(
-      httpClientEngine = get(),
-      config = config,
-    )
-  }
-  factory { (config: TemClientConfig) ->
-    val client: HttpClient = get { parametersOf(config) }
-    val ktorfit = ktorfit {
-      config.serviceUrl?.let { baseUrl(it) }
-      httpClient(client)
-      converterFactories(ApiResponseConverterFactory.create())
-    }
-    ktorfit.createPlatformApi()
-  }
-  single { (threadCount: Int) ->
-    createLibraryScope(threadCount)
-  }
-}
diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt
index b40a4a98607b600e61a43092f05d73aeb75588d6..6c385a94cadaffe14fc106e14d1bda14d5092a96 100644
--- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt
+++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt
@@ -21,6 +21,7 @@ import co.touchlab.kermit.Logger
 import com.skydoves.sandwich.StatusCode
 import com.skydoves.sandwich.ktor.getStatusCode
 import edu.ucsc.its.temerity.core.Temerity
+import edu.ucsc.its.temerity.core.Temerity.Companion.createLogger
 import edu.ucsc.its.temerity.model.NewUser
 import edu.ucsc.its.temerity.model.UserUpdate
 import io.kotest.core.spec.style.FunSpec
@@ -33,6 +34,7 @@ class DevUserApiTests :
   FunSpec({
 
     val dotenv = dotenvVault()
+    val kermit = createLogger("DevUserApiTests")
 
     lateinit var testTemerity: Temerity
     beforeTest {
@@ -45,7 +47,7 @@ class DevUserApiTests :
       runBlocking {
         val returnedUsers = testTemerity.getUsers()
         println("Returned users:")
-        returnedUsers.forEach { Logger.d(it.toString()) }
+        returnedUsers.forEach { kermit.d(it.toString()) }
         assert(returnedUsers.isNotEmpty())
       }
     }
diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUtilityTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUtilityTests.kt
index df9b3ff7a6937b24947f031df55ea9abd0f28fae..4dbaee47333853244df68ab3a2b2afe5be12fa9d 100644
--- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUtilityTests.kt
+++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUtilityTests.kt
@@ -17,23 +17,18 @@
  */
 package edu.ucsc.its.temerity.test
 
-import co.touchlab.kermit.Logger
 import edu.ucsc.its.temerity.core.Temerity
-import edu.ucsc.its.temerity.di.loggerModule
-import io.kotest.core.extensions.Extension
+import edu.ucsc.its.temerity.core.Temerity.Companion.createLogger
 import io.kotest.core.spec.style.FunSpec
 import org.dotenv.vault.dotenvVault
-import org.koin.core.parameter.parametersOf
 import org.koin.test.KoinTest
-import org.koin.test.inject
 import kotlin.time.Duration.Companion.minutes
 
 class DevUtilityTests :
   FunSpec(),
   KoinTest {
 
-  override fun extensions(): List<Extension> = listOf(koinExtension(loggerModule()))
-  private val kermit: Logger by inject { parametersOf("DevUtilityTests") }
+  private val kermit = createLogger("DevUtilityTests")
 
   init {
     coroutineDebugProbes = true
diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt
index 7dd2e2af56f74835c7629cb7da6faa6e0a9cf462..00f46e94e7185ea562e81f324f89c8f33329c901 100644
--- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt
+++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt
@@ -18,8 +18,8 @@
 package edu.ucsc.its.temerity.test
 import edu.ucsc.its.temerity.AuditLogSortOrder.NEW_FIRST
 import edu.ucsc.its.temerity.core.Temerity
+import edu.ucsc.its.temerity.core.Temerity.Companion.createLogger
 import edu.ucsc.its.temerity.currentDate
-import edu.ucsc.its.temerity.di.loggerModule
 import edu.ucsc.its.temerity.model.EventType.AUTOMATED_SESSION_FAILED_TO_START
 import edu.ucsc.its.temerity.model.EventType.AUTOMATED_SESSION_MONITOR
 import edu.ucsc.its.temerity.model.EventType.CAPTURE_ERROR
@@ -31,7 +31,6 @@ import edu.ucsc.its.temerity.model.EventType.HDCP_SIGNAL_DETECTED
 import edu.ucsc.its.temerity.model.EventType.HUB_CAPTURE_PROBLEM
 import edu.ucsc.its.temerity.model.EventType.NEW_LOG_IN
 import edu.ucsc.its.temerity.model.EventType.RECORDING_ERROR
-import io.kotest.core.extensions.Extension
 import io.kotest.core.spec.style.FunSpec
 import io.kotest.matchers.file.shouldNotBeEmpty
 import kotlinx.coroutines.runBlocking
@@ -43,9 +42,7 @@ import kotlinx.datetime.todayIn
 import org.dotenv.vault.dotenvVault
 import org.jetbrains.kotlinx.dataframe.api.toDataFrame
 import org.jetbrains.kotlinx.dataframe.io.writeCSV
-import org.koin.core.parameter.parametersOf
 import org.koin.test.KoinTest
-import org.koin.test.inject
 import java.io.File
 import kotlin.time.Duration.Companion.minutes
 import kotlin.uuid.ExperimentalUuidApi
@@ -57,8 +54,7 @@ class ProdReportTests :
   FunSpec(),
   KoinTest {
 
-  override fun extensions(): List<Extension> = listOf(koinExtension(loggerModule()))
-  private val kermit: KermitLogger by inject { parametersOf("ProdReportTests") }
+  private val kermit: KermitLogger = createLogger("TemerityDevTest")
 
   init {
     coroutineDebugProbes = true
@@ -66,7 +62,7 @@ class ProdReportTests :
     val dotenv = dotenvVault()
 
     lateinit var testTemerity: Temerity
-    val today = Clock.System.todayIn(TimeZone.currentSystemDefault())
+    val today = currentDate()
 
     beforeTest {
       testTemerity = Temerity {
diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdUtilityTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdUtilityTests.kt
index 098fb938d396ebffb480cc5b031e4ee369ba3b53..222d15af6cb85c07520c1e5e43616b508cf93197 100644
--- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdUtilityTests.kt
+++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdUtilityTests.kt
@@ -17,24 +17,16 @@
  */
 package edu.ucsc.its.temerity.test
 
-import co.touchlab.kermit.Logger
 import edu.ucsc.its.temerity.core.Temerity
-import edu.ucsc.its.temerity.di.loggerModule
-import io.kotest.core.extensions.Extension
 import io.kotest.core.spec.style.FunSpec
 import org.dotenv.vault.dotenvVault
-import org.koin.core.parameter.parametersOf
 import org.koin.test.KoinTest
-import org.koin.test.inject
 import kotlin.time.Duration.Companion.minutes
 
 class ProdUtilityTests :
   FunSpec(),
   KoinTest {
 
-  override fun extensions(): List<Extension> = listOf(koinExtension(loggerModule()))
-  private val kermit: Logger by inject { parametersOf("ProdUtilityTests") }
-
   init {
     coroutineDebugProbes = true
 
diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/TemerityDevTest.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/TemerityDevTest.kt
index ebb5510d033c25c3e2fd05683486df89168c01e9..95d28429589872961b83c7dde363e728975b9ab2 100644
--- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/TemerityDevTest.kt
+++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/TemerityDevTest.kt
@@ -24,12 +24,10 @@ import edu.ucsc.its.temerity.AuditLogSortOrder.NEW_FIRST
 import edu.ucsc.its.temerity.core.TemClientConfig
 import edu.ucsc.its.temerity.core.Temerity
 import edu.ucsc.its.temerity.currentDate
-import edu.ucsc.its.temerity.di.loggerModule
 import edu.ucsc.its.temerity.model.EventType.NEW_LOG_IN
 import edu.ucsc.its.temerity.model.NewUser
 import io.github.z4kn4fein.semver.Version
 import io.github.z4kn4fein.semver.toVersion
-import io.kotest.core.extensions.Extension
 import io.kotest.core.spec.style.FunSpec
 import io.kotest.matchers.file.shouldNotBeEmpty
 import io.kotest.matchers.shouldBe
@@ -52,7 +50,6 @@ class TemerityDevTest :
   FunSpec(),
   KoinTest {
 
-  override fun extensions(): List<Extension> = listOf(koinExtension(loggerModule()))
   private lateinit var kermit: Logger
 
   init {