diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts
index a7029afc90f32e9216bd7913df3fbb256adfe40a..b7a239d6292ca1e41d8cb48a041e90f5403dacb1 100644
--- a/build-logic/build.gradle.kts
+++ b/build-logic/build.gradle.kts
@@ -1,6 +1,24 @@
+/*
+ *     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
+ */
 plugins {
     `kotlin-dsl`
     `kotlin-dsl-precompiled-script-plugins`
+    alias(libs.plugins.spotless)
 }
 
 dependencies {
@@ -9,6 +27,59 @@ dependencies {
     implementation(libs.build.gitSemVer)
 }
 
+kotlin {
+    target {
+        compilations.configureEach {
+            kotlinOptions {
+                jvmToolchain(libs.versions.java.get().toInt())
+            }
+        }
+    }
+}
+
+gradlePlugin {
+    plugins {
+        register("formatting-convention") {
+            id = "temerity.formatting-convention"
+            implementationClass = "edu.ucsc.its.temerity.buildlogic.convention.FormattingConventionPlugin"
+        }
+    }
+    plugins {
+        register("publication-convention") {
+            id = "temerity.publication-convention"
+            implementationClass = "edu.ucsc.its.temerity.buildlogic.convention.PublicationConventionPlugin"
+        }
+    }
+    plugins {
+        register("version-convention") {
+            id = "temerity.version-convention"
+            implementationClass = "edu.ucsc.its.temerity.buildlogic.convention.VersionConventionPlugin"
+        }
+    }
+}
+
+spotless {
+    kotlin {
+        target("**/*.kt")
+        targetExclude("${project.layout.buildDirectory}/**/*.kt")
+        ktlint().editorConfigOverride(
+            mapOf(
+                "indent_size" to "2",
+                "continuation_indent_size" to "2",
+            )
+        )
+        licenseHeaderFile(file("../spotless/LicenseHeader.kt"))
+        trimTrailingWhitespace()
+        endWithNewline()
+    }
+    format("kts") {
+        target("**/*.kts")
+        targetExclude("${project.layout.buildDirectory}/**/*.kts")
+        licenseHeaderFile(file("../spotless/LicenseHeader.kt"), "(^(?![\\/ ]\\*).*$)")
+        trimTrailingWhitespace()
+        endWithNewline()
+    }
+}
 
 // Excerpt from Project kt-fuzzy licensed under the MIT license
 // By github.com/solo-studios, author solonovamax. See NOTICE file.
@@ -18,14 +89,3 @@ fun gradlePlugin(id: Provider<PluginDependency>, version: Provider<String>): Str
     val pluginId = id.get().pluginId
     return "$pluginId:$pluginId.gradle.plugin:${version.get()}"
 }
