Removed devices: DeviceRevoked, identity reset and one retry with the ticket

kv-sync: SyncError::DeviceRevoked for 403 device_revoked (drops the session);
the test server answers it after OPAQUE (before the ticket) and for valid
signatures by a revoked device's key.

kv-ffi: CoreError::DeviceRevoked; the foreign DeviceSigner gains reset() (new key
and id). On device_revoked the core resets the identity, forgets the session
and the kept OPAQUE input (no silent re-enrolment) and keeps the vault data; a
login carrying a ticket retries once as the new device. reset_device_identity()
runs the reset on demand. Signed calls (sync, devices, tickets, join) reset too.

kv-wasm: DeviceRevoked; the browser binding replaces the WebCrypto key and id in
IndexedDB (same name and platform), loginWithSetup retries once with a ticket;
resetDeviceIdentity().

Tests: end to end revoked -> reset -> re-enrol with the same ticket (kv-ffi and
web core), no-ticket path, in-browser IndexedDB reset.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-20 22:25:03 +09:00
co-authored by Claude Opus 5.5
parent 460580bcc8
commit 83d56d43e2
16 changed files with 381 additions and 48 deletions
+14
View File
@@ -463,6 +463,20 @@ impl WebCore {
self.lock_inner().device.as_ref().map(|d| d.signer.device_id())
}
/// After `DeviceRevoked` (docs/03 "Removed devices"): forgets the session and the kept OPAQUE input, so that
/// the new identity the caller installs next (`set_device_signer`) is enrolled only by an explicit login.
/// Local vault data stays. The browser binding calls this and replaces the WebCrypto key; it then retries a
/// ticket login once.
pub fn forget_revoked_device(&self) -> Result<()> {
self.store.delete_meta(META_SESSION)?;
let mut inner = self.lock_inner();
inner.api = None;
if let Some(u) = inner.unlocked.as_mut() {
u.auth_input = None;
}
Ok(())
}
pub fn device_key_fingerprint(&self) -> Result<String> {
let inner = self.lock_inner();
let d = inner.device.as_ref().ok_or(CoreError::NotConfigured)?;