fix: complete managed backup key remediation

Recover from structurally valid but undecryptable primary keyrings by selecting a fully cryptographically validated backup or recovery temp and reporting KEYRING_RECOVERED.

Keep committed primary writes successful when best-effort post-publication cleanup fails, preventing ambiguous retries after durable local publication.

Intercept clipboard writes inside the hidden Electron Main-process integration probe, remove the duplicate key-created toast, and make authoritative refresh coverage differ from optimistic state.
This commit is contained in:
Sucukdeluxe
2026-08-22 15:24:33 +02:00
parent 49fa4518c9
commit 8041aeead9
5 changed files with 98 additions and 24 deletions
+55
View File
@@ -339,6 +339,30 @@ describe('encrypted online backup keyring', () => {
assert.deepEqual(snapshot.issues, ['KEYRING_RECOVERED']);
});
it('recovers a cryptographically valid backup when the primary only passes structural validation', async () => {
const first = fixture();
const key = validKey();
await first.keyring.commit(first.keyring.prepare(key, timestamp));
writeKeyring(first.filePath, [{
id: parseOnlineBackupKey(key).id,
encryptedKey: 'enc:v1:YWJjZA',
createdAt: timestamp
}]);
const { createOnlineBackupKeyring } = require('../lib/online-backup-keyring');
const recovered = createOnlineBackupKeyring({
filePath: first.filePath,
encryptField: encrypt,
decryptField: decrypt,
isEncrypted: isCanonicalEnvelope
});
const snapshot = await recovered.list();
assert.deepEqual(snapshot.entries.map(entry => entry.id), [parseOnlineBackupKey(key).id]);
assert.deepEqual(snapshot.issues, ['KEYRING_RECOVERED']);
assert.equal(await recovered.getKey(parseOnlineBackupKey(key).id), key);
});
it('skips a newer cryptographically invalid recovery temp in favor of the validated backup', async () => {
const first = fixture();
const key = validKey();
@@ -421,6 +445,37 @@ describe('encrypted online backup keyring', () => {
assert.equal(await first.keyring.getKey(parseOnlineBackupKey(firstKey).id), firstKey);
});
it('commits successfully once the primary is published even when later cleanup fails', async () => {
const first = fixture();
const firstKey = validKey();
const secondKey = validKey();
await first.keyring.commit(first.keyring.prepare(firstKey, timestamp));
let readdirCalls = 0;
const fsImpl = {
...fs.promises,
readdir: async (...args) => {
readdirCalls++;
if (readdirCalls === 2) throw Object.assign(new Error('cleanup failed'), { code: 'EIO' });
return fs.promises.readdir(...args);
}
};
const { createOnlineBackupKeyring } = require('../lib/online-backup-keyring');
const keyring = createOnlineBackupKeyring({
filePath: first.filePath,
encryptField: encrypt,
decryptField: decrypt,
isEncrypted: isCanonicalEnvelope,
fsImpl
});
assert.equal(await keyring.commit(keyring.prepare(secondKey, '2026-08-22T11:00:00.000Z')), true);
assert.equal(await keyring.getKey(parseOnlineBackupKey(secondKey).id), secondKey);
assert.deepEqual((await keyring.list()).entries.map(entry => entry.id), [
parseOnlineBackupKey(secondKey).id,
parseOnlineBackupKey(firstKey).id
]);
});
it('types invalid documents and never includes plaintext or ciphertext in errors', async () => {
const { filePath, backupPath, keyring } = fixture();
const key = validKey();