//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `auth/oob/identify`. Version: `0.1`.
#[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())
}
}
}
///The two-digit number the service chooses at claim, shows only to the starter (through redeem), and the approver types from the starter's screen. A string so that a leading zero survives.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "MatchNumber",
/// "description": "The two-digit number the service chooses at claim, shows only to the starter (through redeem), and the approver types from the starter's screen. A string so that a leading zero survives.",
/// "type": "string",
/// "pattern": "^[0-9]{2}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct MatchNumber(::std::string::String);
impl ::std::ops::Deref for MatchNumber {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<MatchNumber> for ::std::string::String {
fn from(value: MatchNumber) -> Self {
value.0
}
}
impl ::std::str::FromStr for MatchNumber {
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("^[0-9]{2}$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[0-9]{2}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for MatchNumber {
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 MatchNumber {
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 MatchNumber {
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 MatchNumber {
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())
})
}
}
///A starter key (`K_b`) or an approver lock key (`K_a`), as an Ed25519 `did:key` (`z6Mk…`) generated for this one request and used nowhere else. Ed25519 only: a service refuses any other key type with `auth/oob:keyUnsupported` before parsing beyond the multicodec prefix.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "OobKey",
/// "description": "A starter key (`K_b`) or an approver lock key (`K_a`), as an Ed25519 `did:key` (`z6Mk…`) generated for this one request and used nowhere else. Ed25519 only: a service refuses any other key type with `auth/oob:keyUnsupported` before parsing beyond the multicodec prefix.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 48,
/// "pattern": "^did:key:z6Mk[1-9A-HJ-NP-Za-km-z]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct OobKey(::std::string::String);
impl ::std::ops::Deref for OobKey {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<OobKey> for ::std::string::String {
fn from(value: OobKey) -> Self {
value.0
}
}
impl ::std::str::FromStr for OobKey {
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() < 48usize {
return Err("shorter than 48 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^did:key:z6Mk[1-9A-HJ-NP-Za-km-z]+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^did:key:z6Mk[1-9A-HJ-NP-Za-km-z]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for OobKey {
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 OobKey {
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 OobKey {
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 OobKey {
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())
})
}
}
///A member's DID states that it holds the lock on one out-of-band request and can see the starter's screen. Issued by the approving DID and signed by its VTA for `authentication`; never sent on its own, only carried inside auth/oob/prove. Closed: additionalProperties false and no `ext`, so a VTA that signs it without user verification signs exactly these three members and nothing else. The outer document members (id, type, issuer, recipient, issuedAt, expiresAt, proof) are owned by the framework — SPEC §6.3.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/auth/oob/identify/0.1",
/// "title": "Payload",
/// "description": "A member's DID states that it holds the lock on one out-of-band request and can see the starter's screen. Issued by the approving DID and signed by its VTA for `authentication`; never sent on its own, only carried inside auth/oob/prove. Closed: additionalProperties false and no `ext`, so a VTA that signs it without user verification signs exactly these three members and nothing else. The outer document members (id, type, issuer, recipient, issuedAt, expiresAt, proof) are owned by the framework — SPEC §6.3.",
/// "type": "object",
/// "required": [
/// "approverKey",
/// "enteredNumber",
/// "requestId"
/// ],
/// "properties": {
/// "approverKey": {
/// "description": "The lock key `K_a`. MUST equal the issuer of the prove that carries this document, so the document cannot be re-wrapped by another device.",
/// "$ref": "#/definitions/OobKey"
/// },
/// "enteredNumber": {
/// "description": "The two digits the member typed from the starter's screen.",
/// "$ref": "#/definitions/MatchNumber"
/// },
/// "requestId": {
/// "description": "The request being proved for. MUST equal the requestId of the prove that carries this document.",
/// "$ref": "#/definitions/RequestId"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Payload {
///The lock key `K_a`. MUST equal the issuer of the prove that carries this document, so the document cannot be re-wrapped by another device.
#[serde(rename = "approverKey")]
pub approver_key: OobKey,
///The two digits the member typed from the starter's screen.
#[serde(rename = "enteredNumber")]
pub entered_number: MatchNumber,
///The request being proved for. MUST equal the requestId of the prove that carries this document.
#[serde(rename = "requestId")]
pub request_id: RequestId,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///The service-generated handle of one request: 16 to 32 bytes from a cryptographically secure random source, written as unpadded base64url (22 to 43 characters; 16 bytes, 22 characters, is RECOMMENDED). It is also the nonce of the exchange, so the family needs no separate challenge, and it is the `_id` of the trigger link (VTI-LNK-033). Compared as a string. It confers no authority on its holder.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "RequestId",
/// "description": "The service-generated handle of one request: 16 to 32 bytes from a cryptographically secure random source, written as unpadded base64url (22 to 43 characters; 16 bytes, 22 characters, is RECOMMENDED). It is also the nonce of the exchange, so the family needs no separate challenge, and it is the `_id` of the trigger link (VTI-LNK-033). Compared as a string. It confers no authority on its holder.",
/// "type": "string",
/// "maxLength": 43,
/// "minLength": 22,
/// "pattern": "^[A-Za-z0-9_-]{22,43}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct RequestId(::std::string::String);
impl ::std::ops::Deref for RequestId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<RequestId> for ::std::string::String {
fn from(value: RequestId) -> Self {
value.0
}
}
impl ::std::str::FromStr for RequestId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 43usize {
return Err("longer than 43 characters".into());
}
if value.chars().count() < 22usize {
return Err("shorter than 22 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[A-Za-z0-9_-]{22,43}$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[A-Za-z0-9_-]{22,43}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for RequestId {
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 RequestId {
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 RequestId {
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 RequestId {
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 Payload {
approver_key: ::std::result::Result<super::OobKey, ::std::string::String>,
entered_number: ::std::result::Result<super::MatchNumber, ::std::string::String>,
request_id: ::std::result::Result<super::RequestId, ::std::string::String>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
approver_key: Err("no value supplied for approver_key".to_string()),
entered_number: Err("no value supplied for entered_number".to_string()),
request_id: Err("no value supplied for request_id".to_string()),
}
}
}
impl Payload {
pub fn approver_key<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::OobKey>,
T::Error: ::std::fmt::Display,
{
self.approver_key = value
.try_into()
.map_err(|e| format!("error converting supplied value for approver_key: {e}"));
self
}
pub fn entered_number<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::MatchNumber>,
T::Error: ::std::fmt::Display,
{
self.entered_number = value
.try_into()
.map_err(|e| format!("error converting supplied value for entered_number: {e}"));
self
}
pub fn request_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::RequestId>,
T::Error: ::std::fmt::Display,
{
self.request_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for request_id: {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 {
approver_key: value.approver_key?,
entered_number: value.entered_number?,
request_id: value.request_id?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
approver_key: Ok(value.approver_key),
entered_number: Ok(value.entered_number),
request_id: Ok(value.request_id),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/auth/oob/identify/0.1";
const IS_PROOF_REQUIRED: bool = true;
const IS_ISSUED_AT_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"MatchNumber\": {\n \"description\": \"The two-digit number the service chooses at claim, shows only to the starter (through redeem), and the approver types from the starter's screen. A string so that a leading zero survives.\",\n \"pattern\": \"^[0-9]{2}$\",\n \"title\": \"MatchNumber\",\n \"type\": \"string\"\n },\n \"OobKey\": {\n \"description\": \"A starter key (`K_b`) or an approver lock key (`K_a`), as an Ed25519 `did:key` (`z6Mk…`) generated for this one request and used nowhere else. Ed25519 only: a service refuses any other key type with `auth/oob:keyUnsupported` before parsing beyond the multicodec prefix.\",\n \"maxLength\": 64,\n \"minLength\": 48,\n \"pattern\": \"^did:key:z6Mk[1-9A-HJ-NP-Za-km-z]+$\",\n \"title\": \"OobKey\",\n \"type\": \"string\"\n },\n \"RequestId\": {\n \"description\": \"The service-generated handle of one request: 16 to 32 bytes from a cryptographically secure random source, written as unpadded base64url (22 to 43 characters; 16 bytes, 22 characters, is RECOMMENDED). It is also the nonce of the exchange, so the family needs no separate challenge, and it is the `_id` of the trigger link (VTI-LNK-033). Compared as a string. It confers no authority on its holder.\",\n \"maxLength\": 43,\n \"minLength\": 22,\n \"pattern\": \"^[A-Za-z0-9_-]{22,43}$\",\n \"title\": \"RequestId\",\n \"type\": \"string\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/auth/oob/identify/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"A member's DID states that it holds the lock on one out-of-band request and can see the starter's screen. Issued by the approving DID and signed by its VTA for `authentication`; never sent on its own, only carried inside auth/oob/prove. Closed: additionalProperties false and no `ext`, so a VTA that signs it without user verification signs exactly these three members and nothing else. The outer document members (id, type, issuer, recipient, issuedAt, expiresAt, proof) are owned by the framework — SPEC §6.3.\",\n \"properties\": {\n \"approverKey\": {\n \"$ref\": \"#/$defs/OobKey\",\n \"description\": \"The lock key `K_a`. MUST equal the issuer of the prove that carries this document, so the document cannot be re-wrapped by another device.\"\n },\n \"enteredNumber\": {\n \"$ref\": \"#/$defs/MatchNumber\",\n \"description\": \"The two digits the member typed from the starter's screen.\"\n },\n \"requestId\": {\n \"$ref\": \"#/$defs/RequestId\",\n \"description\": \"The request being proved for. MUST equal the requestId of the prove that carries this document.\"\n }\n },\n \"required\": [\n \"requestId\",\n \"approverKey\",\n \"enteredNumber\"\n ],\n \"title\": \"Auth — OOB Identify — payload\",\n \"type\": \"object\"\n}\n",
);
}
/// The extended error codes this specification declares (SPEC §7.3 item 9,
/// §8.5), in declaration order. Empty when it declares none.
pub const ERROR_CODES: &[crate::DeclaredErrorCode] = &[];