f78005e12eb1

fix a regression I introduced earlier today: adding the CodexJson parser for the Codex blob fix inserted it BETWEEN the @Singleton annotation and 'class VaultRepository', so the annotation landed on the property and the repository stopped being a singleton. Every injection point then got its own vault — createVault unlocked one instance while the screen observed a different, still-locked one 30ms later (proved by logging System.identityHashCode: 100965910 vs 135655535 in the same process).

That is what made the recovery words render empty: the screen's repository had never been unlocked and had a null root key, while the vault genuinely existed. Moved CodexJson to file scope below the imports and restored @Singleton to the class. Verified: a freshly created vault now shows all 12 words. Worth re-testing anything touched since that change — divergent vault instances could plausibly have broken June's Codex restore attempt with her real password too, since the restore writes to one instance and the UI reads another.

time
2026-07-24 21:51 UTC · 3 months ago
machine
koh2
agent
claude-opus-5
session
fix VaultRepository singleton regression
parent
896672fa08f1
1 file app/src/main/java/com/peachpasswords/vault/VaultRepository.kt+3 −2
app/src/main/java/com/peachpasswords/vault/VaultRepository.kt+3 −2
@@ -17,6 +17,9 @@1717 import javax.inject.Inject1818 import javax.inject.Singleton1919 20+/** Lenient parser for the Codex vault-blob wrapper only. */21+private val CodexJson = Json { ignoreUnknownKeys = true; isLenient = true }22+2023 private fun b64(bytes: ByteArray): String = Base64.getEncoder().withoutPadding().encodeToString(bytes)2124 private fun unb64(s: String): ByteArray = Base64.getDecoder().decode(s)2225 @@ -54,8 +57,6 @@5457  *  - destroyVault never touches the Pro license (separate store).5558  */5659 @Singleton57-private val CodexJson = Json { ignoreUnknownKeys = true; isLenient = true }58-5960 class VaultRepository @Inject constructor(6061     private val store: VaultStorage,6162 ) {

view file