//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vault/get`. Version: `0.1`.
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
/// Error types.
pub mod error {
/// Error from a `TryFrom` or `FromStr` implementation.
pub struct ConversionError(::std::borrow::Cow<'static, str>);
impl ::std::error::Error for ConversionError {}
impl ::std::fmt::Display for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Display::fmt(&self.0, f)
}
}
impl ::std::fmt::Debug for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Debug::fmt(&self.0, f)
}
}
impl From<&'static str> for ConversionError {
fn from(value: &'static str) -> Self {
Self(value.into())
}
}
impl From<String> for ConversionError {
fn from(value: String) -> Self {
Self(value.into())
}
}
}
///`AttachmentRef`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "AttachmentRef",
/// "type": "object",
/// "required": [
/// "id",
/// "name",
/// "sha256",
/// "sizeBytes"
/// ],
/// "properties": {
/// "contentType": {
/// "description": "Optional MIME type hint for the consumer UI (e.g. \"text/plain\", \"application/x-pem-file\").",
/// "type": "string"
/// },
/// "id": {
/// "description": "Opaque maintainer-assigned id for this attachment; used to fetch the blob via a separate mechanism.",
/// "type": "string",
/// "minLength": 1
/// },
/// "name": {
/// "description": "User-supplied filename (e.g. \"recovery-codes.txt\").",
/// "type": "string",
/// "maxLength": 256,
/// "minLength": 1
/// },
/// "sha256": {
/// "description": "Hex-encoded SHA-256 of the encrypted blob bytes (post-encryption). Lets the consumer verify integrity after fetch.",
/// "type": "string",
/// "pattern": "^[0-9a-f]{64}$"
/// },
/// "sizeBytes": {
/// "description": "Size of the encrypted blob in bytes. Maintainers MAY enforce a maximum per attachment and per entry.",
/// "type": "integer",
/// "minimum": 0.0
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
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>,
///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,
///Hex-encoded SHA-256 of the encrypted blob bytes (post-encryption). Lets the consumer verify integrity after fetch.
pub sha256: AttachmentRefSha256,
///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 ::std::convert::From<&AttachmentRef> for AttachmentRef {
fn from(value: &AttachmentRef) -> Self {
value.clone()
}
}
///Opaque maintainer-assigned id for this attachment; used to fetch the blob via a separate mechanism.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Opaque maintainer-assigned id for this attachment; used to fetch the blob via a separate mechanism.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[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::convert::From<&AttachmentRefId> for AttachmentRefId {
fn from(value: &AttachmentRefId) -> Self {
value.clone()
}
}
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").
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "User-supplied filename (e.g. \"recovery-codes.txt\").",
/// "type": "string",
/// "maxLength": 256,
/// "minLength": 1
///}
/// ```
/// </details>
#[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::convert::From<&AttachmentRefName> for AttachmentRefName {
fn from(value: &AttachmentRefName) -> Self {
value.clone()
}
}
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())
})
}
}
///Hex-encoded SHA-256 of the encrypted blob bytes (post-encryption). Lets the consumer verify integrity after fetch.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Hex-encoded SHA-256 of the encrypted blob bytes (post-encryption). Lets the consumer verify integrity after fetch.",
/// "type": "string",
/// "pattern": "^[0-9a-f]{64}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct AttachmentRefSha256(::std::string::String);
impl ::std::ops::Deref for AttachmentRefSha256 {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AttachmentRefSha256> for ::std::string::String {
fn from(value: AttachmentRefSha256) -> Self {
value.0
}
}
impl ::std::convert::From<&AttachmentRefSha256> for AttachmentRefSha256 {
fn from(value: &AttachmentRefSha256) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for AttachmentRefSha256 {
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]{64}$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[0-9a-f]{64}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for AttachmentRefSha256 {
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 AttachmentRefSha256 {
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 AttachmentRefSha256 {
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 AttachmentRefSha256 {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Ext",
/// "description": "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.",
/// "type": "object",
/// "minProperties": 1,
/// "additionalProperties": true,
/// "propertyNames": {
/// "pattern": "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$"
/// }
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct Ext(pub ::std::collections::HashMap<ExtKey, ::serde_json::Value>);
impl ::std::ops::Deref for Ext {
type Target = ::std::collections::HashMap<ExtKey, ::serde_json::Value>;
fn deref(&self) -> &::std::collections::HashMap<ExtKey, ::serde_json::Value> {
&self.0
}
}
impl ::std::convert::From<Ext> for ::std::collections::HashMap<ExtKey, ::serde_json::Value> {
fn from(value: Ext) -> Self {
value.0
}
}
impl ::std::convert::From<&Ext> for Ext {
fn from(value: &Ext) -> Self {
value.clone()
}
}
impl ::std::convert::From<::std::collections::HashMap<ExtKey, ::serde_json::Value>> for Ext {
fn from(value: ::std::collections::HashMap<ExtKey, ::serde_json::Value>) -> Self {
Self(value)
}
}
///`ExtKey`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "pattern": "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ExtKey(::std::string::String);
impl ::std::ops::Deref for ExtKey {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ExtKey> for ::std::string::String {
fn from(value: ExtKey) -> Self {
value.0
}
}
impl ::std::convert::From<&ExtKey> for ExtKey {
fn from(value: &ExtKey) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for ExtKey {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for ExtKey {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Fetch the metadata view of a single vault entry by id. Returns the same VaultEntry shape vault/list does, but for one specific entry. Secret material is NEVER returned by this task; use vault/release/0.1 to obtain secret bytes.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/vault/get/0.1",
/// "title": "Payload",
/// "description": "Fetch the metadata view of a single vault entry by id. Returns the same VaultEntry shape vault/list does, but for one specific entry. Secret material is NEVER returned by this task; use vault/release/0.1 to obtain secret bytes.",
/// "type": "object",
/// "required": [
/// "id"
/// ],
/// "properties": {
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "id": {
/// "description": "Vault entry id (as returned in a prior vault/list or vault/sync response).",
/// "type": "string",
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct Payload {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///Vault entry id (as returned in a prior vault/list or vault/sync response).
pub id: PayloadId,
}
impl ::std::convert::From<&Payload> for Payload {
fn from(value: &Payload) -> Self {
value.clone()
}
}
///Vault entry id (as returned in a prior vault/list or vault/sync response).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Vault entry id (as returned in a prior vault/list or vault/sync response).",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[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::convert::From<&PayloadId> for PayloadId {
fn from(value: &PayloadId) -> Self {
value.clone()
}
}
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())
})
}
}
///`Response`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "type": "object",
/// "required": [
/// "entry"
/// ],
/// "properties": {
/// "entry": {
/// "$ref": "#/definitions/VaultEntry"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "redactedFields": {
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct Response {
pub entry: VaultEntry,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
#[serde(
rename = "redactedFields",
default,
skip_serializing_if = "::std::vec::Vec::is_empty"
)]
pub redacted_fields: ::std::vec::Vec<::std::string::String>,
}
impl ::std::convert::From<&Response> for Response {
fn from(value: &Response) -> Self {
value.clone()
}
}
/**Discriminator for the secret type stored in the entry. Definitions:
- `password` — username + password (+ optional TOTP seed).
- `passkey` — WebAuthn discoverable credential (private key + rpId + userHandle).
- `oauth-tokens` — OAuth 2.0 refresh + access token bundle for a specific provider.
- `did-self-issued` — Self-Issued OpenID Provider v2 (SIOP) credential: the entry points at a DID + signing key already managed by the VTA.
- `didcomm-peer` — DIDComm peer identity used to authenticate against a DIDComm-speaking relying party.
- `bearer-token` — opaque bearer token carried in a maintainer-named header (covers API tokens, long-lived JWTs, personal-access tokens).
- `ssh-key` — SSH private key + comment.
- `custom` — arbitrary structured fields; release-time consumer responsible for interpretation.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "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- `oauth-tokens` — OAuth 2.0 refresh + access token bundle for a specific provider.\n- `did-self-issued` — Self-Issued OpenID Provider v2 (SIOP) credential: the entry points at a DID + signing key already managed by the VTA.\n- `didcomm-peer` — DIDComm peer identity used to authenticate against a DIDComm-speaking relying party.\n- `bearer-token` — opaque bearer token carried in a maintainer-named header (covers API tokens, long-lived JWTs, personal-access tokens).\n- `ssh-key` — SSH private key + comment.\n- `custom` — arbitrary structured fields; release-time consumer responsible for interpretation.",
/// "type": "string",
/// "enum": [
/// "password",
/// "passkey",
/// "oauth-tokens",
/// "did-self-issued",
/// "didcomm-peer",
/// "bearer-token",
/// "ssh-key",
/// "custom"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum SecretKind {
#[serde(rename = "password")]
Password,
#[serde(rename = "passkey")]
Passkey,
#[serde(rename = "oauth-tokens")]
OauthTokens,
#[serde(rename = "did-self-issued")]
DidSelfIssued,
#[serde(rename = "didcomm-peer")]
DidcommPeer,
#[serde(rename = "bearer-token")]
BearerToken,
#[serde(rename = "ssh-key")]
SshKey,
#[serde(rename = "custom")]
Custom,
}
impl ::std::convert::From<&Self> for SecretKind {
fn from(value: &SecretKind) -> Self {
value.clone()
}
}
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("oauth-tokens"),
Self::DidSelfIssued => f.write_str("did-self-issued"),
Self::DidcommPeer => f.write_str("didcomm-peer"),
Self::BearerToken => f.write_str("bearer-token"),
Self::SshKey => f.write_str("ssh-key"),
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),
"oauth-tokens" => Ok(Self::OauthTokens),
"did-self-issued" => Ok(Self::DidSelfIssued),
"didcomm-peer" => Ok(Self::DidcommPeer),
"bearer-token" => Ok(Self::BearerToken),
"ssh-key" => 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.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "SiteTarget",
/// "description": "A single binding target for a vault entry. Tagged union over the discriminator `kind`. A VaultEntry's `targets` array MAY mix any number of these.",
/// "oneOf": [
/// {
/// "title": "WebOrigin",
/// "type": "object",
/// "required": [
/// "kind",
/// "origin"
/// ],
/// "properties": {
/// "kind": {
/// "const": "web-origin"
/// },
/// "origin": {
/// "description": "Web origin per RFC 6454 (scheme + host + optional port), e.g. \"https://github.com\". Compared by exact string equality after canonicalisation (lowercase host, default port elided). Consumers wanting subdomain coverage SHOULD add multiple targets, not encode a wildcard.",
/// "type": "string",
/// "format": "uri"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "Did",
/// "type": "object",
/// "required": [
/// "did",
/// "kind"
/// ],
/// "properties": {
/// "did": {
/// "description": "DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.",
/// "type": "string",
/// "minLength": 1
/// },
/// "kind": {
/// "const": "did"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "IosApp",
/// "type": "object",
/// "required": [
/// "bundleId",
/// "kind"
/// ],
/// "properties": {
/// "bundleId": {
/// "description": "iOS bundle identifier in reverse-DNS form (e.g. \"com.github.stwalkerster.codehub\"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z0-9.-]+$"
/// },
/// "kind": {
/// "const": "ios-app"
/// },
/// "teamId": {
/// "description": "Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Z0-9]+$"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "AndroidApp",
/// "type": "object",
/// "required": [
/// "kind",
/// "packageName",
/// "sha256CertFingerprints"
/// ],
/// "properties": {
/// "kind": {
/// "const": "android-app"
/// },
/// "packageName": {
/// "description": "Android package name in reverse-DNS form (e.g. \"com.github.android\").",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$"
/// },
/// "sha256CertFingerprints": {
/// "description": "SHA-256 fingerprints of the app's signing certificates, in colon-separated hex (the format `apksigner` and the Play Console emit). At least one fingerprint MUST be present. The maintainer matches when ANY of the provided fingerprints matches the requesting app's signature — this supports apps signed by multiple keys (e.g. during certificate rotation via Play App Signing).",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "pattern": "^[0-9A-F]{2}(:[0-9A-F]{2}){31}$"
/// },
/// "minItems": 1,
/// "uniqueItems": true
/// }
/// },
/// "additionalProperties": false
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(tag = "kind", deny_unknown_fields)]
pub enum SiteTarget {
///WebOrigin
#[serde(rename = "web-origin")]
WebOrigin {
///Web origin per RFC 6454 (scheme + host + optional port), e.g. "https://github.com". Compared by exact string equality after canonicalisation (lowercase host, default port elided). Consumers wanting subdomain coverage SHOULD add multiple targets, not encode a wildcard.
origin: ::std::string::String,
},
///Did
#[serde(rename = "did")]
Did {
///DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.
did: SiteTargetDid,
},
///IosApp
#[serde(rename = "ios-app")]
IosApp {
///iOS bundle identifier in reverse-DNS form (e.g. "com.github.stwalkerster.codehub"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).
#[serde(rename = "bundleId")]
bundle_id: SiteTargetBundleId,
///Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.
#[serde(
rename = "teamId",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
team_id: ::std::option::Option<SiteTargetTeamId>,
},
///AndroidApp
#[serde(rename = "android-app")]
AndroidApp {
///Android package name in reverse-DNS form (e.g. "com.github.android").
#[serde(rename = "packageName")]
package_name: SiteTargetPackageName,
///SHA-256 fingerprints of the app's signing certificates, in colon-separated hex (the format `apksigner` and the Play Console emit). At least one fingerprint MUST be present. The maintainer matches when ANY of the provided fingerprints matches the requesting app's signature — this supports apps signed by multiple keys (e.g. during certificate rotation via Play App Signing).
#[serde(rename = "sha256CertFingerprints")]
sha256_cert_fingerprints: Vec<SiteTargetSha256CertFingerprintsItem>,
},
}
impl ::std::convert::From<&Self> for SiteTarget {
fn from(value: &SiteTarget) -> Self {
value.clone()
}
}
///iOS bundle identifier in reverse-DNS form (e.g. "com.github.stwalkerster.codehub"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "iOS bundle identifier in reverse-DNS form (e.g. \"com.github.stwalkerster.codehub\"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z0-9.-]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetBundleId(::std::string::String);
impl ::std::ops::Deref for SiteTargetBundleId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetBundleId> for ::std::string::String {
fn from(value: SiteTargetBundleId) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetBundleId> for SiteTargetBundleId {
fn from(value: &SiteTargetBundleId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetBundleId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[A-Za-z0-9.-]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[A-Za-z0-9.-]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetBundleId {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for SiteTargetBundleId {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for SiteTargetBundleId {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for SiteTargetBundleId {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetDid(::std::string::String);
impl ::std::ops::Deref for SiteTargetDid {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetDid> for ::std::string::String {
fn from(value: SiteTargetDid) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetDid> for SiteTargetDid {
fn from(value: &SiteTargetDid) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetDid {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetDid {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for SiteTargetDid {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for SiteTargetDid {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for SiteTargetDid {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Android package name in reverse-DNS form (e.g. "com.github.android").
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Android package name in reverse-DNS form (e.g. \"com.github.android\").",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetPackageName(::std::string::String);
impl ::std::ops::Deref for SiteTargetPackageName {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetPackageName> for ::std::string::String {
fn from(value: SiteTargetPackageName) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetPackageName> for SiteTargetPackageName {
fn from(value: &SiteTargetPackageName) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetPackageName {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err(
"doesn't match pattern \"^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$\""
.into(),
);
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetPackageName {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for SiteTargetPackageName {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for SiteTargetPackageName {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for SiteTargetPackageName {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///`SiteTargetSha256CertFingerprintsItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "pattern": "^[0-9A-F]{2}(:[0-9A-F]{2}){31}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetSha256CertFingerprintsItem(::std::string::String);
impl ::std::ops::Deref for SiteTargetSha256CertFingerprintsItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetSha256CertFingerprintsItem> for ::std::string::String {
fn from(value: SiteTargetSha256CertFingerprintsItem) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetSha256CertFingerprintsItem>
for SiteTargetSha256CertFingerprintsItem
{
fn from(value: &SiteTargetSha256CertFingerprintsItem) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetSha256CertFingerprintsItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^[0-9A-F]{2}(:[0-9A-F]{2}){31}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[0-9A-F]{2}(:[0-9A-F]{2}){31}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetSha256CertFingerprintsItem {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for SiteTargetSha256CertFingerprintsItem {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for SiteTargetSha256CertFingerprintsItem {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for SiteTargetSha256CertFingerprintsItem {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Z0-9]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetTeamId(::std::string::String);
impl ::std::ops::Deref for SiteTargetTeamId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetTeamId> for ::std::string::String {
fn from(value: SiteTargetTeamId) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetTeamId> for SiteTargetTeamId {
fn from(value: &SiteTargetTeamId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetTeamId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[A-Z0-9]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[A-Z0-9]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetTeamId {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for SiteTargetTeamId {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for SiteTargetTeamId {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for SiteTargetTeamId {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///`VaultEntry`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "VaultEntry",
/// "type": "object",
/// "required": [
/// "contextId",
/// "createdAt",
/// "id",
/// "label",
/// "secretKind",
/// "targets",
/// "updatedAt",
/// "version"
/// ],
/// "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.",
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/AttachmentRef"
/// }
/// },
/// "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.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "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.",
/// "type": "string",
/// "minLength": 1
/// },
/// "createdAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "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.",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1
/// },
/// "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.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "ext": {
/// "description": "Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces.",
/// "$ref": "#/definitions/Ext"
/// },
/// "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.",
/// "type": "string",
/// "format": "uri"
/// },
/// "id": {
/// "description": "Opaque vault-maintainer-assigned identifier for the entry. ULID/UUID/base32 are common; the wire spec only requires non-empty string equality.",
/// "type": "string",
/// "minLength": 1
/// },
/// "label": {
/// "description": "Human-readable display name (e.g. \"Work GitHub\", \"Personal bank — checking\"). Maintainers MAY enforce a maximum length; the wire spec does not.",
/// "type": "string",
/// "minLength": 1
/// },
/// "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.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "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.",
/// "type": "string",
/// "maxLength": 4096
/// },
/// "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.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "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 (`did-self-issued`, `didcomm-peer`). Absent for kinds that have no DID concept (`password`, `passkey`, `oauth-tokens`, `bearer-token`, `ssh-key`, `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.",
/// "type": "string",
/// "minLength": 1
/// },
/// "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.",
/// "$ref": "#/definitions/SecretKind"
/// },
/// "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.",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "minLength": 1
/// },
/// "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.",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
/// },
/// "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).",
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/SiteTarget"
/// },
/// "minItems": 1
/// },
/// "updatedAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "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.",
/// "type": "integer",
/// "minimum": 0.0
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
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"). Maintainers MAY enforce a maximum length; the wire spec does not.
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 (`did-self-issued`, `didcomm-peer`). Absent for kinds that have no DID concept (`password`, `passkey`, `oauth-tokens`, `bearer-token`, `ssh-key`, `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 ::std::convert::From<&VaultEntry> for VaultEntry {
fn from(value: &VaultEntry) -> Self {
value.clone()
}
}
///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.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "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.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[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::convert::From<&VaultEntryContextId> for VaultEntryContextId {
fn from(value: &VaultEntryContextId) -> Self {
value.clone()
}
}
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`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1
///}
/// ```
/// </details>
#[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::convert::From<&VaultEntryCustomFieldNamesItem> for VaultEntryCustomFieldNamesItem {
fn from(value: &VaultEntryCustomFieldNamesItem) -> Self {
value.clone()
}
}
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.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Opaque vault-maintainer-assigned identifier for the entry. ULID/UUID/base32 are common; the wire spec only requires non-empty string equality.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[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::convert::From<&VaultEntryId> for VaultEntryId {
fn from(value: &VaultEntryId) -> Self {
value.clone()
}
}
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"). Maintainers MAY enforce a maximum length; the wire spec does not.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Human-readable display name (e.g. \"Work GitHub\", \"Personal bank — checking\"). Maintainers MAY enforce a maximum length; the wire spec does not.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[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::convert::From<&VaultEntryLabel> for VaultEntryLabel {
fn from(value: &VaultEntryLabel) -> Self {
value.clone()
}
}
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() < 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.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "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.",
/// "type": "string",
/// "maxLength": 4096
///}
/// ```
/// </details>
#[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::convert::From<&VaultEntryNotes> for VaultEntryNotes {
fn from(value: &VaultEntryNotes) -> Self {
value.clone()
}
}
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 (`did-self-issued`, `didcomm-peer`). Absent for kinds that have no DID concept (`password`, `passkey`, `oauth-tokens`, `bearer-token`, `ssh-key`, `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.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "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 (`did-self-issued`, `didcomm-peer`). Absent for kinds that have no DID concept (`password`, `passkey`, `oauth-tokens`, `bearer-token`, `ssh-key`, `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.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[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::convert::From<&VaultEntryPrincipalDid> for VaultEntryPrincipalDid {
fn from(value: &VaultEntryPrincipalDid) -> Self {
value.clone()
}
}
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`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct 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::convert::From<&VaultEntrySelectorsItem> for VaultEntrySelectorsItem {
fn from(value: &VaultEntrySelectorsItem) -> Self {
value.clone()
}
}
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`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct 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::convert::From<&VaultEntryTagsItem> for VaultEntryTagsItem {
fn from(value: &VaultEntryTagsItem) -> Self {
value.clone()
}
}
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())
})
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vault/get/0.1";
}
impl crate::Payload for Response {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vault/get/0.1#response";
}
#[cfg(feature = "validate")]
impl crate::validate::ValidatedPayload for Payload {
const SCHEMA_JSON: &'static str = "{\n \"$defs\": {\n \"AttachmentRef\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"contentType\": {\n \"description\": \"Optional MIME type hint for the consumer UI (e.g. \\\"text/plain\\\", \\\"application/x-pem-file\\\").\",\n \"type\": \"string\"\n },\n \"id\": {\n \"description\": \"Opaque maintainer-assigned id for this attachment; used to fetch the blob via a separate mechanism.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"name\": {\n \"description\": \"User-supplied filename (e.g. \\\"recovery-codes.txt\\\").\",\n \"maxLength\": 256,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"sha256\": {\n \"description\": \"Hex-encoded SHA-256 of the encrypted blob bytes (post-encryption). Lets the consumer verify integrity after fetch.\",\n \"pattern\": \"^[0-9a-f]{64}$\",\n \"type\": \"string\"\n },\n \"sizeBytes\": {\n \"description\": \"Size of the encrypted blob in bytes. Maintainers MAY enforce a maximum per attachment and per entry.\",\n \"minimum\": 0,\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"sizeBytes\",\n \"sha256\"\n ],\n \"title\": \"AttachmentRef\",\n \"type\": \"object\"\n },\n \"Ext\": {\n \"additionalProperties\": true,\n \"description\": \"Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)+$\"\n },\n \"title\": \"Ext\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"properties\": {\n \"entry\": {\n \"$ref\": \"#/$defs/VaultEntry\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"redactedFields\": {\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n }\n },\n \"required\": [\n \"entry\"\n ],\n \"title\": \"Vault Get — response payload\",\n \"type\": \"object\"\n },\n \"SecretKind\": {\n \"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- `oauth-tokens` — OAuth 2.0 refresh + access token bundle for a specific provider.\\n- `did-self-issued` — Self-Issued OpenID Provider v2 (SIOP) credential: the entry points at a DID + signing key already managed by the VTA.\\n- `didcomm-peer` — DIDComm peer identity used to authenticate against a DIDComm-speaking relying party.\\n- `bearer-token` — opaque bearer token carried in a maintainer-named header (covers API tokens, long-lived JWTs, personal-access tokens).\\n- `ssh-key` — SSH private key + comment.\\n- `custom` — arbitrary structured fields; release-time consumer responsible for interpretation.\",\n \"enum\": [\n \"password\",\n \"passkey\",\n \"oauth-tokens\",\n \"did-self-issued\",\n \"didcomm-peer\",\n \"bearer-token\",\n \"ssh-key\",\n \"custom\"\n ],\n \"title\": \"SecretKind\",\n \"type\": \"string\"\n },\n \"SiteTarget\": {\n \"description\": \"A single binding target for a vault entry. Tagged union over the discriminator `kind`. A VaultEntry's `targets` array MAY mix any number of these.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"web-origin\"\n },\n \"origin\": {\n \"description\": \"Web origin per RFC 6454 (scheme + host + optional port), e.g. \\\"https://github.com\\\". Compared by exact string equality after canonicalisation (lowercase host, default port elided). Consumers wanting subdomain coverage SHOULD add multiple targets, not encode a wildcard.\",\n \"format\": \"uri\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"origin\"\n ],\n \"title\": \"WebOrigin\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"did\": {\n \"description\": \"DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"did\"\n }\n },\n \"required\": [\n \"kind\",\n \"did\"\n ],\n \"title\": \"Did\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"bundleId\": {\n \"description\": \"iOS bundle identifier in reverse-DNS form (e.g. \\\"com.github.stwalkerster.codehub\\\"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).\",\n \"minLength\": 1,\n \"pattern\": \"^[A-Za-z0-9.-]+$\",\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"ios-app\"\n },\n \"teamId\": {\n \"description\": \"Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.\",\n \"minLength\": 1,\n \"pattern\": \"^[A-Z0-9]+$\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"bundleId\"\n ],\n \"title\": \"IosApp\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"android-app\"\n },\n \"packageName\": {\n \"description\": \"Android package name in reverse-DNS form (e.g. \\\"com.github.android\\\").\",\n \"minLength\": 1,\n \"pattern\": \"^[A-Za-z][A-Za-z0-9_]*(\\\\.[A-Za-z][A-Za-z0-9_]*)+$\",\n \"type\": \"string\"\n },\n \"sha256CertFingerprints\": {\n \"description\": \"SHA-256 fingerprints of the app's signing certificates, in colon-separated hex (the format `apksigner` and the Play Console emit). At least one fingerprint MUST be present. The maintainer matches when ANY of the provided fingerprints matches the requesting app's signature — this supports apps signed by multiple keys (e.g. during certificate rotation via Play App Signing).\",\n \"items\": {\n \"pattern\": \"^[0-9A-F]{2}(:[0-9A-F]{2}){31}$\",\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"type\": \"array\",\n \"uniqueItems\": true\n }\n },\n \"required\": [\n \"kind\",\n \"packageName\",\n \"sha256CertFingerprints\"\n ],\n \"title\": \"AndroidApp\",\n \"type\": \"object\"\n }\n ],\n \"title\": \"SiteTarget\"\n },\n \"VaultEntry\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"attachments\": {\n \"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.\",\n \"items\": {\n \"$ref\": \"#/$defs/AttachmentRef\"\n },\n \"type\": \"array\"\n },\n \"breachedAt\": {\n \"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.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"contextId\": {\n \"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.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"createdBy\": {\n \"description\": \"VID of the consumer that originally created the entry.\",\n \"type\": \"string\"\n },\n \"customFieldNames\": {\n \"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.\",\n \"items\": {\n \"maxLength\": 128,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"type\": \"array\",\n \"uniqueItems\": true\n },\n \"expiresAt\": {\n \"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.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces.\"\n },\n \"favicon\": {\n \"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.\",\n \"format\": \"uri\",\n \"type\": \"string\"\n },\n \"id\": {\n \"description\": \"Opaque vault-maintainer-assigned identifier for the entry. ULID/UUID/base32 are common; the wire spec only requires non-empty string equality.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"label\": {\n \"description\": \"Human-readable display name (e.g. \\\"Work GitHub\\\", \\\"Personal bank — checking\\\"). Maintainers MAY enforce a maximum length; the wire spec does not.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"lastUsedAt\": {\n \"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.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"notes\": {\n \"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.\",\n \"maxLength\": 4096,\n \"type\": \"string\"\n },\n \"passwordChangedAt\": {\n \"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.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"principalDid\": {\n \"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 (`did-self-issued`, `didcomm-peer`). Absent for kinds that have no DID concept (`password`, `passkey`, `oauth-tokens`, `bearer-token`, `ssh-key`, `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.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"secretKind\": {\n \"$ref\": \"#/$defs/SecretKind\",\n \"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.\"\n },\n \"selectors\": {\n \"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.\",\n \"items\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"type\": \"array\",\n \"uniqueItems\": true\n },\n \"tags\": {\n \"description\": \"User-defined tags for organisation and filtering (e.g. [\\\"family\\\", \\\"finance\\\"]). Maintainers MAY enforce a maximum count; the wire spec does not.\",\n \"items\": {\n \"maxLength\": 64,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"type\": \"array\",\n \"uniqueItems\": true\n },\n \"targets\": {\n \"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).\",\n \"items\": {\n \"$ref\": \"#/$defs/SiteTarget\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"updatedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"updatedBy\": {\n \"description\": \"VID of the consumer that last modified the entry.\",\n \"type\": \"string\"\n },\n \"version\": {\n \"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.\",\n \"minimum\": 0,\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"id\",\n \"contextId\",\n \"targets\",\n \"label\",\n \"secretKind\",\n \"createdAt\",\n \"updatedAt\",\n \"version\"\n ],\n \"title\": \"VaultEntry\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/vault/get/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"Fetch the metadata view of a single vault entry by id. Returns the same VaultEntry shape vault/list does, but for one specific entry. Secret material is NEVER returned by this task; use vault/release/0.1 to obtain secret bytes.\",\n \"properties\": {\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"id\": {\n \"description\": \"Vault entry id (as returned in a prior vault/list or vault/sync response).\",\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\"\n ],\n \"title\": \"Vault Get — payload\",\n \"type\": \"object\"\n}\n";
}