v0.0.38: FC-P4 complete — session versioning, wire envelope, auto-backup
FC-P4-T1: Session State Versioning - RatchetState serialize/deserialize with [MAGIC:0xFC][VERSION:1][bincode] - Legacy (raw bincode) still loads — backward compatible - Client + WASM both use versioned format - 2 new tests: roundtrip + legacy compat FC-P4-T2: WireMessage Versioning Envelope - Format: [WZ magic][version:u8][length:u32 BE][bincode payload] - Server + client + WASM accept both envelope and legacy on receive - Client still sends raw bincode (server handles both) - Future version → "update required" error instead of crash - 3 new tests: roundtrip, legacy compat, future version rejection FC-P4-T3: Periodic Auto-Backup - Every 5 minutes, encrypts sessions+contacts+sender_keys to ~/.warzone/backups/ - HKDF-derived key from seed, ChaCha20-Poly1305 AEAD - Atomic writes (temp file + rename), rotates to keep last 3 - /backup command for manual trigger 127 tests passing (was 122) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -212,15 +212,16 @@ impl WasmSession {
|
||||
}
|
||||
|
||||
pub fn save(&self) -> Result<String, JsValue> {
|
||||
let bytes = bincode::serialize(&self.ratchet).map_err(|e| JsValue::from_str(&e.to_string()))?;
|
||||
let bytes = self.ratchet.serialize_versioned()
|
||||
.map_err(|e| JsValue::from_str(&e))?;
|
||||
Ok(base64::Engine::encode(&base64::engine::general_purpose::STANDARD, &bytes))
|
||||
}
|
||||
|
||||
pub fn restore(data: &str) -> Result<WasmSession, JsValue> {
|
||||
let bytes = base64::Engine::decode(&base64::engine::general_purpose::STANDARD, data)
|
||||
.map_err(|e| JsValue::from_str(&e.to_string()))?;
|
||||
let ratchet: RatchetState = bincode::deserialize(&bytes)
|
||||
.map_err(|e| JsValue::from_str(&e.to_string()))?;
|
||||
let ratchet = RatchetState::deserialize_versioned(&bytes)
|
||||
.map_err(|e| JsValue::from_str(&e))?;
|
||||
Ok(WasmSession { ratchet, x3dh_ephemeral_public: None, x3dh_used_otpk_id: None })
|
||||
}
|
||||
}
|
||||
@@ -372,7 +373,7 @@ pub fn decrypt_wire_message(
|
||||
let seed = Seed::from_bytes(sb);
|
||||
let id = seed.derive_identity();
|
||||
|
||||
let wire: WireMessage = bincode::deserialize(message_bytes)
|
||||
let wire: WireMessage = warzone_protocol::message::deserialize_envelope(message_bytes)
|
||||
.map_err(|e| JsValue::from_str(&format!("deserialize wire: {}", e)))?;
|
||||
|
||||
match wire {
|
||||
@@ -403,7 +404,7 @@ pub fn decrypt_wire_message(
|
||||
|
||||
let session_b64 = base64::Engine::encode(
|
||||
&base64::engine::general_purpose::STANDARD,
|
||||
&bincode::serialize(&ratchet).unwrap_or_default(),
|
||||
&ratchet.serialize_versioned().unwrap_or_default(),
|
||||
);
|
||||
|
||||
Ok(serde_json::json!({
|
||||
@@ -424,15 +425,15 @@ pub fn decrypt_wire_message(
|
||||
let session_bytes = base64::Engine::decode(
|
||||
&base64::engine::general_purpose::STANDARD, &session_data,
|
||||
).map_err(|e| JsValue::from_str(&e.to_string()))?;
|
||||
let mut ratchet: RatchetState = bincode::deserialize(&session_bytes)
|
||||
.map_err(|e| JsValue::from_str(&e.to_string()))?;
|
||||
let mut ratchet = RatchetState::deserialize_versioned(&session_bytes)
|
||||
.map_err(|e| JsValue::from_str(&e))?;
|
||||
|
||||
let plain = ratchet.decrypt(&ratchet_message)
|
||||
.map_err(|e| JsValue::from_str(&format!("decrypt: {}", e)))?;
|
||||
|
||||
let session_b64 = base64::Engine::encode(
|
||||
&base64::engine::general_purpose::STANDARD,
|
||||
&bincode::serialize(&ratchet).unwrap_or_default(),
|
||||
&ratchet.serialize_versioned().unwrap_or_default(),
|
||||
);
|
||||
|
||||
Ok(serde_json::json!({
|
||||
|
||||
Reference in New Issue
Block a user