fix: bind removal plans to full key identity

Require both the current record ID and decrypted full key to match a prepared removal plan before deleting local state.

Invalidate mismatched plans before returning KEYRING_REMOVE_PLAN_INVALID so a replacement with the same canonical ID cannot be deleted and the stale plan cannot be reused.

Cover normal, idempotent, rebased, duplicate-ID, and same-ID replacement removal behavior while preserving the replacement generation.
This commit is contained in:
Sucukdeluxe
2026-08-22 16:13:43 +02:00
parent c5d4f4aef8
commit 15c363912f
2 changed files with 32 additions and 1 deletions
+6 -1
View File
@@ -507,10 +507,15 @@ function createOnlineBackupKeyring({
const state = await readState();
const blockingIssue = firstBlockingIssue(state);
if (blockingIssue) throw issueError(blockingIssue);
if (!state.entries.some(current => current.id === plan.id)) {
const currentEntry = state.entries.find(current => current.id === plan.id);
if (!currentEntry) {
removalPlans.delete(plan);
return false;
}
if (currentEntry.key !== plan.key) {
removalPlans.delete(plan);
throw issueError(KEYRING_ERROR_CODES.plan);
}
await writeEntries(
state.entries.filter(current => current.id !== plan.id),
nextGeneration(state.generation)