mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-06 11:48:24 +00:00
Two gaps left by 04ef4128, both of which would have surfaced as a
half-finished release at the flag flip rather than as a failure now.
The mirror ignored the retirement switch. LEGACY_WRITES_RETIRED was private
to LocalPreferences, so GeohashChatIdentityState could not read it and wrote
to its legacy file unconditionally. Flipping the flag would have retired the
four documented mirrors and left this one running. It is `internal` now and
both of that class's legacy writes are gated on it, so the flip is one
switch that stops everything.
Nothing would ever have deleted the identity's legacy file. It is
`secret_keeper_<pubkey hex>`, not `secret_keeper_<npub>` — the writer passed
signer.pubKey where every other caller passes an npub — and the cleanup
enumerates npub-keyed files. It would have sat on disk holding a seed after
every other legacy file was gone. LegacyAccountFiles.delete now clears and
unlinks both, and verify() refuses while the hex file holds an identity the
current store does not.
That check reads geohashSource(), the hex file. An earlier version of it
read the npub file and was reverted for being unable to fire; this is the
corrected form, and it is paired with actually deleting the file it guards.
The copy also had to stop being lazy, and that is the part that would have
bitten users rather than the release. It ran only from
GeohashChatIdentityState, so only for someone who opened a location chat.
Combined with the new gate that is worse than the orphan it replaced: a user
with an identity who never opens another location chat would never be
copied, and their legacy files could then never be deleted at all. It now
runs on the first account load after the upgrade, beside the cleanup call
and before it, so every existing install converges whether or not location
chat is ever touched again.
It sits next to legacyCleanup rather than inside the loader because
innerLoadCurrentAccountFromEncryptedStorage is at the JVM's 64KB method
limit — AccountStoreData's KDoc already records that every suspend call in
there costs a coroutine state, and adding one broke the build with "Method
too large". Outside the lock, once per load, is also where it belongs: this
is migration housekeeping, not part of building AccountSettings.
Tests: four on the gate (an uncopied identity blocks deletion, a copied one
does not, an account that never opened a location chat is not held hostage,
and both files go together) and one on idempotence, which the copy now needs
because it runs on every load.
The plan doc is updated to match: the group and its two quirks, deletion
covering both files, the fourth condition, the flip stopping this mirror
too, and a device-pass step for the seed — the one migrated value whose loss
is silent rather than visible.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXvKXakvup4inNFfAhhr4L