An easy-to-host PDS on the ATProtocol, iPhone and MacOS. Maintain control of your keys and data, always.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(identity-wallet): address Phase 4 code review feedback

- C1: Run cargo fmt to fix formatting issues
- I1: Add submit_claim to FCIS pattern comment
- I2: Add defense-in-depth DID validation in submit_claim
- M1: Remove unused Arc, Mutex import in test_submit_claim_success

authored by

Malpercio and committed by
Tangled
cf060aee dd0905b1

+30 -22
+24 -20
apps/identity-wallet/src-tauri/src/claim.rs
··· 10 10 // endpoint on old PDS to trigger email verification) 11 11 // sign_and_verify_claim (command: calls getRecommendedDidCredentials and 12 12 // signPlcOperation on old PDS, verifies signature and local constraints) 13 + // submit_claim (command: POSTs signed PLC operation to plc.directory, 14 + // persists identity to IdentityStore, clears claim state) 13 15 14 16 use serde::Serialize; 15 17 use tauri::Emitter; ··· 887 889 }; 888 890 889 891 // Parse the stored JSON string back to Value 890 - let operation: serde_json::Value = serde_json::from_str(verified_signed_op_str) 891 - .map_err(|e| ClaimError::NetworkError { 892 + let operation: serde_json::Value = 893 + serde_json::from_str(verified_signed_op_str).map_err(|e| ClaimError::NetworkError { 892 894 message: format!("failed to parse verified signed operation: {}", e), 893 895 })?; 894 896 ··· 911 913 // 3a: Register DID in managed-dids index (may already exist from prior attempts) 912 914 if let Err(e) = store.add_identity(&claim_state.did) { 913 915 // IdentityAlreadyExists is fine — user may have a partially completed prior claim 914 - if !matches!(e, crate::identity_store::IdentityStoreError::IdentityAlreadyExists) { 916 + if !matches!( 917 + e, 918 + crate::identity_store::IdentityStoreError::IdentityAlreadyExists 919 + ) { 915 920 return Err(ClaimError::NetworkError { 916 921 message: format!("failed to add identity: {}", e), 917 922 }); ··· 919 924 } 920 925 921 926 // 3b: Ensure device key exists for the DID 922 - store.get_or_create_device_key(&claim_state.did).map_err(|e| { 923 - ClaimError::NetworkError { 927 + store 928 + .get_or_create_device_key(&claim_state.did) 929 + .map_err(|e| ClaimError::NetworkError { 924 930 message: format!("failed to get or create device key: {}", e), 925 - } 926 - })?; 931 + })?; 927 932 928 933 // 3c: Re-fetch the DID document from plc.directory 929 934 let (_, updated_did_doc) = pds_client 930 935 .discover_pds(&claim_state.did) 931 936 .await 932 - .map_err(|e| { 933 - ClaimError::NetworkError { 934 - message: format!("failed to re-fetch DID document: {}", e), 935 - } 937 + .map_err(|e| ClaimError::NetworkError { 938 + message: format!("failed to re-fetch DID document: {}", e), 936 939 })?; 937 940 938 941 // Store the updated DID document as JSON string ··· 952 955 .collect::<serde_json::Map<String, serde_json::Value>>() 953 956 }); 954 957 955 - let did_doc_json = serde_json::to_string(&did_doc_value).map_err(|e| { 956 - ClaimError::NetworkError { 958 + let did_doc_json = 959 + serde_json::to_string(&did_doc_value).map_err(|e| ClaimError::NetworkError { 957 960 message: format!("failed to serialize DID document: {}", e), 958 - } 959 - })?; 961 + })?; 960 962 961 963 store 962 964 .store_did_doc(&claim_state.did, &did_doc_json) ··· 990 992 #[tauri::command] 991 993 pub async fn submit_claim( 992 994 state: tauri::State<'_, crate::oauth::AppState>, 993 - _did: String, 995 + did: String, 994 996 ) -> Result<ClaimResult, ClaimError> { 995 997 let pds_client = state.pds_client(); 996 998 ··· 1003 1005 let Some(claim_state) = claim_state_copy else { 1004 1006 return Err(ClaimError::Unauthorized); 1005 1007 }; 1008 + 1009 + // Defense-in-depth: validate caller's DID matches ClaimState 1010 + if claim_state.did != did { 1011 + return Err(ClaimError::Unauthorized); 1012 + } 1006 1013 1007 1014 let result = submit_claim_impl(pds_client, &claim_state).await; 1008 1015 ··· 2297 2304 #[tokio::test] 2298 2305 async fn test_submit_claim_success() { 2299 2306 use httpmock::MockServer; 2300 - use std::sync::{Arc, Mutex}; 2301 2307 2302 2308 let mock_server = MockServer::start(); 2303 2309 ··· 2409 2415 services: std::collections::HashMap::new(), 2410 2416 }, 2411 2417 pds_oauth_client: None, 2412 - verified_signed_op: Some( 2413 - r#"{"type":"plc_operation","prev":"bafy123"}"#.to_string(), 2414 - ), 2418 + verified_signed_op: Some(r#"{"type":"plc_operation","prev":"bafy123"}"#.to_string()), 2415 2419 }; 2416 2420 2417 2421 let result = submit_claim_impl(&pds_client, &claim_state).await;
+6 -2
apps/identity-wallet/src-tauri/src/pds_client.rs
··· 1906 1906 "rotationKeys": ["did:key:z123"] 1907 1907 }); 1908 1908 1909 - let result = client.post_plc_operation("did:plc:test123", &operation).await; 1909 + let result = client 1910 + .post_plc_operation("did:plc:test123", &operation) 1911 + .await; 1910 1912 1911 1913 assert!(result.is_ok()); 1912 1914 } ··· 1926 1928 "type": "plc_operation" 1927 1929 }); 1928 1930 1929 - let result = client.post_plc_operation("did:plc:test123", &operation).await; 1931 + let result = client 1932 + .post_plc_operation("did:plc:test123", &operation) 1933 + .await; 1930 1934 1931 1935 assert!(result.is_err()); 1932 1936 match result.unwrap_err() {