//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `auth/passkey/enroll/start`. Version: `0.2`.
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
/// Error types.
pub mod error {
/// Error from a `TryFrom` or `FromStr` implementation.
pub struct ConversionError(::std::borrow::Cow<'static, str>);
impl ::std::error::Error for ConversionError {}
impl ::std::fmt::Display for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Display::fmt(&self.0, f)
}
}
impl ::std::fmt::Debug for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Debug::fmt(&self.0, f)
}
}
impl From<&'static str> for ConversionError {
fn from(value: &'static str) -> Self {
Self(value.into())
}
}
impl From<String> for ConversionError {
fn from(value: String) -> Self {
Self(value.into())
}
}
}
///Server-issued options for `navigator.credentials.create({ publicKey: ... })`. Mirrors the WebAuthn Level 2 `PublicKeyCredentialCreationOptions` dictionary; binary fields are base64url-encoded strings (rather than ArrayBuffers) so the value is JSON-safe over the wire.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "PublicKeyCredentialCreationOptions",
/// "description": "Server-issued options for `navigator.credentials.create({ publicKey: ... })`. Mirrors the WebAuthn Level 2 `PublicKeyCredentialCreationOptions` dictionary; binary fields are base64url-encoded strings (rather than ArrayBuffers) so the value is JSON-safe over the wire.",
/// "type": "object",
/// "required": [
/// "challenge",
/// "pubKeyCredParams",
/// "rp",
/// "user"
/// ],
/// "properties": {
/// "attestation": {
/// "enum": [
/// "none",
/// "indirect",
/// "direct",
/// "enterprise"
/// ]
/// },
/// "authenticatorSelection": {
/// "type": "object",
/// "properties": {
/// "authenticatorAttachment": {
/// "enum": [
/// "platform",
/// "cross-platform"
/// ]
/// },
/// "requireResidentKey": {
/// "type": "boolean"
/// },
/// "residentKey": {
/// "enum": [
/// "discouraged",
/// "preferred",
/// "required"
/// ]
/// },
/// "userVerification": {
/// "enum": [
/// "discouraged",
/// "preferred",
/// "required"
/// ]
/// }
/// },
/// "additionalProperties": false
/// },
/// "challenge": {
/// "description": "base64url-encoded one-time nonce.",
/// "type": "string"
/// },
/// "excludeCredentials": {
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/CredentialDescriptor"
/// }
/// },
/// "extensions": {
/// "description": "\nClient extension inputs, per the WebAuthn Level 2 `AuthenticationExtensionsClientInputs` dictionary.\n\nThis component states that it mirrors the W3C dictionary, and that dictionary defines `extensions`. Omitting it while closing the object with `additionalProperties: false` made the two claims contradict each other: a server emitting standard WebAuthn options could not conform, and the widely-used server libraries emit this member by default.\n\nStructure is deliberately unconstrained. The set of extensions is open and registered outside this framework, so enumerating them here would date the schema against a registry it does not own — and a closed list would reproduce the original defect one revision later.",
/// "type": "object"
/// },
/// "pubKeyCredParams": {
/// "type": "array",
/// "items": {
/// "type": "object",
/// "required": [
/// "alg",
/// "type"
/// ],
/// "properties": {
/// "alg": {
/// "description": "COSE algorithm identifier (e.g. -8 Ed25519, -7 ES256, -257 RS256).",
/// "type": "integer"
/// },
/// "type": {
/// "const": "public-key"
/// }
/// },
/// "additionalProperties": false
/// },
/// "minItems": 1
/// },
/// "rp": {
/// "type": "object",
/// "required": [
/// "id",
/// "name"
/// ],
/// "properties": {
/// "id": {
/// "type": "string",
/// "minLength": 1
/// },
/// "name": {
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
/// },
/// "timeout": {
/// "type": "integer",
/// "minimum": 1.0
/// },
/// "user": {
/// "type": "object",
/// "required": [
/// "displayName",
/// "id",
/// "name"
/// ],
/// "properties": {
/// "displayName": {
/// "type": "string",
/// "maxLength": 64
/// },
/// "id": {
/// "description": "base64url-encoded user handle. SHOULD be a stable opaque identifier — never reuse a human-readable username here.",
/// "type": "string"
/// },
/// "name": {
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "credentialCreationOptions"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CredentialCreationOptions {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub attestation: ::std::option::Option<CredentialCreationOptionsAttestation>,
#[serde(
rename = "authenticatorSelection",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub authenticator_selection:
::std::option::Option<CredentialCreationOptionsAuthenticatorSelection>,
///base64url-encoded one-time nonce.
pub challenge: ::std::string::String,
#[serde(
rename = "excludeCredentials",
default,
skip_serializing_if = "::std::vec::Vec::is_empty"
)]
pub exclude_credentials: ::std::vec::Vec<CredentialDescriptor>,
/**
Client extension inputs, per the WebAuthn Level 2 `AuthenticationExtensionsClientInputs` dictionary.
This component states that it mirrors the W3C dictionary, and that dictionary defines `extensions`. Omitting it while closing the object with `additionalProperties: false` made the two claims contradict each other: a server emitting standard WebAuthn options could not conform, and the widely-used server libraries emit this member by default.
Structure is deliberately unconstrained. The set of extensions is open and registered outside this framework, so enumerating them here would date the schema against a registry it does not own — and a closed list would reproduce the original defect one revision later.*/
#[serde(default, skip_serializing_if = "::serde_json::Map::is_empty")]
pub extensions: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
#[serde(rename = "pubKeyCredParams")]
pub pub_key_cred_params: ::std::vec::Vec<CredentialCreationOptionsPubKeyCredParamsItem>,
pub rp: CredentialCreationOptionsRp,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub timeout: ::std::option::Option<::std::num::NonZeroU64>,
pub user: CredentialCreationOptionsUser,
}
impl CredentialCreationOptions {
pub fn builder() -> builder::CredentialCreationOptions {
Default::default()
}
}
///`CredentialCreationOptionsAttestation`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "enum": [
/// "none",
/// "indirect",
/// "direct",
/// "enterprise"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum CredentialCreationOptionsAttestation {
#[serde(rename = "none")]
None,
#[serde(rename = "indirect")]
Indirect,
#[serde(rename = "direct")]
Direct,
#[serde(rename = "enterprise")]
Enterprise,
}
impl ::std::fmt::Display for CredentialCreationOptionsAttestation {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::None => f.write_str("none"),
Self::Indirect => f.write_str("indirect"),
Self::Direct => f.write_str("direct"),
Self::Enterprise => f.write_str("enterprise"),
}
}
}
impl ::std::str::FromStr for CredentialCreationOptionsAttestation {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"none" => Ok(Self::None),
"indirect" => Ok(Self::Indirect),
"direct" => Ok(Self::Direct),
"enterprise" => Ok(Self::Enterprise),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for CredentialCreationOptionsAttestation {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for CredentialCreationOptionsAttestation {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for CredentialCreationOptionsAttestation {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`CredentialCreationOptionsAuthenticatorSelection`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "properties": {
/// "authenticatorAttachment": {
/// "enum": [
/// "platform",
/// "cross-platform"
/// ]
/// },
/// "requireResidentKey": {
/// "type": "boolean"
/// },
/// "residentKey": {
/// "enum": [
/// "discouraged",
/// "preferred",
/// "required"
/// ]
/// },
/// "userVerification": {
/// "enum": [
/// "discouraged",
/// "preferred",
/// "required"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CredentialCreationOptionsAuthenticatorSelection {
#[serde(
rename = "authenticatorAttachment",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub authenticator_attachment: ::std::option::Option<
CredentialCreationOptionsAuthenticatorSelectionAuthenticatorAttachment,
>,
#[serde(
rename = "requireResidentKey",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub require_resident_key: ::std::option::Option<bool>,
#[serde(
rename = "residentKey",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub resident_key:
::std::option::Option<CredentialCreationOptionsAuthenticatorSelectionResidentKey>,
#[serde(
rename = "userVerification",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub user_verification:
::std::option::Option<CredentialCreationOptionsAuthenticatorSelectionUserVerification>,
}
impl ::std::default::Default for CredentialCreationOptionsAuthenticatorSelection {
fn default() -> Self {
Self {
authenticator_attachment: Default::default(),
require_resident_key: Default::default(),
resident_key: Default::default(),
user_verification: Default::default(),
}
}
}
impl CredentialCreationOptionsAuthenticatorSelection {
pub fn builder() -> builder::CredentialCreationOptionsAuthenticatorSelection {
Default::default()
}
}
///`CredentialCreationOptionsAuthenticatorSelectionAuthenticatorAttachment`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "enum": [
/// "platform",
/// "cross-platform"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum CredentialCreationOptionsAuthenticatorSelectionAuthenticatorAttachment {
#[serde(rename = "platform")]
Platform,
#[serde(rename = "cross-platform")]
CrossPlatform,
}
impl ::std::fmt::Display
for CredentialCreationOptionsAuthenticatorSelectionAuthenticatorAttachment
{
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Platform => f.write_str("platform"),
Self::CrossPlatform => f.write_str("cross-platform"),
}
}
}
impl ::std::str::FromStr
for CredentialCreationOptionsAuthenticatorSelectionAuthenticatorAttachment
{
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"platform" => Ok(Self::Platform),
"cross-platform" => Ok(Self::CrossPlatform),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str>
for CredentialCreationOptionsAuthenticatorSelectionAuthenticatorAttachment
{
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String>
for CredentialCreationOptionsAuthenticatorSelectionAuthenticatorAttachment
{
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String>
for CredentialCreationOptionsAuthenticatorSelectionAuthenticatorAttachment
{
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`CredentialCreationOptionsAuthenticatorSelectionResidentKey`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "enum": [
/// "discouraged",
/// "preferred",
/// "required"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum CredentialCreationOptionsAuthenticatorSelectionResidentKey {
#[serde(rename = "discouraged")]
Discouraged,
#[serde(rename = "preferred")]
Preferred,
#[serde(rename = "required")]
Required,
}
impl ::std::fmt::Display for CredentialCreationOptionsAuthenticatorSelectionResidentKey {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Discouraged => f.write_str("discouraged"),
Self::Preferred => f.write_str("preferred"),
Self::Required => f.write_str("required"),
}
}
}
impl ::std::str::FromStr for CredentialCreationOptionsAuthenticatorSelectionResidentKey {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"discouraged" => Ok(Self::Discouraged),
"preferred" => Ok(Self::Preferred),
"required" => Ok(Self::Required),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for CredentialCreationOptionsAuthenticatorSelectionResidentKey {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String>
for CredentialCreationOptionsAuthenticatorSelectionResidentKey
{
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String>
for CredentialCreationOptionsAuthenticatorSelectionResidentKey
{
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`CredentialCreationOptionsAuthenticatorSelectionUserVerification`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "enum": [
/// "discouraged",
/// "preferred",
/// "required"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum CredentialCreationOptionsAuthenticatorSelectionUserVerification {
#[serde(rename = "discouraged")]
Discouraged,
#[serde(rename = "preferred")]
Preferred,
#[serde(rename = "required")]
Required,
}
impl ::std::fmt::Display for CredentialCreationOptionsAuthenticatorSelectionUserVerification {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Discouraged => f.write_str("discouraged"),
Self::Preferred => f.write_str("preferred"),
Self::Required => f.write_str("required"),
}
}
}
impl ::std::str::FromStr for CredentialCreationOptionsAuthenticatorSelectionUserVerification {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"discouraged" => Ok(Self::Discouraged),
"preferred" => Ok(Self::Preferred),
"required" => Ok(Self::Required),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str>
for CredentialCreationOptionsAuthenticatorSelectionUserVerification
{
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String>
for CredentialCreationOptionsAuthenticatorSelectionUserVerification
{
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String>
for CredentialCreationOptionsAuthenticatorSelectionUserVerification
{
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`CredentialCreationOptionsPubKeyCredParamsItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "alg",
/// "type"
/// ],
/// "properties": {
/// "alg": {
/// "description": "COSE algorithm identifier (e.g. -8 Ed25519, -7 ES256, -257 RS256).",
/// "type": "integer"
/// },
/// "type": {
/// "const": "public-key"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CredentialCreationOptionsPubKeyCredParamsItem {
///COSE algorithm identifier (e.g. -8 Ed25519, -7 ES256, -257 RS256).
pub alg: i64,
#[serde(rename = "type")]
pub type_: ::serde_json::Value,
}
impl CredentialCreationOptionsPubKeyCredParamsItem {
pub fn builder() -> builder::CredentialCreationOptionsPubKeyCredParamsItem {
Default::default()
}
}
///`CredentialCreationOptionsRp`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "id",
/// "name"
/// ],
/// "properties": {
/// "id": {
/// "type": "string",
/// "minLength": 1
/// },
/// "name": {
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CredentialCreationOptionsRp {
pub id: CredentialCreationOptionsRpId,
pub name: CredentialCreationOptionsRpName,
}
impl CredentialCreationOptionsRp {
pub fn builder() -> builder::CredentialCreationOptionsRp {
Default::default()
}
}
///`CredentialCreationOptionsRpId`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct CredentialCreationOptionsRpId(::std::string::String);
impl ::std::ops::Deref for CredentialCreationOptionsRpId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<CredentialCreationOptionsRpId> for ::std::string::String {
fn from(value: CredentialCreationOptionsRpId) -> Self {
value.0
}
}
impl ::std::str::FromStr for CredentialCreationOptionsRpId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for CredentialCreationOptionsRpId {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for CredentialCreationOptionsRpId {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for CredentialCreationOptionsRpId {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for CredentialCreationOptionsRpId {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///`CredentialCreationOptionsRpName`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct CredentialCreationOptionsRpName(::std::string::String);
impl ::std::ops::Deref for CredentialCreationOptionsRpName {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<CredentialCreationOptionsRpName> for ::std::string::String {
fn from(value: CredentialCreationOptionsRpName) -> Self {
value.0
}
}
impl ::std::str::FromStr for CredentialCreationOptionsRpName {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 64usize {
return Err("longer than 64 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for CredentialCreationOptionsRpName {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for CredentialCreationOptionsRpName {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for CredentialCreationOptionsRpName {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for CredentialCreationOptionsRpName {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///`CredentialCreationOptionsUser`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "displayName",
/// "id",
/// "name"
/// ],
/// "properties": {
/// "displayName": {
/// "type": "string",
/// "maxLength": 64
/// },
/// "id": {
/// "description": "base64url-encoded user handle. SHOULD be a stable opaque identifier — never reuse a human-readable username here.",
/// "type": "string"
/// },
/// "name": {
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CredentialCreationOptionsUser {
#[serde(rename = "displayName")]
pub display_name: CredentialCreationOptionsUserDisplayName,
///base64url-encoded user handle. SHOULD be a stable opaque identifier — never reuse a human-readable username here.
pub id: ::std::string::String,
pub name: CredentialCreationOptionsUserName,
}
impl CredentialCreationOptionsUser {
pub fn builder() -> builder::CredentialCreationOptionsUser {
Default::default()
}
}
///`CredentialCreationOptionsUserDisplayName`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 64
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct CredentialCreationOptionsUserDisplayName(::std::string::String);
impl ::std::ops::Deref for CredentialCreationOptionsUserDisplayName {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<CredentialCreationOptionsUserDisplayName> for ::std::string::String {
fn from(value: CredentialCreationOptionsUserDisplayName) -> Self {
value.0
}
}
impl ::std::str::FromStr for CredentialCreationOptionsUserDisplayName {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 64usize {
return Err("longer than 64 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for CredentialCreationOptionsUserDisplayName {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for CredentialCreationOptionsUserDisplayName {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for CredentialCreationOptionsUserDisplayName {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for CredentialCreationOptionsUserDisplayName {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///`CredentialCreationOptionsUserName`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct CredentialCreationOptionsUserName(::std::string::String);
impl ::std::ops::Deref for CredentialCreationOptionsUserName {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<CredentialCreationOptionsUserName> for ::std::string::String {
fn from(value: CredentialCreationOptionsUserName) -> Self {
value.0
}
}
impl ::std::str::FromStr for CredentialCreationOptionsUserName {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 64usize {
return Err("longer than 64 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for CredentialCreationOptionsUserName {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for CredentialCreationOptionsUserName {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for CredentialCreationOptionsUserName {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for CredentialCreationOptionsUserName {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///`CredentialDescriptor`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "PublicKeyCredentialDescriptor",
/// "type": "object",
/// "required": [
/// "id",
/// "type"
/// ],
/// "properties": {
/// "id": {
/// "description": "base64url-encoded credential id.",
/// "type": "string"
/// },
/// "transports": {
/// "type": "array",
/// "items": {
/// "enum": [
/// "usb",
/// "nfc",
/// "ble",
/// "internal",
/// "hybrid"
/// ]
/// }
/// },
/// "type": {
/// "const": "public-key"
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "credentialDescriptor"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CredentialDescriptor {
///base64url-encoded credential id.
pub id: ::std::string::String,
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub transports: ::std::vec::Vec<CredentialDescriptorTransportsItem>,
#[serde(rename = "type")]
pub type_: ::serde_json::Value,
}
impl CredentialDescriptor {
pub fn builder() -> builder::CredentialDescriptor {
Default::default()
}
}
///`CredentialDescriptorTransportsItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "enum": [
/// "usb",
/// "nfc",
/// "ble",
/// "internal",
/// "hybrid"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum CredentialDescriptorTransportsItem {
#[serde(rename = "usb")]
Usb,
#[serde(rename = "nfc")]
Nfc,
#[serde(rename = "ble")]
Ble,
#[serde(rename = "internal")]
Internal,
#[serde(rename = "hybrid")]
Hybrid,
}
impl ::std::fmt::Display for CredentialDescriptorTransportsItem {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Usb => f.write_str("usb"),
Self::Nfc => f.write_str("nfc"),
Self::Ble => f.write_str("ble"),
Self::Internal => f.write_str("internal"),
Self::Hybrid => f.write_str("hybrid"),
}
}
}
impl ::std::str::FromStr for CredentialDescriptorTransportsItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"usb" => Ok(Self::Usb),
"nfc" => Ok(Self::Nfc),
"ble" => Ok(Self::Ble),
"internal" => Ok(Self::Internal),
"hybrid" => Ok(Self::Hybrid),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for CredentialDescriptorTransportsItem {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for CredentialDescriptorTransportsItem {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for CredentialDescriptorTransportsItem {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Server-issued options for `navigator.credentials.get({ publicKey: ... })`.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "PublicKeyCredentialRequestOptions",
/// "description": "Server-issued options for `navigator.credentials.get({ publicKey: ... })`.",
/// "type": "object",
/// "required": [
/// "challenge"
/// ],
/// "properties": {
/// "allowCredentials": {
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/CredentialDescriptor"
/// }
/// },
/// "challenge": {
/// "description": "base64url-encoded one-time nonce.",
/// "type": "string"
/// },
/// "extensions": {
/// "description": "\nClient extension inputs, per the WebAuthn Level 2 `AuthenticationExtensionsClientInputs` dictionary.\n\nThis component states that it mirrors the W3C dictionary, and that dictionary defines `extensions`. Omitting it while closing the object with `additionalProperties: false` made the two claims contradict each other: a server emitting standard WebAuthn options could not conform, and the widely-used server libraries emit this member by default.\n\nStructure is deliberately unconstrained. The set of extensions is open and registered outside this framework, so enumerating them here would date the schema against a registry it does not own — and a closed list would reproduce the original defect one revision later.",
/// "type": "object"
/// },
/// "rpId": {
/// "type": "string",
/// "minLength": 1
/// },
/// "timeout": {
/// "type": "integer",
/// "minimum": 1.0
/// },
/// "userVerification": {
/// "enum": [
/// "discouraged",
/// "preferred",
/// "required"
/// ]
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "credentialRequestOptions"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CredentialRequestOptions {
#[serde(
rename = "allowCredentials",
default,
skip_serializing_if = "::std::vec::Vec::is_empty"
)]
pub allow_credentials: ::std::vec::Vec<CredentialDescriptor>,
///base64url-encoded one-time nonce.
pub challenge: ::std::string::String,
/**
Client extension inputs, per the WebAuthn Level 2 `AuthenticationExtensionsClientInputs` dictionary.
This component states that it mirrors the W3C dictionary, and that dictionary defines `extensions`. Omitting it while closing the object with `additionalProperties: false` made the two claims contradict each other: a server emitting standard WebAuthn options could not conform, and the widely-used server libraries emit this member by default.
Structure is deliberately unconstrained. The set of extensions is open and registered outside this framework, so enumerating them here would date the schema against a registry it does not own — and a closed list would reproduce the original defect one revision later.*/
#[serde(default, skip_serializing_if = "::serde_json::Map::is_empty")]
pub extensions: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
#[serde(
rename = "rpId",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub rp_id: ::std::option::Option<CredentialRequestOptionsRpId>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub timeout: ::std::option::Option<::std::num::NonZeroU64>,
#[serde(
rename = "userVerification",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub user_verification: ::std::option::Option<CredentialRequestOptionsUserVerification>,
}
impl CredentialRequestOptions {
pub fn builder() -> builder::CredentialRequestOptions {
Default::default()
}
}
///`CredentialRequestOptionsRpId`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct CredentialRequestOptionsRpId(::std::string::String);
impl ::std::ops::Deref for CredentialRequestOptionsRpId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<CredentialRequestOptionsRpId> for ::std::string::String {
fn from(value: CredentialRequestOptionsRpId) -> Self {
value.0
}
}
impl ::std::str::FromStr for CredentialRequestOptionsRpId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for CredentialRequestOptionsRpId {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for CredentialRequestOptionsRpId {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for CredentialRequestOptionsRpId {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for CredentialRequestOptionsRpId {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///`CredentialRequestOptionsUserVerification`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "enum": [
/// "discouraged",
/// "preferred",
/// "required"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum CredentialRequestOptionsUserVerification {
#[serde(rename = "discouraged")]
Discouraged,
#[serde(rename = "preferred")]
Preferred,
#[serde(rename = "required")]
Required,
}
impl ::std::fmt::Display for CredentialRequestOptionsUserVerification {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Discouraged => f.write_str("discouraged"),
Self::Preferred => f.write_str("preferred"),
Self::Required => f.write_str("required"),
}
}
}
impl ::std::str::FromStr for CredentialRequestOptionsUserVerification {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"discouraged" => Ok(Self::Discouraged),
"preferred" => Ok(Self::Preferred),
"required" => Ok(Self::Required),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for CredentialRequestOptionsUserVerification {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for CredentialRequestOptionsUserVerification {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for CredentialRequestOptionsUserVerification {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Ext",
/// "description": "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.",
/// "type": "object",
/// "minProperties": 1,
/// "additionalProperties": true,
/// "propertyNames": {
/// "pattern": "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$"
/// }
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct Ext(pub ::std::collections::HashMap<ExtKey, ::serde_json::Value>);
impl ::std::ops::Deref for Ext {
type Target = ::std::collections::HashMap<ExtKey, ::serde_json::Value>;
fn deref(&self) -> &::std::collections::HashMap<ExtKey, ::serde_json::Value> {
&self.0
}
}
impl ::std::convert::From<Ext> for ::std::collections::HashMap<ExtKey, ::serde_json::Value> {
fn from(value: Ext) -> Self {
value.0
}
}
impl ::std::convert::From<::std::collections::HashMap<ExtKey, ::serde_json::Value>> for Ext {
fn from(value: ::std::collections::HashMap<ExtKey, ::serde_json::Value>) -> Self {
Self(value)
}
}
///`ExtKey`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "pattern": "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ExtKey(::std::string::String);
impl ::std::ops::Deref for ExtKey {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ExtKey> for ::std::string::String {
fn from(value: ExtKey) -> Self {
value.0
}
}
impl ::std::str::FromStr for ExtKey {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for ExtKey {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Ask the auth service to begin a WebAuthn registration ceremony. The response carries PublicKeyCredentialCreationOptions; the producer hands them to `navigator.credentials.create({ publicKey: ... })`.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/auth/passkey/enroll/start/0.2",
/// "title": "Payload",
/// "description": "Ask the auth service to begin a WebAuthn registration ceremony. The response carries PublicKeyCredentialCreationOptions; the producer hands them to `navigator.credentials.create({ publicKey: ... })`.",
/// "type": "object",
/// "properties": {
/// "deviceLabel": {
/// "description": "Operator-facing label for the credential (e.g. \"Alice's MacBook\"). Surfaced in the credential list for later management.",
/// "type": "string",
/// "maxLength": 256
/// },
/// "ext": {
/// "description": "Ecosystem-defined extension members per SPEC.md §4.5.1.",
/// "$ref": "#/definitions/Ext"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Payload {
///Operator-facing label for the credential (e.g. "Alice's MacBook"). Surfaced in the credential list for later management.
#[serde(
rename = "deviceLabel",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub device_label: ::std::option::Option<PayloadDeviceLabel>,
///Ecosystem-defined extension members per SPEC.md §4.5.1.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
device_label: Default::default(),
ext: Default::default(),
}
}
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///Operator-facing label for the credential (e.g. "Alice's MacBook"). Surfaced in the credential list for later management.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Operator-facing label for the credential (e.g. \"Alice's MacBook\"). Surfaced in the credential list for later management.",
/// "type": "string",
/// "maxLength": 256
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadDeviceLabel(::std::string::String);
impl ::std::ops::Deref for PayloadDeviceLabel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadDeviceLabel> for ::std::string::String {
fn from(value: PayloadDeviceLabel) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadDeviceLabel {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 256usize {
return Err("longer than 256 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PayloadDeviceLabel {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PayloadDeviceLabel {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PayloadDeviceLabel {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for PayloadDeviceLabel {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Server-issued WebAuthn creation options. Carried in a Trust Task document whose type is https://trusttasks.org/spec/auth/passkey/enroll/start/0.2#response.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "Server-issued WebAuthn creation options. Carried in a Trust Task document whose type is https://trusttasks.org/spec/auth/passkey/enroll/start/0.2#response.",
/// "type": "object",
/// "required": [
/// "enrollmentId",
/// "options"
/// ],
/// "properties": {
/// "enrollmentId": {
/// "description": "Opaque server handle correlating this start with the matching finish. The producer MUST echo it verbatim.",
/// "type": "string",
/// "minLength": 1
/// },
/// "ext": {
/// "description": "Ecosystem-defined extension members per SPEC.md §4.5.1.",
/// "$ref": "#/definitions/Ext"
/// },
/// "options": {
/// "description": "PublicKeyCredentialCreationOptions for navigator.credentials.create.",
/// "$ref": "#/definitions/CredentialCreationOptions"
/// },
/// "uvOptions": {
/// "description": "New in 0.2. PublicKeyCredentialRequestOptions for a concurrent user-verification ceremony against the subject's EXISTING credentials. Present when the consumer requires re-authentication to add an authenticator — normally whenever the subject already has one. Absent for a first enrollment, when there is nothing to re-authenticate against. When present the producer MUST run both ceremonies and return both results to finish.",
/// "$ref": "#/definitions/CredentialRequestOptions"
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Response {
///Opaque server handle correlating this start with the matching finish. The producer MUST echo it verbatim.
#[serde(rename = "enrollmentId")]
pub enrollment_id: ResponseEnrollmentId,
///Ecosystem-defined extension members per SPEC.md §4.5.1.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///PublicKeyCredentialCreationOptions for navigator.credentials.create.
pub options: CredentialCreationOptions,
///New in 0.2. PublicKeyCredentialRequestOptions for a concurrent user-verification ceremony against the subject's EXISTING credentials. Present when the consumer requires re-authentication to add an authenticator — normally whenever the subject already has one. Absent for a first enrollment, when there is nothing to re-authenticate against. When present the producer MUST run both ceremonies and return both results to finish.
#[serde(
rename = "uvOptions",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub uv_options: ::std::option::Option<CredentialRequestOptions>,
}
impl Response {
pub fn builder() -> builder::Response {
Default::default()
}
}
///Opaque server handle correlating this start with the matching finish. The producer MUST echo it verbatim.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Opaque server handle correlating this start with the matching finish. The producer MUST echo it verbatim.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ResponseEnrollmentId(::std::string::String);
impl ::std::ops::Deref for ResponseEnrollmentId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ResponseEnrollmentId> for ::std::string::String {
fn from(value: ResponseEnrollmentId) -> Self {
value.0
}
}
impl ::std::str::FromStr for ResponseEnrollmentId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ResponseEnrollmentId {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for ResponseEnrollmentId {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for ResponseEnrollmentId {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for ResponseEnrollmentId {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
/// Types for composing complex structures.
pub mod builder {
#[derive(Clone, Debug)]
pub struct CredentialCreationOptions {
attestation: ::std::result::Result<
::std::option::Option<super::CredentialCreationOptionsAttestation>,
::std::string::String,
>,
authenticator_selection: ::std::result::Result<
::std::option::Option<super::CredentialCreationOptionsAuthenticatorSelection>,
::std::string::String,
>,
challenge: ::std::result::Result<::std::string::String, ::std::string::String>,
exclude_credentials: ::std::result::Result<
::std::vec::Vec<super::CredentialDescriptor>,
::std::string::String,
>,
extensions: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
pub_key_cred_params: ::std::result::Result<
::std::vec::Vec<super::CredentialCreationOptionsPubKeyCredParamsItem>,
::std::string::String,
>,
rp: ::std::result::Result<super::CredentialCreationOptionsRp, ::std::string::String>,
timeout: ::std::result::Result<
::std::option::Option<::std::num::NonZeroU64>,
::std::string::String,
>,
user: ::std::result::Result<super::CredentialCreationOptionsUser, ::std::string::String>,
}
impl ::std::default::Default for CredentialCreationOptions {
fn default() -> Self {
Self {
attestation: Ok(Default::default()),
authenticator_selection: Ok(Default::default()),
challenge: Err("no value supplied for challenge".to_string()),
exclude_credentials: Ok(Default::default()),
extensions: Ok(Default::default()),
pub_key_cred_params: Err("no value supplied for pub_key_cred_params".to_string()),
rp: Err("no value supplied for rp".to_string()),
timeout: Ok(Default::default()),
user: Err("no value supplied for user".to_string()),
}
}
}
impl CredentialCreationOptions {
pub fn attestation<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<super::CredentialCreationOptionsAttestation>,
>,
T::Error: ::std::fmt::Display,
{
self.attestation = value
.try_into()
.map_err(|e| format!("error converting supplied value for attestation: {e}"));
self
}
pub fn authenticator_selection<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<super::CredentialCreationOptionsAuthenticatorSelection>,
>,
T::Error: ::std::fmt::Display,
{
self.authenticator_selection = value.try_into().map_err(|e| {
format!("error converting supplied value for authenticator_selection: {e}")
});
self
}
pub fn challenge<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::string::String>,
T::Error: ::std::fmt::Display,
{
self.challenge = value
.try_into()
.map_err(|e| format!("error converting supplied value for challenge: {e}"));
self
}
pub fn exclude_credentials<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::CredentialDescriptor>>,
T::Error: ::std::fmt::Display,
{
self.exclude_credentials = value.try_into().map_err(|e| {
format!("error converting supplied value for exclude_credentials: {e}")
});
self
}
pub fn extensions<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
>,
T::Error: ::std::fmt::Display,
{
self.extensions = value
.try_into()
.map_err(|e| format!("error converting supplied value for extensions: {e}"));
self
}
pub fn pub_key_cred_params<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::vec::Vec<super::CredentialCreationOptionsPubKeyCredParamsItem>,
>,
T::Error: ::std::fmt::Display,
{
self.pub_key_cred_params = value.try_into().map_err(|e| {
format!("error converting supplied value for pub_key_cred_params: {e}")
});
self
}
pub fn rp<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::CredentialCreationOptionsRp>,
T::Error: ::std::fmt::Display,
{
self.rp = value
.try_into()
.map_err(|e| format!("error converting supplied value for rp: {e}"));
self
}
pub fn timeout<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::num::NonZeroU64>>,
T::Error: ::std::fmt::Display,
{
self.timeout = value
.try_into()
.map_err(|e| format!("error converting supplied value for timeout: {e}"));
self
}
pub fn user<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::CredentialCreationOptionsUser>,
T::Error: ::std::fmt::Display,
{
self.user = value
.try_into()
.map_err(|e| format!("error converting supplied value for user: {e}"));
self
}
}
impl ::std::convert::TryFrom<CredentialCreationOptions> for super::CredentialCreationOptions {
type Error = super::error::ConversionError;
fn try_from(
value: CredentialCreationOptions,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
attestation: value.attestation?,
authenticator_selection: value.authenticator_selection?,
challenge: value.challenge?,
exclude_credentials: value.exclude_credentials?,
extensions: value.extensions?,
pub_key_cred_params: value.pub_key_cred_params?,
rp: value.rp?,
timeout: value.timeout?,
user: value.user?,
})
}
}
impl ::std::convert::From<super::CredentialCreationOptions> for CredentialCreationOptions {
fn from(value: super::CredentialCreationOptions) -> Self {
Self {
attestation: Ok(value.attestation),
authenticator_selection: Ok(value.authenticator_selection),
challenge: Ok(value.challenge),
exclude_credentials: Ok(value.exclude_credentials),
extensions: Ok(value.extensions),
pub_key_cred_params: Ok(value.pub_key_cred_params),
rp: Ok(value.rp),
timeout: Ok(value.timeout),
user: Ok(value.user),
}
}
}
#[derive(Clone, Debug)]
pub struct CredentialCreationOptionsAuthenticatorSelection {
authenticator_attachment: ::std::result::Result<
::std::option::Option<
super::CredentialCreationOptionsAuthenticatorSelectionAuthenticatorAttachment,
>,
::std::string::String,
>,
require_resident_key:
::std::result::Result<::std::option::Option<bool>, ::std::string::String>,
resident_key: ::std::result::Result<
::std::option::Option<
super::CredentialCreationOptionsAuthenticatorSelectionResidentKey,
>,
::std::string::String,
>,
user_verification: ::std::result::Result<
::std::option::Option<
super::CredentialCreationOptionsAuthenticatorSelectionUserVerification,
>,
::std::string::String,
>,
}
impl ::std::default::Default for CredentialCreationOptionsAuthenticatorSelection {
fn default() -> Self {
Self {
authenticator_attachment: Ok(Default::default()),
require_resident_key: Ok(Default::default()),
resident_key: Ok(Default::default()),
user_verification: Ok(Default::default()),
}
}
}
impl CredentialCreationOptionsAuthenticatorSelection {
pub fn authenticator_attachment<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<
super::CredentialCreationOptionsAuthenticatorSelectionAuthenticatorAttachment,
>,
>,
T::Error: ::std::fmt::Display,
{
self.authenticator_attachment = value.try_into().map_err(|e| {
format!("error converting supplied value for authenticator_attachment: {e}")
});
self
}
pub fn require_resident_key<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<bool>>,
T::Error: ::std::fmt::Display,
{
self.require_resident_key = value.try_into().map_err(|e| {
format!("error converting supplied value for require_resident_key: {e}")
});
self
}
pub fn resident_key<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<
super::CredentialCreationOptionsAuthenticatorSelectionResidentKey,
>,
>,
T::Error: ::std::fmt::Display,
{
self.resident_key = value
.try_into()
.map_err(|e| format!("error converting supplied value for resident_key: {e}"));
self
}
pub fn user_verification<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<
super::CredentialCreationOptionsAuthenticatorSelectionUserVerification,
>,
>,
T::Error: ::std::fmt::Display,
{
self.user_verification = value
.try_into()
.map_err(|e| format!("error converting supplied value for user_verification: {e}"));
self
}
}
impl ::std::convert::TryFrom<CredentialCreationOptionsAuthenticatorSelection>
for super::CredentialCreationOptionsAuthenticatorSelection
{
type Error = super::error::ConversionError;
fn try_from(
value: CredentialCreationOptionsAuthenticatorSelection,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
authenticator_attachment: value.authenticator_attachment?,
require_resident_key: value.require_resident_key?,
resident_key: value.resident_key?,
user_verification: value.user_verification?,
})
}
}
impl ::std::convert::From<super::CredentialCreationOptionsAuthenticatorSelection>
for CredentialCreationOptionsAuthenticatorSelection
{
fn from(value: super::CredentialCreationOptionsAuthenticatorSelection) -> Self {
Self {
authenticator_attachment: Ok(value.authenticator_attachment),
require_resident_key: Ok(value.require_resident_key),
resident_key: Ok(value.resident_key),
user_verification: Ok(value.user_verification),
}
}
}
#[derive(Clone, Debug)]
pub struct CredentialCreationOptionsPubKeyCredParamsItem {
alg: ::std::result::Result<i64, ::std::string::String>,
type_: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for CredentialCreationOptionsPubKeyCredParamsItem {
fn default() -> Self {
Self {
alg: Err("no value supplied for alg".to_string()),
type_: Err("no value supplied for type_".to_string()),
}
}
}
impl CredentialCreationOptionsPubKeyCredParamsItem {
pub fn alg<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<i64>,
T::Error: ::std::fmt::Display,
{
self.alg = value
.try_into()
.map_err(|e| format!("error converting supplied value for alg: {e}"));
self
}
pub fn type_<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.type_ = value
.try_into()
.map_err(|e| format!("error converting supplied value for type_: {e}"));
self
}
}
impl ::std::convert::TryFrom<CredentialCreationOptionsPubKeyCredParamsItem>
for super::CredentialCreationOptionsPubKeyCredParamsItem
{
type Error = super::error::ConversionError;
fn try_from(
value: CredentialCreationOptionsPubKeyCredParamsItem,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
alg: value.alg?,
type_: value.type_?,
})
}
}
impl ::std::convert::From<super::CredentialCreationOptionsPubKeyCredParamsItem>
for CredentialCreationOptionsPubKeyCredParamsItem
{
fn from(value: super::CredentialCreationOptionsPubKeyCredParamsItem) -> Self {
Self {
alg: Ok(value.alg),
type_: Ok(value.type_),
}
}
}
#[derive(Clone, Debug)]
pub struct CredentialCreationOptionsRp {
id: ::std::result::Result<super::CredentialCreationOptionsRpId, ::std::string::String>,
name: ::std::result::Result<super::CredentialCreationOptionsRpName, ::std::string::String>,
}
impl ::std::default::Default for CredentialCreationOptionsRp {
fn default() -> Self {
Self {
id: Err("no value supplied for id".to_string()),
name: Err("no value supplied for name".to_string()),
}
}
}
impl CredentialCreationOptionsRp {
pub fn id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::CredentialCreationOptionsRpId>,
T::Error: ::std::fmt::Display,
{
self.id = value
.try_into()
.map_err(|e| format!("error converting supplied value for id: {e}"));
self
}
pub fn name<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::CredentialCreationOptionsRpName>,
T::Error: ::std::fmt::Display,
{
self.name = value
.try_into()
.map_err(|e| format!("error converting supplied value for name: {e}"));
self
}
}
impl ::std::convert::TryFrom<CredentialCreationOptionsRp> for super::CredentialCreationOptionsRp {
type Error = super::error::ConversionError;
fn try_from(
value: CredentialCreationOptionsRp,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
id: value.id?,
name: value.name?,
})
}
}
impl ::std::convert::From<super::CredentialCreationOptionsRp> for CredentialCreationOptionsRp {
fn from(value: super::CredentialCreationOptionsRp) -> Self {
Self {
id: Ok(value.id),
name: Ok(value.name),
}
}
}
#[derive(Clone, Debug)]
pub struct CredentialCreationOptionsUser {
display_name: ::std::result::Result<
super::CredentialCreationOptionsUserDisplayName,
::std::string::String,
>,
id: ::std::result::Result<::std::string::String, ::std::string::String>,
name:
::std::result::Result<super::CredentialCreationOptionsUserName, ::std::string::String>,
}
impl ::std::default::Default for CredentialCreationOptionsUser {
fn default() -> Self {
Self {
display_name: Err("no value supplied for display_name".to_string()),
id: Err("no value supplied for id".to_string()),
name: Err("no value supplied for name".to_string()),
}
}
}
impl CredentialCreationOptionsUser {
pub fn display_name<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::CredentialCreationOptionsUserDisplayName>,
T::Error: ::std::fmt::Display,
{
self.display_name = value
.try_into()
.map_err(|e| format!("error converting supplied value for display_name: {e}"));
self
}
pub fn id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::string::String>,
T::Error: ::std::fmt::Display,
{
self.id = value
.try_into()
.map_err(|e| format!("error converting supplied value for id: {e}"));
self
}
pub fn name<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::CredentialCreationOptionsUserName>,
T::Error: ::std::fmt::Display,
{
self.name = value
.try_into()
.map_err(|e| format!("error converting supplied value for name: {e}"));
self
}
}
impl ::std::convert::TryFrom<CredentialCreationOptionsUser>
for super::CredentialCreationOptionsUser
{
type Error = super::error::ConversionError;
fn try_from(
value: CredentialCreationOptionsUser,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
display_name: value.display_name?,
id: value.id?,
name: value.name?,
})
}
}
impl ::std::convert::From<super::CredentialCreationOptionsUser> for CredentialCreationOptionsUser {
fn from(value: super::CredentialCreationOptionsUser) -> Self {
Self {
display_name: Ok(value.display_name),
id: Ok(value.id),
name: Ok(value.name),
}
}
}
#[derive(Clone, Debug)]
pub struct CredentialDescriptor {
id: ::std::result::Result<::std::string::String, ::std::string::String>,
transports: ::std::result::Result<
::std::vec::Vec<super::CredentialDescriptorTransportsItem>,
::std::string::String,
>,
type_: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for CredentialDescriptor {
fn default() -> Self {
Self {
id: Err("no value supplied for id".to_string()),
transports: Ok(Default::default()),
type_: Err("no value supplied for type_".to_string()),
}
}
}
impl CredentialDescriptor {
pub fn id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::string::String>,
T::Error: ::std::fmt::Display,
{
self.id = value
.try_into()
.map_err(|e| format!("error converting supplied value for id: {e}"));
self
}
pub fn transports<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::CredentialDescriptorTransportsItem>>,
T::Error: ::std::fmt::Display,
{
self.transports = value
.try_into()
.map_err(|e| format!("error converting supplied value for transports: {e}"));
self
}
pub fn type_<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.type_ = value
.try_into()
.map_err(|e| format!("error converting supplied value for type_: {e}"));
self
}
}
impl ::std::convert::TryFrom<CredentialDescriptor> for super::CredentialDescriptor {
type Error = super::error::ConversionError;
fn try_from(
value: CredentialDescriptor,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
id: value.id?,
transports: value.transports?,
type_: value.type_?,
})
}
}
impl ::std::convert::From<super::CredentialDescriptor> for CredentialDescriptor {
fn from(value: super::CredentialDescriptor) -> Self {
Self {
id: Ok(value.id),
transports: Ok(value.transports),
type_: Ok(value.type_),
}
}
}
#[derive(Clone, Debug)]
pub struct CredentialRequestOptions {
allow_credentials: ::std::result::Result<
::std::vec::Vec<super::CredentialDescriptor>,
::std::string::String,
>,
challenge: ::std::result::Result<::std::string::String, ::std::string::String>,
extensions: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
rp_id: ::std::result::Result<
::std::option::Option<super::CredentialRequestOptionsRpId>,
::std::string::String,
>,
timeout: ::std::result::Result<
::std::option::Option<::std::num::NonZeroU64>,
::std::string::String,
>,
user_verification: ::std::result::Result<
::std::option::Option<super::CredentialRequestOptionsUserVerification>,
::std::string::String,
>,
}
impl ::std::default::Default for CredentialRequestOptions {
fn default() -> Self {
Self {
allow_credentials: Ok(Default::default()),
challenge: Err("no value supplied for challenge".to_string()),
extensions: Ok(Default::default()),
rp_id: Ok(Default::default()),
timeout: Ok(Default::default()),
user_verification: Ok(Default::default()),
}
}
}
impl CredentialRequestOptions {
pub fn allow_credentials<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::CredentialDescriptor>>,
T::Error: ::std::fmt::Display,
{
self.allow_credentials = value
.try_into()
.map_err(|e| format!("error converting supplied value for allow_credentials: {e}"));
self
}
pub fn challenge<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::string::String>,
T::Error: ::std::fmt::Display,
{
self.challenge = value
.try_into()
.map_err(|e| format!("error converting supplied value for challenge: {e}"));
self
}
pub fn extensions<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
>,
T::Error: ::std::fmt::Display,
{
self.extensions = value
.try_into()
.map_err(|e| format!("error converting supplied value for extensions: {e}"));
self
}
pub fn rp_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::CredentialRequestOptionsRpId>>,
T::Error: ::std::fmt::Display,
{
self.rp_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for rp_id: {e}"));
self
}
pub fn timeout<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::num::NonZeroU64>>,
T::Error: ::std::fmt::Display,
{
self.timeout = value
.try_into()
.map_err(|e| format!("error converting supplied value for timeout: {e}"));
self
}
pub fn user_verification<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<super::CredentialRequestOptionsUserVerification>,
>,
T::Error: ::std::fmt::Display,
{
self.user_verification = value
.try_into()
.map_err(|e| format!("error converting supplied value for user_verification: {e}"));
self
}
}
impl ::std::convert::TryFrom<CredentialRequestOptions> for super::CredentialRequestOptions {
type Error = super::error::ConversionError;
fn try_from(
value: CredentialRequestOptions,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
allow_credentials: value.allow_credentials?,
challenge: value.challenge?,
extensions: value.extensions?,
rp_id: value.rp_id?,
timeout: value.timeout?,
user_verification: value.user_verification?,
})
}
}
impl ::std::convert::From<super::CredentialRequestOptions> for CredentialRequestOptions {
fn from(value: super::CredentialRequestOptions) -> Self {
Self {
allow_credentials: Ok(value.allow_credentials),
challenge: Ok(value.challenge),
extensions: Ok(value.extensions),
rp_id: Ok(value.rp_id),
timeout: Ok(value.timeout),
user_verification: Ok(value.user_verification),
}
}
}
#[derive(Clone, Debug)]
pub struct Payload {
device_label: ::std::result::Result<
::std::option::Option<super::PayloadDeviceLabel>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
device_label: Ok(Default::default()),
ext: Ok(Default::default()),
}
}
}
impl Payload {
pub fn device_label<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::PayloadDeviceLabel>>,
T::Error: ::std::fmt::Display,
{
self.device_label = value
.try_into()
.map_err(|e| format!("error converting supplied value for device_label: {e}"));
self
}
pub fn ext<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ext>>,
T::Error: ::std::fmt::Display,
{
self.ext = value
.try_into()
.map_err(|e| format!("error converting supplied value for ext: {e}"));
self
}
}
impl ::std::convert::TryFrom<Payload> for super::Payload {
type Error = super::error::ConversionError;
fn try_from(value: Payload) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
device_label: value.device_label?,
ext: value.ext?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
device_label: Ok(value.device_label),
ext: Ok(value.ext),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
enrollment_id: ::std::result::Result<super::ResponseEnrollmentId, ::std::string::String>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
options: ::std::result::Result<super::CredentialCreationOptions, ::std::string::String>,
uv_options: ::std::result::Result<
::std::option::Option<super::CredentialRequestOptions>,
::std::string::String,
>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
enrollment_id: Err("no value supplied for enrollment_id".to_string()),
ext: Ok(Default::default()),
options: Err("no value supplied for options".to_string()),
uv_options: Ok(Default::default()),
}
}
}
impl Response {
pub fn enrollment_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ResponseEnrollmentId>,
T::Error: ::std::fmt::Display,
{
self.enrollment_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for enrollment_id: {e}"));
self
}
pub fn ext<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ext>>,
T::Error: ::std::fmt::Display,
{
self.ext = value
.try_into()
.map_err(|e| format!("error converting supplied value for ext: {e}"));
self
}
pub fn options<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::CredentialCreationOptions>,
T::Error: ::std::fmt::Display,
{
self.options = value
.try_into()
.map_err(|e| format!("error converting supplied value for options: {e}"));
self
}
pub fn uv_options<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::CredentialRequestOptions>>,
T::Error: ::std::fmt::Display,
{
self.uv_options = value
.try_into()
.map_err(|e| format!("error converting supplied value for uv_options: {e}"));
self
}
}
impl ::std::convert::TryFrom<Response> for super::Response {
type Error = super::error::ConversionError;
fn try_from(value: Response) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
enrollment_id: value.enrollment_id?,
ext: value.ext?,
options: value.options?,
uv_options: value.uv_options?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
enrollment_id: Ok(value.enrollment_id),
ext: Ok(value.ext),
options: Ok(value.options),
uv_options: Ok(value.uv_options),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/auth/passkey/enroll/start/0.2";
const IS_PROOF_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"CredentialCreationOptions\": {\n \"$anchor\": \"credentialCreationOptions\",\n \"additionalProperties\": false,\n \"description\": \"Server-issued options for `navigator.credentials.create({ publicKey: ... })`. Mirrors the WebAuthn Level 2 `PublicKeyCredentialCreationOptions` dictionary; binary fields are base64url-encoded strings (rather than ArrayBuffers) so the value is JSON-safe over the wire.\",\n \"properties\": {\n \"attestation\": {\n \"enum\": [\n \"none\",\n \"indirect\",\n \"direct\",\n \"enterprise\"\n ]\n },\n \"authenticatorSelection\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"authenticatorAttachment\": {\n \"enum\": [\n \"platform\",\n \"cross-platform\"\n ]\n },\n \"requireResidentKey\": {\n \"type\": \"boolean\"\n },\n \"residentKey\": {\n \"enum\": [\n \"discouraged\",\n \"preferred\",\n \"required\"\n ]\n },\n \"userVerification\": {\n \"enum\": [\n \"discouraged\",\n \"preferred\",\n \"required\"\n ]\n }\n },\n \"type\": \"object\"\n },\n \"challenge\": {\n \"description\": \"base64url-encoded one-time nonce.\",\n \"type\": \"string\"\n },\n \"excludeCredentials\": {\n \"items\": {\n \"$ref\": \"#/$defs/CredentialDescriptor\"\n },\n \"type\": \"array\"\n },\n \"extensions\": {\n \"description\": \"Client extension inputs, per the WebAuthn Level 2 `AuthenticationExtensionsClientInputs` dictionary.\\n\\nThis component states that it mirrors the W3C dictionary, and that dictionary defines `extensions`. Omitting it while closing the object with `additionalProperties: false` made the two claims contradict each other: a server emitting standard WebAuthn options could not conform, and the widely-used server libraries emit this member by default.\\n\\nStructure is deliberately unconstrained. The set of extensions is open and registered outside this framework, so enumerating them here would date the schema against a registry it does not own — and a closed list would reproduce the original defect one revision later.\",\n \"type\": \"object\"\n },\n \"pubKeyCredParams\": {\n \"items\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"alg\": {\n \"description\": \"COSE algorithm identifier (e.g. -8 Ed25519, -7 ES256, -257 RS256).\",\n \"type\": \"integer\"\n },\n \"type\": {\n \"const\": \"public-key\"\n }\n },\n \"required\": [\n \"type\",\n \"alg\"\n ],\n \"type\": \"object\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"rp\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"id\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"name\": {\n \"maxLength\": 64,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"name\"\n ],\n \"type\": \"object\"\n },\n \"timeout\": {\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"user\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"displayName\": {\n \"maxLength\": 64,\n \"type\": \"string\"\n },\n \"id\": {\n \"description\": \"base64url-encoded user handle. SHOULD be a stable opaque identifier — never reuse a human-readable username here.\",\n \"type\": \"string\"\n },\n \"name\": {\n \"maxLength\": 64,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"displayName\"\n ],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"challenge\",\n \"rp\",\n \"user\",\n \"pubKeyCredParams\"\n ],\n \"title\": \"PublicKeyCredentialCreationOptions\",\n \"type\": \"object\"\n },\n \"CredentialDescriptor\": {\n \"$anchor\": \"credentialDescriptor\",\n \"additionalProperties\": false,\n \"properties\": {\n \"id\": {\n \"description\": \"base64url-encoded credential id.\",\n \"type\": \"string\"\n },\n \"transports\": {\n \"items\": {\n \"enum\": [\n \"usb\",\n \"nfc\",\n \"ble\",\n \"internal\",\n \"hybrid\"\n ]\n },\n \"type\": \"array\"\n },\n \"type\": {\n \"const\": \"public-key\"\n }\n },\n \"required\": [\n \"type\",\n \"id\"\n ],\n \"title\": \"PublicKeyCredentialDescriptor\",\n \"type\": \"object\"\n },\n \"CredentialRequestOptions\": {\n \"$anchor\": \"credentialRequestOptions\",\n \"additionalProperties\": false,\n \"description\": \"Server-issued options for `navigator.credentials.get({ publicKey: ... })`.\",\n \"properties\": {\n \"allowCredentials\": {\n \"items\": {\n \"$ref\": \"#/$defs/CredentialDescriptor\"\n },\n \"type\": \"array\"\n },\n \"challenge\": {\n \"description\": \"base64url-encoded one-time nonce.\",\n \"type\": \"string\"\n },\n \"extensions\": {\n \"description\": \"Client extension inputs, per the WebAuthn Level 2 `AuthenticationExtensionsClientInputs` dictionary.\\n\\nThis component states that it mirrors the W3C dictionary, and that dictionary defines `extensions`. Omitting it while closing the object with `additionalProperties: false` made the two claims contradict each other: a server emitting standard WebAuthn options could not conform, and the widely-used server libraries emit this member by default.\\n\\nStructure is deliberately unconstrained. The set of extensions is open and registered outside this framework, so enumerating them here would date the schema against a registry it does not own — and a closed list would reproduce the original defect one revision later.\",\n \"type\": \"object\"\n },\n \"rpId\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"timeout\": {\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"userVerification\": {\n \"enum\": [\n \"discouraged\",\n \"preferred\",\n \"required\"\n ]\n }\n },\n \"required\": [\n \"challenge\"\n ],\n \"title\": \"PublicKeyCredentialRequestOptions\",\n \"type\": \"object\"\n },\n \"Ext\": {\n \"additionalProperties\": true,\n \"description\": \"Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)+$\"\n },\n \"title\": \"Ext\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"Server-issued WebAuthn creation options. Carried in a Trust Task document whose type is https://trusttasks.org/spec/auth/passkey/enroll/start/0.2#response.\",\n \"properties\": {\n \"enrollmentId\": {\n \"description\": \"Opaque server handle correlating this start with the matching finish. The producer MUST echo it verbatim.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1.\"\n },\n \"options\": {\n \"$ref\": \"#/$defs/CredentialCreationOptions\",\n \"description\": \"PublicKeyCredentialCreationOptions for navigator.credentials.create.\"\n },\n \"uvOptions\": {\n \"$ref\": \"#/$defs/CredentialRequestOptions\",\n \"description\": \"New in 0.2. PublicKeyCredentialRequestOptions for a concurrent user-verification ceremony against the subject's EXISTING credentials. Present when the consumer requires re-authentication to add an authenticator — normally whenever the subject already has one. Absent for a first enrollment, when there is nothing to re-authenticate against. When present the producer MUST run both ceremonies and return both results to finish.\"\n }\n },\n \"required\": [\n \"enrollmentId\",\n \"options\"\n ],\n \"title\": \"Auth Passkey Enroll Start — response payload\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/auth/passkey/enroll/start/0.2\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"Ask the auth service to begin a WebAuthn registration ceremony. The response carries PublicKeyCredentialCreationOptions; the producer hands them to `navigator.credentials.create({ publicKey: ... })`.\",\n \"properties\": {\n \"deviceLabel\": {\n \"description\": \"Operator-facing label for the credential (e.g. \\\"Alice's MacBook\\\"). Surfaced in the credential list for later management.\",\n \"maxLength\": 256,\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1.\"\n }\n },\n \"title\": \"Auth — Passkey Enroll (start)\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str =
"https://trusttasks.org/spec/auth/passkey/enroll/start/0.2#response";
const IS_PROOF_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"CredentialCreationOptions\": {\n \"$anchor\": \"credentialCreationOptions\",\n \"additionalProperties\": false,\n \"description\": \"Server-issued options for `navigator.credentials.create({ publicKey: ... })`. Mirrors the WebAuthn Level 2 `PublicKeyCredentialCreationOptions` dictionary; binary fields are base64url-encoded strings (rather than ArrayBuffers) so the value is JSON-safe over the wire.\",\n \"properties\": {\n \"attestation\": {\n \"enum\": [\n \"none\",\n \"indirect\",\n \"direct\",\n \"enterprise\"\n ]\n },\n \"authenticatorSelection\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"authenticatorAttachment\": {\n \"enum\": [\n \"platform\",\n \"cross-platform\"\n ]\n },\n \"requireResidentKey\": {\n \"type\": \"boolean\"\n },\n \"residentKey\": {\n \"enum\": [\n \"discouraged\",\n \"preferred\",\n \"required\"\n ]\n },\n \"userVerification\": {\n \"enum\": [\n \"discouraged\",\n \"preferred\",\n \"required\"\n ]\n }\n },\n \"type\": \"object\"\n },\n \"challenge\": {\n \"description\": \"base64url-encoded one-time nonce.\",\n \"type\": \"string\"\n },\n \"excludeCredentials\": {\n \"items\": {\n \"$ref\": \"#/$defs/CredentialDescriptor\"\n },\n \"type\": \"array\"\n },\n \"extensions\": {\n \"description\": \"Client extension inputs, per the WebAuthn Level 2 `AuthenticationExtensionsClientInputs` dictionary.\\n\\nThis component states that it mirrors the W3C dictionary, and that dictionary defines `extensions`. Omitting it while closing the object with `additionalProperties: false` made the two claims contradict each other: a server emitting standard WebAuthn options could not conform, and the widely-used server libraries emit this member by default.\\n\\nStructure is deliberately unconstrained. The set of extensions is open and registered outside this framework, so enumerating them here would date the schema against a registry it does not own — and a closed list would reproduce the original defect one revision later.\",\n \"type\": \"object\"\n },\n \"pubKeyCredParams\": {\n \"items\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"alg\": {\n \"description\": \"COSE algorithm identifier (e.g. -8 Ed25519, -7 ES256, -257 RS256).\",\n \"type\": \"integer\"\n },\n \"type\": {\n \"const\": \"public-key\"\n }\n },\n \"required\": [\n \"type\",\n \"alg\"\n ],\n \"type\": \"object\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"rp\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"id\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"name\": {\n \"maxLength\": 64,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"name\"\n ],\n \"type\": \"object\"\n },\n \"timeout\": {\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"user\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"displayName\": {\n \"maxLength\": 64,\n \"type\": \"string\"\n },\n \"id\": {\n \"description\": \"base64url-encoded user handle. SHOULD be a stable opaque identifier — never reuse a human-readable username here.\",\n \"type\": \"string\"\n },\n \"name\": {\n \"maxLength\": 64,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"displayName\"\n ],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"challenge\",\n \"rp\",\n \"user\",\n \"pubKeyCredParams\"\n ],\n \"title\": \"PublicKeyCredentialCreationOptions\",\n \"type\": \"object\"\n },\n \"CredentialDescriptor\": {\n \"$anchor\": \"credentialDescriptor\",\n \"additionalProperties\": false,\n \"properties\": {\n \"id\": {\n \"description\": \"base64url-encoded credential id.\",\n \"type\": \"string\"\n },\n \"transports\": {\n \"items\": {\n \"enum\": [\n \"usb\",\n \"nfc\",\n \"ble\",\n \"internal\",\n \"hybrid\"\n ]\n },\n \"type\": \"array\"\n },\n \"type\": {\n \"const\": \"public-key\"\n }\n },\n \"required\": [\n \"type\",\n \"id\"\n ],\n \"title\": \"PublicKeyCredentialDescriptor\",\n \"type\": \"object\"\n },\n \"CredentialRequestOptions\": {\n \"$anchor\": \"credentialRequestOptions\",\n \"additionalProperties\": false,\n \"description\": \"Server-issued options for `navigator.credentials.get({ publicKey: ... })`.\",\n \"properties\": {\n \"allowCredentials\": {\n \"items\": {\n \"$ref\": \"#/$defs/CredentialDescriptor\"\n },\n \"type\": \"array\"\n },\n \"challenge\": {\n \"description\": \"base64url-encoded one-time nonce.\",\n \"type\": \"string\"\n },\n \"extensions\": {\n \"description\": \"Client extension inputs, per the WebAuthn Level 2 `AuthenticationExtensionsClientInputs` dictionary.\\n\\nThis component states that it mirrors the W3C dictionary, and that dictionary defines `extensions`. Omitting it while closing the object with `additionalProperties: false` made the two claims contradict each other: a server emitting standard WebAuthn options could not conform, and the widely-used server libraries emit this member by default.\\n\\nStructure is deliberately unconstrained. The set of extensions is open and registered outside this framework, so enumerating them here would date the schema against a registry it does not own — and a closed list would reproduce the original defect one revision later.\",\n \"type\": \"object\"\n },\n \"rpId\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"timeout\": {\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"userVerification\": {\n \"enum\": [\n \"discouraged\",\n \"preferred\",\n \"required\"\n ]\n }\n },\n \"required\": [\n \"challenge\"\n ],\n \"title\": \"PublicKeyCredentialRequestOptions\",\n \"type\": \"object\"\n },\n \"Ext\": {\n \"additionalProperties\": true,\n \"description\": \"Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)+$\"\n },\n \"title\": \"Ext\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"Server-issued WebAuthn creation options. Carried in a Trust Task document whose type is https://trusttasks.org/spec/auth/passkey/enroll/start/0.2#response.\",\n \"properties\": {\n \"enrollmentId\": {\n \"description\": \"Opaque server handle correlating this start with the matching finish. The producer MUST echo it verbatim.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1.\"\n },\n \"options\": {\n \"$ref\": \"#/$defs/CredentialCreationOptions\",\n \"description\": \"PublicKeyCredentialCreationOptions for navigator.credentials.create.\"\n },\n \"uvOptions\": {\n \"$ref\": \"#/$defs/CredentialRequestOptions\",\n \"description\": \"New in 0.2. PublicKeyCredentialRequestOptions for a concurrent user-verification ceremony against the subject's EXISTING credentials. Present when the consumer requires re-authentication to add an authenticator — normally whenever the subject already has one. Absent for a first enrollment, when there is nothing to re-authenticate against. When present the producer MUST run both ceremonies and return both results to finish.\"\n }\n },\n \"required\": [\n \"enrollmentId\",\n \"options\"\n ],\n \"title\": \"Auth Passkey Enroll Start — response payload\",\n \"type\": \"object\"\n }\n },\n \"$ref\": \"#/$defs/Response\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n}\n",
);
}
impl crate::RequestPayload for Payload {
type Response = Response;
}
#[cfg(test)]
mod conformance {
//! Round-trip tests harvested from the spec's `spec.md`,
//! plus a `rejects_invalid_examples` test for any fixtures
//! in `payload.invalid-examples.json` (validate feature).
#[test]
fn response_example_1() {
const JSON: &str = "{\n \"id\": \"33333333-dddd-eeee-ffff-444444444444\",\n \"type\": \"https://trusttasks.org/spec/auth/passkey/enroll/start/0.2#response\",\n \"threadId\": \"11111111-aaaa-bbbb-cccc-222222222222\",\n \"issuer\": \"did:web:auth.example\",\n \"recipient\": \"did:web:alice.example\",\n \"issuedAt\": \"2026-05-23T12:00:01Z\",\n \"payload\": {\n \"enrollmentId\": \"enr_1a2b3c4d5e6f7890\",\n \"options\": {\n \"challenge\": \"Zm9vYmFyYmF6cXV4\",\n \"rp\": { \"id\": \"auth.example\", \"name\": \"Auth Example\" },\n \"user\": {\n \"id\": \"dXNyXzhmMmMxZDRlOWE3YjMwNTY\",\n \"name\": \"alice\",\n \"displayName\": \"Alice\"\n },\n \"pubKeyCredParams\": [\n { \"type\": \"public-key\", \"alg\": -8 },\n { \"type\": \"public-key\", \"alg\": -7 }\n ],\n \"timeout\": 60000,\n \"attestation\": \"none\",\n \"authenticatorSelection\": {\n \"residentKey\": \"preferred\",\n \"userVerification\": \"preferred\"\n }\n }\n }\n}\n";
let doc: crate::TrustTask<super::Response> =
serde_json::from_str(JSON).expect("deserialize response example");
let rendered = serde_json::to_value(&doc).expect("re-serialize");
let expected: serde_json::Value = serde_json::from_str(JSON).expect("re-parse expected");
assert_eq!(rendered, expected, "response example failed round-trip");
}
#[test]
fn response_example_2() {
const JSON: &str = "{\n \"id\": \"55555555-eeee-ffff-0000-666666666666\",\n \"type\": \"https://trusttasks.org/spec/auth/passkey/enroll/start/0.2#response\",\n \"threadId\": \"11111111-aaaa-bbbb-cccc-222222222222\",\n \"issuer\": \"did:web:auth.example\",\n \"recipient\": \"did:web:alice.example\",\n \"issuedAt\": \"2026-07-27T12:00:01Z\",\n \"payload\": {\n \"enrollmentId\": \"enr_9e8d7c6b5a493827\",\n \"options\": {\n \"challenge\": \"ZW5yb2xsLWNoYWxsZW5nZQ\",\n \"rp\": { \"id\": \"auth.example\", \"name\": \"Auth Example\" },\n \"user\": {\n \"id\": \"dXNyXzhmMmMxZDRlOWE3YjMwNTY\",\n \"name\": \"alice\",\n \"displayName\": \"Alice\"\n },\n \"pubKeyCredParams\": [{ \"type\": \"public-key\", \"alg\": -8 }],\n \"excludeCredentials\": [\n { \"type\": \"public-key\", \"id\": \"q1w2e3r4t5y6u7i8o9p0\" }\n ]\n },\n \"uvOptions\": {\n \"challenge\": \"cmVhdXRoLWNoYWxsZW5nZQ\",\n \"rpId\": \"auth.example\",\n \"userVerification\": \"required\",\n \"allowCredentials\": [\n { \"type\": \"public-key\", \"id\": \"q1w2e3r4t5y6u7i8o9p0\", \"transports\": [\"internal\"] }\n ]\n }\n }\n}\n";
let doc: crate::TrustTask<super::Response> =
serde_json::from_str(JSON).expect("deserialize response example");
let rendered = serde_json::to_value(&doc).expect("re-serialize");
let expected: serde_json::Value = serde_json::from_str(JSON).expect("re-parse expected");
assert_eq!(rendered, expected, "response example failed round-trip");
}
/// Each fixture in `payload.invalid-examples.json` MUST be
/// rejected by at least one of: serde deserialization, or
/// JSON-Schema validation under the `validate` feature. The
/// fixture file documents the producer-side bug class that
/// each payload exemplifies; this generated test pins it.
#[cfg(feature = "validate")]
#[test]
fn rejects_invalid_examples() {
use crate::validate::ValidatedPayload;
let fixtures: &[(&str, &str)] = &[
(
"Unknown top-level payload member.",
"{\n \"rpId\": \"example.com\"\n}",
),
(
"Bare/unnamespaced ext key.",
"{\n \"ext\": {\n \"bare-key\": {\n \"anything\": \"here\"\n }\n }\n}",
),
];
for (i, (note, raw)) in fixtures.iter().enumerate() {
let value: serde_json::Value = match serde_json::from_str(raw) {
Ok(v) => v,
Err(_) => continue,
};
let serde_ok = serde_json::from_value::<super::Payload>(value.clone()).is_ok();
let schema_ok = super::Payload::validate_value(&value).is_ok();
assert!(
!(serde_ok && schema_ok),
"invalid-example #{} ({:?}) was accepted by both serde and JSON Schema; \
the fixture's stated failure class is no longer caught:\n{}",
i + 1,
note,
raw
);
}
}
}