models.rs (8125B)
1 use serde::{Deserialize, Serialize}; 2 use uuid::Uuid; 3 use axum::{ 4 response::{IntoResponse, Response}, 5 http::{StatusCode, header}, 6 }; 7 8 pub struct PrettyJson<T>(pub T); 9 10 impl<T> IntoResponse for PrettyJson<T> 11 where 12 T: Serialize, 13 { 14 fn into_response(self) -> Response { 15 match serde_json::to_string_pretty(&self.0) { 16 Ok(json) => ( 17 StatusCode::OK, 18 [(header::CONTENT_TYPE, "application/json")], 19 json, 20 ).into_response(), 21 Err(e) => ( 22 StatusCode::INTERNAL_SERVER_ERROR, 23 format!("Serialization error: {}", e), 24 ).into_response(), 25 } 26 } 27 } 28 29 #[derive(Debug, Deserialize, Serialize)] 30 pub struct SetupResponse { 31 pub nonce: String, 32 } 33 34 #[derive(Debug, Deserialize)] 35 pub struct AuthorizeQuery { 36 pub response_type: String, 37 pub client_id: String, 38 pub redirect_uri: String, 39 pub state: String, 40 pub scope: String, 41 } 42 43 #[derive(Debug, Deserialize, Serialize)] 44 pub struct AuthorizeResponse { 45 #[serde(rename = "verificationId")] 46 pub verification_id: Uuid, 47 pub verification_url: String, 48 #[serde(skip_serializing_if = "Option::is_none")] 49 pub verification_deeplink: Option<String>, 50 pub state: String, 51 } 52 53 #[derive(Debug, Deserialize, Serialize)] 54 pub struct TokenRequest { 55 pub grant_type: String, 56 pub code: String, 57 pub client_id: String, 58 pub client_secret: String, 59 pub redirect_uri: String, 60 } 61 62 #[derive(Debug, Deserialize, Serialize)] 63 pub struct TokenResponse { 64 pub access_token: String, 65 pub token_type: String, 66 pub expires_in: u64, 67 } 68 69 // Info endpoint 70 #[derive(Debug, Deserialize, Serialize, Clone)] 71 pub struct VerifiableCredential { 72 #[serde(flatten)] 73 pub data: serde_json::Value, 74 } 75 76 // Notification webhook from Swiyu Verifier 77 #[derive(Debug, Deserialize, Serialize)] 78 pub struct NotificationRequest { 79 pub verification_id: Uuid, 80 pub timestamp: String, 81 } 82 83 // Status endpoint 84 #[derive(Debug, Deserialize)] 85 pub struct StatusQuery { 86 pub state: String, 87 } 88 89 #[derive(Debug, Serialize)] 90 pub struct StatusResponse { 91 pub status: String, 92 } 93 94 #[derive(Debug, Serialize)] 95 pub struct ConfigResponse { 96 pub name: String, 97 pub version: String, 98 pub status: String, 99 pub vc_type: String, 100 pub vc_format: String, 101 pub vc_algorithms: Vec<String>, 102 pub vc_claims: Vec<String>, 103 } 104 105 // Notification payload sent to Client (Exchange, etc.) 106 #[derive(Debug, Serialize)] 107 pub struct ClientNotification { 108 pub nonce: String, 109 pub status: String, 110 pub code: String, 111 pub verification_id: Uuid, 112 pub timestamp: String, 113 } 114 115 // Error response 116 #[derive(Debug, Serialize, Deserialize)] 117 pub struct ErrorResponse { 118 pub error: String, 119 } 120 121 impl ErrorResponse { 122 pub fn new(error: impl Into<String>) -> Self { 123 Self { 124 error: error.into(), 125 } 126 } 127 } 128 129 // Swiyu Verifier API models 130 131 /// Request body for creating a verification with Swiyu Verifier 132 /// POST /management/api/verifications 133 /// 134 /// The verifier dropped DIF Presentation Exchange with its 3.0.0 release 135 /// ("Dropped support for SWIYU-API-Version 1"); `dcql_query` is the only way 136 /// to state what is to be presented and is a required field. Trust anchors 137 /// moved out of this request and into the verifier's own configuration 138 /// (`SWIYU_TRUST_ISSUER_DID`) in 5.0.0, and `response_type` is no longer part 139 /// of the schema, so neither is sent any more. 140 #[derive(Debug, Serialize, Deserialize)] 141 pub struct SwiyuCreateVerificationRequest { 142 pub accepted_issuer_dids: Vec<String>, 143 144 /// If omitted, Swiyu defaults to true (beta requires true) 145 #[serde(skip_serializing_if = "Option::is_none")] 146 pub jwt_secured_authorization_request: Option<bool>, 147 148 /// Response mode: how the wallet sends the response back 149 /// REQUIRED - will throw NullPointerException if omitted 150 pub response_mode: ResponseMode, 151 152 /// What the wallet is asked to present. REQUIRED by the verifier. 153 pub dcql_query: DcqlQuery, 154 155 pub configuration_override: ConfigurationOverride, 156 } 157 158 /// Response mode type 159 #[derive(Debug, Serialize, Deserialize, Clone)] 160 #[serde(rename_all = "snake_case")] 161 pub enum ResponseMode { 162 /// Wallet sends a clear text response 163 DirectPost, 164 165 /// Wallet sends an encrypted response 166 #[serde(rename = "direct_post.jwt")] 167 DirectPostJwt, 168 } 169 170 /// Configuration override for a specific verification 171 /// Can be empty object with all fields set to None 172 #[derive(Debug, Serialize, Deserialize, Clone, Default)] 173 pub struct ConfigurationOverride { 174 /// Override for the EXTERNAL_URL - the url the wallet should call 175 #[serde(skip_serializing_if = "Option::is_none")] 176 pub external_url: Option<String>, 177 178 #[serde(skip_serializing_if = "Option::is_none")] 179 pub verifier_did: Option<String>, 180 181 #[serde(skip_serializing_if = "Option::is_none")] 182 pub verification_method: Option<String>, 183 184 /// ID of the key in the HSM 185 #[serde(skip_serializing_if = "Option::is_none")] 186 pub key_id: Option<String>, 187 188 /// The pin which protects the key in the HSM 189 #[serde(skip_serializing_if = "Option::is_none")] 190 pub key_pin: Option<String>, 191 } 192 193 /// Identifier of the one credential query KyCH sends, and therefore the key 194 /// under which the verifier reports the disclosed claims back in 195 /// `wallet_response.dcql_response`. Must match `^[a-zA-Z0-9_-]+$`. 196 pub const DCQL_CREDENTIAL_ID: &str = "kych_verification"; 197 198 /// A DCQL query as defined in OpenID4VP 1.0 section 6. 199 #[derive(Debug, Serialize, Deserialize, Clone)] 200 pub struct DcqlQuery { 201 pub credentials: Vec<DcqlCredential>, 202 } 203 204 /// One credential query (OpenID4VP 1.0 section 6.1). 205 #[derive(Debug, Serialize, Deserialize, Clone)] 206 pub struct DcqlCredential { 207 /// Identifies this credential in the response; see `DCQL_CREDENTIAL_ID`. 208 pub id: String, 209 210 /// Credential format identifier; the verifier accepts `dc+sd-jwt` (the 211 /// canonical SD-JWT VC type) and still `vc+sd-jwt`. 212 pub format: String, 213 214 pub meta: DcqlCredentialMeta, 215 216 /// The claims to disclose. Omitted rather than sent empty, because the 217 /// verifier rejects an empty `claims` array. 218 #[serde(skip_serializing_if = "Option::is_none")] 219 pub claims: Option<Vec<DcqlClaim>>, 220 221 /// KyCH always requires holder binding: the credential must be presented 222 /// by the wallet that holds its key, not merely be known to it. 223 pub require_cryptographic_holder_binding: bool, 224 } 225 226 /// Metadata constraints of a credential query; for SD-JWT VCs the accepted 227 /// values of the `vct` claim. 228 #[derive(Debug, Serialize, Deserialize, Clone)] 229 pub struct DcqlCredentialMeta { 230 pub vct_values: Vec<String>, 231 } 232 233 /// One claims query (OpenID4VP 1.0 section 6.3). `path` is a claims path 234 /// pointer, so a top-level claim is a single-element path. 235 #[derive(Debug, Serialize, Deserialize, Clone)] 236 pub struct DcqlClaim { 237 pub path: Vec<String>, 238 } 239 240 /// Response from Swiyu Verifier Management API 241 /// Used for both POST /management/api/verifications and GET /management/api/verifications/{id} 242 #[derive(Debug, Serialize, Deserialize)] 243 pub struct SwiyuManagementResponse { 244 pub id: Uuid, 245 #[serde(skip_serializing_if = "Option::is_none")] 246 pub request_nonce: Option<String>, 247 pub state: SwiyuVerificationStatus, 248 pub verification_url: String, 249 #[serde(skip_serializing_if = "Option::is_none")] 250 pub verification_deeplink: Option<String>, 251 #[serde(skip_serializing_if = "Option::is_none")] 252 pub dcql_query: Option<serde_json::Value>, 253 #[serde(skip_serializing_if = "Option::is_none")] 254 pub wallet_response: Option<serde_json::Value>, 255 /// Per-credential trust and status results. Only present when the 256 /// verifier runs with `additional-audit-information.credential-evaluation-enabled`. 257 #[serde(skip_serializing_if = "Option::is_none")] 258 pub credential_evaluation: Option<serde_json::Value>, 259 } 260 261 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] 262 #[serde(rename_all = "UPPERCASE")] 263 pub enum SwiyuVerificationStatus { 264 Pending, 265 Success, 266 Failed, 267 }