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
↓ peach-android-6f6df5c7.tar.gzatlas at this save
files changed6 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 −0app/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 =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 adoptedapp/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 adoptedapp/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 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()