6f6df5c7d877

fix: Redact release sync logging (PB-26-031, v2.14.95)

time
2026-09-02 11:47 UTC · 1 month ago
machine
koh2
parent
df203bf39bec
6 files VERSION+1 −1app/src/main/java/com/peachpasswords/sync/CloudRelayReconnectListener.kt+27 −3app/src/main/java/com/peachpasswords/sync/RelayAdoptionHost.kt+1 −2app/src/main/java/com/peachpasswords/sync/RelayAdoptionReceiver.kt+3 −4app/src/main/java/com/peachpasswords/sync/SyncCoordinator.kt+1 −1app/src/test/java/com/peachpasswords/sync/CloudRelayReconnectListenerTest.kt+11 −0
VERSION+1 −1
@@ -1 +1 @@1-2.14.941+2.14.95

view file

app/src/main/java/com/peachpasswords/sync/CloudRelayReconnectListener.kt+27 −3
@@ -1,6 +1,7 @@11 package com.peachpasswords.sync22 33 import android.util.Log4+import com.peachpasswords.BuildConfig45 import com.peachpasswords.vault.VaultCrypto56 import kotlinx.coroutines.CancellationException67 import kotlinx.coroutines.CompletableDeferred@@ -75,11 +76,12 @@7576     fun e(message: String) = sink(Log.ERROR, message)7677 7778     private fun writeToLogcat(priority: Int, message: String) {79+        val safeMessage = if (BuildConfig.DEBUG) relayLogDetail(message) else releaseSyncLogEvent(message)7880         try {7981             when (priority) {80-                Log.INFO -> Log.i(PEACH_SYNC_LOG_TAG, message)81-                Log.WARN -> Log.w(PEACH_SYNC_LOG_TAG, message)82-                else -> Log.e(PEACH_SYNC_LOG_TAG, message)82+                Log.INFO -> Log.i(PEACH_SYNC_LOG_TAG, safeMessage)83+                Log.WARN -> Log.w(PEACH_SYNC_LOG_TAG, safeMessage)84+                else -> Log.e(PEACH_SYNC_LOG_TAG, safeMessage)8385             }8486         } catch (error: RuntimeException) {8587             // Local JVM tests link android.jar's throwing Log stub; a device@@ -87,6 +89,28 @@8789             if (!error.message.orEmpty().contains("not mocked")) throw error8890         }8991     }92+}93+94+/** Fixed release event vocabulary; all dynamic protocol/error detail is discarded. */95+internal fun releaseSyncLogEvent(message: String): String = when {96+    message.startsWith("sync-stage: clock skew") -> "SYNC_CLOCK_SKEW"97+    message.startsWith("sync-stage:") -> "SYNC_STAGE_WAIT"98+    message.startsWith("cloud-relay: reconcile start") -> "SYNC_RELAY_RECONCILE_START"99+    message.startsWith("cloud-relay: reconcile — no eligible") -> "SYNC_RELAY_NO_ELIGIBLE_PEERS"100+    message.startsWith("cloud-relay: reconcile requested") -> "SYNC_RELAY_RECONCILE_REQUESTED"101+    message.startsWith("cloud-relay: refreshing") -> "SYNC_RELAY_REFRESH"102+    message.startsWith("cloud-relay: open failed") -> "SYNC_RELAY_OPEN_FAILED"103+    message.startsWith("cloud-relay: open ok") -> "SYNC_RELAY_OPEN_OK"104+    message.startsWith("cloud-relay: open") -> "SYNC_RELAY_OPEN"105+    message.startsWith("cloud-relay: wait") -> "SYNC_RELAY_WAIT"106+    message.startsWith("cloud-relay: socket closed") -> "SYNC_RELAY_SOCKET_CLOSED"107+    message.startsWith("cloud-relay: dial failed") -> "SYNC_RELAY_DIAL_FAILED"108+    message.startsWith("cloud-relay: dial ok") -> "SYNC_RELAY_DIAL_OK"109+    message.startsWith("cloud-relay: dial") -> "SYNC_RELAY_DIAL"110+    message.startsWith("adoption: snapshot receive timed out") -> "SYNC_ADOPTION_SNAPSHOT_TIMEOUT"111+    message.startsWith("adoption: snapshot receive failed") -> "SYNC_ADOPTION_SNAPSHOT_FAILED"112+    message.startsWith("adoption: snapshot send failed") -> "SYNC_ADOPTION_SNAPSHOT_SEND_FAILED"113+    else -> "SYNC_EVENT"90114 }91115 92116 internal fun relayLogDetail(detail: String): String =

view file

app/src/main/java/com/peachpasswords/sync/RelayAdoptionHost.kt+1 −2
@@ -1,6 +1,5 @@11 package com.peachpasswords.sync22 3-import android.util.Log43 import java.security.MessageDigest54 import javax.inject.Inject65 import javax.inject.Singleton@@ -233,7 +232,7 @@233232             } catch (error: Exception) {234233                 if (error is SnapshotDuressFrameTooLargeException) throw error235234                 if (error is kotlinx.coroutines.CancellationException) throw error236-                Log.w("PeachAdopt", "source inline snapshot send failed, receiver falls back to sync", error)235+                PeachSyncLog.w("adoption: snapshot send failed — reason=${relayLogReason(error)}")237236             }238237         }239238         return adopted

