//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vault/proxy-login`. 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())
}
}
}
///`ConsumerContext`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ConsumerContext",
/// "type": "object",
/// "properties": {
/// "deviceId": {
/// "description": "Device-binding id assigned at registration. The maintainer cross-checks this against the authenticated transport identity.",
/// "type": "string",
/// "minLength": 1
/// },
/// "lastUserVerificationAt": {
/// "description": "Most recent local user-verification on the consumer device (WebAuthn UV, biometric unlock). The maintainer's policy may require this to be within N seconds.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "networkClass": {
/// "description": "Producer-supplied network classification. Advisory.",
/// "type": "string",
/// "enum": [
/// "unknown",
/// "home",
/// "corp",
/// "public",
/// "vpn"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct ConsumerContext {
///Device-binding id assigned at registration. The maintainer cross-checks this against the authenticated transport identity.
#[serde(
rename = "deviceId",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub device_id: ::std::option::Option<ConsumerContextDeviceId>,
///Most recent local user-verification on the consumer device (WebAuthn UV, biometric unlock). The maintainer's policy may require this to be within N seconds.
#[serde(
rename = "lastUserVerificationAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub last_user_verification_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///Producer-supplied network classification. Advisory.
#[serde(
rename = "networkClass",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub network_class: ::std::option::Option<ConsumerContextNetworkClass>,
}
impl ::std::convert::From<&ConsumerContext> for ConsumerContext {
fn from(value: &ConsumerContext) -> Self {
value.clone()
}
}
impl ::std::default::Default for ConsumerContext {
fn default() -> Self {
Self {
device_id: Default::default(),
last_user_verification_at: Default::default(),
network_class: Default::default(),
}
}
}
///Device-binding id assigned at registration. The maintainer cross-checks this against the authenticated transport identity.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Device-binding id assigned at registration. The maintainer cross-checks this against the authenticated transport identity.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ConsumerContextDeviceId(::std::string::String);
impl ::std::ops::Deref for ConsumerContextDeviceId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ConsumerContextDeviceId> for ::std::string::String {
fn from(value: ConsumerContextDeviceId) -> Self {
value.0
}
}
impl ::std::convert::From<&ConsumerContextDeviceId> for ConsumerContextDeviceId {
fn from(value: &ConsumerContextDeviceId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for ConsumerContextDeviceId {
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 ConsumerContextDeviceId {
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 ConsumerContextDeviceId {
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 ConsumerContextDeviceId {
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 ConsumerContextDeviceId {
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())
})
}
}
///Producer-supplied network classification. Advisory.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Producer-supplied network classification. Advisory.",
/// "type": "string",
/// "enum": [
/// "unknown",
/// "home",
/// "corp",
/// "public",
/// "vpn"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum ConsumerContextNetworkClass {
#[serde(rename = "unknown")]
Unknown,
#[serde(rename = "home")]
Home,
#[serde(rename = "corp")]
Corp,
#[serde(rename = "public")]
Public,
#[serde(rename = "vpn")]
Vpn,
}
impl ::std::convert::From<&Self> for ConsumerContextNetworkClass {
fn from(value: &ConsumerContextNetworkClass) -> Self {
value.clone()
}
}
impl ::std::fmt::Display for ConsumerContextNetworkClass {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Unknown => f.write_str("unknown"),
Self::Home => f.write_str("home"),
Self::Corp => f.write_str("corp"),
Self::Public => f.write_str("public"),
Self::Vpn => f.write_str("vpn"),
}
}
}
impl ::std::str::FromStr for ConsumerContextNetworkClass {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"unknown" => Ok(Self::Unknown),
"home" => Ok(Self::Home),
"corp" => Ok(Self::Corp),
"public" => Ok(Self::Public),
"vpn" => Ok(Self::Vpn),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ConsumerContextNetworkClass {
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 ConsumerContextNetworkClass {
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 ConsumerContextNetworkClass {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
/**DIDComm v2 authcrypt JWE (ECDH-1PU + A256CBC-HS512, X25519/P-256 key agreement). Sender authentication is the JWE's `skid` — the producer's DID#keyAgreement. The maintainer's keyAgreement key is the recipient. Cleartext is JCS-canonical JSON of the variant's payload type.
M2A is the only implementation today; this is also the canonical default for new code.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "DidcommAuthcryptEnvelope",
/// "description": "DIDComm v2 authcrypt JWE (ECDH-1PU + A256CBC-HS512, X25519/P-256 key agreement). Sender authentication is the JWE's `skid` — the producer's DID#keyAgreement. The maintainer's keyAgreement key is the recipient. Cleartext is JCS-canonical JSON of the variant's payload type.\n\nM2A is the only implementation today; this is also the canonical default for new code.",
/// "type": "object",
/// "required": [
/// "envelope",
/// "jwe"
/// ],
/// "properties": {
/// "envelope": {
/// "const": "didcomm-authcrypt"
/// },
/// "jwe": {
/// "description": "Compact DIDComm v2 JWE (base64url-encoded, dot-separated). Unpacks via the framework's standard DIDComm machinery; cleartext is the payload-specific JSON.",
/// "type": "string",
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct DidcommAuthcryptEnvelope {
pub envelope: ::serde_json::Value,
///Compact DIDComm v2 JWE (base64url-encoded, dot-separated). Unpacks via the framework's standard DIDComm machinery; cleartext is the payload-specific JSON.
pub jwe: DidcommAuthcryptEnvelopeJwe,
}
impl ::std::convert::From<&DidcommAuthcryptEnvelope> for DidcommAuthcryptEnvelope {
fn from(value: &DidcommAuthcryptEnvelope) -> Self {
value.clone()
}
}
///Compact DIDComm v2 JWE (base64url-encoded, dot-separated). Unpacks via the framework's standard DIDComm machinery; cleartext is the payload-specific JSON.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Compact DIDComm v2 JWE (base64url-encoded, dot-separated). Unpacks via the framework's standard DIDComm machinery; cleartext is the payload-specific JSON.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct DidcommAuthcryptEnvelopeJwe(::std::string::String);
impl ::std::ops::Deref for DidcommAuthcryptEnvelopeJwe {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DidcommAuthcryptEnvelopeJwe> for ::std::string::String {
fn from(value: DidcommAuthcryptEnvelopeJwe) -> Self {
value.0
}
}
impl ::std::convert::From<&DidcommAuthcryptEnvelopeJwe> for DidcommAuthcryptEnvelopeJwe {
fn from(value: &DidcommAuthcryptEnvelopeJwe) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for DidcommAuthcryptEnvelopeJwe {
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 DidcommAuthcryptEnvelopeJwe {
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 DidcommAuthcryptEnvelopeJwe {
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 DidcommAuthcryptEnvelopeJwe {
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 DidcommAuthcryptEnvelopeJwe {
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())
})
}
}
///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<&Ext> for Ext {
fn from(value: &Ext) -> Self {
value.clone()
}
}
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::convert::From<&ExtKey> for ExtKey {
fn from(value: &ExtKey) -> Self {
value.clone()
}
}
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())
})
}
}
/**OpenPGP-style ASCII-armored HPKE bundle — the existing OpenVTC sealed-transfer wire form (X25519-HKDF-SHA256 KEM + ChaCha20-Poly1305 AEAD, framed in armor with Bundle-Id / Digest-Algo headers and a CRC24 checksum). Producer assertion (`did-signed` / `attested` / `pinned-only`) is the integrity / authenticity anchor.
No open-source implementation reads this yet outside vta-sdk's `sealed_transfer` crate; new code SHOULD prefer the DIDComm variant. Defined here for parity with the existing offline-bundle / cross-VTA workflows that the design plan reserves for M5+.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "HpkeArmoredEnvelope",
/// "description": "OpenPGP-style ASCII-armored HPKE bundle — the existing OpenVTC sealed-transfer wire form (X25519-HKDF-SHA256 KEM + ChaCha20-Poly1305 AEAD, framed in armor with Bundle-Id / Digest-Algo headers and a CRC24 checksum). Producer assertion (`did-signed` / `attested` / `pinned-only`) is the integrity / authenticity anchor.\n\nNo open-source implementation reads this yet outside vta-sdk's `sealed_transfer` crate; new code SHOULD prefer the DIDComm variant. Defined here for parity with the existing offline-bundle / cross-VTA workflows that the design plan reserves for M5+.",
/// "type": "object",
/// "required": [
/// "armored",
/// "envelope",
/// "recipientKeyId"
/// ],
/// "properties": {
/// "armored": {
/// "description": "ASCII-armored bundle text. Multi-line base64 with framing headers + CRC24.",
/// "type": "string",
/// "minLength": 1
/// },
/// "envelope": {
/// "const": "hpke-armored"
/// },
/// "producerAssertion": {
/// "description": "Producer-assertion mode per the sealed-transfer framework. `did-signed` = Ed25519 signature by issuer; `attested` = TEE attestation quote (e.g. Nitro); `pinned-only` = OOB SHA-256 digest only (dev/test, NOT for production).",
/// "default": "did-signed",
/// "type": "string",
/// "enum": [
/// "did-signed",
/// "attested",
/// "pinned-only"
/// ]
/// },
/// "recipientKeyId": {
/// "description": "did:key identifier of the X25519 public key the envelope was sealed to. The recipient uses this to select the matching private key.",
/// "type": "string",
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct HpkeArmoredEnvelope {
///ASCII-armored bundle text. Multi-line base64 with framing headers + CRC24.
pub armored: HpkeArmoredEnvelopeArmored,
pub envelope: ::serde_json::Value,
///Producer-assertion mode per the sealed-transfer framework. `did-signed` = Ed25519 signature by issuer; `attested` = TEE attestation quote (e.g. Nitro); `pinned-only` = OOB SHA-256 digest only (dev/test, NOT for production).
#[serde(
rename = "producerAssertion",
default = "defaults::hpke_armored_envelope_producer_assertion"
)]
pub producer_assertion: HpkeArmoredEnvelopeProducerAssertion,
///did:key identifier of the X25519 public key the envelope was sealed to. The recipient uses this to select the matching private key.
#[serde(rename = "recipientKeyId")]
pub recipient_key_id: HpkeArmoredEnvelopeRecipientKeyId,
}
impl ::std::convert::From<&HpkeArmoredEnvelope> for HpkeArmoredEnvelope {
fn from(value: &HpkeArmoredEnvelope) -> Self {
value.clone()
}
}
///ASCII-armored bundle text. Multi-line base64 with framing headers + CRC24.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "ASCII-armored bundle text. Multi-line base64 with framing headers + CRC24.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct HpkeArmoredEnvelopeArmored(::std::string::String);
impl ::std::ops::Deref for HpkeArmoredEnvelopeArmored {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<HpkeArmoredEnvelopeArmored> for ::std::string::String {
fn from(value: HpkeArmoredEnvelopeArmored) -> Self {
value.0
}
}
impl ::std::convert::From<&HpkeArmoredEnvelopeArmored> for HpkeArmoredEnvelopeArmored {
fn from(value: &HpkeArmoredEnvelopeArmored) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for HpkeArmoredEnvelopeArmored {
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 HpkeArmoredEnvelopeArmored {
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 HpkeArmoredEnvelopeArmored {
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 HpkeArmoredEnvelopeArmored {
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 HpkeArmoredEnvelopeArmored {
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())
})
}
}
///Producer-assertion mode per the sealed-transfer framework. `did-signed` = Ed25519 signature by issuer; `attested` = TEE attestation quote (e.g. Nitro); `pinned-only` = OOB SHA-256 digest only (dev/test, NOT for production).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Producer-assertion mode per the sealed-transfer framework. `did-signed` = Ed25519 signature by issuer; `attested` = TEE attestation quote (e.g. Nitro); `pinned-only` = OOB SHA-256 digest only (dev/test, NOT for production).",
/// "default": "did-signed",
/// "type": "string",
/// "enum": [
/// "did-signed",
/// "attested",
/// "pinned-only"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum HpkeArmoredEnvelopeProducerAssertion {
#[serde(rename = "did-signed")]
DidSigned,
#[serde(rename = "attested")]
Attested,
#[serde(rename = "pinned-only")]
PinnedOnly,
}
impl ::std::convert::From<&Self> for HpkeArmoredEnvelopeProducerAssertion {
fn from(value: &HpkeArmoredEnvelopeProducerAssertion) -> Self {
value.clone()
}
}
impl ::std::fmt::Display for HpkeArmoredEnvelopeProducerAssertion {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::DidSigned => f.write_str("did-signed"),
Self::Attested => f.write_str("attested"),
Self::PinnedOnly => f.write_str("pinned-only"),
}
}
}
impl ::std::str::FromStr for HpkeArmoredEnvelopeProducerAssertion {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"did-signed" => Ok(Self::DidSigned),
"attested" => Ok(Self::Attested),
"pinned-only" => Ok(Self::PinnedOnly),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for HpkeArmoredEnvelopeProducerAssertion {
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 HpkeArmoredEnvelopeProducerAssertion {
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 HpkeArmoredEnvelopeProducerAssertion {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::default::Default for HpkeArmoredEnvelopeProducerAssertion {
fn default() -> Self {
HpkeArmoredEnvelopeProducerAssertion::DidSigned
}
}
///did:key identifier of the X25519 public key the envelope was sealed to. The recipient uses this to select the matching private key.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "did:key identifier of the X25519 public key the envelope was sealed to. The recipient uses this to select the matching private key.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct HpkeArmoredEnvelopeRecipientKeyId(::std::string::String);
impl ::std::ops::Deref for HpkeArmoredEnvelopeRecipientKeyId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<HpkeArmoredEnvelopeRecipientKeyId> for ::std::string::String {
fn from(value: HpkeArmoredEnvelopeRecipientKeyId) -> Self {
value.0
}
}
impl ::std::convert::From<&HpkeArmoredEnvelopeRecipientKeyId>
for HpkeArmoredEnvelopeRecipientKeyId
{
fn from(value: &HpkeArmoredEnvelopeRecipientKeyId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for HpkeArmoredEnvelopeRecipientKeyId {
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 HpkeArmoredEnvelopeRecipientKeyId {
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 HpkeArmoredEnvelopeRecipientKeyId {
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 HpkeArmoredEnvelopeRecipientKeyId {
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 HpkeArmoredEnvelopeRecipientKeyId {
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())
})
}
}
///Consumer requests that the vault maintainer perform a login at the bound third-party site on the consumer's behalf, using the entry's secret material WITHOUT releasing it to the consumer. The maintainer returns a SessionBlob in a pluggable cipher envelope (see vault/_shared/0.1/sealed-envelope) containing the resulting cookies/headers the consumer can use to operate the session — but never the long-term credential.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/vault/proxy-login/0.1",
/// "title": "Payload",
/// "description": "Consumer requests that the vault maintainer perform a login at the bound third-party site on the consumer's behalf, using the entry's secret material WITHOUT releasing it to the consumer. The maintainer returns a SessionBlob in a pluggable cipher envelope (see vault/_shared/0.1/sealed-envelope) containing the resulting cookies/headers the consumer can use to operate the session — but never the long-term credential.",
/// "type": "object",
/// "required": [
/// "entryId"
/// ],
/// "properties": {
/// "consumerContext": {
/// "description": "Caller's situational context — fed to the maintainer's policy engine to decide proxy vs fill, require step-up, etc. Producers populate what they can observe; fields are advisory and the maintainer MUST cross-check anything security-relevant against its own state.",
/// "$ref": "#/definitions/ConsumerContext"
/// },
/// "entryId": {
/// "description": "Vault entry id to log in with.",
/// "type": "string",
/// "minLength": 1
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "nonce": {
/// "description": "Optional caller-supplied nonce the maintainer SHOULD embed verbatim in the resulting session credential when one applies — typically the relying party's challenge for SIOPv2-shaped flows, where the SIOP id_token's `nonce` claim MUST match the RP's authorization-request `nonce` for the RP to verify the token. When omitted, the maintainer generates its own nonce; that path is appropriate for flows where the consumer doesn't need to bind the credential to an external challenge (e.g. push-mode logins that don't pre-fetch a challenge). Drivers that have no nonce concept (Password POST, OAuth refresh) ignore this field.",
/// "type": "string",
/// "maxLength": 512,
/// "minLength": 1
/// },
/// "stepUpProof": {
/// "description": "Optional — included on retry after a prior proxy-login attempt returned `step_up_required`.",
/// "$ref": "#/definitions/StepUpProof"
/// },
/// "target": {
/// "description": "Optional — when an entry has multiple targets, names which one the consumer is acting against. The maintainer matches this against the entry's `targets[]`; if not supplied, the maintainer chooses the most specific target compatible with the requesting consumer's form factor (e.g. an iOS Companion gets the iOS-app target if one exists; otherwise the web-origin target).",
/// "$ref": "#/definitions/SiteTarget"
/// },
/// "ttlSecondsHint": {
/// "description": "Optional caller-preferred session TTL in seconds. The maintainer caps server-side per its policy; a higher hint MUST be silently truncated rather than rejected. Drivers that have a fixed-TTL bearer (e.g. SIOP id_tokens with their own `exp`) MUST NOT extend beyond the underlying credential's lifetime regardless of hint.",
/// "type": "integer",
/// "maximum": 86400.0,
/// "minimum": 1.0
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct Payload {
///Caller's situational context — fed to the maintainer's policy engine to decide proxy vs fill, require step-up, etc. Producers populate what they can observe; fields are advisory and the maintainer MUST cross-check anything security-relevant against its own state.
#[serde(
rename = "consumerContext",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub consumer_context: ::std::option::Option<ConsumerContext>,
///Vault entry id to log in with.
#[serde(rename = "entryId")]
pub entry_id: PayloadEntryId,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///Optional caller-supplied nonce the maintainer SHOULD embed verbatim in the resulting session credential when one applies — typically the relying party's challenge for SIOPv2-shaped flows, where the SIOP id_token's `nonce` claim MUST match the RP's authorization-request `nonce` for the RP to verify the token. When omitted, the maintainer generates its own nonce; that path is appropriate for flows where the consumer doesn't need to bind the credential to an external challenge (e.g. push-mode logins that don't pre-fetch a challenge). Drivers that have no nonce concept (Password POST, OAuth refresh) ignore this field.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub nonce: ::std::option::Option<PayloadNonce>,
///Optional — included on retry after a prior proxy-login attempt returned `step_up_required`.
#[serde(
rename = "stepUpProof",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub step_up_proof: ::std::option::Option<StepUpProof>,
///Optional — when an entry has multiple targets, names which one the consumer is acting against. The maintainer matches this against the entry's `targets[]`; if not supplied, the maintainer chooses the most specific target compatible with the requesting consumer's form factor (e.g. an iOS Companion gets the iOS-app target if one exists; otherwise the web-origin target).
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub target: ::std::option::Option<SiteTarget>,
///Optional caller-preferred session TTL in seconds. The maintainer caps server-side per its policy; a higher hint MUST be silently truncated rather than rejected. Drivers that have a fixed-TTL bearer (e.g. SIOP id_tokens with their own `exp`) MUST NOT extend beyond the underlying credential's lifetime regardless of hint.
#[serde(
rename = "ttlSecondsHint",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub ttl_seconds_hint: ::std::option::Option<::std::num::NonZeroU64>,
}
impl ::std::convert::From<&Payload> for Payload {
fn from(value: &Payload) -> Self {
value.clone()
}
}
///Vault entry id to log in with.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Vault entry id to log in with.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadEntryId(::std::string::String);
impl ::std::ops::Deref for PayloadEntryId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadEntryId> for ::std::string::String {
fn from(value: PayloadEntryId) -> Self {
value.0
}
}
impl ::std::convert::From<&PayloadEntryId> for PayloadEntryId {
fn from(value: &PayloadEntryId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for PayloadEntryId {
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 PayloadEntryId {
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 PayloadEntryId {
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 PayloadEntryId {
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 PayloadEntryId {
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())
})
}
}
///Optional caller-supplied nonce the maintainer SHOULD embed verbatim in the resulting session credential when one applies — typically the relying party's challenge for SIOPv2-shaped flows, where the SIOP id_token's `nonce` claim MUST match the RP's authorization-request `nonce` for the RP to verify the token. When omitted, the maintainer generates its own nonce; that path is appropriate for flows where the consumer doesn't need to bind the credential to an external challenge (e.g. push-mode logins that don't pre-fetch a challenge). Drivers that have no nonce concept (Password POST, OAuth refresh) ignore this field.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Optional caller-supplied nonce the maintainer SHOULD embed verbatim in the resulting session credential when one applies — typically the relying party's challenge for SIOPv2-shaped flows, where the SIOP id_token's `nonce` claim MUST match the RP's authorization-request `nonce` for the RP to verify the token. When omitted, the maintainer generates its own nonce; that path is appropriate for flows where the consumer doesn't need to bind the credential to an external challenge (e.g. push-mode logins that don't pre-fetch a challenge). Drivers that have no nonce concept (Password POST, OAuth refresh) ignore this field.",
/// "type": "string",
/// "maxLength": 512,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadNonce(::std::string::String);
impl ::std::ops::Deref for PayloadNonce {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadNonce> for ::std::string::String {
fn from(value: PayloadNonce) -> Self {
value.0
}
}
impl ::std::convert::From<&PayloadNonce> for PayloadNonce {
fn from(value: &PayloadNonce) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for PayloadNonce {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 512usize {
return Err("longer than 512 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 PayloadNonce {
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 PayloadNonce {
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 PayloadNonce {
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 PayloadNonce {
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())
})
}
}
///`Response`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "type": "object",
/// "required": [
/// "sealedSessionBlob"
/// ],
/// "properties": {
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "sealedSessionBlob": {
/// "description": "Pluggable cipher envelope containing the SessionBlob cleartext (see `vault/_shared/0.1/session-blob`). The consumer unseals to recover cookies/headers, then injects into its browser session for the bound origin. Consumers reject envelope kinds they don't implement with `vault/proxy-login:envelope_unsupported`.",
/// "$ref": "#/definitions/SealedEnvelope"
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct Response {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///Pluggable cipher envelope containing the SessionBlob cleartext (see `vault/_shared/0.1/session-blob`). The consumer unseals to recover cookies/headers, then injects into its browser session for the bound origin. Consumers reject envelope kinds they don't implement with `vault/proxy-login:envelope_unsupported`.
#[serde(rename = "sealedSessionBlob")]
pub sealed_session_blob: SealedEnvelope,
}
impl ::std::convert::From<&Response> for Response {
fn from(value: &Response) -> Self {
value.clone()
}
}
///Discriminated by `envelope`. Exactly one variant matches per document.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "SealedEnvelope",
/// "description": "Discriminated by `envelope`. Exactly one variant matches per document.",
/// "oneOf": [
/// {
/// "$ref": "#/definitions/DidcommAuthcryptEnvelope"
/// },
/// {
/// "$ref": "#/definitions/HpkeArmoredEnvelope"
/// },
/// {
/// "$ref": "#/definitions/TspMessageEnvelope"
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged)]
pub enum SealedEnvelope {
DidcommAuthcryptEnvelope(DidcommAuthcryptEnvelope),
HpkeArmoredEnvelope(HpkeArmoredEnvelope),
TspMessageEnvelope(TspMessageEnvelope),
}
impl ::std::convert::From<&Self> for SealedEnvelope {
fn from(value: &SealedEnvelope) -> Self {
value.clone()
}
}
impl ::std::convert::From<DidcommAuthcryptEnvelope> for SealedEnvelope {
fn from(value: DidcommAuthcryptEnvelope) -> Self {
Self::DidcommAuthcryptEnvelope(value)
}
}
impl ::std::convert::From<HpkeArmoredEnvelope> for SealedEnvelope {
fn from(value: HpkeArmoredEnvelope) -> Self {
Self::HpkeArmoredEnvelope(value)
}
}
impl ::std::convert::From<TspMessageEnvelope> for SealedEnvelope {
fn from(value: TspMessageEnvelope) -> Self {
Self::TspMessageEnvelope(value)
}
}
///A single binding target for a vault entry. Tagged union over the discriminator `kind`. A VaultEntry's `targets` array MAY mix any number of these.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "SiteTarget",
/// "description": "A single binding target for a vault entry. Tagged union over the discriminator `kind`. A VaultEntry's `targets` array MAY mix any number of these.",
/// "oneOf": [
/// {
/// "title": "WebOrigin",
/// "type": "object",
/// "required": [
/// "kind",
/// "origin"
/// ],
/// "properties": {
/// "kind": {
/// "const": "web-origin"
/// },
/// "origin": {
/// "description": "Web origin per RFC 6454 (scheme + host + optional port), e.g. \"https://github.com\". Compared by exact string equality after canonicalisation (lowercase host, default port elided). Consumers wanting subdomain coverage SHOULD add multiple targets, not encode a wildcard.",
/// "type": "string",
/// "format": "uri"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "Did",
/// "type": "object",
/// "required": [
/// "did",
/// "kind"
/// ],
/// "properties": {
/// "did": {
/// "description": "DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.",
/// "type": "string",
/// "minLength": 1
/// },
/// "kind": {
/// "const": "did"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "IosApp",
/// "type": "object",
/// "required": [
/// "bundleId",
/// "kind"
/// ],
/// "properties": {
/// "bundleId": {
/// "description": "iOS bundle identifier in reverse-DNS form (e.g. \"com.github.stwalkerster.codehub\"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z0-9.-]+$"
/// },
/// "kind": {
/// "const": "ios-app"
/// },
/// "teamId": {
/// "description": "Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Z0-9]+$"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "AndroidApp",
/// "type": "object",
/// "required": [
/// "kind",
/// "packageName",
/// "sha256CertFingerprints"
/// ],
/// "properties": {
/// "kind": {
/// "const": "android-app"
/// },
/// "packageName": {
/// "description": "Android package name in reverse-DNS form (e.g. \"com.github.android\").",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$"
/// },
/// "sha256CertFingerprints": {
/// "description": "SHA-256 fingerprints of the app's signing certificates, in colon-separated hex (the format `apksigner` and the Play Console emit). At least one fingerprint MUST be present. The maintainer matches when ANY of the provided fingerprints matches the requesting app's signature — this supports apps signed by multiple keys (e.g. during certificate rotation via Play App Signing).",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "pattern": "^[0-9A-F]{2}(:[0-9A-F]{2}){31}$"
/// },
/// "minItems": 1,
/// "uniqueItems": true
/// }
/// },
/// "additionalProperties": false
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(tag = "kind", deny_unknown_fields)]
pub enum SiteTarget {
///WebOrigin
#[serde(rename = "web-origin")]
WebOrigin {
///Web origin per RFC 6454 (scheme + host + optional port), e.g. "https://github.com". Compared by exact string equality after canonicalisation (lowercase host, default port elided). Consumers wanting subdomain coverage SHOULD add multiple targets, not encode a wildcard.
origin: ::std::string::String,
},
///Did
#[serde(rename = "did")]
Did {
///DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.
did: SiteTargetDid,
},
///IosApp
#[serde(rename = "ios-app")]
IosApp {
///iOS bundle identifier in reverse-DNS form (e.g. "com.github.stwalkerster.codehub"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).
#[serde(rename = "bundleId")]
bundle_id: SiteTargetBundleId,
///Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.
#[serde(
rename = "teamId",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
team_id: ::std::option::Option<SiteTargetTeamId>,
},
///AndroidApp
#[serde(rename = "android-app")]
AndroidApp {
///Android package name in reverse-DNS form (e.g. "com.github.android").
#[serde(rename = "packageName")]
package_name: SiteTargetPackageName,
///SHA-256 fingerprints of the app's signing certificates, in colon-separated hex (the format `apksigner` and the Play Console emit). At least one fingerprint MUST be present. The maintainer matches when ANY of the provided fingerprints matches the requesting app's signature — this supports apps signed by multiple keys (e.g. during certificate rotation via Play App Signing).
#[serde(rename = "sha256CertFingerprints")]
sha256_cert_fingerprints: Vec<SiteTargetSha256CertFingerprintsItem>,
},
}
impl ::std::convert::From<&Self> for SiteTarget {
fn from(value: &SiteTarget) -> Self {
value.clone()
}
}
///iOS bundle identifier in reverse-DNS form (e.g. "com.github.stwalkerster.codehub"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "iOS bundle identifier in reverse-DNS form (e.g. \"com.github.stwalkerster.codehub\"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z0-9.-]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetBundleId(::std::string::String);
impl ::std::ops::Deref for SiteTargetBundleId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetBundleId> for ::std::string::String {
fn from(value: SiteTargetBundleId) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetBundleId> for SiteTargetBundleId {
fn from(value: &SiteTargetBundleId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetBundleId {
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());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[A-Za-z0-9.-]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[A-Za-z0-9.-]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetBundleId {
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 SiteTargetBundleId {
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 SiteTargetBundleId {
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 SiteTargetBundleId {
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())
})
}
}
///DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetDid(::std::string::String);
impl ::std::ops::Deref for SiteTargetDid {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetDid> for ::std::string::String {
fn from(value: SiteTargetDid) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetDid> for SiteTargetDid {
fn from(value: &SiteTargetDid) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetDid {
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 SiteTargetDid {
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 SiteTargetDid {
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 SiteTargetDid {
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 SiteTargetDid {
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())
})
}
}
///Android package name in reverse-DNS form (e.g. "com.github.android").
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Android package name in reverse-DNS form (e.g. \"com.github.android\").",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetPackageName(::std::string::String);
impl ::std::ops::Deref for SiteTargetPackageName {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetPackageName> for ::std::string::String {
fn from(value: SiteTargetPackageName) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetPackageName> for SiteTargetPackageName {
fn from(value: &SiteTargetPackageName) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetPackageName {
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());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err(
"doesn't match pattern \"^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$\""
.into(),
);
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetPackageName {
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 SiteTargetPackageName {
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 SiteTargetPackageName {
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 SiteTargetPackageName {
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())
})
}
}
///`SiteTargetSha256CertFingerprintsItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "pattern": "^[0-9A-F]{2}(:[0-9A-F]{2}){31}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetSha256CertFingerprintsItem(::std::string::String);
impl ::std::ops::Deref for SiteTargetSha256CertFingerprintsItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetSha256CertFingerprintsItem> for ::std::string::String {
fn from(value: SiteTargetSha256CertFingerprintsItem) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetSha256CertFingerprintsItem>
for SiteTargetSha256CertFingerprintsItem
{
fn from(value: &SiteTargetSha256CertFingerprintsItem) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetSha256CertFingerprintsItem {
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-9A-F]{2}(:[0-9A-F]{2}){31}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[0-9A-F]{2}(:[0-9A-F]{2}){31}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetSha256CertFingerprintsItem {
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 SiteTargetSha256CertFingerprintsItem {
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 SiteTargetSha256CertFingerprintsItem {
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 SiteTargetSha256CertFingerprintsItem {
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())
})
}
}
///Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Z0-9]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetTeamId(::std::string::String);
impl ::std::ops::Deref for SiteTargetTeamId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetTeamId> for ::std::string::String {
fn from(value: SiteTargetTeamId) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetTeamId> for SiteTargetTeamId {
fn from(value: &SiteTargetTeamId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetTeamId {
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());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[A-Z0-9]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[A-Z0-9]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetTeamId {
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 SiteTargetTeamId {
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 SiteTargetTeamId {
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 SiteTargetTeamId {
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())
})
}
}
///`StepUpProof`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "StepUpProof",
/// "type": "object",
/// "required": [
/// "challengeId",
/// "kind",
/// "proof"
/// ],
/// "properties": {
/// "challengeId": {
/// "description": "Maintainer-issued challenge id the proof responds to.",
/// "type": "string",
/// "minLength": 1
/// },
/// "kind": {
/// "type": "string",
/// "enum": [
/// "webauthn-uv",
/// "push-approval",
/// "totp"
/// ]
/// },
/// "proof": {
/// "description": "Format depends on kind: WebAuthn assertion (base64url), DIDComm approval-response message id, or 6–8-digit TOTP code.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct StepUpProof {
///Maintainer-issued challenge id the proof responds to.
#[serde(rename = "challengeId")]
pub challenge_id: StepUpProofChallengeId,
pub kind: StepUpProofKind,
///Format depends on kind: WebAuthn assertion (base64url), DIDComm approval-response message id, or 6–8-digit TOTP code.
pub proof: ::std::string::String,
}
impl ::std::convert::From<&StepUpProof> for StepUpProof {
fn from(value: &StepUpProof) -> Self {
value.clone()
}
}
///Maintainer-issued challenge id the proof responds to.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Maintainer-issued challenge id the proof responds to.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct StepUpProofChallengeId(::std::string::String);
impl ::std::ops::Deref for StepUpProofChallengeId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<StepUpProofChallengeId> for ::std::string::String {
fn from(value: StepUpProofChallengeId) -> Self {
value.0
}
}
impl ::std::convert::From<&StepUpProofChallengeId> for StepUpProofChallengeId {
fn from(value: &StepUpProofChallengeId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for StepUpProofChallengeId {
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 StepUpProofChallengeId {
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 StepUpProofChallengeId {
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 StepUpProofChallengeId {
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 StepUpProofChallengeId {
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())
})
}
}
///`StepUpProofKind`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "webauthn-uv",
/// "push-approval",
/// "totp"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum StepUpProofKind {
#[serde(rename = "webauthn-uv")]
WebauthnUv,
#[serde(rename = "push-approval")]
PushApproval,
#[serde(rename = "totp")]
Totp,
}
impl ::std::convert::From<&Self> for StepUpProofKind {
fn from(value: &StepUpProofKind) -> Self {
value.clone()
}
}
impl ::std::fmt::Display for StepUpProofKind {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::WebauthnUv => f.write_str("webauthn-uv"),
Self::PushApproval => f.write_str("push-approval"),
Self::Totp => f.write_str("totp"),
}
}
}
impl ::std::str::FromStr for StepUpProofKind {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"webauthn-uv" => Ok(Self::WebauthnUv),
"push-approval" => Ok(Self::PushApproval),
"totp" => Ok(Self::Totp),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for StepUpProofKind {
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 StepUpProofKind {
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 StepUpProofKind {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Trust Spanning Protocol message (https://trustoverip.github.io/tswg-tsp-specification/). Reserved variant; no OpenVTC component reads or emits this today. Listed in the union so implementations can declare intent to use TSP in discovery and so consumers reject `tsp-message` envelopes explicitly (`envelope_unsupported`) until they're wired up — rather than silently failing in DIDComm parsing.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "TspMessageEnvelope",
/// "description": "Trust Spanning Protocol message (https://trustoverip.github.io/tswg-tsp-specification/). Reserved variant; no OpenVTC component reads or emits this today. Listed in the union so implementations can declare intent to use TSP in discovery and so consumers reject `tsp-message` envelopes explicitly (`envelope_unsupported`) until they're wired up — rather than silently failing in DIDComm parsing.",
/// "type": "object",
/// "required": [
/// "envelope",
/// "message"
/// ],
/// "properties": {
/// "envelope": {
/// "const": "tsp-message"
/// },
/// "message": {
/// "description": "Base64url-encoded TSP message bytes. Format reference: https://trustoverip.github.io/tswg-tsp-specification/#message-format",
/// "type": "string",
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct TspMessageEnvelope {
pub envelope: ::serde_json::Value,
///Base64url-encoded TSP message bytes. Format reference: https://trustoverip.github.io/tswg-tsp-specification/#message-format
pub message: TspMessageEnvelopeMessage,
}
impl ::std::convert::From<&TspMessageEnvelope> for TspMessageEnvelope {
fn from(value: &TspMessageEnvelope) -> Self {
value.clone()
}
}
///Base64url-encoded TSP message bytes. Format reference: https://trustoverip.github.io/tswg-tsp-specification/#message-format
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Base64url-encoded TSP message bytes. Format reference: https://trustoverip.github.io/tswg-tsp-specification/#message-format",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct TspMessageEnvelopeMessage(::std::string::String);
impl ::std::ops::Deref for TspMessageEnvelopeMessage {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<TspMessageEnvelopeMessage> for ::std::string::String {
fn from(value: TspMessageEnvelopeMessage) -> Self {
value.0
}
}
impl ::std::convert::From<&TspMessageEnvelopeMessage> for TspMessageEnvelopeMessage {
fn from(value: &TspMessageEnvelopeMessage) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for TspMessageEnvelopeMessage {
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 TspMessageEnvelopeMessage {
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 TspMessageEnvelopeMessage {
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 TspMessageEnvelopeMessage {
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 TspMessageEnvelopeMessage {
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())
})
}
}
/// Generation of default values for serde.
pub mod defaults {
pub(super) fn hpke_armored_envelope_producer_assertion(
) -> super::HpkeArmoredEnvelopeProducerAssertion {
super::HpkeArmoredEnvelopeProducerAssertion::DidSigned
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vault/proxy-login/0.1";
const IS_PROOF_REQUIRED: bool = true;
}
impl crate::Payload for Response {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vault/proxy-login/0.1#response";
const IS_PROOF_REQUIRED: bool = true;
}
#[cfg(feature = "validate")]
impl crate::validate::ValidatedPayload for Payload {
const SCHEMA_JSON: &'static str = "{\n \"$defs\": {\n \"ConsumerContext\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"deviceId\": {\n \"description\": \"Device-binding id assigned at registration. The maintainer cross-checks this against the authenticated transport identity.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"lastUserVerificationAt\": {\n \"description\": \"Most recent local user-verification on the consumer device (WebAuthn UV, biometric unlock). The maintainer's policy may require this to be within N seconds.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"networkClass\": {\n \"description\": \"Producer-supplied network classification. Advisory.\",\n \"enum\": [\n \"unknown\",\n \"home\",\n \"corp\",\n \"public\",\n \"vpn\"\n ],\n \"type\": \"string\"\n }\n },\n \"title\": \"ConsumerContext\",\n \"type\": \"object\"\n },\n \"DidcommAuthcryptEnvelope\": {\n \"additionalProperties\": false,\n \"description\": \"DIDComm v2 authcrypt JWE (ECDH-1PU + A256CBC-HS512, X25519/P-256 key agreement). Sender authentication is the JWE's `skid` — the producer's DID#keyAgreement. The maintainer's keyAgreement key is the recipient. Cleartext is JCS-canonical JSON of the variant's payload type.\\n\\nM2A is the only implementation today; this is also the canonical default for new code.\",\n \"properties\": {\n \"envelope\": {\n \"const\": \"didcomm-authcrypt\"\n },\n \"jwe\": {\n \"description\": \"Compact DIDComm v2 JWE (base64url-encoded, dot-separated). Unpacks via the framework's standard DIDComm machinery; cleartext is the payload-specific JSON.\",\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"envelope\",\n \"jwe\"\n ],\n \"title\": \"DidcommAuthcryptEnvelope\",\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 \"HpkeArmoredEnvelope\": {\n \"additionalProperties\": false,\n \"description\": \"OpenPGP-style ASCII-armored HPKE bundle — the existing OpenVTC sealed-transfer wire form (X25519-HKDF-SHA256 KEM + ChaCha20-Poly1305 AEAD, framed in armor with Bundle-Id / Digest-Algo headers and a CRC24 checksum). Producer assertion (`did-signed` / `attested` / `pinned-only`) is the integrity / authenticity anchor.\\n\\nNo open-source implementation reads this yet outside vta-sdk's `sealed_transfer` crate; new code SHOULD prefer the DIDComm variant. Defined here for parity with the existing offline-bundle / cross-VTA workflows that the design plan reserves for M5+.\",\n \"properties\": {\n \"armored\": {\n \"description\": \"ASCII-armored bundle text. Multi-line base64 with framing headers + CRC24.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"envelope\": {\n \"const\": \"hpke-armored\"\n },\n \"producerAssertion\": {\n \"default\": \"did-signed\",\n \"description\": \"Producer-assertion mode per the sealed-transfer framework. `did-signed` = Ed25519 signature by issuer; `attested` = TEE attestation quote (e.g. Nitro); `pinned-only` = OOB SHA-256 digest only (dev/test, NOT for production).\",\n \"enum\": [\n \"did-signed\",\n \"attested\",\n \"pinned-only\"\n ],\n \"type\": \"string\"\n },\n \"recipientKeyId\": {\n \"description\": \"did:key identifier of the X25519 public key the envelope was sealed to. The recipient uses this to select the matching private key.\",\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"envelope\",\n \"armored\",\n \"recipientKeyId\"\n ],\n \"title\": \"HpkeArmoredEnvelope\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"properties\": {\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"sealedSessionBlob\": {\n \"$ref\": \"#/$defs/SealedEnvelope\",\n \"description\": \"Pluggable cipher envelope containing the SessionBlob cleartext (see `vault/_shared/0.1/session-blob`). The consumer unseals to recover cookies/headers, then injects into its browser session for the bound origin. Consumers reject envelope kinds they don't implement with `vault/proxy-login:envelope_unsupported`.\"\n }\n },\n \"required\": [\n \"sealedSessionBlob\"\n ],\n \"title\": \"Vault Proxy-Login — response payload\",\n \"type\": \"object\"\n },\n \"SealedEnvelope\": {\n \"description\": \"Discriminated by `envelope`. Exactly one variant matches per document.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/DidcommAuthcryptEnvelope\"\n },\n {\n \"$ref\": \"#/$defs/HpkeArmoredEnvelope\"\n },\n {\n \"$ref\": \"#/$defs/TspMessageEnvelope\"\n }\n ],\n \"title\": \"SealedEnvelope\"\n },\n \"SiteTarget\": {\n \"description\": \"A single binding target for a vault entry. Tagged union over the discriminator `kind`. A VaultEntry's `targets` array MAY mix any number of these.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"web-origin\"\n },\n \"origin\": {\n \"description\": \"Web origin per RFC 6454 (scheme + host + optional port), e.g. \\\"https://github.com\\\". Compared by exact string equality after canonicalisation (lowercase host, default port elided). Consumers wanting subdomain coverage SHOULD add multiple targets, not encode a wildcard.\",\n \"format\": \"uri\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"origin\"\n ],\n \"title\": \"WebOrigin\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"did\": {\n \"description\": \"DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"did\"\n }\n },\n \"required\": [\n \"kind\",\n \"did\"\n ],\n \"title\": \"Did\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"bundleId\": {\n \"description\": \"iOS bundle identifier in reverse-DNS form (e.g. \\\"com.github.stwalkerster.codehub\\\"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).\",\n \"minLength\": 1,\n \"pattern\": \"^[A-Za-z0-9.-]+$\",\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"ios-app\"\n },\n \"teamId\": {\n \"description\": \"Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.\",\n \"minLength\": 1,\n \"pattern\": \"^[A-Z0-9]+$\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"bundleId\"\n ],\n \"title\": \"IosApp\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"android-app\"\n },\n \"packageName\": {\n \"description\": \"Android package name in reverse-DNS form (e.g. \\\"com.github.android\\\").\",\n \"minLength\": 1,\n \"pattern\": \"^[A-Za-z][A-Za-z0-9_]*(\\\\.[A-Za-z][A-Za-z0-9_]*)+$\",\n \"type\": \"string\"\n },\n \"sha256CertFingerprints\": {\n \"description\": \"SHA-256 fingerprints of the app's signing certificates, in colon-separated hex (the format `apksigner` and the Play Console emit). At least one fingerprint MUST be present. The maintainer matches when ANY of the provided fingerprints matches the requesting app's signature — this supports apps signed by multiple keys (e.g. during certificate rotation via Play App Signing).\",\n \"items\": {\n \"pattern\": \"^[0-9A-F]{2}(:[0-9A-F]{2}){31}$\",\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"type\": \"array\",\n \"uniqueItems\": true\n }\n },\n \"required\": [\n \"kind\",\n \"packageName\",\n \"sha256CertFingerprints\"\n ],\n \"title\": \"AndroidApp\",\n \"type\": \"object\"\n }\n ],\n \"title\": \"SiteTarget\"\n },\n \"StepUpProof\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"challengeId\": {\n \"description\": \"Maintainer-issued challenge id the proof responds to.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"kind\": {\n \"enum\": [\n \"webauthn-uv\",\n \"push-approval\",\n \"totp\"\n ],\n \"type\": \"string\"\n },\n \"proof\": {\n \"description\": \"Format depends on kind: WebAuthn assertion (base64url), DIDComm approval-response message id, or 6–8-digit TOTP code.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"proof\",\n \"challengeId\"\n ],\n \"title\": \"StepUpProof\",\n \"type\": \"object\"\n },\n \"TspMessageEnvelope\": {\n \"additionalProperties\": false,\n \"description\": \"Trust Spanning Protocol message (https://trustoverip.github.io/tswg-tsp-specification/). Reserved variant; no OpenVTC component reads or emits this today. Listed in the union so implementations can declare intent to use TSP in discovery and so consumers reject `tsp-message` envelopes explicitly (`envelope_unsupported`) until they're wired up — rather than silently failing in DIDComm parsing.\",\n \"properties\": {\n \"envelope\": {\n \"const\": \"tsp-message\"\n },\n \"message\": {\n \"description\": \"Base64url-encoded TSP message bytes. Format reference: https://trustoverip.github.io/tswg-tsp-specification/#message-format\",\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"envelope\",\n \"message\"\n ],\n \"title\": \"TspMessageEnvelope\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/vault/proxy-login/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"Consumer requests that the vault maintainer perform a login at the bound third-party site on the consumer's behalf, using the entry's secret material WITHOUT releasing it to the consumer. The maintainer returns a SessionBlob in a pluggable cipher envelope (see vault/_shared/0.1/sealed-envelope) containing the resulting cookies/headers the consumer can use to operate the session — but never the long-term credential.\",\n \"properties\": {\n \"consumerContext\": {\n \"$ref\": \"#/$defs/ConsumerContext\",\n \"description\": \"Caller's situational context — fed to the maintainer's policy engine to decide proxy vs fill, require step-up, etc. Producers populate what they can observe; fields are advisory and the maintainer MUST cross-check anything security-relevant against its own state.\"\n },\n \"entryId\": {\n \"description\": \"Vault entry id to log in with.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"nonce\": {\n \"description\": \"Optional caller-supplied nonce the maintainer SHOULD embed verbatim in the resulting session credential when one applies — typically the relying party's challenge for SIOPv2-shaped flows, where the SIOP id_token's `nonce` claim MUST match the RP's authorization-request `nonce` for the RP to verify the token. When omitted, the maintainer generates its own nonce; that path is appropriate for flows where the consumer doesn't need to bind the credential to an external challenge (e.g. push-mode logins that don't pre-fetch a challenge). Drivers that have no nonce concept (Password POST, OAuth refresh) ignore this field.\",\n \"maxLength\": 512,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"stepUpProof\": {\n \"$ref\": \"#/$defs/StepUpProof\",\n \"description\": \"Optional — included on retry after a prior proxy-login attempt returned `step_up_required`.\"\n },\n \"target\": {\n \"$ref\": \"#/$defs/SiteTarget\",\n \"description\": \"Optional — when an entry has multiple targets, names which one the consumer is acting against. The maintainer matches this against the entry's `targets[]`; if not supplied, the maintainer chooses the most specific target compatible with the requesting consumer's form factor (e.g. an iOS Companion gets the iOS-app target if one exists; otherwise the web-origin target).\"\n },\n \"ttlSecondsHint\": {\n \"description\": \"Optional caller-preferred session TTL in seconds. The maintainer caps server-side per its policy; a higher hint MUST be silently truncated rather than rejected. Drivers that have a fixed-TTL bearer (e.g. SIOP id_tokens with their own `exp`) MUST NOT extend beyond the underlying credential's lifetime regardless of hint.\",\n \"maximum\": 86400,\n \"minimum\": 1,\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"entryId\"\n ],\n \"title\": \"Vault Proxy-Login — payload\",\n \"type\": \"object\"\n}\n";
}