Skip to content

Erasing a synced device erases the account, and stays erased - #148

Merged
suskozaver merged 1 commit into
ArunNGun:betafrom
suskozaver:erasing-a-synced-device-erases-the-account
Oct 22, 2026
Merged

suskozaver merged 1 commit into
ArunNGun:betafrom
suskozaver:erasing-a-synced-device-erases-the-account

Conversation

@suskozaver

Copy link
Copy Markdown
Collaborator

Reported by a user: backup, Erase everything, confirm, another backup, and the data was still there. Three times. On a synced device the erase was undone within seconds, every time.

Why it came back. resetAll wrote EMPTY_DATA over the store, settings included. settings.sync is where the device remembers which server version it last agreed with. Without it the device was an empty one that had never agreed with the server, which decideSync treats as a fresh install and answers by pulling the server's copy. The erase triggered a sync, and the sync put everything back.

The fix. resetAll keeps settings.sync and resets every other setting as before. The device stays in step with the server and holds a change, so the next run pushes the empty document and every other device on the account pulls it. I considered keeping the erase to this browser only and rejected it: on a synced device the account copy is the data, and erasing one browser is what signing out already does, with a check that the server holds everything first.

The warning above the button changes while sync is running, with a new string in en, de, sl and pl. The existing one promised "no copy anywhere else". That was untrue on a synced device and is the opposite of what now happens.

Rescue copy. The guard in setItem saw every record go, set them aside, and RescueNotice then offered them back. That guard is for losses nobody meant. A confirmed erase is the one deletion the app knows was meant, so it now goes the way wipeLocal does: no baseline to compare the write against, and any copy left over from an earlier attempt is removed. lastWritten is cleared before set, because the persist write that reads it starts inside set.

Tests. The new src/lib/store.test.ts checks that the store keeps the sync record and resets the rest, and that decideSync chooses push rather than pull for the state the erase leaves behind. Both fail without the change. The trap is written up in document/06-traps.md.

Checks: tsc --noEmit clean, next lint with no warnings, 1754 tests passing, also under TZ=America/New_York.

🤖 Generated with Claude Code

https://claude.ai/code/session_013mcSGbUb6y7ciu653EjmdX

Reported by a user: backup, Erase everything, confirm, another backup, and
the data was all still there. Three times. On a synced device the erase was
undone within seconds, every time.

`resetAll` wrote `EMPTY_DATA` over the store, settings included, and
`settings.sync` is where the device remembers which server version it last
agreed with. Losing it made the device an empty one that has never agreed
with the server, which `decideSync` treats as a fresh install and answers by
pulling the server's copy. The erase arrived, the change triggered a sync, and
the sync put everything back.

`resetAll` now keeps `settings.sync` and resets every other setting as before.
The device stays in step with the server and holds a change, so the next run
pushes the empty document, and every other device on the account pulls it.
Keeping the old behaviour and only erasing this browser was rejected: on a
synced device the account copy is the data, and erasing one browser is what
signing out already does, with a check that the server holds everything first.
The warning above the button says so when sync is running, with a separate
string in all four languages, since the existing one promised "no copy
anywhere else", which was untrue on a synced device and is the opposite of what
now happens.

The rescue guard also saw every record go, set them aside, and the notice then
offered them back. That guard is for losses nobody meant. This is the one
deletion the app knows was meant, behind its own confirmation, so it now goes
the way `wipeLocal` goes: no baseline to compare the write against, and any
copy left from an earlier attempt removed. `lastWritten` is cleared before
`set`, because the persist write that reads it starts inside `set`.

New `store.test.ts` covers the store keeping the sync record and resetting
the rest, and `decideSync` choosing push rather than pull for the state the
erase leaves behind. Both of those fail without the change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013mcSGbUb6y7ciu653EjmdX
@vercel

vercel Bot commented Oct 22, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Arun's projects Team on Vercel.

A member of the Team first needs to authorize it.

@suskozaver
suskozaver merged commit 2118d45 into ArunNGun:beta Oct 22, 2026
1 of 2 checks passed
@suskozaver
suskozaver deleted the erasing-a-synced-device-erases-the-account branch October 22, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant