"Require published keys" switched itself off every restart
It was a plain in-memory field on the trust object. The switch set it, nothing wrote it down, and the phase it was read back from defaulted to false — so somebody who turned it on was protected until they next closed the app, and nothing told them it had lapsed. The switch simply read off again. A security control that quietly disarms itself is worse than one that was never offered, because the person is relying on it. iOS has persisted this in UserDefaults all along. Android now stores it beside the other device preferences, restores it into the trust object at sign-in, and seeds the phase from the same value so the switch shows what is actually being enforced rather than disagreeing with it. Still off by default, which is deliberate and unchanged: a relay older than the transparency log has no log to prove anything against, and enforcing it there would refuse every peer for a reason the user cannot fix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
93674d249c
commit
047003a509
@@ -24,6 +24,27 @@ class MediaSettings(context: Context) {
|
||||
get() = prefs.getBoolean(FULL_QUALITY, false)
|
||||
set(value) = prefs.edit().putBoolean(FULL_QUALITY, value).apply()
|
||||
|
||||
/**
|
||||
* Refuse to send unless the relay can prove the recipient's keys appear in
|
||||
* the log it publishes.
|
||||
*
|
||||
* 🔴 **This lives here because it was not stored anywhere at all.** It was
|
||||
* a plain in-memory field on the trust object, set from the switch and
|
||||
* never written down, so it reverted to off on every launch. A person who
|
||||
* turned it on was protected until they next closed the app, and nothing
|
||||
* told them it had lapsed — the switch simply read off again, and a
|
||||
* setting that quietly disarms itself is worse than one that was never
|
||||
* offered. iOS has always persisted this in UserDefaults; Android had
|
||||
* nothing.
|
||||
*
|
||||
* ⚠️ Still off by default, deliberately. A relay older than the
|
||||
* transparency log has no log to prove anything against, so enforcing it
|
||||
* everywhere would refuse every peer on those deployments.
|
||||
*/
|
||||
var requireKeyLog: Boolean
|
||||
get() = prefs.getBoolean(REQUIRE_KEY_LOG, false)
|
||||
set(value) = prefs.edit().putBoolean(REQUIRE_KEY_LOG, value).apply()
|
||||
|
||||
/**
|
||||
* Generate a preview card when sending a link.
|
||||
*
|
||||
@@ -38,6 +59,7 @@ class MediaSettings(context: Context) {
|
||||
|
||||
companion object {
|
||||
private const val PREFS = "media-settings"
|
||||
private const val REQUIRE_KEY_LOG = "requireKeyLog"
|
||||
private const val FULL_QUALITY = "full_quality"
|
||||
private const val LINK_PREVIEWS = "link_previews"
|
||||
}
|
||||
|
||||
@@ -481,6 +481,15 @@ class MessengerViewModel(app: Application) : AndroidViewModel(app) {
|
||||
|
||||
val fetchedBuddies = runCatching { session!!.roster() }
|
||||
val fetchedGroups = runCatching { session!!.relay.listGroups() }
|
||||
|
||||
// 🔴 Restore the strict key-log requirement the user chose. Without
|
||||
// this it reverted to off on every launch: the switch was read from a
|
||||
// field that only ever existed in memory, so somebody who turned it on
|
||||
// was protected until they next closed the app and was never told it
|
||||
// had lapsed.
|
||||
val strictKeyLog = MediaSettings(getApplication()).requireKeyLog
|
||||
session!!.conversations.trust.requireKeyLog = strictKeyLog
|
||||
|
||||
return Phase.SignedIn(
|
||||
handle = account.username,
|
||||
userId = account.userId,
|
||||
@@ -488,6 +497,11 @@ class MessengerViewModel(app: Application) : AndroidViewModel(app) {
|
||||
relay = config.host,
|
||||
fnid = fnid,
|
||||
status = "Registered with ${preKeys.size} one-time prekeys published.",
|
||||
// ⚠️ The switch has to read what is actually enforced. Restoring
|
||||
// the trust object without this would leave the toggle showing off
|
||||
// while sends were being refused, which is the same confusion in
|
||||
// the opposite direction.
|
||||
requireKeyLog = strictKeyLog,
|
||||
buddies = fetchedBuddies.getOrDefault(emptyList()),
|
||||
buddiesLoaded = fetchedBuddies.isSuccess,
|
||||
avatars = session?.avatars(
|
||||
@@ -664,6 +678,9 @@ class MessengerViewModel(app: Application) : AndroidViewModel(app) {
|
||||
* Pinning is always on regardless; this is the stricter, opt-in half.
|
||||
*/
|
||||
fun setRequireKeyLog(required: Boolean) {
|
||||
// Written down as well as applied. See MediaSettings.requireKeyLog for
|
||||
// why: this used to be memory-only and silently lapsed on restart.
|
||||
MediaSettings(getApplication()).requireKeyLog = required
|
||||
session?.conversations?.trust?.requireKeyLog = required
|
||||
update { it.copy(requireKeyLog = required) }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user