fix(messages): address S2 review — partner key refresh + reactive me
- On a decrypt failure, refresh the partner's cached public key (and drop the stale derived conversation key) once per pass and retry. A passphrase reset rotates a keypair, so a partner who cached the old public key would otherwise encrypt undecryptable messages until a reload; the first failed decrypt now self-heals reads AND future sends. (pubCache was assumed set-once.) - KeyGate reads has_password via a reactive useQuery(['me'], enabled:false) passive observer instead of a one-shot getQueryData, so the reset password field stays correct even if me resolves after mount. - Document the remaining multi-device staleness (a reset on another device leaves this one 'ready' with the dead key) as a known limitation in useKeyState.
This commit is contained in:
@@ -185,6 +185,13 @@ export async function unlock(
|
||||
await installKey(userId, await importPrivate(pkcs8));
|
||||
}
|
||||
|
||||
// Drop the cached derived conversation key for a partner. convKeyFor caches by partnerId alone, so
|
||||
// after a partner rotates their public key (a passphrase reset) the caller must call this before
|
||||
// re-deriving with the fresh key — otherwise the stale key would be returned.
|
||||
export function forgetConv(partnerId: number): void {
|
||||
convKeys.delete(partnerId);
|
||||
}
|
||||
|
||||
// --- per-conversation encryption ---
|
||||
async function convKeyFor(partnerId: number, partnerPubB64: string): Promise<CryptoKey> {
|
||||
const cached = convKeys.get(partnerId);
|
||||
|
||||
Reference in New Issue
Block a user