From 8a592687387e65fb459375ca4dbb62cdefb94d34 Mon Sep 17 00:00:00 2001 From: greenart7c3 Date: Mon, 28 Sep 2026 10:50:28 -0300 Subject: [PATCH] desktop: adapt to the new Quartz listener/auth APIs + hermetic tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Master's Quartz upgrade made RelayConnectionListener.onIncomingMessage a suspend fun and gave RelayAuthenticator's auth lambda (relay, event, isReconnect) parameters; the desktop module still compiled against the old shapes, breaking the build after the rebase. Update the overrides in BunkerEngine, RelayChecker and the E2E test, and the auth lambda in AmberDesktop, to the new signatures (same launch-inside-listener pattern as NotificationSubscription). The desktop test suite also failed on machines with a real install: AppDirs resolves XDG_DATA_HOME before user.home, so a real ~/.local/share/amber holding a passphrase-wrapped master.key.enc leaked into the worker JVMs and every DesktopKeyStore operation threw LockedException. Point the test workers' XDG_DATA_HOME and user.home at a pristine dir under build/ that is wiped per run (config-cache safe; note Gradle cannot remove worker env vars — null becomes the literal string "null" and previously materialized desktop/null/amber, now gitignored). :desktop:test 51/51 green, :desktop:ktlintCheck and :app:compileFreeDebugKotlin pass. Co-Authored-By: Claude --- .gitignore | 1 + desktop/build.gradle.kts | 20 +++++++++++++++++++ .../nostrsigner/desktop/core/AmberDesktop.kt | 2 +- .../nostrsigner/desktop/core/BunkerEngine.kt | 2 +- .../nostrsigner/desktop/core/RelayChecker.kt | 2 +- .../nostrsigner/desktop/BunkerE2eTest.kt | 2 +- 6 files changed, 25 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index e654a1ee..d3c2b01d 100644 --- a/.gitignore +++ b/.gitignore @@ -139,3 +139,4 @@ quartz/ .ai-jail trace_processor perf-traces +/desktop/null/ diff --git a/desktop/build.gradle.kts b/desktop/build.gradle.kts index 59cc5068..d0df1dc9 100644 --- a/desktop/build.gradle.kts +++ b/desktop/build.gradle.kts @@ -1,3 +1,4 @@ +import java.io.File import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { @@ -11,6 +12,25 @@ kotlin { jvmToolchain(21) } +// Tests must never see the developer machine's real desktop state: AppDirs.dataDir +// resolves from XDG_DATA_HOME *before* user.home, so a real ~/.local/share/amber +// with a passphrase-locked master.key.enc freezes into the suite and fails every +// DesktopKeyStore operation with LockedException. Scrub XDG_DATA_HOME from the +// worker env, point user.home at a pristine dir under build/, and wipe it per run. +tasks.test { + useJUnit() + val testHome = layout.buildDirectory.dir("desktop-test-home").get().asFile + // Gradle cannot remove env vars for workers (null becomes the literal string + // "null", which AppDirs happily uses as a directory name), so point + // XDG_DATA_HOME at the pristine home instead. + environment("XDG_DATA_HOME", File(testHome, "xdg-data").absolutePath) + systemProperty("user.home", testHome.absolutePath) + doFirst { + testHome.deleteRecursively() + testHome.mkdirs() + } +} + dependencies { implementation(compose.desktop.currentOs) implementation(compose.material3) diff --git a/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/AmberDesktop.kt b/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/AmberDesktop.kt index 9a37f08b..53ffcd00 100644 --- a/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/AmberDesktop.kt +++ b/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/AmberDesktop.kt @@ -48,7 +48,7 @@ object AmberDesktop { // Authenticates with relays that request NIP-42 AUTH. @Suppress("unused") private val authCoordinator by lazy { - RelayAuthenticator(client, applicationIOScope) { event -> + RelayAuthenticator(client, applicationIOScope) { _, event, _ -> accounts().map { it.signer.sign(event) } } } diff --git a/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/BunkerEngine.kt b/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/BunkerEngine.kt index dd0c8e35..7303e414 100644 --- a/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/BunkerEngine.kt +++ b/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/BunkerEngine.kt @@ -95,7 +95,7 @@ class BunkerEngine( client.addConnectionListener(this) } - override fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) { + override suspend fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) { if (msg is EventMessage) { if (subIds.containsValue(msg.subId)) { scope.launch { diff --git a/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/RelayChecker.kt b/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/RelayChecker.kt index 56cae320..19fdccd5 100644 --- a/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/RelayChecker.kt +++ b/desktop/src/main/kotlin/com/greenart7c3/nostrsigner/desktop/core/RelayChecker.kt @@ -98,7 +98,7 @@ object RelayChecker { super.onConnected(relay, pingMillis, compressed) } - override fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) { + override suspend fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) { if (msg is EventMessage && msg.subId == subId && msg.event.id == signedEvent.id) { filterResult = true } diff --git a/desktop/src/test/kotlin/com/greenart7c3/nostrsigner/desktop/BunkerE2eTest.kt b/desktop/src/test/kotlin/com/greenart7c3/nostrsigner/desktop/BunkerE2eTest.kt index d040cc95..f149b2f3 100644 --- a/desktop/src/test/kotlin/com/greenart7c3/nostrsigner/desktop/BunkerE2eTest.kt +++ b/desktop/src/test/kotlin/com/greenart7c3/nostrsigner/desktop/BunkerE2eTest.kt @@ -84,7 +84,7 @@ class BunkerE2eTest { init { client.addConnectionListener( object : RelayConnectionListener { - override fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) { + override suspend fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) { if (msg is EventMessage && msg.event.kind == NostrConnectEvent.KIND) { scope.launch { runCatching {