//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vault/upsert`. Version: `0.3`.
#![allow(deprecated)]
/// Why this specification version is deprecated (SPEC "Superseded and
/// Withdrawn Versions"), or `None` while it is current.
pub const DEPRECATION: Option<&str> = Some("superseded by vault/upsert/0.4");
#[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())
}
}
}
///`AttachmentRef`
///
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct AttachmentRef {
///Optional MIME type hint for the consumer UI (e.g. "text/plain", "application/x-pem-file").
#[serde(
rename = "contentType",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub content_type: ::std::option::Option<::std::string::String>,
///Digest over the encrypted blob bytes (post-encryption), so the consumer can verify integrity after fetch. Taken over the bytes as stored, not over a canonicalization: the blob is an opaque artifact, not a JSON document.
#[serde(rename = "digestMultibase")]
pub digest_multibase: DigestMultibase,
///Opaque maintainer-assigned id for this attachment; used to fetch the blob via a separate mechanism.
pub id: AttachmentRefId,
///User-supplied filename (e.g. "recovery-codes.txt").
pub name: AttachmentRefName,
///Size of the encrypted blob in bytes. Maintainers MAY enforce a maximum per attachment and per entry.
#[serde(rename = "sizeBytes")]
pub size_bytes: u64,
}
impl AttachmentRef {
pub fn builder() -> builder::AttachmentRef {
Default::default()
}
}
///Opaque maintainer-assigned id for this attachment; used to fetch the blob via a separate mechanism.
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct AttachmentRefId(::std::string::String);
impl ::std::ops::Deref for AttachmentRefId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AttachmentRefId> for ::std::string::String {
fn from(value: AttachmentRefId) -> Self {
value.0
}
}
impl ::std::str::FromStr for AttachmentRefId {
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 AttachmentRefId {
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 AttachmentRefId {
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 AttachmentRefId {
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 AttachmentRefId {
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())
})
}
}
///User-supplied filename (e.g. "recovery-codes.txt").
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct AttachmentRefName(::std::string::String);
impl ::std::ops::Deref for AttachmentRefName {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AttachmentRefName> for ::std::string::String {
fn from(value: AttachmentRefName) -> Self {
value.0
}
}
impl ::std::str::FromStr for AttachmentRefName {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 256usize {
return Err("longer than 256 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for AttachmentRefName {
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 AttachmentRefName {
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 AttachmentRefName {
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 AttachmentRefName {
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())
})
}
}
/**
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.*/
///
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
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 DidcommAuthcryptEnvelope {
pub fn builder() -> builder::DidcommAuthcryptEnvelope {
Default::default()
}
}
///Compact DIDComm v2 JWE (base64url-encoded, dot-separated). Unpacks via the framework's standard DIDComm machinery; cleartext is the payload-specific JSON.
///
#[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::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())
})
}
}
/**
A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.
Multihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.
This definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.
Restricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that "interoperability is not guaranteed between implementations using such values", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.*/
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct DigestMultibase(::std::string::String);
impl ::std::ops::Deref for DigestMultibase {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DigestMultibase> for ::std::string::String {
fn from(value: DigestMultibase) -> Self {
value.0
}
}
impl ::std::str::FromStr for DigestMultibase {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 16usize {
return Err("shorter than 16 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err(
"doesn't match pattern \"^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$\"".into(),
);
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for DigestMultibase {
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 DigestMultibase {
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 DigestMultibase {
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 DigestMultibase {
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.
///
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct Ext(pub ::std::collections::HashMap<ExtKey, ::serde_json::Value>);
impl ::std::ops::Deref for Ext {
type Target = ::std::collections::HashMap<ExtKey, ::serde_json::Value>;
fn deref(&self) -> &::std::collections::HashMap<ExtKey, ::serde_json::Value> {
&self.0
}
}
impl ::std::convert::From<Ext> for ::std::collections::HashMap<ExtKey, ::serde_json::Value> {
fn from(value: Ext) -> Self {
value.0
}
}
impl ::std::convert::From<::std::collections::HashMap<ExtKey, ::serde_json::Value>> for Ext {
fn from(value: ::std::collections::HashMap<ExtKey, ::serde_json::Value>) -> Self {
Self(value)
}
}
///`ExtKey`
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ExtKey(::std::string::String);
impl ::std::ops::Deref for ExtKey {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ExtKey> for ::std::string::String {
fn from(value: ExtKey) -> Self {
value.0
}
}
impl ::std::str::FromStr for ExtKey {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for ExtKey {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
/**
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 (`didSigned` / `attested` / `pinnedOnly`) 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+.*/
///
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
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. `didSigned` = Ed25519 signature by issuer; `attested` = TEE attestation quote (e.g. Nitro); `pinnedOnly` = 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 HpkeArmoredEnvelope {
pub fn builder() -> builder::HpkeArmoredEnvelope {
Default::default()
}
}
///ASCII-armored bundle text. Multi-line base64 with framing headers + CRC24.
///
#[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::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. `didSigned` = Ed25519 signature by issuer; `attested` = TEE attestation quote (e.g. Nitro); `pinnedOnly` = OOB SHA-256 digest only (dev/test, NOT for production).
///
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum HpkeArmoredEnvelopeProducerAssertion {
#[serde(rename = "didSigned")]
DidSigned,
#[serde(rename = "attested")]
Attested,
#[serde(rename = "pinnedOnly")]
PinnedOnly,
}
impl ::std::fmt::Display for HpkeArmoredEnvelopeProducerAssertion {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::DidSigned => f.write_str("didSigned"),
Self::Attested => f.write_str("attested"),
Self::PinnedOnly => f.write_str("pinnedOnly"),
}
}
}
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 {
"didSigned" => Ok(Self::DidSigned),
"attested" => Ok(Self::Attested),
"pinnedOnly" => 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.
///
#[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::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())
})
}
}
///Create a new vault entry or update an existing one. The secret material — if present — rides inside a pluggable cipher envelope (see `vault/_shared/0.1/sealed-envelope`), so the Trust Task carries ciphertext and an authenticator, not plaintext. Updates may be partial: any populated metadata field replaces the current value; omitted fields are left untouched; explicit null clears the field (per `clearFields`). Optimistic-concurrency check via `expectedVersion`.
///
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
#[deprecated(note = "superseded by vault/upsert/0.4")]
pub struct Payload {
///List of metadata fields to explicitly clear on this upsert. Distinguishes "don't touch" (field omitted from payload) from "clear" (field listed here).
#[serde(
rename = "clearFields",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub clear_fields: ::std::option::Option<Vec<PayloadClearFieldsItem>>,
///Trust context the entry belongs to. Cannot be changed by upsert; to move an entry between contexts the consumer MUST delete and recreate.
#[serde(rename = "contextId")]
pub context_id: PayloadContextId,
#[serde(
rename = "customFieldNames",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub custom_field_names: ::std::option::Option<Vec<PayloadCustomFieldNamesItem>>,
///When updating, the consumer's last-observed `version` for the entry. The maintainer rejects with `vault/upsert:versionConflict` if the current version differs. Omit on create.
#[serde(
rename = "expectedVersion",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub expected_version: ::std::option::Option<u64>,
#[serde(
rename = "expiresAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub expires_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub favicon: ::std::option::Option<::std::string::String>,
///Entry id. Omit to create; supply to update. Maintainers MAY accept consumer-supplied ids on create (recommended: ULID) or MAY assign their own and return the assigned id in the response.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub id: ::std::option::Option<PayloadId>,
pub label: PayloadLabel,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub notes: ::std::option::Option<PayloadNotes>,
///Pluggable cipher envelope (discriminated by `envelope`) whose cleartext is a JCS-canonical JSON conforming to `vault/_shared/0.1/vault-secret#/$defs/VaultSecret`. The supported envelope kinds are listed in the SealedEnvelope shared schema; M2A consumers reject any kind they don't implement with `vault/upsert:envelopeUnsupported`. REQUIRED on create unless `secretKind` is `didSelfIssued` or `didcommPeer` (those carry only references to maintainer-internal key ids and have no extra secret bytes). On update, omit if the secret material is unchanged; populate if the secret is being rotated.
#[serde(
rename = "sealedSecret",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub sealed_secret: ::std::option::Option<SealedEnvelope>,
#[serde(rename = "secretKind")]
pub secret_kind: SecretKind,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub selectors: ::std::option::Option<Vec<PayloadSelectorsItem>>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub tags: ::std::option::Option<Vec<PayloadTagsItem>>,
pub targets: ::std::vec::Vec<SiteTarget>,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///`PayloadClearFieldsItem`
///
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum PayloadClearFieldsItem {
#[serde(rename = "notes")]
Notes,
#[serde(rename = "favicon")]
Favicon,
#[serde(rename = "expiresAt")]
ExpiresAt,
#[serde(rename = "tags")]
Tags,
#[serde(rename = "selectors")]
Selectors,
#[serde(rename = "customFieldNames")]
CustomFieldNames,
}
impl ::std::fmt::Display for PayloadClearFieldsItem {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Notes => f.write_str("notes"),
Self::Favicon => f.write_str("favicon"),
Self::ExpiresAt => f.write_str("expiresAt"),
Self::Tags => f.write_str("tags"),
Self::Selectors => f.write_str("selectors"),
Self::CustomFieldNames => f.write_str("customFieldNames"),
}
}
}
impl ::std::str::FromStr for PayloadClearFieldsItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"notes" => Ok(Self::Notes),
"favicon" => Ok(Self::Favicon),
"expiresAt" => Ok(Self::ExpiresAt),
"tags" => Ok(Self::Tags),
"selectors" => Ok(Self::Selectors),
"customFieldNames" => Ok(Self::CustomFieldNames),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PayloadClearFieldsItem {
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 PayloadClearFieldsItem {
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 PayloadClearFieldsItem {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Trust context the entry belongs to. Cannot be changed by upsert; to move an entry between contexts the consumer MUST delete and recreate.
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadContextId(::std::string::String);
impl ::std::ops::Deref for PayloadContextId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadContextId> for ::std::string::String {
fn from(value: PayloadContextId) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadContextId {
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 PayloadContextId {
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 PayloadContextId {
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 PayloadContextId {
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 PayloadContextId {
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())
})
}
}
///`PayloadCustomFieldNamesItem`
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadCustomFieldNamesItem(::std::string::String);
impl ::std::ops::Deref for PayloadCustomFieldNamesItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadCustomFieldNamesItem> for ::std::string::String {
fn from(value: PayloadCustomFieldNamesItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadCustomFieldNamesItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 128usize {
return Err("longer than 128 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 PayloadCustomFieldNamesItem {
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 PayloadCustomFieldNamesItem {
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 PayloadCustomFieldNamesItem {
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 PayloadCustomFieldNamesItem {
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())
})
}
}
///Entry id. Omit to create; supply to update. Maintainers MAY accept consumer-supplied ids on create (recommended: ULID) or MAY assign their own and return the assigned id in the response.
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadId(::std::string::String);
impl ::std::ops::Deref for PayloadId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadId> for ::std::string::String {
fn from(value: PayloadId) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadId {
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 PayloadId {
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 PayloadId {
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 PayloadId {
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 PayloadId {
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())
})
}
}
///`PayloadLabel`
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadLabel(::std::string::String);
impl ::std::ops::Deref for PayloadLabel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadLabel> for ::std::string::String {
fn from(value: PayloadLabel) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadLabel {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 256usize {
return Err("longer than 256 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PayloadLabel {
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 PayloadLabel {
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 PayloadLabel {
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 PayloadLabel {
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())
})
}
}
///`PayloadNotes`
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadNotes(::std::string::String);
impl ::std::ops::Deref for PayloadNotes {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadNotes> for ::std::string::String {
fn from(value: PayloadNotes) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadNotes {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 4096usize {
return Err("longer than 4096 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PayloadNotes {
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 PayloadNotes {
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 PayloadNotes {
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 PayloadNotes {
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())
})
}
}
///`PayloadSelectorsItem`
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadSelectorsItem(::std::string::String);
impl ::std::ops::Deref for PayloadSelectorsItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadSelectorsItem> for ::std::string::String {
fn from(value: PayloadSelectorsItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadSelectorsItem {
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 PayloadSelectorsItem {
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 PayloadSelectorsItem {
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 PayloadSelectorsItem {
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 PayloadSelectorsItem {
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())
})
}
}
///`PayloadTagsItem`
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadTagsItem(::std::string::String);
impl ::std::ops::Deref for PayloadTagsItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadTagsItem> for ::std::string::String {
fn from(value: PayloadTagsItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadTagsItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 64usize {
return Err("longer than 64 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PayloadTagsItem {
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 PayloadTagsItem {
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 PayloadTagsItem {
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 PayloadTagsItem {
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`
///
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
#[deprecated(note = "superseded by vault/upsert/0.4")]
pub struct Response {
///true when this upsert created a new entry; false when it updated an existing one.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub created: ::std::option::Option<bool>,
pub entry: VaultEntry,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
}
impl Response {
pub fn builder() -> builder::Response {
Default::default()
}
}
///Discriminated by `envelope`. Exactly one variant matches per document.
///
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged)]
#[non_exhaustive]
pub enum SealedEnvelope {
DidcommAuthcryptEnvelope(DidcommAuthcryptEnvelope),
HpkeArmoredEnvelope(HpkeArmoredEnvelope),
TspMessageEnvelope(TspMessageEnvelope),
}
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)
}
}
/**Discriminator for the secret type stored in the entry. Definitions:
- `password` — username + password (+ optional TOTP seed).
- `passkey` — WebAuthn discoverable credential (private key + rpId + userHandle).
- `oauthTokens` — OAuth 2.0 refresh + access token bundle for a specific provider.
- `didSelfIssued` — Self-Issued OpenID Provider v2 (SIOP) credential: the entry points at a DID + signing key already managed by the VTA.
- `didcommPeer` — DIDComm peer identity used to authenticate against a DIDComm-speaking relying party.
- `bearerToken` — opaque bearer token carried in a maintainer-named header (covers API tokens, long-lived JWTs, personal-access tokens).
- `sshKey` — SSH private key + comment.
- `custom` — arbitrary structured fields; release-time consumer responsible for interpretation.*/
///
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum SecretKind {
#[serde(rename = "password")]
Password,
#[serde(rename = "passkey")]
Passkey,
#[serde(rename = "oauthTokens")]
OauthTokens,
#[serde(rename = "didSelfIssued")]
DidSelfIssued,
#[serde(rename = "didcommPeer")]
DidcommPeer,
#[serde(rename = "bearerToken")]
BearerToken,
#[serde(rename = "sshKey")]
SshKey,
#[serde(rename = "custom")]
Custom,
}
impl ::std::fmt::Display for SecretKind {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Password => f.write_str("password"),
Self::Passkey => f.write_str("passkey"),
Self::OauthTokens => f.write_str("oauthTokens"),
Self::DidSelfIssued => f.write_str("didSelfIssued"),
Self::DidcommPeer => f.write_str("didcommPeer"),
Self::BearerToken => f.write_str("bearerToken"),
Self::SshKey => f.write_str("sshKey"),
Self::Custom => f.write_str("custom"),
}
}
}
impl ::std::str::FromStr for SecretKind {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"password" => Ok(Self::Password),
"passkey" => Ok(Self::Passkey),
"oauthTokens" => Ok(Self::OauthTokens),
"didSelfIssued" => Ok(Self::DidSelfIssued),
"didcommPeer" => Ok(Self::DidcommPeer),
"bearerToken" => Ok(Self::BearerToken),
"sshKey" => Ok(Self::SshKey),
"custom" => Ok(Self::Custom),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for SecretKind {
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 SecretKind {
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 SecretKind {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///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.
///
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(tag = "kind", deny_unknown_fields)]
#[non_exhaustive]
pub enum SiteTarget {
///WebOrigin
#[serde(rename = "webOrigin")]
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 = "iosApp")]
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 = "androidApp")]
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>,
},
}
///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).
///
#[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::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.
///
#[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::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").
///
#[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::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`
///
#[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::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.
///
#[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::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())
})
}
}
///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 `tspMessage` envelopes explicitly (`envelopeUnsupported`) until they're wired up — rather than silently failing in DIDComm parsing.
///
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
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 TspMessageEnvelope {
pub fn builder() -> builder::TspMessageEnvelope {
Default::default()
}
}
///Base64url-encoded TSP message bytes. Format reference: https://trustoverip.github.io/tswg-tsp-specification/#message-format
///
#[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::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())
})
}
}
///`VaultEntry`
///
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct VaultEntry {
///References to encrypted blobs associated with the entry (recovery codes, PEM files, screenshots of authenticator setup). The blobs themselves are fetched via a separate mechanism the maintainer documents; metadata view exposes only the descriptor.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub attachments: ::std::vec::Vec<AttachmentRef>,
///Set by the maintainer (via HIBP integration or equivalent) when the password material associated with this entry is known to appear in a public breach. Consumers SHOULD surface this prominently. Cleared when the user rotates the password and the new password is not in any known breach.
#[serde(
rename = "breachedAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub breached_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///Identifier of the trust context (persona) the entry belongs to. Opaque string interpreted by the vault maintainer; corresponds to a single ContextRecord on the VTA side.
#[serde(rename = "contextId")]
pub context_id: VaultEntryContextId,
#[serde(rename = "createdAt")]
pub created_at: ::chrono::DateTime<::chrono::offset::Utc>,
///VID of the consumer that originally created the entry.
#[serde(
rename = "createdBy",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub created_by: ::std::option::Option<::std::string::String>,
///Names of additional fields the user has attached (e.g. ["security-question-1", "account-number"]). The VALUES live in the secret payload and are only delivered by vault/release/0.1. Exposing names in metadata lets the consumer render the right form layout before requesting release.
#[serde(
rename = "customFieldNames",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub custom_field_names: ::std::option::Option<Vec<VaultEntryCustomFieldNamesItem>>,
///Optional time after which the credential is no longer expected to be valid (e.g. an OAuth refresh token's known expiry, a time-limited API token, an enterprise password rotation policy). Maintainers MAY surface this in the consumer UI as a warning.
#[serde(
rename = "expiresAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub expires_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///Optional URI of an icon to display in the consumer UI. Maintainers MAY fetch and cache; consumers SHOULD treat as untrusted content and fetch via a sandboxed pipeline.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub favicon: ::std::option::Option<::std::string::String>,
///Opaque vault-maintainer-assigned identifier for the entry. ULID/UUID/base32 are common; the wire spec only requires non-empty string equality.
pub id: VaultEntryId,
///Human-readable display name (e.g. "Work GitHub", "Personal bank — checking"). Bounded on the wire at 256 characters; a maintainer MAY enforce a shorter limit.
pub label: VaultEntryLabel,
///Most recent time the entry was used (either released or proxy-login performed). Maintainers MAY return this with reduced precision (e.g. hour-floored) when releasing to a less-trusted consumer.
#[serde(
rename = "lastUsedAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub last_used_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///Non-sensitive notes the user attached to the entry. Visible in metadata view (suitable for support contact, account number, expiry policy memos). SENSITIVE notes belong in the secret payload as a `secureNotes` field — those are only released by vault/release/0.1.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub notes: ::std::option::Option<VaultEntryNotes>,
///Set whenever the password component of the secret payload is rotated. Maintainers MUST update this on every secret-material change for entries of kind `password` (or any kind that carries a password component). Used by consumers to surface rotation-overdue warnings.
#[serde(
rename = "passwordChangedAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub password_changed_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///Optional cached DID the entry will act AS for DID-shaped flows — mirrors the `did` field of the entry's secret payload when `secretKind` carries one (`didSelfIssued`, `didcommPeer`). Absent for kinds that have no DID concept (`password`, `passkey`, `oauthTokens`, `bearerToken`, `sshKey`, `custom`). MAINTAINER-DERIVED, NOT CONSUMER-SUPPLIED: the maintainer MUST recompute this from the canonical secret at every upsert / secret rotation; a producer-supplied value on `vault/upsert/0.1` MUST be ignored (no error, but no honour). Read-only on the wire, present in metadata views so consumers can drive RP-side flows (e.g. fetch `/auth/challenge` keyed on the principal DID before requesting a proxy-login) without releasing the secret.
#[serde(
rename = "principalDid",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub principal_did: ::std::option::Option<VaultEntryPrincipalDid>,
///Discriminator for the kind of secret this entry holds. The secret material itself is NEVER returned in metadata views; the kind is exposed so consumers can render an appropriate UI affordance and so policy decisions can route by kind.
#[serde(rename = "secretKind")]
pub secret_kind: SecretKind,
///Opaque maintainer-defined selector strings fed to the policy engine when this entry is requested (e.g. "recent_uv_required", "network_class=corp", "step_up_push"). Consumers MUST treat selectors as opaque; they exist for policy authoring on the maintainer side.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub selectors: ::std::option::Option<Vec<VaultEntrySelectorsItem>>,
///User-defined tags for organisation and filtering (e.g. ["family", "finance"]). Maintainers MAY enforce a maximum count; the wire spec does not.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub tags: ::std::option::Option<Vec<VaultEntryTagsItem>>,
///One or more binding targets — web origins, mobile app identifiers, and/or DIDs — that this credential applies to. A request from any matching target uses this entry. A typical entry for a service that exists as both a website and mobile apps will list a web origin, an iOS bundle id, and an Android package id; passkeys for that service typically list only the origin (because iOS Associated Domains and Android Asset Links bind apps to the domain at the OS level).
pub targets: ::std::vec::Vec<SiteTarget>,
#[serde(rename = "updatedAt")]
pub updated_at: ::chrono::DateTime<::chrono::offset::Utc>,
///VID of the consumer that last modified the entry.
#[serde(
rename = "updatedBy",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub updated_by: ::std::option::Option<::std::string::String>,
///Monotonic version counter incremented on every mutation. Used by consumers for optimistic-concurrency checks on vault/upsert and as the seq baseline for vault/sync.
pub version: u64,
}
impl VaultEntry {
pub fn builder() -> builder::VaultEntry {
Default::default()
}
}
///Identifier of the trust context (persona) the entry belongs to. Opaque string interpreted by the vault maintainer; corresponds to a single ContextRecord on the VTA side.
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VaultEntryContextId(::std::string::String);
impl ::std::ops::Deref for VaultEntryContextId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VaultEntryContextId> for ::std::string::String {
fn from(value: VaultEntryContextId) -> Self {
value.0
}
}
impl ::std::str::FromStr for VaultEntryContextId {
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 VaultEntryContextId {
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 VaultEntryContextId {
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 VaultEntryContextId {
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 VaultEntryContextId {
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())
})
}
}
///`VaultEntryCustomFieldNamesItem`
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VaultEntryCustomFieldNamesItem(::std::string::String);
impl ::std::ops::Deref for VaultEntryCustomFieldNamesItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VaultEntryCustomFieldNamesItem> for ::std::string::String {
fn from(value: VaultEntryCustomFieldNamesItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for VaultEntryCustomFieldNamesItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 128usize {
return Err("longer than 128 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 VaultEntryCustomFieldNamesItem {
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 VaultEntryCustomFieldNamesItem {
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 VaultEntryCustomFieldNamesItem {
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 VaultEntryCustomFieldNamesItem {
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())
})
}
}
///Opaque vault-maintainer-assigned identifier for the entry. ULID/UUID/base32 are common; the wire spec only requires non-empty string equality.
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VaultEntryId(::std::string::String);
impl ::std::ops::Deref for VaultEntryId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VaultEntryId> for ::std::string::String {
fn from(value: VaultEntryId) -> Self {
value.0
}
}
impl ::std::str::FromStr for VaultEntryId {
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 VaultEntryId {
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 VaultEntryId {
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 VaultEntryId {
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 VaultEntryId {
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())
})
}
}
///Human-readable display name (e.g. "Work GitHub", "Personal bank — checking"). Bounded on the wire at 256 characters; a maintainer MAY enforce a shorter limit.
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VaultEntryLabel(::std::string::String);
impl ::std::ops::Deref for VaultEntryLabel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VaultEntryLabel> for ::std::string::String {
fn from(value: VaultEntryLabel) -> Self {
value.0
}
}
impl ::std::str::FromStr for VaultEntryLabel {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 256usize {
return Err("longer than 256 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for VaultEntryLabel {
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 VaultEntryLabel {
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 VaultEntryLabel {
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 VaultEntryLabel {
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())
})
}
}
///Non-sensitive notes the user attached to the entry. Visible in metadata view (suitable for support contact, account number, expiry policy memos). SENSITIVE notes belong in the secret payload as a `secureNotes` field — those are only released by vault/release/0.1.
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VaultEntryNotes(::std::string::String);
impl ::std::ops::Deref for VaultEntryNotes {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VaultEntryNotes> for ::std::string::String {
fn from(value: VaultEntryNotes) -> Self {
value.0
}
}
impl ::std::str::FromStr for VaultEntryNotes {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 4096usize {
return Err("longer than 4096 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for VaultEntryNotes {
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 VaultEntryNotes {
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 VaultEntryNotes {
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 VaultEntryNotes {
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 cached DID the entry will act AS for DID-shaped flows — mirrors the `did` field of the entry's secret payload when `secretKind` carries one (`didSelfIssued`, `didcommPeer`). Absent for kinds that have no DID concept (`password`, `passkey`, `oauthTokens`, `bearerToken`, `sshKey`, `custom`). MAINTAINER-DERIVED, NOT CONSUMER-SUPPLIED: the maintainer MUST recompute this from the canonical secret at every upsert / secret rotation; a producer-supplied value on `vault/upsert/0.1` MUST be ignored (no error, but no honour). Read-only on the wire, present in metadata views so consumers can drive RP-side flows (e.g. fetch `/auth/challenge` keyed on the principal DID before requesting a proxy-login) without releasing the secret.
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VaultEntryPrincipalDid(::std::string::String);
impl ::std::ops::Deref for VaultEntryPrincipalDid {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VaultEntryPrincipalDid> for ::std::string::String {
fn from(value: VaultEntryPrincipalDid) -> Self {
value.0
}
}
impl ::std::str::FromStr for VaultEntryPrincipalDid {
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 VaultEntryPrincipalDid {
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 VaultEntryPrincipalDid {
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 VaultEntryPrincipalDid {
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 VaultEntryPrincipalDid {
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())
})
}
}
///`VaultEntrySelectorsItem`
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VaultEntrySelectorsItem(::std::string::String);
impl ::std::ops::Deref for VaultEntrySelectorsItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VaultEntrySelectorsItem> for ::std::string::String {
fn from(value: VaultEntrySelectorsItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for VaultEntrySelectorsItem {
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 VaultEntrySelectorsItem {
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 VaultEntrySelectorsItem {
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 VaultEntrySelectorsItem {
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 VaultEntrySelectorsItem {
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())
})
}
}
///`VaultEntryTagsItem`
///
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VaultEntryTagsItem(::std::string::String);
impl ::std::ops::Deref for VaultEntryTagsItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VaultEntryTagsItem> for ::std::string::String {
fn from(value: VaultEntryTagsItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for VaultEntryTagsItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 64usize {
return Err("longer than 64 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for VaultEntryTagsItem {
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 VaultEntryTagsItem {
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 VaultEntryTagsItem {
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 VaultEntryTagsItem {
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 AttachmentRef {
content_type: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
digest_multibase: ::std::result::Result<super::DigestMultibase, ::std::string::String>,
id: ::std::result::Result<super::AttachmentRefId, ::std::string::String>,
name: ::std::result::Result<super::AttachmentRefName, ::std::string::String>,
size_bytes: ::std::result::Result<u64, ::std::string::String>,
}
impl ::std::default::Default for AttachmentRef {
fn default() -> Self {
Self {
content_type: Ok(Default::default()),
digest_multibase: Err("no value supplied for digest_multibase".to_string()),
id: Err("no value supplied for id".to_string()),
name: Err("no value supplied for name".to_string()),
size_bytes: Err("no value supplied for size_bytes".to_string()),
}
}
}
impl AttachmentRef {
pub fn content_type<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.content_type = value
.try_into()
.map_err(|e| format!("error converting supplied value for content_type: {e}"));
self
}
pub fn digest_multibase<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DigestMultibase>,
T::Error: ::std::fmt::Display,
{
self.digest_multibase = value
.try_into()
.map_err(|e| format!("error converting supplied value for digest_multibase: {e}"));
self
}
pub fn id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::AttachmentRefId>,
T::Error: ::std::fmt::Display,
{
self.id = value
.try_into()
.map_err(|e| format!("error converting supplied value for id: {e}"));
self
}
pub fn name<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::AttachmentRefName>,
T::Error: ::std::fmt::Display,
{
self.name = value
.try_into()
.map_err(|e| format!("error converting supplied value for name: {e}"));
self
}
pub fn size_bytes<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<u64>,
T::Error: ::std::fmt::Display,
{
self.size_bytes = value
.try_into()
.map_err(|e| format!("error converting supplied value for size_bytes: {e}"));
self
}
}
impl ::std::convert::TryFrom<AttachmentRef> for super::AttachmentRef {
type Error = super::error::ConversionError;
fn try_from(
value: AttachmentRef,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
content_type: value.content_type?,
digest_multibase: value.digest_multibase?,
id: value.id?,
name: value.name?,
size_bytes: value.size_bytes?,
})
}
}
impl ::std::convert::From<super::AttachmentRef> for AttachmentRef {
fn from(value: super::AttachmentRef) -> Self {
Self {
content_type: Ok(value.content_type),
digest_multibase: Ok(value.digest_multibase),
id: Ok(value.id),
name: Ok(value.name),
size_bytes: Ok(value.size_bytes),
}
}
}
#[derive(Clone, Debug)]
pub struct DidcommAuthcryptEnvelope {
envelope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
jwe: ::std::result::Result<super::DidcommAuthcryptEnvelopeJwe, ::std::string::String>,
}
impl ::std::default::Default for DidcommAuthcryptEnvelope {
fn default() -> Self {
Self {
envelope: Err("no value supplied for envelope".to_string()),
jwe: Err("no value supplied for jwe".to_string()),
}
}
}
impl DidcommAuthcryptEnvelope {
pub fn envelope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.envelope = value
.try_into()
.map_err(|e| format!("error converting supplied value for envelope: {e}"));
self
}
pub fn jwe<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DidcommAuthcryptEnvelopeJwe>,
T::Error: ::std::fmt::Display,
{
self.jwe = value
.try_into()
.map_err(|e| format!("error converting supplied value for jwe: {e}"));
self
}
}
impl ::std::convert::TryFrom<DidcommAuthcryptEnvelope> for super::DidcommAuthcryptEnvelope {
type Error = super::error::ConversionError;
fn try_from(
value: DidcommAuthcryptEnvelope,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
envelope: value.envelope?,
jwe: value.jwe?,
})
}
}
impl ::std::convert::From<super::DidcommAuthcryptEnvelope> for DidcommAuthcryptEnvelope {
fn from(value: super::DidcommAuthcryptEnvelope) -> Self {
Self {
envelope: Ok(value.envelope),
jwe: Ok(value.jwe),
}
}
}
#[derive(Clone, Debug)]
pub struct HpkeArmoredEnvelope {
armored: ::std::result::Result<super::HpkeArmoredEnvelopeArmored, ::std::string::String>,
envelope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
producer_assertion: ::std::result::Result<
super::HpkeArmoredEnvelopeProducerAssertion,
::std::string::String,
>,
recipient_key_id:
::std::result::Result<super::HpkeArmoredEnvelopeRecipientKeyId, ::std::string::String>,
}
impl ::std::default::Default for HpkeArmoredEnvelope {
fn default() -> Self {
Self {
armored: Err("no value supplied for armored".to_string()),
envelope: Err("no value supplied for envelope".to_string()),
producer_assertion: Ok(super::defaults::hpke_armored_envelope_producer_assertion()),
recipient_key_id: Err("no value supplied for recipient_key_id".to_string()),
}
}
}
impl HpkeArmoredEnvelope {
pub fn armored<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::HpkeArmoredEnvelopeArmored>,
T::Error: ::std::fmt::Display,
{
self.armored = value
.try_into()
.map_err(|e| format!("error converting supplied value for armored: {e}"));
self
}
pub fn envelope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.envelope = value
.try_into()
.map_err(|e| format!("error converting supplied value for envelope: {e}"));
self
}
pub fn producer_assertion<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::HpkeArmoredEnvelopeProducerAssertion>,
T::Error: ::std::fmt::Display,
{
self.producer_assertion = value.try_into().map_err(|e| {
format!("error converting supplied value for producer_assertion: {e}")
});
self
}
pub fn recipient_key_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::HpkeArmoredEnvelopeRecipientKeyId>,
T::Error: ::std::fmt::Display,
{
self.recipient_key_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for recipient_key_id: {e}"));
self
}
}
impl ::std::convert::TryFrom<HpkeArmoredEnvelope> for super::HpkeArmoredEnvelope {
type Error = super::error::ConversionError;
fn try_from(
value: HpkeArmoredEnvelope,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
armored: value.armored?,
envelope: value.envelope?,
producer_assertion: value.producer_assertion?,
recipient_key_id: value.recipient_key_id?,
})
}
}
impl ::std::convert::From<super::HpkeArmoredEnvelope> for HpkeArmoredEnvelope {
fn from(value: super::HpkeArmoredEnvelope) -> Self {
Self {
armored: Ok(value.armored),
envelope: Ok(value.envelope),
producer_assertion: Ok(value.producer_assertion),
recipient_key_id: Ok(value.recipient_key_id),
}
}
}
#[derive(Clone, Debug)]
pub struct Payload {
clear_fields: ::std::result::Result<
::std::option::Option<Vec<super::PayloadClearFieldsItem>>,
::std::string::String,
>,
context_id: ::std::result::Result<super::PayloadContextId, ::std::string::String>,
custom_field_names: ::std::result::Result<
::std::option::Option<Vec<super::PayloadCustomFieldNamesItem>>,
::std::string::String,
>,
expected_version: ::std::result::Result<::std::option::Option<u64>, ::std::string::String>,
expires_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
favicon: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
id: ::std::result::Result<::std::option::Option<super::PayloadId>, ::std::string::String>,
label: ::std::result::Result<super::PayloadLabel, ::std::string::String>,
notes: ::std::result::Result<
::std::option::Option<super::PayloadNotes>,
::std::string::String,
>,
sealed_secret: ::std::result::Result<
::std::option::Option<super::SealedEnvelope>,
::std::string::String,
>,
secret_kind: ::std::result::Result<super::SecretKind, ::std::string::String>,
selectors: ::std::result::Result<
::std::option::Option<Vec<super::PayloadSelectorsItem>>,
::std::string::String,
>,
tags: ::std::result::Result<
::std::option::Option<Vec<super::PayloadTagsItem>>,
::std::string::String,
>,
targets: ::std::result::Result<::std::vec::Vec<super::SiteTarget>, ::std::string::String>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
clear_fields: Ok(Default::default()),
context_id: Err("no value supplied for context_id".to_string()),
custom_field_names: Ok(Default::default()),
expected_version: Ok(Default::default()),
expires_at: Ok(Default::default()),
ext: Ok(Default::default()),
favicon: Ok(Default::default()),
id: Ok(Default::default()),
label: Err("no value supplied for label".to_string()),
notes: Ok(Default::default()),
sealed_secret: Ok(Default::default()),
secret_kind: Err("no value supplied for secret_kind".to_string()),
selectors: Ok(Default::default()),
tags: Ok(Default::default()),
targets: Err("no value supplied for targets".to_string()),
}
}
}
impl Payload {
pub fn clear_fields<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<Vec<super::PayloadClearFieldsItem>>>,
T::Error: ::std::fmt::Display,
{
self.clear_fields = value
.try_into()
.map_err(|e| format!("error converting supplied value for clear_fields: {e}"));
self
}
pub fn context_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::PayloadContextId>,
T::Error: ::std::fmt::Display,
{
self.context_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for context_id: {e}"));
self
}
pub fn custom_field_names<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<Vec<super::PayloadCustomFieldNamesItem>>,
>,
T::Error: ::std::fmt::Display,
{
self.custom_field_names = value.try_into().map_err(|e| {
format!("error converting supplied value for custom_field_names: {e}")
});
self
}
pub fn expected_version<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<u64>>,
T::Error: ::std::fmt::Display,
{
self.expected_version = value
.try_into()
.map_err(|e| format!("error converting supplied value for expected_version: {e}"));
self
}
pub fn expires_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.expires_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for expires_at: {e}"));
self
}
pub fn ext<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ext>>,
T::Error: ::std::fmt::Display,
{
self.ext = value
.try_into()
.map_err(|e| format!("error converting supplied value for ext: {e}"));
self
}
pub fn favicon<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.favicon = value
.try_into()
.map_err(|e| format!("error converting supplied value for favicon: {e}"));
self
}
pub fn id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::PayloadId>>,
T::Error: ::std::fmt::Display,
{
self.id = value
.try_into()
.map_err(|e| format!("error converting supplied value for id: {e}"));
self
}
pub fn label<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::PayloadLabel>,
T::Error: ::std::fmt::Display,
{
self.label = value
.try_into()
.map_err(|e| format!("error converting supplied value for label: {e}"));
self
}
pub fn notes<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::PayloadNotes>>,
T::Error: ::std::fmt::Display,
{
self.notes = value
.try_into()
.map_err(|e| format!("error converting supplied value for notes: {e}"));
self
}
pub fn sealed_secret<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::SealedEnvelope>>,
T::Error: ::std::fmt::Display,
{
self.sealed_secret = value
.try_into()
.map_err(|e| format!("error converting supplied value for sealed_secret: {e}"));
self
}
pub fn secret_kind<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::SecretKind>,
T::Error: ::std::fmt::Display,
{
self.secret_kind = value
.try_into()
.map_err(|e| format!("error converting supplied value for secret_kind: {e}"));
self
}
pub fn selectors<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<Vec<super::PayloadSelectorsItem>>>,
T::Error: ::std::fmt::Display,
{
self.selectors = value
.try_into()
.map_err(|e| format!("error converting supplied value for selectors: {e}"));
self
}
pub fn tags<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<Vec<super::PayloadTagsItem>>>,
T::Error: ::std::fmt::Display,
{
self.tags = value
.try_into()
.map_err(|e| format!("error converting supplied value for tags: {e}"));
self
}
pub fn targets<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::SiteTarget>>,
T::Error: ::std::fmt::Display,
{
self.targets = value
.try_into()
.map_err(|e| format!("error converting supplied value for targets: {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 {
clear_fields: value.clear_fields?,
context_id: value.context_id?,
custom_field_names: value.custom_field_names?,
expected_version: value.expected_version?,
expires_at: value.expires_at?,
ext: value.ext?,
favicon: value.favicon?,
id: value.id?,
label: value.label?,
notes: value.notes?,
sealed_secret: value.sealed_secret?,
secret_kind: value.secret_kind?,
selectors: value.selectors?,
tags: value.tags?,
targets: value.targets?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
clear_fields: Ok(value.clear_fields),
context_id: Ok(value.context_id),
custom_field_names: Ok(value.custom_field_names),
expected_version: Ok(value.expected_version),
expires_at: Ok(value.expires_at),
ext: Ok(value.ext),
favicon: Ok(value.favicon),
id: Ok(value.id),
label: Ok(value.label),
notes: Ok(value.notes),
sealed_secret: Ok(value.sealed_secret),
secret_kind: Ok(value.secret_kind),
selectors: Ok(value.selectors),
tags: Ok(value.tags),
targets: Ok(value.targets),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
created: ::std::result::Result<::std::option::Option<bool>, ::std::string::String>,
entry: ::std::result::Result<super::VaultEntry, ::std::string::String>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
created: Ok(Default::default()),
entry: Err("no value supplied for entry".to_string()),
ext: Ok(Default::default()),
}
}
}
impl Response {
pub fn created<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<bool>>,
T::Error: ::std::fmt::Display,
{
self.created = value
.try_into()
.map_err(|e| format!("error converting supplied value for created: {e}"));
self
}
pub fn entry<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::VaultEntry>,
T::Error: ::std::fmt::Display,
{
self.entry = value
.try_into()
.map_err(|e| format!("error converting supplied value for entry: {e}"));
self
}
pub fn ext<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ext>>,
T::Error: ::std::fmt::Display,
{
self.ext = value
.try_into()
.map_err(|e| format!("error converting supplied value for ext: {e}"));
self
}
}
impl ::std::convert::TryFrom<Response> for super::Response {
type Error = super::error::ConversionError;
fn try_from(value: Response) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
created: value.created?,
entry: value.entry?,
ext: value.ext?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
created: Ok(value.created),
entry: Ok(value.entry),
ext: Ok(value.ext),
}
}
}
#[derive(Clone, Debug)]
pub struct TspMessageEnvelope {
envelope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
message: ::std::result::Result<super::TspMessageEnvelopeMessage, ::std::string::String>,
}
impl ::std::default::Default for TspMessageEnvelope {
fn default() -> Self {
Self {
envelope: Err("no value supplied for envelope".to_string()),
message: Err("no value supplied for message".to_string()),
}
}
}
impl TspMessageEnvelope {
pub fn envelope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.envelope = value
.try_into()
.map_err(|e| format!("error converting supplied value for envelope: {e}"));
self
}
pub fn message<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::TspMessageEnvelopeMessage>,
T::Error: ::std::fmt::Display,
{
self.message = value
.try_into()
.map_err(|e| format!("error converting supplied value for message: {e}"));
self
}
}
impl ::std::convert::TryFrom<TspMessageEnvelope> for super::TspMessageEnvelope {
type Error = super::error::ConversionError;
fn try_from(
value: TspMessageEnvelope,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
envelope: value.envelope?,
message: value.message?,
})
}
}
impl ::std::convert::From<super::TspMessageEnvelope> for TspMessageEnvelope {
fn from(value: super::TspMessageEnvelope) -> Self {
Self {
envelope: Ok(value.envelope),
message: Ok(value.message),
}
}
}
#[derive(Clone, Debug)]
pub struct VaultEntry {
attachments:
::std::result::Result<::std::vec::Vec<super::AttachmentRef>, ::std::string::String>,
breached_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
context_id: ::std::result::Result<super::VaultEntryContextId, ::std::string::String>,
created_at:
::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
created_by: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
custom_field_names: ::std::result::Result<
::std::option::Option<Vec<super::VaultEntryCustomFieldNamesItem>>,
::std::string::String,
>,
expires_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
favicon: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
id: ::std::result::Result<super::VaultEntryId, ::std::string::String>,
label: ::std::result::Result<super::VaultEntryLabel, ::std::string::String>,
last_used_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
notes: ::std::result::Result<
::std::option::Option<super::VaultEntryNotes>,
::std::string::String,
>,
password_changed_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
principal_did: ::std::result::Result<
::std::option::Option<super::VaultEntryPrincipalDid>,
::std::string::String,
>,
secret_kind: ::std::result::Result<super::SecretKind, ::std::string::String>,
selectors: ::std::result::Result<
::std::option::Option<Vec<super::VaultEntrySelectorsItem>>,
::std::string::String,
>,
tags: ::std::result::Result<
::std::option::Option<Vec<super::VaultEntryTagsItem>>,
::std::string::String,
>,
targets: ::std::result::Result<::std::vec::Vec<super::SiteTarget>, ::std::string::String>,
updated_at:
::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
updated_by: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
version: ::std::result::Result<u64, ::std::string::String>,
}
impl ::std::default::Default for VaultEntry {
fn default() -> Self {
Self {
attachments: Ok(Default::default()),
breached_at: Ok(Default::default()),
context_id: Err("no value supplied for context_id".to_string()),
created_at: Err("no value supplied for created_at".to_string()),
created_by: Ok(Default::default()),
custom_field_names: Ok(Default::default()),
expires_at: Ok(Default::default()),
ext: Ok(Default::default()),
favicon: Ok(Default::default()),
id: Err("no value supplied for id".to_string()),
label: Err("no value supplied for label".to_string()),
last_used_at: Ok(Default::default()),
notes: Ok(Default::default()),
password_changed_at: Ok(Default::default()),
principal_did: Ok(Default::default()),
secret_kind: Err("no value supplied for secret_kind".to_string()),
selectors: Ok(Default::default()),
tags: Ok(Default::default()),
targets: Err("no value supplied for targets".to_string()),
updated_at: Err("no value supplied for updated_at".to_string()),
updated_by: Ok(Default::default()),
version: Err("no value supplied for version".to_string()),
}
}
}
impl VaultEntry {
pub fn attachments<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::AttachmentRef>>,
T::Error: ::std::fmt::Display,
{
self.attachments = value
.try_into()
.map_err(|e| format!("error converting supplied value for attachments: {e}"));
self
}
pub fn breached_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.breached_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for breached_at: {e}"));
self
}
pub fn context_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::VaultEntryContextId>,
T::Error: ::std::fmt::Display,
{
self.context_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for context_id: {e}"));
self
}
pub fn created_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::chrono::DateTime<::chrono::offset::Utc>>,
T::Error: ::std::fmt::Display,
{
self.created_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for created_at: {e}"));
self
}
pub fn created_by<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.created_by = value
.try_into()
.map_err(|e| format!("error converting supplied value for created_by: {e}"));
self
}
pub fn custom_field_names<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<Vec<super::VaultEntryCustomFieldNamesItem>>,
>,
T::Error: ::std::fmt::Display,
{
self.custom_field_names = value.try_into().map_err(|e| {
format!("error converting supplied value for custom_field_names: {e}")
});
self
}
pub fn expires_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.expires_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for expires_at: {e}"));
self
}
pub fn ext<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ext>>,
T::Error: ::std::fmt::Display,
{
self.ext = value
.try_into()
.map_err(|e| format!("error converting supplied value for ext: {e}"));
self
}
pub fn favicon<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.favicon = value
.try_into()
.map_err(|e| format!("error converting supplied value for favicon: {e}"));
self
}
pub fn id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::VaultEntryId>,
T::Error: ::std::fmt::Display,
{
self.id = value
.try_into()
.map_err(|e| format!("error converting supplied value for id: {e}"));
self
}
pub fn label<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::VaultEntryLabel>,
T::Error: ::std::fmt::Display,
{
self.label = value
.try_into()
.map_err(|e| format!("error converting supplied value for label: {e}"));
self
}
pub fn last_used_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.last_used_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for last_used_at: {e}"));
self
}
pub fn notes<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::VaultEntryNotes>>,
T::Error: ::std::fmt::Display,
{
self.notes = value
.try_into()
.map_err(|e| format!("error converting supplied value for notes: {e}"));
self
}
pub fn password_changed_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.password_changed_at = value.try_into().map_err(|e| {
format!("error converting supplied value for password_changed_at: {e}")
});
self
}
pub fn principal_did<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::VaultEntryPrincipalDid>>,
T::Error: ::std::fmt::Display,
{
self.principal_did = value
.try_into()
.map_err(|e| format!("error converting supplied value for principal_did: {e}"));
self
}
pub fn secret_kind<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::SecretKind>,
T::Error: ::std::fmt::Display,
{
self.secret_kind = value
.try_into()
.map_err(|e| format!("error converting supplied value for secret_kind: {e}"));
self
}
pub fn selectors<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<Vec<super::VaultEntrySelectorsItem>>>,
T::Error: ::std::fmt::Display,
{
self.selectors = value
.try_into()
.map_err(|e| format!("error converting supplied value for selectors: {e}"));
self
}
pub fn tags<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<Vec<super::VaultEntryTagsItem>>>,
T::Error: ::std::fmt::Display,
{
self.tags = value
.try_into()
.map_err(|e| format!("error converting supplied value for tags: {e}"));
self
}
pub fn targets<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::SiteTarget>>,
T::Error: ::std::fmt::Display,
{
self.targets = value
.try_into()
.map_err(|e| format!("error converting supplied value for targets: {e}"));
self
}
pub fn updated_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::chrono::DateTime<::chrono::offset::Utc>>,
T::Error: ::std::fmt::Display,
{
self.updated_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for updated_at: {e}"));
self
}
pub fn updated_by<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.updated_by = value
.try_into()
.map_err(|e| format!("error converting supplied value for updated_by: {e}"));
self
}
pub fn version<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<u64>,
T::Error: ::std::fmt::Display,
{
self.version = value
.try_into()
.map_err(|e| format!("error converting supplied value for version: {e}"));
self
}
}
impl ::std::convert::TryFrom<VaultEntry> for super::VaultEntry {
type Error = super::error::ConversionError;
fn try_from(
value: VaultEntry,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
attachments: value.attachments?,
breached_at: value.breached_at?,
context_id: value.context_id?,
created_at: value.created_at?,
created_by: value.created_by?,
custom_field_names: value.custom_field_names?,
expires_at: value.expires_at?,
ext: value.ext?,
favicon: value.favicon?,
id: value.id?,
label: value.label?,
last_used_at: value.last_used_at?,
notes: value.notes?,
password_changed_at: value.password_changed_at?,
principal_did: value.principal_did?,
secret_kind: value.secret_kind?,
selectors: value.selectors?,
tags: value.tags?,
targets: value.targets?,
updated_at: value.updated_at?,
updated_by: value.updated_by?,
version: value.version?,
})
}
}
impl ::std::convert::From<super::VaultEntry> for VaultEntry {
fn from(value: super::VaultEntry) -> Self {
Self {
attachments: Ok(value.attachments),
breached_at: Ok(value.breached_at),
context_id: Ok(value.context_id),
created_at: Ok(value.created_at),
created_by: Ok(value.created_by),
custom_field_names: Ok(value.custom_field_names),
expires_at: Ok(value.expires_at),
ext: Ok(value.ext),
favicon: Ok(value.favicon),
id: Ok(value.id),
label: Ok(value.label),
last_used_at: Ok(value.last_used_at),
notes: Ok(value.notes),
password_changed_at: Ok(value.password_changed_at),
principal_did: Ok(value.principal_did),
secret_kind: Ok(value.secret_kind),
selectors: Ok(value.selectors),
tags: Ok(value.tags),
targets: Ok(value.targets),
updated_at: Ok(value.updated_at),
updated_by: Ok(value.updated_by),
version: Ok(value.version),
}
}
}
}
/// 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/upsert/0.3";
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(
"{\"$defs\":{\"AttachmentRef\":{\"additionalProperties\":false,\"properties\":{\"contentType\":{\"description\":\"Optional MIME type hint for the consumer UI (e.g. \\\"text/plain\\\", \\\"application/x-pem-file\\\").\",\"type\":\"string\"},\"digestMultibase\":{\"$ref\":\"#/$defs/DigestMultibase\",\"description\":\"Digest over the encrypted blob bytes (post-encryption), so the consumer can verify integrity after fetch. Taken over the bytes as stored, not over a canonicalization: the blob is an opaque artifact, not a JSON document.\"},\"id\":{\"description\":\"Opaque maintainer-assigned id for this attachment; used to fetch the blob via a separate mechanism.\",\"minLength\":1,\"type\":\"string\"},\"name\":{\"description\":\"User-supplied filename (e.g. \\\"recovery-codes.txt\\\").\",\"maxLength\":256,\"minLength\":1,\"type\":\"string\"},\"sizeBytes\":{\"description\":\"Size of the encrypted blob in bytes. Maintainers MAY enforce a maximum per attachment and per entry.\",\"minimum\":0,\"type\":\"integer\"}},\"required\":[\"id\",\"name\",\"sizeBytes\",\"digestMultibase\"],\"title\":\"AttachmentRef\",\"type\":\"object\"},\"DidcommAuthcryptEnvelope\":{\"additionalProperties\":false,\"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.\",\"properties\":{\"envelope\":{\"const\":\"didcommAuthcrypt\"},\"jwe\":{\"description\":\"Compact DIDComm v2 JWE (base64url-encoded, dot-separated). Unpacks via the framework's standard DIDComm machinery; cleartext is the payload-specific JSON.\",\"minLength\":1,\"type\":\"string\"}},\"required\":[\"envelope\",\"jwe\"],\"title\":\"DidcommAuthcryptEnvelope\",\"type\":\"object\"},\"DigestMultibase\":{\"description\":\"A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\\n\\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\\n\\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\\n\\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \\\"interoperability is not guaranteed between implementations using such values\\\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.\",\"examples\":[\"zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR\"],\"minLength\":16,\"pattern\":\"^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$\",\"title\":\"DigestMultibase\",\"type\":\"string\"},\"Ext\":{\"additionalProperties\":true,\"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.\",\"minProperties\":1,\"propertyNames\":{\"pattern\":\"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)+$\"},\"title\":\"Ext\",\"type\":\"object\"},\"HpkeArmoredEnvelope\":{\"additionalProperties\":false,\"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 (`didSigned` / `attested` / `pinnedOnly`) 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+.\",\"properties\":{\"armored\":{\"description\":\"ASCII-armored bundle text. Multi-line base64 with framing headers + CRC24.\",\"minLength\":1,\"type\":\"string\"},\"envelope\":{\"const\":\"hpkeArmored\"},\"producerAssertion\":{\"default\":\"didSigned\",\"description\":\"Producer-assertion mode per the sealed-transfer framework. `didSigned` = Ed25519 signature by issuer; `attested` = TEE attestation quote (e.g. Nitro); `pinnedOnly` = OOB SHA-256 digest only (dev/test, NOT for production).\",\"enum\":[\"didSigned\",\"attested\",\"pinnedOnly\"],\"type\":\"string\"},\"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.\",\"minLength\":1,\"type\":\"string\"}},\"required\":[\"envelope\",\"armored\",\"recipientKeyId\"],\"title\":\"HpkeArmoredEnvelope\",\"type\":\"object\"},\"Response\":{\"$anchor\":\"response\",\"additionalProperties\":false,\"properties\":{\"created\":{\"description\":\"true when this upsert created a new entry; false when it updated an existing one.\",\"type\":\"boolean\"},\"entry\":{\"$ref\":\"#/$defs/VaultEntry\"},\"ext\":{\"$ref\":\"#/$defs/Ext\"}},\"required\":[\"entry\"],\"title\":\"Vault Upsert — response payload\",\"type\":\"object\"},\"SealedEnvelope\":{\"description\":\"Discriminated by `envelope`. Exactly one variant matches per document.\",\"oneOf\":[{\"$ref\":\"#/$defs/DidcommAuthcryptEnvelope\"},{\"$ref\":\"#/$defs/HpkeArmoredEnvelope\"},{\"$ref\":\"#/$defs/TspMessageEnvelope\"}],\"title\":\"SealedEnvelope\"},\"SecretKind\":{\"description\":\"Discriminator for the secret type stored in the entry. Definitions:\\n- `password` — username + password (+ optional TOTP seed).\\n- `passkey` — WebAuthn discoverable credential (private key + rpId + userHandle).\\n- `oauthTokens` — OAuth 2.0 refresh + access token bundle for a specific provider.\\n- `didSelfIssued` — Self-Issued OpenID Provider v2 (SIOP) credential: the entry points at a DID + signing key already managed by the VTA.\\n- `didcommPeer` — DIDComm peer identity used to authenticate against a DIDComm-speaking relying party.\\n- `bearerToken` — opaque bearer token carried in a maintainer-named header (covers API tokens, long-lived JWTs, personal-access tokens).\\n- `sshKey` — SSH private key + comment.\\n- `custom` — arbitrary structured fields; release-time consumer responsible for interpretation.\",\"enum\":[\"password\",\"passkey\",\"oauthTokens\",\"didSelfIssued\",\"didcommPeer\",\"bearerToken\",\"sshKey\",\"custom\"],\"title\":\"SecretKind\",\"type\":\"string\"},\"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\":[{\"additionalProperties\":false,\"properties\":{\"kind\":{\"const\":\"webOrigin\"},\"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.\",\"format\":\"uri\",\"type\":\"string\"}},\"required\":[\"kind\",\"origin\"],\"title\":\"WebOrigin\",\"type\":\"object\"},{\"additionalProperties\":false,\"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.\",\"minLength\":1,\"type\":\"string\"},\"kind\":{\"const\":\"did\"}},\"required\":[\"kind\",\"did\"],\"title\":\"Did\",\"type\":\"object\"},{\"additionalProperties\":false,\"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).\",\"minLength\":1,\"pattern\":\"^[A-Za-z0-9.-]+$\",\"type\":\"string\"},\"kind\":{\"const\":\"iosApp\"},\"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.\",\"minLength\":1,\"pattern\":\"^[A-Z0-9]+$\",\"type\":\"string\"}},\"required\":[\"kind\",\"bundleId\"],\"title\":\"IosApp\",\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"kind\":{\"const\":\"androidApp\"},\"packageName\":{\"description\":\"Android package name in reverse-DNS form (e.g. \\\"com.github.android\\\").\",\"minLength\":1,\"pattern\":\"^[A-Za-z][A-Za-z0-9_]*(\\\\.[A-Za-z][A-Za-z0-9_]*)+$\",\"type\":\"string\"},\"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).\",\"items\":{\"pattern\":\"^[0-9A-F]{2}(:[0-9A-F]{2}){31}$\",\"type\":\"string\"},\"minItems\":1,\"type\":\"array\",\"uniqueItems\":true}},\"required\":[\"kind\",\"packageName\",\"sha256CertFingerprints\"],\"title\":\"AndroidApp\",\"type\":\"object\"}],\"title\":\"SiteTarget\"},\"TspMessageEnvelope\":{\"additionalProperties\":false,\"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 `tspMessage` envelopes explicitly (`envelopeUnsupported`) until they're wired up — rather than silently failing in DIDComm parsing.\",\"properties\":{\"envelope\":{\"const\":\"tspMessage\"},\"message\":{\"description\":\"Base64url-encoded TSP message bytes. Format reference: https://trustoverip.github.io/tswg-tsp-specification/#message-format\",\"minLength\":1,\"type\":\"string\"}},\"required\":[\"envelope\",\"message\"],\"title\":\"TspMessageEnvelope\",\"type\":\"object\"},\"VaultEntry\":{\"additionalProperties\":false,\"properties\":{\"attachments\":{\"description\":\"References to encrypted blobs associated with the entry (recovery codes, PEM files, screenshots of authenticator setup). The blobs themselves are fetched via a separate mechanism the maintainer documents; metadata view exposes only the descriptor.\",\"items\":{\"$ref\":\"#/$defs/AttachmentRef\"},\"type\":\"array\"},\"breachedAt\":{\"description\":\"Set by the maintainer (via HIBP integration or equivalent) when the password material associated with this entry is known to appear in a public breach. Consumers SHOULD surface this prominently. Cleared when the user rotates the password and the new password is not in any known breach.\",\"format\":\"date-time\",\"type\":\"string\"},\"contextId\":{\"description\":\"Identifier of the trust context (persona) the entry belongs to. Opaque string interpreted by the vault maintainer; corresponds to a single ContextRecord on the VTA side.\",\"minLength\":1,\"type\":\"string\"},\"createdAt\":{\"format\":\"date-time\",\"type\":\"string\"},\"createdBy\":{\"description\":\"VID of the consumer that originally created the entry.\",\"type\":\"string\"},\"customFieldNames\":{\"description\":\"Names of additional fields the user has attached (e.g. [\\\"security-question-1\\\", \\\"account-number\\\"]). The VALUES live in the secret payload and are only delivered by vault/release/0.1. Exposing names in metadata lets the consumer render the right form layout before requesting release.\",\"items\":{\"maxLength\":128,\"minLength\":1,\"type\":\"string\"},\"type\":\"array\",\"uniqueItems\":true},\"expiresAt\":{\"description\":\"Optional time after which the credential is no longer expected to be valid (e.g. an OAuth refresh token's known expiry, a time-limited API token, an enterprise password rotation policy). Maintainers MAY surface this in the consumer UI as a warning.\",\"format\":\"date-time\",\"type\":\"string\"},\"ext\":{\"$ref\":\"#/$defs/Ext\",\"description\":\"Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces.\"},\"favicon\":{\"description\":\"Optional URI of an icon to display in the consumer UI. Maintainers MAY fetch and cache; consumers SHOULD treat as untrusted content and fetch via a sandboxed pipeline.\",\"format\":\"uri\",\"type\":\"string\"},\"id\":{\"description\":\"Opaque vault-maintainer-assigned identifier for the entry. ULID/UUID/base32 are common; the wire spec only requires non-empty string equality.\",\"minLength\":1,\"type\":\"string\"},\"label\":{\"description\":\"Human-readable display name (e.g. \\\"Work GitHub\\\", \\\"Personal bank — checking\\\"). Bounded on the wire at 256 characters; a maintainer MAY enforce a shorter limit.\",\"maxLength\":256,\"minLength\":1,\"type\":\"string\"},\"lastUsedAt\":{\"description\":\"Most recent time the entry was used (either released or proxy-login performed). Maintainers MAY return this with reduced precision (e.g. hour-floored) when releasing to a less-trusted consumer.\",\"format\":\"date-time\",\"type\":\"string\"},\"notes\":{\"description\":\"Non-sensitive notes the user attached to the entry. Visible in metadata view (suitable for support contact, account number, expiry policy memos). SENSITIVE notes belong in the secret payload as a `secureNotes` field — those are only released by vault/release/0.1.\",\"maxLength\":4096,\"type\":\"string\"},\"passwordChangedAt\":{\"description\":\"Set whenever the password component of the secret payload is rotated. Maintainers MUST update this on every secret-material change for entries of kind `password` (or any kind that carries a password component). Used by consumers to surface rotation-overdue warnings.\",\"format\":\"date-time\",\"type\":\"string\"},\"principalDid\":{\"description\":\"Optional cached DID the entry will act AS for DID-shaped flows — mirrors the `did` field of the entry's secret payload when `secretKind` carries one (`didSelfIssued`, `didcommPeer`). Absent for kinds that have no DID concept (`password`, `passkey`, `oauthTokens`, `bearerToken`, `sshKey`, `custom`). MAINTAINER-DERIVED, NOT CONSUMER-SUPPLIED: the maintainer MUST recompute this from the canonical secret at every upsert / secret rotation; a producer-supplied value on `vault/upsert/0.1` MUST be ignored (no error, but no honour). Read-only on the wire, present in metadata views so consumers can drive RP-side flows (e.g. fetch `/auth/challenge` keyed on the principal DID before requesting a proxy-login) without releasing the secret.\",\"minLength\":1,\"type\":\"string\"},\"secretKind\":{\"$ref\":\"#/$defs/SecretKind\",\"description\":\"Discriminator for the kind of secret this entry holds. The secret material itself is NEVER returned in metadata views; the kind is exposed so consumers can render an appropriate UI affordance and so policy decisions can route by kind.\"},\"selectors\":{\"description\":\"Opaque maintainer-defined selector strings fed to the policy engine when this entry is requested (e.g. \\\"recent_uv_required\\\", \\\"network_class=corp\\\", \\\"step_up_push\\\"). Consumers MUST treat selectors as opaque; they exist for policy authoring on the maintainer side.\",\"items\":{\"minLength\":1,\"type\":\"string\"},\"type\":\"array\",\"uniqueItems\":true},\"tags\":{\"description\":\"User-defined tags for organisation and filtering (e.g. [\\\"family\\\", \\\"finance\\\"]). Maintainers MAY enforce a maximum count; the wire spec does not.\",\"items\":{\"maxLength\":64,\"minLength\":1,\"type\":\"string\"},\"type\":\"array\",\"uniqueItems\":true},\"targets\":{\"description\":\"One or more binding targets — web origins, mobile app identifiers, and/or DIDs — that this credential applies to. A request from any matching target uses this entry. A typical entry for a service that exists as both a website and mobile apps will list a web origin, an iOS bundle id, and an Android package id; passkeys for that service typically list only the origin (because iOS Associated Domains and Android Asset Links bind apps to the domain at the OS level).\",\"items\":{\"$ref\":\"#/$defs/SiteTarget\"},\"minItems\":1,\"type\":\"array\"},\"updatedAt\":{\"format\":\"date-time\",\"type\":\"string\"},\"updatedBy\":{\"description\":\"VID of the consumer that last modified the entry.\",\"type\":\"string\"},\"version\":{\"description\":\"Monotonic version counter incremented on every mutation. Used by consumers for optimistic-concurrency checks on vault/upsert and as the seq baseline for vault/sync.\",\"minimum\":0,\"type\":\"integer\"}},\"required\":[\"id\",\"contextId\",\"targets\",\"label\",\"secretKind\",\"createdAt\",\"updatedAt\",\"version\"],\"title\":\"VaultEntry\",\"type\":\"object\"}},\"$id\":\"https://trusttasks.org/spec/vault/upsert/0.3\",\"$schema\":\"https://json-schema.org/draft/2020-12/schema\",\"additionalProperties\":false,\"description\":\"Create a new vault entry or update an existing one. The secret material — if present — rides inside a pluggable cipher envelope (see `vault/_shared/0.1/sealed-envelope`), so the Trust Task carries ciphertext and an authenticator, not plaintext. Updates may be partial: any populated metadata field replaces the current value; omitted fields are left untouched; explicit null clears the field (per `clearFields`). Optimistic-concurrency check via `expectedVersion`.\",\"properties\":{\"clearFields\":{\"description\":\"List of metadata fields to explicitly clear on this upsert. Distinguishes \\\"don't touch\\\" (field omitted from payload) from \\\"clear\\\" (field listed here).\",\"items\":{\"enum\":[\"notes\",\"favicon\",\"expiresAt\",\"tags\",\"selectors\",\"customFieldNames\"],\"type\":\"string\"},\"type\":\"array\",\"uniqueItems\":true},\"contextId\":{\"description\":\"Trust context the entry belongs to. Cannot be changed by upsert; to move an entry between contexts the consumer MUST delete and recreate.\",\"minLength\":1,\"type\":\"string\"},\"customFieldNames\":{\"items\":{\"maxLength\":128,\"minLength\":1,\"type\":\"string\"},\"type\":\"array\",\"uniqueItems\":true},\"expectedVersion\":{\"description\":\"When updating, the consumer's last-observed `version` for the entry. The maintainer rejects with `vault/upsert:versionConflict` if the current version differs. Omit on create.\",\"minimum\":0,\"type\":\"integer\"},\"expiresAt\":{\"format\":\"date-time\",\"type\":\"string\"},\"ext\":{\"$ref\":\"#/$defs/Ext\"},\"favicon\":{\"format\":\"uri\",\"type\":\"string\"},\"id\":{\"description\":\"Entry id. Omit to create; supply to update. Maintainers MAY accept consumer-supplied ids on create (recommended: ULID) or MAY assign their own and return the assigned id in the response.\",\"minLength\":1,\"type\":\"string\"},\"label\":{\"maxLength\":256,\"minLength\":1,\"type\":\"string\"},\"notes\":{\"maxLength\":4096,\"type\":\"string\"},\"sealedSecret\":{\"$ref\":\"#/$defs/SealedEnvelope\",\"description\":\"Pluggable cipher envelope (discriminated by `envelope`) whose cleartext is a JCS-canonical JSON conforming to `vault/_shared/0.1/vault-secret#/$defs/VaultSecret`. The supported envelope kinds are listed in the SealedEnvelope shared schema; M2A consumers reject any kind they don't implement with `vault/upsert:envelopeUnsupported`. REQUIRED on create unless `secretKind` is `didSelfIssued` or `didcommPeer` (those carry only references to maintainer-internal key ids and have no extra secret bytes). On update, omit if the secret material is unchanged; populate if the secret is being rotated.\"},\"secretKind\":{\"$ref\":\"#/$defs/SecretKind\"},\"selectors\":{\"items\":{\"minLength\":1,\"type\":\"string\"},\"type\":\"array\",\"uniqueItems\":true},\"tags\":{\"items\":{\"maxLength\":64,\"minLength\":1,\"type\":\"string\"},\"type\":\"array\",\"uniqueItems\":true},\"targets\":{\"items\":{\"$ref\":\"#/$defs/SiteTarget\"},\"minItems\":1,\"type\":\"array\"}},\"required\":[\"contextId\",\"targets\",\"label\",\"secretKind\"],\"title\":\"Vault Upsert — payload\",\"type\":\"object\"}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vault/upsert/0.3#response";
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(
"{\"$defs\":{\"AttachmentRef\":{\"additionalProperties\":false,\"properties\":{\"contentType\":{\"description\":\"Optional MIME type hint for the consumer UI (e.g. \\\"text/plain\\\", \\\"application/x-pem-file\\\").\",\"type\":\"string\"},\"digestMultibase\":{\"$ref\":\"#/$defs/DigestMultibase\",\"description\":\"Digest over the encrypted blob bytes (post-encryption), so the consumer can verify integrity after fetch. Taken over the bytes as stored, not over a canonicalization: the blob is an opaque artifact, not a JSON document.\"},\"id\":{\"description\":\"Opaque maintainer-assigned id for this attachment; used to fetch the blob via a separate mechanism.\",\"minLength\":1,\"type\":\"string\"},\"name\":{\"description\":\"User-supplied filename (e.g. \\\"recovery-codes.txt\\\").\",\"maxLength\":256,\"minLength\":1,\"type\":\"string\"},\"sizeBytes\":{\"description\":\"Size of the encrypted blob in bytes. Maintainers MAY enforce a maximum per attachment and per entry.\",\"minimum\":0,\"type\":\"integer\"}},\"required\":[\"id\",\"name\",\"sizeBytes\",\"digestMultibase\"],\"title\":\"AttachmentRef\",\"type\":\"object\"},\"DidcommAuthcryptEnvelope\":{\"additionalProperties\":false,\"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.\",\"properties\":{\"envelope\":{\"const\":\"didcommAuthcrypt\"},\"jwe\":{\"description\":\"Compact DIDComm v2 JWE (base64url-encoded, dot-separated). Unpacks via the framework's standard DIDComm machinery; cleartext is the payload-specific JSON.\",\"minLength\":1,\"type\":\"string\"}},\"required\":[\"envelope\",\"jwe\"],\"title\":\"DidcommAuthcryptEnvelope\",\"type\":\"object\"},\"DigestMultibase\":{\"description\":\"A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\\n\\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\\n\\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\\n\\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \\\"interoperability is not guaranteed between implementations using such values\\\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.\",\"examples\":[\"zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR\"],\"minLength\":16,\"pattern\":\"^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$\",\"title\":\"DigestMultibase\",\"type\":\"string\"},\"Ext\":{\"additionalProperties\":true,\"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.\",\"minProperties\":1,\"propertyNames\":{\"pattern\":\"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)+$\"},\"title\":\"Ext\",\"type\":\"object\"},\"HpkeArmoredEnvelope\":{\"additionalProperties\":false,\"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 (`didSigned` / `attested` / `pinnedOnly`) 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+.\",\"properties\":{\"armored\":{\"description\":\"ASCII-armored bundle text. Multi-line base64 with framing headers + CRC24.\",\"minLength\":1,\"type\":\"string\"},\"envelope\":{\"const\":\"hpkeArmored\"},\"producerAssertion\":{\"default\":\"didSigned\",\"description\":\"Producer-assertion mode per the sealed-transfer framework. `didSigned` = Ed25519 signature by issuer; `attested` = TEE attestation quote (e.g. Nitro); `pinnedOnly` = OOB SHA-256 digest only (dev/test, NOT for production).\",\"enum\":[\"didSigned\",\"attested\",\"pinnedOnly\"],\"type\":\"string\"},\"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.\",\"minLength\":1,\"type\":\"string\"}},\"required\":[\"envelope\",\"armored\",\"recipientKeyId\"],\"title\":\"HpkeArmoredEnvelope\",\"type\":\"object\"},\"Response\":{\"$anchor\":\"response\",\"additionalProperties\":false,\"properties\":{\"created\":{\"description\":\"true when this upsert created a new entry; false when it updated an existing one.\",\"type\":\"boolean\"},\"entry\":{\"$ref\":\"#/$defs/VaultEntry\"},\"ext\":{\"$ref\":\"#/$defs/Ext\"}},\"required\":[\"entry\"],\"title\":\"Vault Upsert — response payload\",\"type\":\"object\"},\"SealedEnvelope\":{\"description\":\"Discriminated by `envelope`. Exactly one variant matches per document.\",\"oneOf\":[{\"$ref\":\"#/$defs/DidcommAuthcryptEnvelope\"},{\"$ref\":\"#/$defs/HpkeArmoredEnvelope\"},{\"$ref\":\"#/$defs/TspMessageEnvelope\"}],\"title\":\"SealedEnvelope\"},\"SecretKind\":{\"description\":\"Discriminator for the secret type stored in the entry. Definitions:\\n- `password` — username + password (+ optional TOTP seed).\\n- `passkey` — WebAuthn discoverable credential (private key + rpId + userHandle).\\n- `oauthTokens` — OAuth 2.0 refresh + access token bundle for a specific provider.\\n- `didSelfIssued` — Self-Issued OpenID Provider v2 (SIOP) credential: the entry points at a DID + signing key already managed by the VTA.\\n- `didcommPeer` — DIDComm peer identity used to authenticate against a DIDComm-speaking relying party.\\n- `bearerToken` — opaque bearer token carried in a maintainer-named header (covers API tokens, long-lived JWTs, personal-access tokens).\\n- `sshKey` — SSH private key + comment.\\n- `custom` — arbitrary structured fields; release-time consumer responsible for interpretation.\",\"enum\":[\"password\",\"passkey\",\"oauthTokens\",\"didSelfIssued\",\"didcommPeer\",\"bearerToken\",\"sshKey\",\"custom\"],\"title\":\"SecretKind\",\"type\":\"string\"},\"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\":[{\"additionalProperties\":false,\"properties\":{\"kind\":{\"const\":\"webOrigin\"},\"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.\",\"format\":\"uri\",\"type\":\"string\"}},\"required\":[\"kind\",\"origin\"],\"title\":\"WebOrigin\",\"type\":\"object\"},{\"additionalProperties\":false,\"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.\",\"minLength\":1,\"type\":\"string\"},\"kind\":{\"const\":\"did\"}},\"required\":[\"kind\",\"did\"],\"title\":\"Did\",\"type\":\"object\"},{\"additionalProperties\":false,\"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).\",\"minLength\":1,\"pattern\":\"^[A-Za-z0-9.-]+$\",\"type\":\"string\"},\"kind\":{\"const\":\"iosApp\"},\"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.\",\"minLength\":1,\"pattern\":\"^[A-Z0-9]+$\",\"type\":\"string\"}},\"required\":[\"kind\",\"bundleId\"],\"title\":\"IosApp\",\"type\":\"object\"},{\"additionalProperties\":false,\"properties\":{\"kind\":{\"const\":\"androidApp\"},\"packageName\":{\"description\":\"Android package name in reverse-DNS form (e.g. \\\"com.github.android\\\").\",\"minLength\":1,\"pattern\":\"^[A-Za-z][A-Za-z0-9_]*(\\\\.[A-Za-z][A-Za-z0-9_]*)+$\",\"type\":\"string\"},\"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).\",\"items\":{\"pattern\":\"^[0-9A-F]{2}(:[0-9A-F]{2}){31}$\",\"type\":\"string\"},\"minItems\":1,\"type\":\"array\",\"uniqueItems\":true}},\"required\":[\"kind\",\"packageName\",\"sha256CertFingerprints\"],\"title\":\"AndroidApp\",\"type\":\"object\"}],\"title\":\"SiteTarget\"},\"TspMessageEnvelope\":{\"additionalProperties\":false,\"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 `tspMessage` envelopes explicitly (`envelopeUnsupported`) until they're wired up — rather than silently failing in DIDComm parsing.\",\"properties\":{\"envelope\":{\"const\":\"tspMessage\"},\"message\":{\"description\":\"Base64url-encoded TSP message bytes. Format reference: https://trustoverip.github.io/tswg-tsp-specification/#message-format\",\"minLength\":1,\"type\":\"string\"}},\"required\":[\"envelope\",\"message\"],\"title\":\"TspMessageEnvelope\",\"type\":\"object\"},\"VaultEntry\":{\"additionalProperties\":false,\"properties\":{\"attachments\":{\"description\":\"References to encrypted blobs associated with the entry (recovery codes, PEM files, screenshots of authenticator setup). The blobs themselves are fetched via a separate mechanism the maintainer documents; metadata view exposes only the descriptor.\",\"items\":{\"$ref\":\"#/$defs/AttachmentRef\"},\"type\":\"array\"},\"breachedAt\":{\"description\":\"Set by the maintainer (via HIBP integration or equivalent) when the password material associated with this entry is known to appear in a public breach. Consumers SHOULD surface this prominently. Cleared when the user rotates the password and the new password is not in any known breach.\",\"format\":\"date-time\",\"type\":\"string\"},\"contextId\":{\"description\":\"Identifier of the trust context (persona) the entry belongs to. Opaque string interpreted by the vault maintainer; corresponds to a single ContextRecord on the VTA side.\",\"minLength\":1,\"type\":\"string\"},\"createdAt\":{\"format\":\"date-time\",\"type\":\"string\"},\"createdBy\":{\"description\":\"VID of the consumer that originally created the entry.\",\"type\":\"string\"},\"customFieldNames\":{\"description\":\"Names of additional fields the user has attached (e.g. [\\\"security-question-1\\\", \\\"account-number\\\"]). The VALUES live in the secret payload and are only delivered by vault/release/0.1. Exposing names in metadata lets the consumer render the right form layout before requesting release.\",\"items\":{\"maxLength\":128,\"minLength\":1,\"type\":\"string\"},\"type\":\"array\",\"uniqueItems\":true},\"expiresAt\":{\"description\":\"Optional time after which the credential is no longer expected to be valid (e.g. an OAuth refresh token's known expiry, a time-limited API token, an enterprise password rotation policy). Maintainers MAY surface this in the consumer UI as a warning.\",\"format\":\"date-time\",\"type\":\"string\"},\"ext\":{\"$ref\":\"#/$defs/Ext\",\"description\":\"Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces.\"},\"favicon\":{\"description\":\"Optional URI of an icon to display in the consumer UI. Maintainers MAY fetch and cache; consumers SHOULD treat as untrusted content and fetch via a sandboxed pipeline.\",\"format\":\"uri\",\"type\":\"string\"},\"id\":{\"description\":\"Opaque vault-maintainer-assigned identifier for the entry. ULID/UUID/base32 are common; the wire spec only requires non-empty string equality.\",\"minLength\":1,\"type\":\"string\"},\"label\":{\"description\":\"Human-readable display name (e.g. \\\"Work GitHub\\\", \\\"Personal bank — checking\\\"). Bounded on the wire at 256 characters; a maintainer MAY enforce a shorter limit.\",\"maxLength\":256,\"minLength\":1,\"type\":\"string\"},\"lastUsedAt\":{\"description\":\"Most recent time the entry was used (either released or proxy-login performed). Maintainers MAY return this with reduced precision (e.g. hour-floored) when releasing to a less-trusted consumer.\",\"format\":\"date-time\",\"type\":\"string\"},\"notes\":{\"description\":\"Non-sensitive notes the user attached to the entry. Visible in metadata view (suitable for support contact, account number, expiry policy memos). SENSITIVE notes belong in the secret payload as a `secureNotes` field — those are only released by vault/release/0.1.\",\"maxLength\":4096,\"type\":\"string\"},\"passwordChangedAt\":{\"description\":\"Set whenever the password component of the secret payload is rotated. Maintainers MUST update this on every secret-material change for entries of kind `password` (or any kind that carries a password component). Used by consumers to surface rotation-overdue warnings.\",\"format\":\"date-time\",\"type\":\"string\"},\"principalDid\":{\"description\":\"Optional cached DID the entry will act AS for DID-shaped flows — mirrors the `did` field of the entry's secret payload when `secretKind` carries one (`didSelfIssued`, `didcommPeer`). Absent for kinds that have no DID concept (`password`, `passkey`, `oauthTokens`, `bearerToken`, `sshKey`, `custom`). MAINTAINER-DERIVED, NOT CONSUMER-SUPPLIED: the maintainer MUST recompute this from the canonical secret at every upsert / secret rotation; a producer-supplied value on `vault/upsert/0.1` MUST be ignored (no error, but no honour). Read-only on the wire, present in metadata views so consumers can drive RP-side flows (e.g. fetch `/auth/challenge` keyed on the principal DID before requesting a proxy-login) without releasing the secret.\",\"minLength\":1,\"type\":\"string\"},\"secretKind\":{\"$ref\":\"#/$defs/SecretKind\",\"description\":\"Discriminator for the kind of secret this entry holds. The secret material itself is NEVER returned in metadata views; the kind is exposed so consumers can render an appropriate UI affordance and so policy decisions can route by kind.\"},\"selectors\":{\"description\":\"Opaque maintainer-defined selector strings fed to the policy engine when this entry is requested (e.g. \\\"recent_uv_required\\\", \\\"network_class=corp\\\", \\\"step_up_push\\\"). Consumers MUST treat selectors as opaque; they exist for policy authoring on the maintainer side.\",\"items\":{\"minLength\":1,\"type\":\"string\"},\"type\":\"array\",\"uniqueItems\":true},\"tags\":{\"description\":\"User-defined tags for organisation and filtering (e.g. [\\\"family\\\", \\\"finance\\\"]). Maintainers MAY enforce a maximum count; the wire spec does not.\",\"items\":{\"maxLength\":64,\"minLength\":1,\"type\":\"string\"},\"type\":\"array\",\"uniqueItems\":true},\"targets\":{\"description\":\"One or more binding targets — web origins, mobile app identifiers, and/or DIDs — that this credential applies to. A request from any matching target uses this entry. A typical entry for a service that exists as both a website and mobile apps will list a web origin, an iOS bundle id, and an Android package id; passkeys for that service typically list only the origin (because iOS Associated Domains and Android Asset Links bind apps to the domain at the OS level).\",\"items\":{\"$ref\":\"#/$defs/SiteTarget\"},\"minItems\":1,\"type\":\"array\"},\"updatedAt\":{\"format\":\"date-time\",\"type\":\"string\"},\"updatedBy\":{\"description\":\"VID of the consumer that last modified the entry.\",\"type\":\"string\"},\"version\":{\"description\":\"Monotonic version counter incremented on every mutation. Used by consumers for optimistic-concurrency checks on vault/upsert and as the seq baseline for vault/sync.\",\"minimum\":0,\"type\":\"integer\"}},\"required\":[\"id\",\"contextId\",\"targets\",\"label\",\"secretKind\",\"createdAt\",\"updatedAt\",\"version\"],\"title\":\"VaultEntry\",\"type\":\"object\"}},\"$ref\":\"#/$defs/Response\",\"$schema\":\"https://json-schema.org/draft/2020-12/schema\"}\n",
);
}
impl crate::RequestPayload for Payload {
type Response = Response;
}
/// The earlier `MAJOR.MINOR` of this slug that this version declares it
/// extends (front matter `extends`, SPEC §5.2 "Declared extension"), or
/// `None`. Only the direct declaration; walk a chain with
/// [`crate::extension::extends_for`].
pub const EXTENDS: Option<&str> = None;
/// 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] = &[
error_codes::CONTEXT_NOT_FOUND,
error_codes::NOT_FOUND,
error_codes::VERSION_CONFLICT,
error_codes::SEALED_SECRET_INVALID,
error_codes::SECRET_REQUIRED,
error_codes::ENVELOPE_UNSUPPORTED,
error_codes::CONTEXT_CHANGE_FORBIDDEN,
];
/// One constant per extended error code this specification declares
/// (SPEC §7.3 item 9), named for its local part.
///
/// Emit these rather than a string literal: the code is read from the
/// specification, so it cannot name a code the specification never
/// declared.
pub mod error_codes {
/// `vault/upsert:contextNotFound`
///
/// The supplied `contextId` does not exist.
///
/// Declared `retryable: false`.
pub const CONTEXT_NOT_FOUND: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vault/upsert:contextNotFound",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vault/upsert:notFound`
///
/// An `id` was supplied (update path) but no entry with that id exists in the consumer's visible scope.
///
/// Declared `retryable: false`.
pub const NOT_FOUND: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vault/upsert:notFound",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vault/upsert:versionConflict`
///
/// An `expectedVersion` was supplied and does not match the current version. The consumer SHOULD re-read the entry (vault/get) and retry the upsert with the up-to-date version.
///
/// Declared `retryable: true`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const VERSION_CONFLICT: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vault/upsert:versionConflict",
retryable: true,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"currentVersion\":{\"minimum\":0,\"type\":\"integer\"}},\"type\":\"object\"}",
),
};
/// `vault/upsert:sealedSecretInvalid`
///
/// The sealedSecret envelope failed verification (digest mismatch, signature invalid, recipient key unknown, or armor malformed).
///
/// Declared `retryable: false`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const SEALED_SECRET_INVALID: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vault/upsert:sealedSecretInvalid",
retryable: false,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"reason\":{\"enum\":[\"armor_malformed\",\"recipient_key_unknown\",\"signature_invalid\",\"digest_mismatch\"],\"type\":\"string\"}},\"type\":\"object\"}",
),
};
/// `vault/upsert:secretRequired`
///
/// A create or rotation was attempted without `sealedSecret` for a secretKind that requires one.
///
/// Declared `retryable: false`.
pub const SECRET_REQUIRED: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vault/upsert:secretRequired",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vault/upsert:envelopeUnsupported`
///
/// The `sealedSecret.envelope` kind is not one the maintainer implements (e.g. a TSP message arriving at a maintainer that only speaks `didcommAuthcrypt`). Producers SHOULD consult `trust-task-discovery/0.1` to learn which envelope kinds the maintainer accepts.
///
/// Declared `retryable: false`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const ENVELOPE_UNSUPPORTED: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vault/upsert:envelopeUnsupported",
retryable: false,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"receivedEnvelope\":{\"type\":\"string\"},\"supportedEnvelopes\":{\"items\":{\"type\":\"string\"},\"type\":\"array\"}},\"type\":\"object\"}",
),
};
/// `vault/upsert:contextChangeForbidden`
///
/// The consumer attempted to change `contextId` on an existing entry. Move-between-contexts MUST be done as delete + recreate.
///
/// Declared `retryable: false`.
pub const CONTEXT_CHANGE_FORBIDDEN: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vault/upsert:contextChangeForbidden",
retryable: false,
details_schema: ::core::option::Option::None,
};
}