One-time migration: push any statuses persisted by the old localStorage
store into the backend, then retire the blob. Papers that no longer exist
are skipped (404 → their status is unrecoverable anyway); papers on no
reading list apply as a 0-list no-op. Any other failure keeps the blob so
the next fetch retries — the PUTs are idempotent. Never throws.
One-time migration: push any statuses persisted by the old localStorage store into the backend, then retire the blob. Papers that no longer exist are skipped (404 → their status is unrecoverable anyway); papers on no reading list apply as a 0-list no-op. Any other failure keeps the blob so the next fetch retries — the PUTs are idempotent. Never throws.