1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#![doc = include_str!("../README.md")]
use serde::{Deserialize, Serialize};
mod b64url;
mod credential_scope;
mod document;
mod editable_field;
mod extensions;
mod identity;
mod login;
mod passkey;
pub use self::{
b64url::*, credential_scope::*, document::*, editable_field::*, extensions::*, identity::*,
login::*, passkey::*,
};
type Uri = String;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", bound(deserialize = "E: Deserialize<'de>"))]
pub struct Header<E = ()> {
/// The version of the format definition contained within this exchange payload. The version
/// MUST correspond to a published level of the CXF standard.
pub version: Version,
/// The name of the exporting app as a [relying party identifier](https://www.w3.org/TR/webauthn-3/#relying-party-identifier).
pub exporter_rp_id: String,
/// The display name of the exporting app to be presented to the user.
pub exporter_display_name: String,
/// The UNIX timestamp during at which the export document was completed.
pub timestamp: u64,
/// The list of [Account]s being exported.
pub accounts: Vec<Account<E>>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Version {
/// The major version of the payload's format. Changes to this version indicates an
/// incompatible breaking change with previous versions.
pub major: u8,
/// The minor version of the payload's format. Changes to this version indicates new
/// functionality which is purely additive and that is compatible with previous versions under
/// the same [Version::major].
pub minor: u8,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", bound(deserialize = "E: Deserialize<'de>"))]
pub struct Account<E = ()> {
/// A unique identifier for the [Account] which is machine generated and an opaque byte
/// sequence with a maximum size of 64 bytes. It SHOULD NOT to be displayed to the user.
pub id: B64Url,
/// A pseudonym defined by the user to name their account. If none is set, this should be an
/// empty string.
pub username: String,
/// The email used to register the account in the previous provider.
pub email: String,
/// This field holds the user’s full name.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub full_name: Option<String>,
/// All the collections this account owns. If the user has collections that were shared with
/// them by another account, it MUST NOT be present in this list.
pub collections: Vec<Collection<E>>,
/// All items that this account owns. If the user has access to items that were shared with
/// them by another account, it MUST NOT be present in this list.
pub items: Vec<Item<E>>,
/// This field contains all the extensions to the [Account]’s attributes.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<Vec<Extension<E>>>, // default []
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", bound(deserialize = "E: Deserialize<'de>"))]
pub struct Collection<E = ()> {
/// A unique identifier for the [Collection] which is machine generated and an opaque byte
/// sequence with a maximum size of 64 bytes. It SHOULD NOT be displayed to the user.
pub id: B64Url,
/// This member contains the UNIX timestamp in seconds at which this [Collection] was
/// originally created. If this member is not set, but the importing provider requires this
/// member in their proprietary data model, the importer SHOULD use the current timestamp at
/// the time the provider encounters this 8Collection].
#[serde(default, skip_serializing_if = "Option::is_none")]
pub creation_at: Option<u64>,
/// This member contains the UNIX timestamp in seconds of the last modification brought to this
/// [Collection]. If this member is not set, but the importing provider requires this member in
/// their proprietary data model, the importer SHOULD use the current timestamp at the time the
/// provider encounters this [Collection].
#[serde(default, skip_serializing_if = "Option::is_none")]
pub modified_at: Option<u64>,
/// The display name of the [Collection].
pub title: String,
/// This field is a subtitle or a description of the [Collection].
#[serde(default, skip_serializing_if = "Option::is_none")]
pub subtitle: Option<String>,
/// Enumerates all the [LinkedItem] in this [Collection]. A [LinkedItem] contains the necessary
/// data to indicate which [Items][Item] are part of this [Collection].
pub items: Vec<LinkedItem>,
#[serde(default, skip_serializing_if = "Option::is_none")]
/// Enumerates any sub-collections if the provider supports recursive organization.
pub sub_collections: Option<Vec<Collection<E>>>,
/// This enumeration contains all the extensions to the [Collection]’s attributes.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<Vec<Extension<E>>>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LinkedItem {
/// The [Item’s id][Item::id] that this [LinkedItem] refers to. Note that this [Item] might not
/// be sent as part of the current exchange.
pub item: B64Url,
/// This member indicates the [Account’s id][Account::id] the referenced [Item] belongs to. If
/// not present, the [Item] belongs to the current [Account] being exchanged.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub account: Option<B64Url>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", bound(deserialize = "E: Deserialize<'de>"))]
pub struct Item<E = ()> {
/// A unique identifier for the [Item] which is machine generated and an opaque byte sequence
/// with a maximum size of 64 bytes. It SHOULD NOT be displayed to the user.
pub id: B64Url,
/// The member contains the UNIX timestamp in seconds at which this item was originally
/// created. If this member is not set, but the importing provider requires this
/// member in their proprietary data model, the importer SHOULD use the current timestamp
/// at the time the provider encounters this [Item].
#[serde(default, skip_serializing_if = "Option::is_none")]
pub creation_at: Option<u64>,
/// This member contains the UNIX timestamp in seconds of the last modification brought to this
/// [Item]. If this member is not set, but the importing provider requires this member in
/// their proprietary data model, the importer SHOULD use the current timestamp at the time
/// the provider encounters this [Item].
#[serde(default, skip_serializing_if = "Option::is_none")]
pub modified_at: Option<u64>,
/// This member’s value is the user-defined name or title of the item.
pub title: String,
/// This member is a subtitle or description for the [Item].
#[serde(default, skip_serializing_if = "Option::is_none")]
pub subtitle: Option<String>,
/// This member denotes whether the user has marked the [Item] as a favorite to easily present
/// in the UI.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub favorite: Option<bool>,
/// This member defines the scope where the [Item::credentials] SHOULD be presented. The
/// credentials SHOULD only be presented within this scope unless otherwise specified by a
/// specific [Credential] type.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub scope: Option<CredentialScope>,
/// This member contains a set of [Credentials][Item::credentials] that SHOULD be associated to
/// the type.
pub credentials: Vec<Credential<E>>,
/// This member contains user-defined tags that they may use to organize the item.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<String>>,
/// This member contains all the extensions the exporter MAY have to define the [Item] type
/// that is being exported to be as complete of an export as possible.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<Vec<Extension<E>>>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(
tag = "type",
rename_all = "kebab-case",
bound(deserialize = "E: Deserialize<'de>")
)]
#[non_exhaustive]
pub enum Credential<E = ()> {
Address(Box<AddressCredential<E>>),
ApiKey(Box<ApiKeyCredential<E>>),
BasicAuth(Box<BasicAuthCredential<E>>),
CreditCard(Box<CreditCardCredential<E>>),
CustomFields(Box<CustomFieldsCredential<E>>),
DriversLicense(Box<DriversLicenseCredential<E>>),
File(Box<FileCredential>),
GeneratedPassword(Box<GeneratedPasswordCredential>),
IdentityDocument(Box<IdentityDocumentCredential<E>>),
ItemReference(Box<ItemReferenceCredential>),
Note(Box<NoteCredential<E>>),
Passkey(Box<PasskeyCredential>),
Passport(Box<PassportCredential<E>>),
PersonName(Box<PersonNameCredential<E>>),
SshKey(Box<SshKeyCredential<E>>),
Totp(Box<TotpCredential>),
Wifi(Box<WifiCredential<E>>),
#[serde(untagged)]
Unknown {
ty: String,
#[serde(flatten)]
content: serde_json::Map<String, serde_json::Value>,
},
}
/// An [ItemReferenceCredential] is a pointer to another [Item], denoting that the two items MAY be
/// logically linked together.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemReferenceCredential {
/// A [LinkedItem] which references another [Item].
///
/// **Note**: The other [item][Item] SHOULD be in the exchange if it is owned by the same
/// [Account]. However, the other item MAY NOT be in the exchange if it is owned by a different
/// account and shared with the currenly exchanged account.
pub reference: LinkedItem,
}