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.

feat(identity-wallet): add NextStep enum to catch unrecognized relay values

Replaces `next_step: String` in CreateMobileAccountResponse and
CreateAccountResult with a typed `NextStep` enum. Serde rejects any
relay response with an unrecognized next_step value at deserialization
time, surfacing it as CreateAccountError::Unknown rather than silently
forwarding an unknown string to the frontend.

TypeScript now sees `nextStep: 'did_creation'` (a literal type), so
the redundant if/else check in +page.svelte is removed — the type
system and Rust enum together guarantee the value at this point.

Adds three NextStep serde tests: correct deserialization, correct
serialization, and rejection of unknown values.

authored by

Malpercio and committed by
Tangled
cbf43921 3b7b90ce

+37 -11
+33 -3
apps/identity-wallet/src-tauri/src/lib.rs
··· 29 29 struct CreateMobileAccountResponse { 30 30 device_token: String, 31 31 session_token: String, 32 - next_step: String, 32 + next_step: NextStep, 33 33 } 34 34 35 35 /// Relay error envelope: { "error": { "code": "...", "message": "..." } } ··· 45 45 46 46 // ── IPC result / error types (returned to the frontend) ───────────────────── 47 47 48 + /// The next step the client should take after successful account creation. 49 + /// 50 + /// If the relay returns an unrecognized value, serde deserialization fails and 51 + /// `create_account` returns `CreateAccountError::Unknown` — unrecognized relay 52 + /// protocol values are caught here rather than silently forwarded to the frontend. 53 + #[derive(Debug, Deserialize, Serialize, PartialEq)] 54 + #[serde(rename_all = "snake_case")] 55 + pub enum NextStep { 56 + DidCreation, 57 + } 58 + 48 59 /// Successful result returned to the Svelte frontend. 49 60 #[derive(Serialize)] 50 61 #[serde(rename_all = "camelCase")] 51 62 pub struct CreateAccountResult { 52 - pub next_step: String, 63 + pub next_step: NextStep, 53 64 } 54 65 55 66 /// Typed error returned to the Svelte frontend as a rejected Promise. ··· 210 221 #[test] 211 222 fn create_account_result_serializes_camel_case() { 212 223 let result = CreateAccountResult { 213 - next_step: "did_creation".into(), 224 + next_step: NextStep::DidCreation, 214 225 }; 215 226 let json = serde_json::to_value(&result).unwrap(); 216 227 assert_eq!(json["nextStep"], "did_creation"); 228 + } 229 + 230 + // -- NextStep serde round-trip -- 231 + #[test] 232 + fn next_step_did_creation_deserializes_correctly() { 233 + let result: NextStep = serde_json::from_str(r#""did_creation""#).unwrap(); 234 + assert_eq!(result, NextStep::DidCreation); 235 + } 236 + 237 + #[test] 238 + fn next_step_did_creation_serializes_correctly() { 239 + let json = serde_json::to_value(NextStep::DidCreation).unwrap(); 240 + assert_eq!(json, "did_creation"); 241 + } 242 + 243 + #[test] 244 + fn next_step_unknown_value_fails_deserialization() { 245 + let result: Result<NextStep, _> = serde_json::from_str(r#""email_verification""#); 246 + assert!(result.is_err()); 217 247 } 218 248 219 249 // -- AC3.1: CreateAccountError::ExpiredCode serialization --
+1 -1
apps/identity-wallet/src/lib/ipc.ts
··· 13 13 * This is a pure data shape returned on success. 14 14 */ 15 15 export type CreateAccountResult = { 16 - nextStep: string; 16 + nextStep: 'did_creation'; 17 17 }; 18 18 19 19 /**
+3 -7
apps/identity-wallet/src/routes/+page.svelte
··· 57 57 handle: form.handle, 58 58 }); 59 59 60 - if (result.nextStep === 'did_creation') { 61 - step = 'did_ceremony'; 62 - } else { 63 - // Unexpected nextStep value — treat as success and advance anyway. 64 - console.error('Unexpected nextStep:', result.nextStep); 65 - step = 'did_ceremony'; 66 - } 60 + // Rust guarantees nextStep is 'did_creation' on success; unrecognized 61 + // relay values fail deserialization and surface as CreateAccountError::Unknown. 62 + step = 'did_ceremony'; 67 63 } catch (raw: unknown) { 68 64 // Guard against non-CreateAccountError shapes (e.g. JS runtime errors). 69 65 if (