view file

app/src/main/java/com/peachpasswords/sync/RelayAdoptionReceiver.kt+3 −4
@@ -1,6 +1,5 @@11 package com.peachpasswords.sync22 3-import android.util.Log43 import java.security.MessageDigest54 import javax.inject.Inject65 import javax.inject.Singleton@@ -286,10 +285,10 @@286285                     } catch (_: Exception) {}287286                     boundDeps.markSynced(adopted.deviceId)288287                 } else {289-                    Log.i("PeachAdopt", "receiver inline snapshot timed out, falling back to sync")288+                    PeachSyncLog.i("adoption: snapshot receive timed out")290289                 }291290             } catch (e: Exception) {292-                Log.w("PeachAdopt", "receiver inline snapshot failed, falling back to sync", e)291+                PeachSyncLog.w("adoption: snapshot receive failed — reason=${relayLogReason(e)}")293292             }294293         }295294         return adopted@@ -405,7 +404,7 @@405404             } catch (error: Exception) {406405                 if (error is SnapshotDuressFrameTooLargeException) throw error407406                 if (error is CancellationException) throw error408-                Log.w("PeachAdopt", "source inline snapshot send failed, receiver falls back to sync", error)407+                PeachSyncLog.w("adoption: snapshot send failed — reason=${relayLogReason(error)}")409408             }410409         }411410         return adopted

view file

app/src/main/java/com/peachpasswords/sync/SyncCoordinator.kt+1 −1
@@ -312,7 +312,7 @@312312     // is small relative to any sane wall-clock value, so no arithmetic on these two313313     // longs can overflow for realistic inputs.314314     if (remoteTime < localTime - CLOCK_SKEW_WARN_MS || remoteTime > localTime + CLOCK_SKEW_WARN_MS) {315-        android.util.Log.w("peach-sync", "clock skew detected: local=$localTime remote=$remoteTime")315+        PeachSyncLog.w("sync-stage: clock skew detected — local=$localTime remote=$remoteTime")316316     }317317 }318318 

view file

app/src/test/java/com/peachpasswords/sync/CloudRelayReconnectListenerTest.kt+11 −0
@@ -46,6 +46,17 @@4646 }4747 4848 class CloudRelayReconnectListenerTest {49+50+    @Test51+    fun `release sync logs reduce diagnostics to opaque allowlisted events`() {52+        val hostile = "cloud-relay: open failed — reason=token=secret peer=device-123\nstack detail"53+54+        assertEquals("SYNC_RELAY_OPEN_FAILED", releaseSyncLogEvent(hostile))55+        assertEquals("SYNC_RELAY_SOCKET_CLOSED", releaseSyncLogEvent("cloud-relay: socket closed — reason=bad frame"))56+        assertEquals("SYNC_ADOPTION_SNAPSHOT_FAILED", releaseSyncLogEvent("adoption: snapshot receive failed — secret"))57+        assertEquals("SYNC_CLOCK_SKEW", releaseSyncLogEvent("sync-stage: clock skew detected — local=1 remote=2"))58+        assertEquals("SYNC_EVENT", releaseSyncLogEvent("unrecognized secret-bearing detail"))59+    }4960     @Test5061     fun `relay reconcile requests preserve a conflated waiter refresh`() {5162         val requests = RelayReconcileRequests()

view file