-
-
-kotlin {
-    target {
-        compilations.configureEach {
-            kotlinOptions {
-                jvmToolchain(libs.versions.java.get().toInt())
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts
index 030b00897134503fe14d2bb0049a47dd1380f8ab..0d67e312ab086538cb490dd4336d7d19e4e3c3ac 100644
--- a/build-logic/settings.gradle.kts
+++ b/build-logic/settings.gradle.kts
@@ -1,3 +1,20 @@
+/*
+ *     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
+ */
 @file:Suppress("UnstableApiUsage")
 
 rootProject.name = "build-logic"
@@ -15,4 +32,4 @@ dependencyResolutionManagement {
             from(files("../gradle/libs.versions.toml"))
         }
     }
-}
\ No newline at end of file
+}
diff --git a/build-logic/src/main/kotlin/convention.formatting.gradle.kts b/build-logic/src/main/kotlin/convention.formatting.gradle.kts
deleted file mode 100644
index 29f76de5f911b2e0b4c0e6412953d9496f8b1785..0000000000000000000000000000000000000000
--- a/build-logic/src/main/kotlin/convention.formatting.gradle.kts
+++ /dev/null
@@ -1,26 +0,0 @@
-plugins {
-    id("com.diffplug.spotless")
-}
-
-spotless {
-    kotlin {
-        target("**/*.kt")
-        targetExclude("${layout.buildDirectory}/**/*.kt")
-        ktlint().editorConfigOverride(
-            mapOf(
-                "indent_size" to "2",
-                "continuation_indent_size" to "2",
-            )
-        )
-        licenseHeaderFile(rootProject.file("spotless/libHeader.kt"))
-        trimTrailingWhitespace()
-        endWithNewline()
-    }
-    format("kts") {
-        target("**/*.kts")
-        targetExclude("${layout.buildDirectory}/**/*.kts")
-        licenseHeaderFile(rootProject.file("spotless/libHeader.kt"), "(^(?![\\/ ]\\*).*$)")
-        trimTrailingWhitespace()
-        endWithNewline()
-    }
-}
\ No newline at end of file
diff --git a/build-logic/src/main/kotlin/convention.publication.gradle.kts b/build-logic/src/main/kotlin/convention.publication.gradle.kts
deleted file mode 100644
index 260041957d6228b507e11a6f11163cc8e57f5567..0000000000000000000000000000000000000000
--- a/build-logic/src/main/kotlin/convention.publication.gradle.kts
+++ /dev/null
@@ -1,48 +0,0 @@
-//Publishing your Kotlin Multiplatform library to Maven Central
-//https://dev.to/kotlin/how-to-build-and-publish-a-kotlin-multiplatform-library-going-public-4a8k
-
-import org.gradle.api.publish.maven.MavenPublication
-import org.gradle.api.tasks.bundling.Jar
-import org.gradle.kotlin.dsl.`maven-publish`
-import org.gradle.kotlin.dsl.signing
-import java.util.*
-
-plugins {
-    id("maven-publish")
-    id("signing")
-}
-
-publishing {
-    // Configure maven repository
-    repositories {
-        maven {
-            name = "GitlabProjectRepository"
-            url = uri("https://git.ucsc.edu/api/v4/projects/12162/packages/maven")
-            credentials(HttpHeaderCredentials::class) {
-                name = "Job-Token"
-                value = System.getenv("CI_JOB_TOKEN")
-            }
-            authentication {
-                create("header", HttpHeaderAuthentication::class)
-            }
-        }
-    }
-}
-
-signing {
-    val signingKeyId: String? by project
-    val signingKey: String? by project
-    val signingPassword: String? by project
-    if (!signingKey.isNullOrEmpty()){
-        useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
-        publishing.publications {
-            sign(publishing.publications)
-        }
-    }
-}
-
-//https://github.com/gradle/gradle/issues/26132
-val signingTasks = tasks.withType<Sign>()
-tasks.withType<AbstractPublishToMaven>().configureEach {
-    mustRunAfter(signingTasks)
-}
\ No newline at end of file
diff --git a/build-logic/src/main/kotlin/convention.version.gradle.kts b/build-logic/src/main/kotlin/convention.version.gradle.kts
deleted file mode 100644
index 1d740e35091ba4fc2b69e8f5b5e05cd8f1fbfa90..0000000000000000000000000000000000000000
--- a/build-logic/src/main/kotlin/convention.version.gradle.kts
+++ /dev/null
@@ -1,7 +0,0 @@
-plugins {
-    id("org.danilopianini.git-sensitive-semantic-versioning")
-}
-
-gitSemVer {
-    maxVersionLength.set(20)
-}
diff --git a/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/FormattingConventionPlugin.kt b/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/FormattingConventionPlugin.kt
new file mode 100644
index 0000000000000000000000000000000000000000..4cb05356feddd63d524191e16d0538277869476a
--- /dev/null
+++ b/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/FormattingConventionPlugin.kt
@@ -0,0 +1,33 @@
+package edu.ucsc.its.temerity.buildlogic.convention
+
+import com.diffplug.gradle.spotless.SpotlessExtension
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+class FormattingConventionPlugin : Plugin<Project> {
+  override fun apply(project: Project) = with(project) {
+    pluginManager.apply("com.diffplug.spotless")
+    extensions.configure(SpotlessExtension::class.java) {
+      kotlin {
+        target("**/*.kt")
+        targetExclude("${layout.buildDirectory}/**/*.kt")
+        ktlint().editorConfigOverride(
+          mapOf(
+            "indent_size" to "2",
+            "continuation_indent_size" to "2",
+          ),
+        )
+        licenseHeaderFile(file("../spotless/LicenseHeader.kt"))
+        trimTrailingWhitespace()
+        endWithNewline()
+      }
+      format("kts") {
+        target("**/*.kts")
+        targetExclude("${layout.buildDirectory}/**/*.kts")
+        licenseHeaderFile(file("../spotless/LicenseHeader.kt"), "(^(?![\\/ ]\\*).*$)")
+        trimTrailingWhitespace()
+        endWithNewline()
+      }
+    }
+  }
+}
diff --git a/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/KmpConventionPlugin.kt b/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/KmpConventionPlugin.kt
new file mode 100644
index 0000000000000000000000000000000000000000..10bda6e35a811607a7d2a7dfd078d4195c98ff15
--- /dev/null
+++ b/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/KmpConventionPlugin.kt
@@ -0,0 +1,4 @@
+package edu.ucsc.its.temerity.buildlogic.convention
+
+class KmpConventionPlugin {
+}
diff --git a/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/PublicationConventionPlugin.kt b/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/PublicationConventionPlugin.kt
new file mode 100644
index 0000000000000000000000000000000000000000..13886f43166affdda8d741110d1354d0067cf29b
--- /dev/null
+++ b/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/PublicationConventionPlugin.kt
@@ -0,0 +1,75 @@
+/*
+ *     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.buildlogic.convention
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.credentials.HttpHeaderCredentials
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven
+import org.gradle.authentication.http.HttpHeaderAuthentication
+import org.gradle.kotlin.dsl.create
+import org.gradle.kotlin.dsl.credentials
+import org.gradle.kotlin.dsl.provideDelegate
+import org.gradle.kotlin.dsl.withType
+import org.gradle.plugins.signing.Sign
+import org.gradle.plugins.signing.SigningExtension
+import java.net.URI
+
+class PublicationConventionPlugin : Plugin<Project> {
+  override fun apply(project: Project) = with(project) {
+    pluginManager.apply("maven-publish")
+    extensions.configure(PublishingExtension::class.java) {
+      // Configure maven repository
+      repositories {
+        maven {
+          name = "GitlabProjectRepository"
+          url = URI("https://git.ucsc.edu/api/v4/projects/12162/packages/maven")
+          credentials(HttpHeaderCredentials::class) {
+            name = "Job-Token"
+            value = System.getenv("CI_JOB_TOKEN")
+          }
+          authentication {
+            create("header", HttpHeaderAuthentication::class)
+          }
+        }
+      }
+    }
+
+    pluginManager.apply("signing")
+    extensions.configure(SigningExtension::class.java) {
+      val signingKeyId: String? by project
+      val signingKey: String? by project
+      val signingPassword: String? by project
+      if (!signingKey.isNullOrEmpty()) {
+        useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
+        extensions.configure(PublishingExtension::class.java) {
+          val pubExt = this
+          publications {
+            sign(pubExt.publications)
+          }
+        }
+      }
+    }
+
+    val signingTasks = tasks.withType<Sign>()
+    tasks.withType<AbstractPublishToMaven>().configureEach {
+      mustRunAfter(signingTasks)
+    }
+  }
+}
diff --git a/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/VersionConventionPlugin.kt b/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/VersionConventionPlugin.kt
new file mode 100644
index 0000000000000000000000000000000000000000..54f82322fee06e19affb95eaa465ac09899a635f
--- /dev/null
+++ b/build-logic/src/main/kotlin/edu/ucsc/its/temerity/buildlogic/convention/VersionConventionPlugin.kt
@@ -0,0 +1,31 @@
+/*
+ *     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.buildlogic.convention
+
+import org.danilopianini.gradle.gitsemver.GitSemVerExtension
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+class VersionConventionPlugin : Plugin<Project> {
+  override fun apply(project: Project) = with(project) {
+    pluginManager.apply("org.danilopianini.git-sensitive-semantic-versioning")
+    extensions.configure(GitSemVerExtension::class.java) {
+      maxVersionLength.set(20)
+    }
+  }
+}
diff --git a/spotless/libHeader.kt b/spotless/LicenseHeader.kt
similarity index 99%
rename from spotless/libHeader.kt
rename to spotless/LicenseHeader.kt
index abf1bcf00a1c94a45c4a4da32a83637499845ea9..ad7271bc23a2838d8e7d8b3e9a61de9bfa2bceb6 100644
--- a/spotless/libHeader.kt
+++ b/spotless/LicenseHeader.kt
@@ -14,4 +14,4 @@
  *     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
- */
\ No newline at end of file
+ */
diff --git a/spotless/appHeader.kt b/spotless/appHeader.kt
deleted file mode 100644
index dd533b16d82499dfccbd78c595c1dc01f1586ec5..0000000000000000000000000000000000000000
--- a/spotless/appHeader.kt
+++ /dev/null
@@ -1,16 +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.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
\ No newline at end of file
diff --git a/spotless/appHeader.xml b/spotless/appHeader.xml
deleted file mode 100644
index 4dcfd18c07968cf26a0c871ed31dbaa1e9c0ede4..0000000000000000000000000000000000000000
--- a/spotless/appHeader.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    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.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
\ No newline at end of file
diff --git a/spotless/libHeader.xml b/spotless/libHeader.xml
deleted file mode 100644
index fac8567168d9f7bdfa1e85605791702396c8bd0e..0000000000000000000000000000000000000000
--- a/spotless/libHeader.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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
--->
\ No newline at end of file
diff --git a/temerity/build.gradle.kts b/temerity/build.gradle.kts
index 0ab804f4a3d9707799d5b0532699745587dce8ea..10e38070333cc5d56439413bf07b39930599db52 100644
--- a/temerity/build.gradle.kts
+++ b/temerity/build.gradle.kts
@@ -32,10 +32,10 @@ plugins {
     alias(libs.plugins.kotestMultiplatform)
     alias(libs.plugins.buildConfig)
 
-    id("convention.formatting")
-    id("convention.version")
+    id("temerity.formatting-convention")
+    id("temerity.version-convention")
     alias(libs.plugins.dokka)
-    id("convention.publication")
+    id("temerity.publication-convention")
 
     alias(libs.plugins.dataframe)
 
@@ -132,7 +132,7 @@ kotlin {
         val androidMain by getting {
             dependencies {
                 implementation(libs.ktor.client.android)
-                // TODO: Add slf4f-api
+                // TODO: Add logging for Android
             }
         }
         val jvmTest by getting {
diff --git a/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.android.kt b/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.android.kt
index bb98a1e554585bbdc31135f62c2040b2caac7e78..5e7ed34b3306cda5702f8a937b282346d9560c59 100644
--- a/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.android.kt
+++ b/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.android.kt
@@ -18,7 +18,6 @@
 package edu.ucsc.its.temerity.core
 
 import co.touchlab.kermit.Logger
-import edu.ucsc.its.temerity.TemClientConfig
 
 internal actual fun createCommonLogger(
   tag: String?,
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/TemerityApi.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/api/TemerityApi.kt
similarity index 93%
rename from temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/TemerityApi.kt
rename to temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/api/TemerityApi.kt
index cf4110f1d1ccd178aaa4965b05b9222c872ee3b1..04473d6eec4f31b9f8f64b716e1ec7c82fc57f16 100644
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/TemerityApi.kt
+++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/api/TemerityApi.kt
@@ -15,10 +15,12 @@
  *     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
+package edu.ucsc.its.temerity.api
 
 import edu.ucsc.its.temerity.extensions.datetime.DateTimeExt.currentDate
 import edu.ucsc.its.temerity.model.AuditLogEntry
+import edu.ucsc.its.temerity.model.AuditLogSortOrder
+import edu.ucsc.its.temerity.model.BuildVariant
 import edu.ucsc.its.temerity.model.Course
 import edu.ucsc.its.temerity.model.Device
 import edu.ucsc.its.temerity.model.DeviceRecordingSession
@@ -261,7 +263,7 @@ public interface TemerityApi {
   public suspend fun getCachedUserRoles(refresh: Boolean = true): List<String>
 }
 
-// Objects used by library consumers and re-implementations of the Temerity API spec
+// Properties used by library consumers and re-implementations of the Temerity API spec
 
 public val AUDIT_LOG_REQUEST_DATE_FORMAT: DateTimeFormat<LocalDate> = LocalDate.Format {
   dayOfMonth()
@@ -291,19 +293,6 @@ public val SCHEDULED_SESSION_DATE_FORMAT: DateTimeFormat<LocalDate> = LocalDate.
   year()
 }
 
-/**
- * Enum class used to define the sort order for audit log entries.
- */
-public enum class AuditLogSortOrder {
-  NEW_FIRST,
-  OLD_FIRST,
-  ;
-
-  public companion object {
-    public fun fromBoolean(value: Boolean): AuditLogSortOrder = if (value) NEW_FIRST else OLD_FIRST
-  }
-}
-
 /**
  * Sorts a list of [AuditLogEntry] objects by their creation date.
  * @param sortOrder The order in which to sort the entries.
@@ -314,21 +303,3 @@ public fun ArrayList<AuditLogEntry>.sortByCreationDate(sortOrder: AuditLogSortOr
     AuditLogSortOrder.OLD_FIRST -> sortBy { auditLogEntry -> auditLogEntry.creationTimestamp }
   }
 }
-
-/**
- * Enum class used to define the build variant of the library.
- * For debugging purposes.
- */
-public enum class BuildVariant(public val variant: String) {
-  RELEASE("RELEASE"),
-  DEBUG("DEBUG"),
-  ;
-
-  internal companion object {
-    internal fun of(variant: String): BuildVariant = when (variant) {
-      "RELEASE" -> RELEASE
-      "DEBUG" -> DEBUG
-      else -> throw IllegalArgumentException("Invalid build variant: $variant")
-    }
-  }
-}
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
index eae0e55d1ac6f140e52c3baaf6a6a7d94766233a..f92bc986b6b0051a6dea235dbc2997a761e30871 100644
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.kt
+++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.kt
@@ -18,7 +18,6 @@
 package edu.ucsc.its.temerity.core
 
 import co.touchlab.kermit.Logger
-import edu.ucsc.its.temerity.TemClientConfig
 
 internal object LoggerFactory {
   internal fun createLogger(tag: String?, config: TemClientConfig? = null, supportKtxNotebook: Boolean = false) = createCommonLogger(tag = tag, config = config, supportKtxNotebook = supportKtxNotebook)
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/TemClientConfig.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/TemClientConfig.kt
similarity index 88%
rename from temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/TemClientConfig.kt
rename to temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/TemClientConfig.kt
index 491f006cd23c7ba5e4e3b89a6dc90309ea65ef9b..4b2ef17f062902a894325c97f44f6ee2fdd809fa 100644
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/TemClientConfig.kt
+++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/TemClientConfig.kt
@@ -15,9 +15,8 @@
  *     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
+package edu.ucsc.its.temerity.core
 
-import edu.ucsc.its.temerity.core.TemDsl
 import io.ktor.client.HttpClient
 import io.ktor.client.HttpClientConfig
 import io.ktor.client.engine.HttpClientEngineConfig
@@ -35,8 +34,8 @@ import kotlin.time.Duration
  *
  * @property optExpectSuccess Specifies whether to expect successful responses by default
  * @property optUseWebTimeout Specifies whether to use a timeout  other than default for web requests
- * @property optWebTimeoutDuration Specifies the timeout [Duration] to use when making web requests
- * @property optCacheTimeoutDuration Specifies the timeout [Duration] to use when storing cache entries. Affects keep-alive time for cached instance data like user role type fields.
+ * @property optWebTimeoutDuration Specifies the timeout [kotlin.time.Duration] to use when making web requests
+ * @property optCacheTimeoutDuration Specifies the timeout [kotlin.time.Duration] to use when storing cache entries. Affects keep-alive time for cached instance data like user role type fields.
  * @property optThreadCount Specifies the number of threads to use for each client instance. Defaults to 2 at a minimum
  */
 @TemDsl
@@ -80,7 +79,7 @@ public class TemClientConfig {
   }
 
   /**
-   * Creates an custom [HttpClient] with the specified [HttpClientEngineFactory] and optional [block] configuration.
+   * Creates an custom [HttpClient] with the specified [io.ktor.client.engine.HttpClientEngineFactory] and optional [block] configuration.
    * Note that the Temerity config will be added afterwards.
    */
   public fun <T : HttpClientEngineConfig> httpClient(
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 308ae29be437764f40e0f99a025f33276881520e..973acb0b0731e4ef8cd6439f356158e6584a24c2 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
@@ -24,17 +24,14 @@ import com.skydoves.sandwich.getOrThrow
 import com.skydoves.sandwich.ktor.executeApiResponse
 import com.skydoves.sandwich.ktor.statusCode
 import com.skydoves.sandwich.onSuccess
-import edu.ucsc.its.temerity.AuditLogSortOrder
-import edu.ucsc.its.temerity.AuditLogSortOrder.NEW_FIRST
 import edu.ucsc.its.temerity.BuildConfig
 import edu.ucsc.its.temerity.BuildConfig.BUILD_DATE
 import edu.ucsc.its.temerity.BuildConfig.BUILD_TIMEZONE
 import edu.ucsc.its.temerity.BuildConfig.BUILD_VARIANT
 import edu.ucsc.its.temerity.BuildConfig.LIB_VERSION
-import edu.ucsc.its.temerity.BuildVariant
-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.TemerityApi
+import edu.ucsc.its.temerity.api.sortByCreationDate
 import edu.ucsc.its.temerity.core.Temerity.Companion.DEFAULT_WEB_TIMEOUT
 import edu.ucsc.its.temerity.di.LibModule.libModule
 import edu.ucsc.its.temerity.di.platformModule
@@ -43,6 +40,9 @@ import edu.ucsc.its.temerity.extensions.coroutines.createJobScope
 import edu.ucsc.its.temerity.extensions.time.applyAuditLogFormat
 import edu.ucsc.its.temerity.extensions.time.applyScheduledSessionDateFormat
 import edu.ucsc.its.temerity.model.AuditLogEntry
+import edu.ucsc.its.temerity.model.AuditLogSortOrder
+import edu.ucsc.its.temerity.model.AuditLogSortOrder.NEW_FIRST
+import edu.ucsc.its.temerity.model.BuildVariant
 import edu.ucsc.its.temerity.model.Course
 import edu.ucsc.its.temerity.model.Device
 import edu.ucsc.its.temerity.model.DeviceRecordingSession
@@ -54,7 +54,6 @@ 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.sortByCreationDate
 import io.ktor.client.HttpClient
 import io.ktor.client.HttpClientConfig
 import io.ktor.client.engine.HttpClientEngine
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/LibModule.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/LibModule.kt
index d6fbe81f556afa013b7acc10362d538977c9b6a3..6f236350e0fcb19ecc2dc3ed45f637d8af302c6b 100644
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/LibModule.kt
+++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/LibModule.kt
@@ -19,9 +19,9 @@ 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.TemClientConfig
 import edu.ucsc.its.temerity.core.Temerity.Companion.createLogger
 import edu.ucsc.its.temerity.core.buildHttpClient
 import edu.ucsc.its.temerity.extensions.coroutines.createLibraryScope
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/DateTimeExtensions.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/DateTimeExtensions.kt
index 7ed64322b5d44f0fd76206566d0b49c49e09f028..937184a81effcd30fa56e2e7c6035ca4ef089653 100644
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/DateTimeExtensions.kt
+++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/DateTimeExtensions.kt
@@ -17,8 +17,8 @@
  */
 package edu.ucsc.its.temerity.extensions.time
 
-import edu.ucsc.its.temerity.AUDIT_LOG_REQUEST_DATE_FORMAT
-import edu.ucsc.its.temerity.SCHEDULED_SESSION_DATE_FORMAT
+import edu.ucsc.its.temerity.api.AUDIT_LOG_REQUEST_DATE_FORMAT
+import edu.ucsc.its.temerity.api.SCHEDULED_SESSION_DATE_FORMAT
 import kotlinx.datetime.LocalDate
 import kotlinx.datetime.format
 
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/LocalDateTimeSerializer.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/LocalDateTimeSerializer.kt
index 96695252d3ce72acaa684e88cb9f2a96b62533bb..030e4ecb6b50206ee0024b2ece33b3be39a6bd99 100644
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/LocalDateTimeSerializer.kt
+++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/extensions/time/LocalDateTimeSerializer.kt
@@ -17,7 +17,7 @@
  */
 package edu.ucsc.its.temerity.extensions.time
 
-import edu.ucsc.its.temerity.AUDIT_LOG_TIMESTAMP_FORMAT
+import edu.ucsc.its.temerity.api.AUDIT_LOG_TIMESTAMP_FORMAT
 import edu.ucsc.its.temerity.model.AuditLogEntry
 import kotlinx.datetime.LocalDateTime
 import kotlinx.datetime.format
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/model/AuditLogSortOrder.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/model/AuditLogSortOrder.kt
new file mode 100644
index 0000000000000000000000000000000000000000..71fd0780714ddddb0726e9a505d618e2ec205280
--- /dev/null
+++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/model/AuditLogSortOrder.kt
@@ -0,0 +1,31 @@
+/*
+ *     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.model
+
+/**
+ * Enum class used to define the sort order for audit log entries.
+ */
+public enum class AuditLogSortOrder {
+  NEW_FIRST,
+  OLD_FIRST,
+  ;
+
+  public companion object {
+    public fun fromBoolean(value: Boolean): AuditLogSortOrder = if (value) NEW_FIRST else OLD_FIRST
+  }
+}
diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/model/BuildVariant.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/model/BuildVariant.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9276003d9f0a61ba0aa0e39d586b98f9402dcd2c
--- /dev/null
+++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/model/BuildVariant.kt
@@ -0,0 +1,36 @@
+/*
+ *     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.model
+
+/**
+ * Enum class used to define the build variant of the library.
+ * For debugging purposes.
+ */
+public enum class BuildVariant(public val variant: String) {
+  RELEASE("RELEASE"),
+  DEBUG("DEBUG"),
+  ;
+
+  internal companion object {
+    internal fun of(variant: String): BuildVariant = when (variant) {
+      "RELEASE" -> RELEASE
+      "DEBUG" -> DEBUG
+      else -> throw IllegalArgumentException("Invalid build variant: $variant")
+    }
+  }
+}
diff --git a/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.jvm.kt b/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.jvm.kt
index 9cb64854d8f7a4c32115b92efa2ad55f5cc893cd..a076421f0c82a0085d521c473b7c80225a3a1add 100644
--- a/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.jvm.kt
+++ b/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.jvm.kt
@@ -23,7 +23,6 @@ import co.touchlab.kermit.NoTagFormatter
 import co.touchlab.kermit.Severity.Debug
 import co.touchlab.kermit.loggerConfigInit
 import co.touchlab.kermit.platformLogWriter
-import edu.ucsc.its.temerity.TemClientConfig
 
 internal actual fun createCommonLogger(tag: String?, config: TemClientConfig?, supportKtxNotebook: Boolean): Logger = when (config) {
   null -> {
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 9589c8b017e9964c2fd66982fdc5d5f256efb1c9..ec0e28666aa40da5528082abbda2e9fc1d2789a4 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
@@ -17,8 +17,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.model.AuditLogSortOrder.NEW_FIRST
 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
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 dd216fc4d88704d0742311d2397f67286a3302c7..8ae6e130ed5eb1bc61d3312c4c2820c213f8d063 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
@@ -20,8 +20,8 @@ package edu.ucsc.its.temerity.test
 import co.touchlab.kermit.Logger
 import com.skydoves.sandwich.StatusCode
 import com.skydoves.sandwich.ktor.getStatusCode
-import edu.ucsc.its.temerity.AuditLogSortOrder.NEW_FIRST
 import edu.ucsc.its.temerity.core.Temerity
+import edu.ucsc.its.temerity.model.AuditLogSortOrder.NEW_FIRST
 import edu.ucsc.its.temerity.model.EventType.NEW_LOG_IN
 import edu.ucsc.its.temerity.model.NewUser
 import edu.ucsc.its.temerity.util.currentDate
diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/Util.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/Util.kt
index 299c20b2fa6bc737fe5c8a424bff81f6d6256db8..d343b206640489762e84e2164050d4ee1e883571 100644
--- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/Util.kt
+++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/Util.kt
@@ -17,7 +17,7 @@
  */
 package edu.ucsc.its.temerity.test
 
-import edu.ucsc.its.temerity.TemClientConfig
+import edu.ucsc.its.temerity.core.TemClientConfig
 import edu.ucsc.its.temerity.core.Temerity
 import edu.ucsc.its.temerity.core.Temerity.Companion.createLogger
 import io.github.cdimascio.dotenv.Configuration