//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `persona/profile/get`. Version: `1.0`.
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
/// Error types.
pub mod error {
/// Error from a `TryFrom` or `FromStr` implementation.
pub struct ConversionError(::std::borrow::Cow<'static, str>);
impl ::std::error::Error for ConversionError {}
impl ::std::fmt::Display for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Display::fmt(&self.0, f)
}
}
impl ::std::fmt::Debug for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Debug::fmt(&self.0, f)
}
}
impl From<&'static str> for ConversionError {
fn from(value: &'static str) -> Self {
Self(value.into())
}
}
impl From<String> for ConversionError {
fn from(value: String) -> Self {
Self(value.into())
}
}
}
/**
The vocabulary token naming what a value IS — `name.legal`, `phone.mobile`, `address.postal`, `person.birthDate`. Dotted, most-general segment first, so that a consumer with no knowledge of the specific token can still group by its prefix.
The token is the maintainer's own; no external vocabulary is primary. External vocabularies (vCard/jCard, OIDC standard claims, schema.org) are mappings applied at PRESENTATION by a renderer, not at rest, so that a query written in any of them can be matched without the store having to live inside any one of them.
The `x:` prefix is an open extension namespace and is not decoration. The closest prior art — Windows CardSpace's self-issued card — supported exactly fifteen predefined claim types with no extensibility, and that is the specific way it failed the requirement a holder actually has. An `x:` attribute stores, composes, binds and discloses exactly like a known one; it renders generically and matches only an explicit query.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ClaimType",
/// "description": "\nThe vocabulary token naming what a value IS — `name.legal`, `phone.mobile`, `address.postal`, `person.birthDate`. Dotted, most-general segment first, so that a consumer with no knowledge of the specific token can still group by its prefix.\n\nThe token is the maintainer's own; no external vocabulary is primary. External vocabularies (vCard/jCard, OIDC standard claims, schema.org) are mappings applied at PRESENTATION by a renderer, not at rest, so that a query written in any of them can be matched without the store having to live inside any one of them.\n\nThe `x:` prefix is an open extension namespace and is not decoration. The closest prior art — Windows CardSpace's self-issued card — supported exactly fifteen predefined claim types with no extensibility, and that is the specific way it failed the requirement a holder actually has. An `x:` attribute stores, composes, binds and discloses exactly like a known one; it renders generically and matches only an explicit query.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1,
/// "pattern": "^(x:)?[a-z][a-zA-Z0-9]*(\\.[a-z][a-zA-Z0-9]*)*$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ClaimType(::std::string::String);
impl ::std::ops::Deref for ClaimType {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ClaimType> for ::std::string::String {
fn from(value: ClaimType) -> Self {
value.0
}
}
impl ::std::str::FromStr for ClaimType {
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());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^(x:)?[a-z][a-zA-Z0-9]*(\\.[a-z][a-zA-Z0-9]*)*$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err(
"doesn't match pattern \"^(x:)?[a-z][a-zA-Z0-9]*(\\.[a-z][a-zA-Z0-9]*)*$\"".into(),
);
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ClaimType {
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 ClaimType {
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 ClaimType {
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 ClaimType {
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<::std::collections::HashMap<ExtKey, ::serde_json::Value>> for Ext {
fn from(value: ::std::collections::HashMap<ExtKey, ::serde_json::Value>) -> Self {
Self(value)
}
}
///`ExtKey`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "pattern": "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ExtKey(::std::string::String);
impl ::std::ops::Deref for ExtKey {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ExtKey> for ::std::string::String {
fn from(value: ExtKey) -> Self {
value.0
}
}
impl ::std::str::FromStr for ExtKey {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for ExtKey {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
/**
Where a pool face may be worn. `anywhere` is the default and what an absent member means. `only` names the contexts it may be worn in, and a maintainer MUST refuse to wear it in any other (persona/binding/set `outsideReach`).
A tagged object rather than a bare list of contexts, deliberately: an empty list has been read as both 'unrestricted' and 'nowhere' in this family's neighbours, and a shape where the two cannot be confused is worth more than one where they must be remembered. So `only` requires at least one context, and 'nowhere' is not a reach — it is a retired face.
A context-local face has no reach: it lives in its context and is worn there by construction.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "FaceReach",
/// "description": "\nWhere a pool face may be worn. `anywhere` is the default and what an absent member means. `only` names the contexts it may be worn in, and a maintainer MUST refuse to wear it in any other (persona/binding/set `outsideReach`).\n\nA tagged object rather than a bare list of contexts, deliberately: an empty list has been read as both 'unrestricted' and 'nowhere' in this family's neighbours, and a shape where the two cannot be confused is worth more than one where they must be remembered. So `only` requires at least one context, and 'nowhere' is not a reach — it is a retired face.\n\nA context-local face has no reach: it lives in its context and is worn there by construction.",
/// "oneOf": [
/// {
/// "type": "object",
/// "required": [
/// "kind"
/// ],
/// "properties": {
/// "kind": {
/// "const": "anywhere"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "type": "object",
/// "required": [
/// "contextIds",
/// "kind"
/// ],
/// "properties": {
/// "contextIds": {
/// "type": "array",
/// "items": {
/// "type": "string",
/// "minLength": 1
/// },
/// "maxItems": 256,
/// "minItems": 1,
/// "uniqueItems": true
/// },
/// "kind": {
/// "const": "only"
/// }
/// },
/// "additionalProperties": false
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(tag = "kind", content = "contextIds")]
#[non_exhaustive]
pub enum FaceReach {
#[serde(rename = "anywhere")]
Anywhere,
#[serde(rename = "only")]
Only(Vec<FaceReachContextIdsItem>),
}
impl ::std::convert::From<Vec<FaceReachContextIdsItem>> for FaceReach {
fn from(value: Vec<FaceReachContextIdsItem>) -> Self {
Self::Only(value)
}
}
///`FaceReachContextIdsItem`
///
/// <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 FaceReachContextIdsItem(::std::string::String);
impl ::std::ops::Deref for FaceReachContextIdsItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<FaceReachContextIdsItem> for ::std::string::String {
fn from(value: FaceReachContextIdsItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for FaceReachContextIdsItem {
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 FaceReachContextIdsItem {
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 FaceReachContextIdsItem {
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 FaceReachContextIdsItem {
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 FaceReachContextIdsItem {
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())
})
}
}
///Read one profile, either as composed (the entries the holder wrote) or as resolved (the claims it would actually present).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/persona/profile/get/1.0",
/// "title": "Payload",
/// "description": "Read one profile, either as composed (the entries the holder wrote) or as resolved (the claims it would actually present).",
/// "type": "object",
/// "required": [
/// "profileId"
/// ],
/// "properties": {
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "profileId": {
/// "$ref": "#/definitions/Ulid"
/// },
/// "resolve": {
/// "description": "When false (the default) the profile is returned as composed — entries as written, references unresolved. When true the maintainer resolves every entry against the pool and returns the claims the profile would present, which is what a preview renders and what a holder is really asking when they ask what a profile says. The default is the cheap, non-disclosing one.",
/// "default": false,
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Payload {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
#[serde(rename = "profileId")]
pub profile_id: Ulid,
///When false (the default) the profile is returned as composed — entries as written, references unresolved. When true the maintainer resolves every entry against the pool and returns the claims the profile would present, which is what a preview renders and what a holder is really asking when they ask what a profile says. The default is the cheap, non-disclosing one.
#[serde(default)]
pub resolve: bool,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///A named projection over the pool. Agent-scoped, like the pool it draws from. `entries` is ordered and the order is display order.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Profile",
/// "description": "A named projection over the pool. Agent-scoped, like the pool it draws from. `entries` is ordered and the order is display order.",
/// "type": "object",
/// "required": [
/// "entries",
/// "name",
/// "profileId",
/// "updatedAt",
/// "version"
/// ],
/// "properties": {
/// "createdAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "credentialRefs": {
/// "description": "Vault identifiers of credentials associated with this profile as INVENTORY, distinct from the evidence relationship a `credentialBacked` attribute expresses. The two answer different questions — what can this persona prove, versus what backs this specific claim — and a consumer MUST NOT read one as the other.",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "minLength": 1
/// },
/// "maxItems": 256
/// },
/// "entries": {
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/ProfileEntry"
/// },
/// "maxItems": 256
/// },
/// "name": {
/// "description": "The holder's name for this profile — \"Work\", \"Gaming\". Not disclosed.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1
/// },
/// "profileId": {
/// "$ref": "#/definitions/Ulid"
/// },
/// "reach": {
/// "$ref": "#/definitions/FaceReach"
/// },
/// "retiredAt": {
/// "description": "When the face was retired. Present exactly when `status` is `retired`.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "status": {
/// "description": "`retired`: the face is worn nowhere, is left out of pickers and default listings, and cannot be worn until reinstated (persona/profile/retire, persona/profile/reinstate). Its disclosure history and every value it carries are kept — retiring is 'stop being this', not 'forget this'. Absent reads as `active`.",
/// "default": "active",
/// "type": "string",
/// "enum": [
/// "active",
/// "retired"
/// ]
/// },
/// "updatedAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "version": {
/// "$ref": "#/definitions/Version"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Profile {
#[serde(
rename = "createdAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub created_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///Vault identifiers of credentials associated with this profile as INVENTORY, distinct from the evidence relationship a `credentialBacked` attribute expresses. The two answer different questions — what can this persona prove, versus what backs this specific claim — and a consumer MUST NOT read one as the other.
#[serde(
rename = "credentialRefs",
default,
skip_serializing_if = "::std::vec::Vec::is_empty"
)]
pub credential_refs: ::std::vec::Vec<ProfileCredentialRefsItem>,
pub entries: ::std::vec::Vec<ProfileEntry>,
///The holder's name for this profile — "Work", "Gaming". Not disclosed.
pub name: ProfileName,
#[serde(rename = "profileId")]
pub profile_id: Ulid,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reach: ::std::option::Option<FaceReach>,
///When the face was retired. Present exactly when `status` is `retired`.
#[serde(
rename = "retiredAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub retired_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///`retired`: the face is worn nowhere, is left out of pickers and default listings, and cannot be worn until reinstated (persona/profile/retire, persona/profile/reinstate). Its disclosure history and every value it carries are kept — retiring is 'stop being this', not 'forget this'. Absent reads as `active`.
#[serde(default = "defaults::profile_status")]
pub status: ProfileStatus,
#[serde(rename = "updatedAt")]
pub updated_at: ::chrono::DateTime<::chrono::offset::Utc>,
pub version: Version,
}
impl Profile {
pub fn builder() -> builder::Profile {
Default::default()
}
}
///`ProfileCredentialRefsItem`
///
/// <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 ProfileCredentialRefsItem(::std::string::String);
impl ::std::ops::Deref for ProfileCredentialRefsItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProfileCredentialRefsItem> for ::std::string::String {
fn from(value: ProfileCredentialRefsItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProfileCredentialRefsItem {
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 ProfileCredentialRefsItem {
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 ProfileCredentialRefsItem {
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 ProfileCredentialRefsItem {
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 ProfileCredentialRefsItem {
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())
})
}
}
/**
One line of a profile, in exactly one of four forms. Together they are the whole of a profile's flexibility, and each exists for a case the others handle badly.
`{ref}` — use the pool attribute, live. Editing the pool updates every profile that references it, which is the point.
`{ref, pinVersion}` — use the value as it was at that version. For a profile that must keep presenting the value a counterparty already verified.
`{ref, override}` — the same fact, a different value here. ("In the gaming profile my display name is different.")
`{inline}` — a value that never enters the pool, and so never leaks into another profile.
Omission is exclusion; there is no removal marker.
Any form MAY carry a `slot` naming the role the entry plays in the profile — see `Slot`. A maintainer MUST refuse a profile in which two entries carry the same slot: a slot exists to answer one question with one entry.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ProfileEntry",
/// "description": "\nOne line of a profile, in exactly one of four forms. Together they are the whole of a profile's flexibility, and each exists for a case the others handle badly.\n\n`{ref}` — use the pool attribute, live. Editing the pool updates every profile that references it, which is the point.\n\n`{ref, pinVersion}` — use the value as it was at that version. For a profile that must keep presenting the value a counterparty already verified.\n\n`{ref, override}` — the same fact, a different value here. (\"In the gaming profile my display name is different.\")\n\n`{inline}` — a value that never enters the pool, and so never leaks into another profile.\n\nOmission is exclusion; there is no removal marker.\n\nAny form MAY carry a `slot` naming the role the entry plays in the profile — see `Slot`. A maintainer MUST refuse a profile in which two entries carry the same slot: a slot exists to answer one question with one entry.",
/// "type": "object",
/// "oneOf": [
/// {
/// "required": [
/// "ref"
/// ],
/// "properties": {
/// "ref": {
/// "$ref": "#/definitions/Ulid"
/// },
/// "slot": {
/// "$ref": "#/definitions/Slot"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "required": [
/// "pinVersion",
/// "ref"
/// ],
/// "properties": {
/// "pinVersion": {
/// "$ref": "#/definitions/Version"
/// },
/// "ref": {
/// "$ref": "#/definitions/Ulid"
/// },
/// "slot": {
/// "$ref": "#/definitions/Slot"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "required": [
/// "override",
/// "ref"
/// ],
/// "properties": {
/// "override": {
/// "description": "Replaces the pool attribute's value for this profile only. `type`, `valueType` and `provenance` are inherited from the referenced attribute and MUST NOT be overridden — an override that changed provenance would let a self-asserted value present as attested.",
/// "type": "object",
/// "required": [
/// "value"
/// ],
/// "properties": {
/// "label": {
/// "type": "string",
/// "maxLength": 128
/// },
/// "value": {}
/// },
/// "additionalProperties": false
/// },
/// "ref": {
/// "$ref": "#/definitions/Ulid"
/// },
/// "slot": {
/// "$ref": "#/definitions/Slot"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "required": [
/// "inline"
/// ],
/// "properties": {
/// "inline": {
/// "type": "object",
/// "required": [
/// "provenance",
/// "type",
/// "value",
/// "valueType"
/// ],
/// "properties": {
/// "label": {
/// "type": "string",
/// "maxLength": 128
/// },
/// "provenance": {
/// "$ref": "#/definitions/Provenance"
/// },
/// "type": {
/// "$ref": "#/definitions/ClaimType"
/// },
/// "value": {},
/// "valueType": {
/// "$ref": "#/definitions/ValueType"
/// }
/// },
/// "additionalProperties": false
/// },
/// "slot": {
/// "$ref": "#/definitions/Slot"
/// }
/// },
/// "additionalProperties": false
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged, deny_unknown_fields)]
#[non_exhaustive]
pub enum ProfileEntry {
Variant0 {
#[serde(rename = "ref")]
ref_: Ulid,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
slot: ::std::option::Option<Slot>,
},
Variant1 {
#[serde(rename = "pinVersion")]
pin_version: Version,
#[serde(rename = "ref")]
ref_: Ulid,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
slot: ::std::option::Option<Slot>,
},
Variant2 {
#[serde(rename = "override")]
override_: ProfileEntryVariant2Override,
#[serde(rename = "ref")]
ref_: Ulid,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
slot: ::std::option::Option<Slot>,
},
Variant3 {
inline: ProfileEntryVariant3Inline,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
slot: ::std::option::Option<Slot>,
},
}
///Replaces the pool attribute's value for this profile only. `type`, `valueType` and `provenance` are inherited from the referenced attribute and MUST NOT be overridden — an override that changed provenance would let a self-asserted value present as attested.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Replaces the pool attribute's value for this profile only. `type`, `valueType` and `provenance` are inherited from the referenced attribute and MUST NOT be overridden — an override that changed provenance would let a self-asserted value present as attested.",
/// "type": "object",
/// "required": [
/// "value"
/// ],
/// "properties": {
/// "label": {
/// "type": "string",
/// "maxLength": 128
/// },
/// "value": {}
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct ProfileEntryVariant2Override {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub label: ::std::option::Option<ProfileEntryVariant2OverrideLabel>,
pub value: ::serde_json::Value,
}
impl ProfileEntryVariant2Override {
pub fn builder() -> builder::ProfileEntryVariant2Override {
Default::default()
}
}
///`ProfileEntryVariant2OverrideLabel`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 128
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ProfileEntryVariant2OverrideLabel(::std::string::String);
impl ::std::ops::Deref for ProfileEntryVariant2OverrideLabel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProfileEntryVariant2OverrideLabel> for ::std::string::String {
fn from(value: ProfileEntryVariant2OverrideLabel) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProfileEntryVariant2OverrideLabel {
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());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ProfileEntryVariant2OverrideLabel {
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 ProfileEntryVariant2OverrideLabel {
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 ProfileEntryVariant2OverrideLabel {
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 ProfileEntryVariant2OverrideLabel {
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())
})
}
}
///`ProfileEntryVariant3Inline`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "provenance",
/// "type",
/// "value",
/// "valueType"
/// ],
/// "properties": {
/// "label": {
/// "type": "string",
/// "maxLength": 128
/// },
/// "provenance": {
/// "$ref": "#/definitions/Provenance"
/// },
/// "type": {
/// "$ref": "#/definitions/ClaimType"
/// },
/// "value": {},
/// "valueType": {
/// "$ref": "#/definitions/ValueType"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct ProfileEntryVariant3Inline {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub label: ::std::option::Option<ProfileEntryVariant3InlineLabel>,
pub provenance: Provenance,
#[serde(rename = "type")]
pub type_: ClaimType,
pub value: ::serde_json::Value,
#[serde(rename = "valueType")]
pub value_type: ValueType,
}
impl ProfileEntryVariant3Inline {
pub fn builder() -> builder::ProfileEntryVariant3Inline {
Default::default()
}
}
///`ProfileEntryVariant3InlineLabel`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 128
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ProfileEntryVariant3InlineLabel(::std::string::String);
impl ::std::ops::Deref for ProfileEntryVariant3InlineLabel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProfileEntryVariant3InlineLabel> for ::std::string::String {
fn from(value: ProfileEntryVariant3InlineLabel) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProfileEntryVariant3InlineLabel {
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());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ProfileEntryVariant3InlineLabel {
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 ProfileEntryVariant3InlineLabel {
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 ProfileEntryVariant3InlineLabel {
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 ProfileEntryVariant3InlineLabel {
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())
})
}
}
///The holder's name for this profile — "Work", "Gaming". Not disclosed.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The holder's name for this profile — \"Work\", \"Gaming\". Not disclosed.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ProfileName(::std::string::String);
impl ::std::ops::Deref for ProfileName {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProfileName> for ::std::string::String {
fn from(value: ProfileName) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProfileName {
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 ProfileName {
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 ProfileName {
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 ProfileName {
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 ProfileName {
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())
})
}
}
///`retired`: the face is worn nowhere, is left out of pickers and default listings, and cannot be worn until reinstated (persona/profile/retire, persona/profile/reinstate). Its disclosure history and every value it carries are kept — retiring is 'stop being this', not 'forget this'. Absent reads as `active`.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "`retired`: the face is worn nowhere, is left out of pickers and default listings, and cannot be worn until reinstated (persona/profile/retire, persona/profile/reinstate). Its disclosure history and every value it carries are kept — retiring is 'stop being this', not 'forget this'. Absent reads as `active`.",
/// "default": "active",
/// "type": "string",
/// "enum": [
/// "active",
/// "retired"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ProfileStatus {
#[serde(rename = "active")]
Active,
#[serde(rename = "retired")]
Retired,
}
impl ::std::fmt::Display for ProfileStatus {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Active => f.write_str("active"),
Self::Retired => f.write_str("retired"),
}
}
}
impl ::std::str::FromStr for ProfileStatus {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"active" => Ok(Self::Active),
"retired" => Ok(Self::Retired),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ProfileStatus {
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 ProfileStatus {
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 ProfileStatus {
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 ProfileStatus {
fn default() -> Self {
ProfileStatus::Active
}
}
/**
How strongly a credential-backed claim is hidden when presented, ordered most private first. `predicate` proves a statement over a claim without disclosing the claim. `derived` discloses exactly the claims needed via an unlinkable derived proof, so two presentations cannot be joined. `selectiveDisclosure` discloses exactly the claims needed but carries the issuer's signature unchanged, so two presentations ARE linkable. `whole` discloses the entire credential.
The distinction between the first two and the last two is of kind, not degree: only `predicate` and `derived` avoid handing two verifiers a join key. A maintainer MUST default to the highest rung the credential's format supports, and MUST NOT silently fall to a lower one — a request that cannot be satisfied at the rung a producer asked for is refused, because a silent privacy downgrade discloses material the holder believed was hidden.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ProofRung",
/// "description": "\nHow strongly a credential-backed claim is hidden when presented, ordered most private first. `predicate` proves a statement over a claim without disclosing the claim. `derived` discloses exactly the claims needed via an unlinkable derived proof, so two presentations cannot be joined. `selectiveDisclosure` discloses exactly the claims needed but carries the issuer's signature unchanged, so two presentations ARE linkable. `whole` discloses the entire credential.\n\nThe distinction between the first two and the last two is of kind, not degree: only `predicate` and `derived` avoid handing two verifiers a join key. A maintainer MUST default to the highest rung the credential's format supports, and MUST NOT silently fall to a lower one — a request that cannot be satisfied at the rung a producer asked for is refused, because a silent privacy downgrade discloses material the holder believed was hidden.",
/// "type": "string",
/// "enum": [
/// "predicate",
/// "derived",
/// "selectiveDisclosure",
/// "whole"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ProofRung {
#[serde(rename = "predicate")]
Predicate,
#[serde(rename = "derived")]
Derived,
#[serde(rename = "selectiveDisclosure")]
SelectiveDisclosure,
#[serde(rename = "whole")]
Whole,
}
impl ::std::fmt::Display for ProofRung {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Predicate => f.write_str("predicate"),
Self::Derived => f.write_str("derived"),
Self::SelectiveDisclosure => f.write_str("selectiveDisclosure"),
Self::Whole => f.write_str("whole"),
}
}
}
impl ::std::str::FromStr for ProofRung {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"predicate" => Ok(Self::Predicate),
"derived" => Ok(Self::Derived),
"selectiveDisclosure" => Ok(Self::SelectiveDisclosure),
"whole" => Ok(Self::Whole),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ProofRung {
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 ProofRung {
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 ProofRung {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
/**
Where a value comes from, and the member that makes this family worth building on a trust stack rather than in an address book. It survives to the verifier, so a recipient can tell — per field — what the holder typed from what an issuer attested.
`selfAsserted` — the holder supplied it.
`credentialBacked` — the value is derived from a credential in the vault at `claimPath`. The stored value is a CACHE FOR DISPLAY; the credential is the truth. A maintainer MUST re-derive it on read and MUST fail closed (never presenting a stale value) when the credential has been revoked, has expired, or has been archived or deleted.
`generated` — the value is minted per verifier at disclosure time and recorded against that verifier, so every relying party receives a different one that routes back to the holder. This is the shape of the most widely adopted consumer privacy feature in this space; a maintainer need not operate a relay to conform, but the shape must exist, because retrofitting per-verifier values into a pool-of-values model is a migration rather than an addition.
`derived` — the value was taken from a source the holder connected or supplied — a code-hosting profile, an uploaded CV — rather than typed by them or attested by an issuer. Nobody signed it: it is the holder's claim that the source said so, and a consumer MUST NOT present it as attested. It exists as its own kind because a derived value is neither of the others — the holder did not author it, and no one vouches for it — and a holder deciding whether to disclose deserves to know which of their values they typed.
For how strongly a disclosed value identifies the holder, the kinds rank `credentialBacked` above `derived` above `selfAsserted`; `generated` values are per-verifier and do not correlate.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Provenance",
/// "description": "\nWhere a value comes from, and the member that makes this family worth building on a trust stack rather than in an address book. It survives to the verifier, so a recipient can tell — per field — what the holder typed from what an issuer attested.\n\n`selfAsserted` — the holder supplied it.\n\n`credentialBacked` — the value is derived from a credential in the vault at `claimPath`. The stored value is a CACHE FOR DISPLAY; the credential is the truth. A maintainer MUST re-derive it on read and MUST fail closed (never presenting a stale value) when the credential has been revoked, has expired, or has been archived or deleted.\n\n`generated` — the value is minted per verifier at disclosure time and recorded against that verifier, so every relying party receives a different one that routes back to the holder. This is the shape of the most widely adopted consumer privacy feature in this space; a maintainer need not operate a relay to conform, but the shape must exist, because retrofitting per-verifier values into a pool-of-values model is a migration rather than an addition.\n\n`derived` — the value was taken from a source the holder connected or supplied — a code-hosting profile, an uploaded CV — rather than typed by them or attested by an issuer. Nobody signed it: it is the holder's claim that the source said so, and a consumer MUST NOT present it as attested. It exists as its own kind because a derived value is neither of the others — the holder did not author it, and no one vouches for it — and a holder deciding whether to disclose deserves to know which of their values they typed.\n\nFor how strongly a disclosed value identifies the holder, the kinds rank `credentialBacked` above `derived` above `selfAsserted`; `generated` values are per-verifier and do not correlate.",
/// "type": "object",
/// "oneOf": [
/// {
/// "required": [
/// "kind"
/// ],
/// "properties": {
/// "kind": {
/// "const": "selfAsserted"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "required": [
/// "claimPath",
/// "credentialId",
/// "kind"
/// ],
/// "properties": {
/// "claimPath": {
/// "description": "RFC 6901 JSON Pointer to the claim within the credential, e.g. `/credentialSubject/familyName`.",
/// "type": "string",
/// "pattern": "^(/[^/~]*(~[01][^/~]*)*)*$"
/// },
/// "credentialId": {
/// "description": "Vault identifier of the backing credential.",
/// "type": "string",
/// "minLength": 1
/// },
/// "issuerDid": {
/// "description": "Issuer of the backing credential. Advisory: a consumer MUST verify the credential rather than trusting this member.",
/// "type": "string",
/// "minLength": 1
/// },
/// "kind": {
/// "const": "credentialBacked"
/// },
/// "proof": {
/// "description": "The disclosure rung this claim was, or will be, presented at.",
/// "$ref": "#/definitions/ProofRung"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "required": [
/// "generator",
/// "kind"
/// ],
/// "properties": {
/// "generator": {
/// "description": "Names the minting scheme, e.g. `relayEmail`. Maintainer-defined.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
/// },
/// "kind": {
/// "const": "generated"
/// },
/// "perVerifier": {
/// "description": "When true (the default and the only useful setting), a distinct value is minted for each verifier.",
/// "default": true,
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "required": [
/// "derivedAt",
/// "kind",
/// "source"
/// ],
/// "properties": {
/// "derivedAt": {
/// "description": "When the value was taken from the source. A derived value is a snapshot: the source may have changed since, and nothing re-derives it.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "kind": {
/// "const": "derived"
/// },
/// "source": {
/// "description": "The KIND of source the value was taken from — `github`, `cvUpload`, `linkedIn` — never an account, handle or URL. Provenance survives to the verifier, so this member is disclosed with the claim; a handle here would disclose an identifier the holder never chose to share.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1,
/// "pattern": "^[a-z][A-Za-z0-9.-]*$"
/// }
/// },
/// "additionalProperties": false
/// }
/// ],
/// "required": [
/// "kind"
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged, deny_unknown_fields)]
#[non_exhaustive]
pub enum Provenance {
Variant0 {
kind: ::serde_json::Value,
},
Variant1 {
///RFC 6901 JSON Pointer to the claim within the credential, e.g. `/credentialSubject/familyName`.
#[serde(rename = "claimPath")]
claim_path: ProvenanceVariant1ClaimPath,
///Vault identifier of the backing credential.
#[serde(rename = "credentialId")]
credential_id: ProvenanceVariant1CredentialId,
///Issuer of the backing credential. Advisory: a consumer MUST verify the credential rather than trusting this member.
#[serde(
rename = "issuerDid",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
issuer_did: ::std::option::Option<ProvenanceVariant1IssuerDid>,
kind: ::serde_json::Value,
///The disclosure rung this claim was, or will be, presented at.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
proof: ::std::option::Option<ProofRung>,
},
Variant2 {
///Names the minting scheme, e.g. `relayEmail`. Maintainer-defined.
generator: ProvenanceVariant2Generator,
kind: ::serde_json::Value,
///When true (the default and the only useful setting), a distinct value is minted for each verifier.
#[serde(rename = "perVerifier", default = "defaults::default_bool::<true>")]
per_verifier: bool,
},
Variant3 {
///When the value was taken from the source. A derived value is a snapshot: the source may have changed since, and nothing re-derives it.
#[serde(rename = "derivedAt")]
derived_at: ::chrono::DateTime<::chrono::offset::Utc>,
kind: ::serde_json::Value,
///The KIND of source the value was taken from — `github`, `cvUpload`, `linkedIn` — never an account, handle or URL. Provenance survives to the verifier, so this member is disclosed with the claim; a handle here would disclose an identifier the holder never chose to share.
source: ProvenanceVariant3Source,
},
}
///RFC 6901 JSON Pointer to the claim within the credential, e.g. `/credentialSubject/familyName`.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "RFC 6901 JSON Pointer to the claim within the credential, e.g. `/credentialSubject/familyName`.",
/// "type": "string",
/// "pattern": "^(/[^/~]*(~[01][^/~]*)*)*$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ProvenanceVariant1ClaimPath(::std::string::String);
impl ::std::ops::Deref for ProvenanceVariant1ClaimPath {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProvenanceVariant1ClaimPath> for ::std::string::String {
fn from(value: ProvenanceVariant1ClaimPath) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProvenanceVariant1ClaimPath {
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("^(/[^/~]*(~[01][^/~]*)*)*$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^(/[^/~]*(~[01][^/~]*)*)*$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ProvenanceVariant1ClaimPath {
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 ProvenanceVariant1ClaimPath {
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 ProvenanceVariant1ClaimPath {
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 ProvenanceVariant1ClaimPath {
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())
})
}
}
///Vault identifier of the backing credential.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Vault identifier of the backing credential.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ProvenanceVariant1CredentialId(::std::string::String);
impl ::std::ops::Deref for ProvenanceVariant1CredentialId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProvenanceVariant1CredentialId> for ::std::string::String {
fn from(value: ProvenanceVariant1CredentialId) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProvenanceVariant1CredentialId {
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 ProvenanceVariant1CredentialId {
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 ProvenanceVariant1CredentialId {
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 ProvenanceVariant1CredentialId {
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 ProvenanceVariant1CredentialId {
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())
})
}
}
///Issuer of the backing credential. Advisory: a consumer MUST verify the credential rather than trusting this member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Issuer of the backing credential. Advisory: a consumer MUST verify the credential rather than trusting this member.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ProvenanceVariant1IssuerDid(::std::string::String);
impl ::std::ops::Deref for ProvenanceVariant1IssuerDid {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProvenanceVariant1IssuerDid> for ::std::string::String {
fn from(value: ProvenanceVariant1IssuerDid) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProvenanceVariant1IssuerDid {
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 ProvenanceVariant1IssuerDid {
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 ProvenanceVariant1IssuerDid {
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 ProvenanceVariant1IssuerDid {
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 ProvenanceVariant1IssuerDid {
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())
})
}
}
///Names the minting scheme, e.g. `relayEmail`. Maintainer-defined.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Names the minting scheme, e.g. `relayEmail`. Maintainer-defined.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ProvenanceVariant2Generator(::std::string::String);
impl ::std::ops::Deref for ProvenanceVariant2Generator {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProvenanceVariant2Generator> for ::std::string::String {
fn from(value: ProvenanceVariant2Generator) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProvenanceVariant2Generator {
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 ProvenanceVariant2Generator {
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 ProvenanceVariant2Generator {
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 ProvenanceVariant2Generator {
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 ProvenanceVariant2Generator {
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())
})
}
}
///The KIND of source the value was taken from — `github`, `cvUpload`, `linkedIn` — never an account, handle or URL. Provenance survives to the verifier, so this member is disclosed with the claim; a handle here would disclose an identifier the holder never chose to share.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The KIND of source the value was taken from — `github`, `cvUpload`, `linkedIn` — never an account, handle or URL. Provenance survives to the verifier, so this member is disclosed with the claim; a handle here would disclose an identifier the holder never chose to share.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1,
/// "pattern": "^[a-z][A-Za-z0-9.-]*$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ProvenanceVariant3Source(::std::string::String);
impl ::std::ops::Deref for ProvenanceVariant3Source {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProvenanceVariant3Source> for ::std::string::String {
fn from(value: ProvenanceVariant3Source) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProvenanceVariant3Source {
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());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[a-z][A-Za-z0-9.-]*$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z][A-Za-z0-9.-]*$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ProvenanceVariant3Source {
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 ProvenanceVariant3Source {
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 ProvenanceVariant3Source {
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 ProvenanceVariant3Source {
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())
})
}
}
/**
One line of a profile AFTER resolution: what the profile would present at this entry, rather than how the entry is written.
Distinct from `Attribute` because a profile is a PROJECTION and may contain values that have no pool record behind them. An `inline` entry is a value the holder keeps in one profile and nowhere else — it has no `attributeId`, no `version` and no `updatedAt`, because there is no pool attribute to have them. Describing a resolved profile with the pool record's shape therefore cannot represent one at all, which leaves a maintainer choosing between synthesising an `attributeId` — a false claim about where a value lives — and omitting the entry, which returns a profile that appears to present less than it does. Neither is acceptable, so the projection gets its own shape.
The three pool members are consequently OPTIONAL and their absence is meaningful: it says this value is inline. Their PRESENCE is equally informative — `version` alongside a pinned entry is what lets a holder see that a profile is frozen at v3 while the pool has moved on.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ResolvedClaim",
/// "description": "\nOne line of a profile AFTER resolution: what the profile would present at this entry, rather than how the entry is written.\n\nDistinct from `Attribute` because a profile is a PROJECTION and may contain values that have no pool record behind them. An `inline` entry is a value the holder keeps in one profile and nowhere else — it has no `attributeId`, no `version` and no `updatedAt`, because there is no pool attribute to have them. Describing a resolved profile with the pool record's shape therefore cannot represent one at all, which leaves a maintainer choosing between synthesising an `attributeId` — a false claim about where a value lives — and omitting the entry, which returns a profile that appears to present less than it does. Neither is acceptable, so the projection gets its own shape.\n\nThe three pool members are consequently OPTIONAL and their absence is meaningful: it says this value is inline. Their PRESENCE is equally informative — `version` alongside a pinned entry is what lets a holder see that a profile is frozen at v3 while the pool has moved on.",
/// "type": "object",
/// "required": [
/// "provenance",
/// "type",
/// "valueType"
/// ],
/// "properties": {
/// "attributeId": {
/// "description": "The pool attribute this entry resolves against. ABSENT for an `inline` entry, which is the whole distinction this member draws.",
/// "$ref": "#/definitions/Ulid"
/// },
/// "label": {
/// "description": "The holder's own words, from the override where one is given and from the pool attribute otherwise. Never disclosed to a verifier.",
/// "type": "string",
/// "maxLength": 128
/// },
/// "provenance": {
/// "$ref": "#/definitions/Provenance"
/// },
/// "slot": {
/// "description": "The slot of the entry this claim resolved from, where it has one.",
/// "$ref": "#/definitions/Slot"
/// },
/// "stale": {
/// "description": "Present and true when this entry cannot be presented — a credential-backed value that could not be re-derived, or a pin naming a version the maintainer no longer holds. Surfaced rather than omitted so a holder learns why a disclosure would be short.",
/// "type": "boolean"
/// },
/// "staleReason": {
/// "description": "Why the entry cannot be presented. Present only alongside `stale`.",
/// "type": "string",
/// "enum": [
/// "revoked",
/// "expired",
/// "archived",
/// "deleted",
/// "notFound"
/// ]
/// },
/// "type": {
/// "$ref": "#/definitions/ClaimType"
/// },
/// "updatedAt": {
/// "description": "When the pool attribute behind this entry was last written. ABSENT for an `inline` entry.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "value": {
/// "description": "What this entry would present, with any override applied. Absent when `stale`, because a claim that could not be re-derived MUST NOT be disclosed and MUST NOT be shown as though it would be."
/// },
/// "valueType": {
/// "$ref": "#/definitions/ValueType"
/// },
/// "version": {
/// "description": "The pool attribute's version this entry resolved to — the pinned one for a pinned entry, the current one otherwise. ABSENT for an `inline` entry.",
/// "$ref": "#/definitions/Version"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct ResolvedClaim {
///The pool attribute this entry resolves against. ABSENT for an `inline` entry, which is the whole distinction this member draws.
#[serde(
rename = "attributeId",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub attribute_id: ::std::option::Option<Ulid>,
///The holder's own words, from the override where one is given and from the pool attribute otherwise. Never disclosed to a verifier.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub label: ::std::option::Option<ResolvedClaimLabel>,
pub provenance: Provenance,
///The slot of the entry this claim resolved from, where it has one.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub slot: ::std::option::Option<Slot>,
///Present and true when this entry cannot be presented — a credential-backed value that could not be re-derived, or a pin naming a version the maintainer no longer holds. Surfaced rather than omitted so a holder learns why a disclosure would be short.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub stale: ::std::option::Option<bool>,
///Why the entry cannot be presented. Present only alongside `stale`.
#[serde(
rename = "staleReason",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub stale_reason: ::std::option::Option<ResolvedClaimStaleReason>,
#[serde(rename = "type")]
pub type_: ClaimType,
///When the pool attribute behind this entry was last written. ABSENT for an `inline` entry.
#[serde(
rename = "updatedAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub updated_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///What this entry would present, with any override applied. Absent when `stale`, because a claim that could not be re-derived MUST NOT be disclosed and MUST NOT be shown as though it would be.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub value: ::std::option::Option<::serde_json::Value>,
#[serde(rename = "valueType")]
pub value_type: ValueType,
///The pool attribute's version this entry resolved to — the pinned one for a pinned entry, the current one otherwise. ABSENT for an `inline` entry.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub version: ::std::option::Option<Version>,
}
impl ResolvedClaim {
pub fn builder() -> builder::ResolvedClaim {
Default::default()
}
}
///The holder's own words, from the override where one is given and from the pool attribute otherwise. Never disclosed to a verifier.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The holder's own words, from the override where one is given and from the pool attribute otherwise. Never disclosed to a verifier.",
/// "type": "string",
/// "maxLength": 128
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ResolvedClaimLabel(::std::string::String);
impl ::std::ops::Deref for ResolvedClaimLabel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ResolvedClaimLabel> for ::std::string::String {
fn from(value: ResolvedClaimLabel) -> Self {
value.0
}
}
impl ::std::str::FromStr for ResolvedClaimLabel {
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());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ResolvedClaimLabel {
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 ResolvedClaimLabel {
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 ResolvedClaimLabel {
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 ResolvedClaimLabel {
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())
})
}
}
///Why the entry cannot be presented. Present only alongside `stale`.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Why the entry cannot be presented. Present only alongside `stale`.",
/// "type": "string",
/// "enum": [
/// "revoked",
/// "expired",
/// "archived",
/// "deleted",
/// "notFound"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ResolvedClaimStaleReason {
#[serde(rename = "revoked")]
Revoked,
#[serde(rename = "expired")]
Expired,
#[serde(rename = "archived")]
Archived,
#[serde(rename = "deleted")]
Deleted,
#[serde(rename = "notFound")]
NotFound,
}
impl ::std::fmt::Display for ResolvedClaimStaleReason {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Revoked => f.write_str("revoked"),
Self::Expired => f.write_str("expired"),
Self::Archived => f.write_str("archived"),
Self::Deleted => f.write_str("deleted"),
Self::NotFound => f.write_str("notFound"),
}
}
}
impl ::std::str::FromStr for ResolvedClaimStaleReason {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"revoked" => Ok(Self::Revoked),
"expired" => Ok(Self::Expired),
"archived" => Ok(Self::Archived),
"deleted" => Ok(Self::Deleted),
"notFound" => Ok(Self::NotFound),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ResolvedClaimStaleReason {
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 ResolvedClaimStaleReason {
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 ResolvedClaimStaleReason {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Success response to persona/profile/get. Type https://trusttasks.org/spec/persona/profile/get/1.0#response.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "Success response to persona/profile/get. Type https://trusttasks.org/spec/persona/profile/get/1.0#response.",
/// "type": "object",
/// "required": [
/// "profile"
/// ],
/// "properties": {
/// "disclosedTo": {
/// "description": "How many distinct parties this face has disclosed to, across how many contexts, from the holder's disclosure history. Counts, not identifiers; persona/disclosure/history names them. A producer shows this before a delete: deleting a face does not un-tell anyone what it told them.",
/// "type": "object",
/// "required": [
/// "contextCount",
/// "partyCount"
/// ],
/// "properties": {
/// "contextCount": {
/// "type": "integer",
/// "minimum": 0.0
/// },
/// "partyCount": {
/// "type": "integer",
/// "minimum": 0.0
/// }
/// },
/// "additionalProperties": false
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "profile": {
/// "$ref": "#/definitions/Profile"
/// },
/// "resolved": {
/// "description": "\nPresent only when `resolve` was true: the claims this profile would present, in entry order, with overrides applied and pinned versions honoured. A credential-backed claim whose backing could not be re-derived appears carrying `stale`, because a holder inspecting a profile needs to see that it has stopped being fully presentable.\n\nTyped as `ResolvedClaim` rather than `Attribute`: a profile is a projection and may contain `inline` values, which have no pool record and therefore no `attributeId`, `version` or `updatedAt`. The pool record's shape requires all three, so it cannot describe such an entry at all.",
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/ResolvedClaim"
/// },
/// "maxItems": 256
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Response {
#[serde(
rename = "disclosedTo",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub disclosed_to: ::std::option::Option<ResponseDisclosedTo>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
pub profile: Profile,
/**
Present only when `resolve` was true: the claims this profile would present, in entry order, with overrides applied and pinned versions honoured. A credential-backed claim whose backing could not be re-derived appears carrying `stale`, because a holder inspecting a profile needs to see that it has stopped being fully presentable.
Typed as `ResolvedClaim` rather than `Attribute`: a profile is a projection and may contain `inline` values, which have no pool record and therefore no `attributeId`, `version` or `updatedAt`. The pool record's shape requires all three, so it cannot describe such an entry at all.*/
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub resolved: ::std::vec::Vec<ResolvedClaim>,
}
impl Response {
pub fn builder() -> builder::Response {
Default::default()
}
}
///How many distinct parties this face has disclosed to, across how many contexts, from the holder's disclosure history. Counts, not identifiers; persona/disclosure/history names them. A producer shows this before a delete: deleting a face does not un-tell anyone what it told them.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "How many distinct parties this face has disclosed to, across how many contexts, from the holder's disclosure history. Counts, not identifiers; persona/disclosure/history names them. A producer shows this before a delete: deleting a face does not un-tell anyone what it told them.",
/// "type": "object",
/// "required": [
/// "contextCount",
/// "partyCount"
/// ],
/// "properties": {
/// "contextCount": {
/// "type": "integer",
/// "minimum": 0.0
/// },
/// "partyCount": {
/// "type": "integer",
/// "minimum": 0.0
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct ResponseDisclosedTo {
#[serde(rename = "contextCount")]
pub context_count: u64,
#[serde(rename = "partyCount")]
pub party_count: u64,
}
impl ResponseDisclosedTo {
pub fn builder() -> builder::ResponseDisclosedTo {
Default::default()
}
}
/**
A role a profile entry plays within its profile, so a consumer can find it without guessing from its claim type. A profile MAY hold several entries of one type — a legal name and a display name, two phone numbers — and only a slot says which answers a given question. Unique within a profile.
Well-known slots:
- `displayName` — what this face calls itself. The entry a consumer renders as the face's name to anyone it is shown to. Distinct from the profile's own `name`, which is the holder's private label and never disclosed.
- `primaryEmail`, `primaryPhone`, `primaryAddress` — the entry to use where a counterparty asks for one of a kind and the profile holds several.
- `avatar` — the image this face presents.
Other values are the holder's or the producer's own and carry no meaning a maintainer interprets.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Slot",
/// "description": "\nA role a profile entry plays within its profile, so a consumer can find it without guessing from its claim type. A profile MAY hold several entries of one type — a legal name and a display name, two phone numbers — and only a slot says which answers a given question. Unique within a profile.\n\nWell-known slots:\n\n- `displayName` — what this face calls itself. The entry a consumer renders as the face's name to anyone it is shown to. Distinct from the profile's own `name`, which is the holder's private label and never disclosed.\n- `primaryEmail`, `primaryPhone`, `primaryAddress` — the entry to use where a counterparty asks for one of a kind and the profile holds several.\n- `avatar` — the image this face presents.\n\nOther values are the holder's or the producer's own and carry no meaning a maintainer interprets.",
/// "type": "string",
/// "pattern": "^[a-z][A-Za-z0-9]{0,31}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct Slot(::std::string::String);
impl ::std::ops::Deref for Slot {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<Slot> for ::std::string::String {
fn from(value: Slot) -> Self {
value.0
}
}
impl ::std::str::FromStr for Slot {
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-Za-z0-9]{0,31}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z][A-Za-z0-9]{0,31}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for Slot {
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 Slot {
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 Slot {
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 Slot {
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 ULID in Crockford base32, uppercase. Used for `attributeId` and `profileId`. Chosen over a UUID because the leading 48 bits are a timestamp, so a key-ordered scan of the store is also creation-ordered and a `list` needs no secondary sort. Server-assigned on create; a producer MAY supply one to make a create idempotent, and a maintainer MUST reject a supplied value that already exists rather than silently overwriting.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Ulid",
/// "description": "A ULID in Crockford base32, uppercase. Used for `attributeId` and `profileId`. Chosen over a UUID because the leading 48 bits are a timestamp, so a key-ordered scan of the store is also creation-ordered and a `list` needs no secondary sort. Server-assigned on create; a producer MAY supply one to make a create idempotent, and a maintainer MUST reject a supplied value that already exists rather than silently overwriting.",
/// "type": "string",
/// "pattern": "^[0-9A-HJKMNP-TV-Z]{26}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct Ulid(::std::string::String);
impl ::std::ops::Deref for Ulid {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<Ulid> for ::std::string::String {
fn from(value: Ulid) -> Self {
value.0
}
}
impl ::std::str::FromStr for Ulid {
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-HJKMNP-TV-Z]{26}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[0-9A-HJKMNP-TV-Z]{26}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for Ulid {
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 Ulid {
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 Ulid {
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 Ulid {
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())
})
}
}
///The JSON shape of `value`, declared so that a consumer can render and compare without guessing. The maintainer validates that `value` agrees with this member and does nothing further: it does NOT validate a phone number against a phone-number grammar. That is a producer's affordance, and a store that grows opinions about the contents of its records eventually blocks its consumer's release.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ValueType",
/// "description": "The JSON shape of `value`, declared so that a consumer can render and compare without guessing. The maintainer validates that `value` agrees with this member and does nothing further: it does NOT validate a phone number against a phone-number grammar. That is a producer's affordance, and a store that grows opinions about the contents of its records eventually blocks its consumer's release.",
/// "type": "string",
/// "enum": [
/// "string",
/// "number",
/// "boolean",
/// "date",
/// "object"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ValueType {
#[serde(rename = "string")]
String,
#[serde(rename = "number")]
Number,
#[serde(rename = "boolean")]
Boolean,
#[serde(rename = "date")]
Date,
#[serde(rename = "object")]
Object,
}
impl ::std::fmt::Display for ValueType {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::String => f.write_str("string"),
Self::Number => f.write_str("number"),
Self::Boolean => f.write_str("boolean"),
Self::Date => f.write_str("date"),
Self::Object => f.write_str("object"),
}
}
}
impl ::std::str::FromStr for ValueType {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"string" => Ok(Self::String),
"number" => Ok(Self::Number),
"boolean" => Ok(Self::Boolean),
"date" => Ok(Self::Date),
"object" => Ok(Self::Object),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ValueType {
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 ValueType {
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 ValueType {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///A value of the store's monotonic write counter. Server-assigned; a producer never chooses one.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Version",
/// "description": "A value of the store's monotonic write counter. Server-assigned; a producer never chooses one.",
/// "type": "integer",
/// "minimum": 1.0
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct Version(pub ::std::num::NonZeroU64);
impl ::std::ops::Deref for Version {
type Target = ::std::num::NonZeroU64;
fn deref(&self) -> &::std::num::NonZeroU64 {
&self.0
}
}
impl ::std::convert::From<Version> for ::std::num::NonZeroU64 {
fn from(value: Version) -> Self {
value.0
}
}
impl ::std::convert::From<::std::num::NonZeroU64> for Version {
fn from(value: ::std::num::NonZeroU64) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for Version {
type Err = <::std::num::NonZeroU64 as ::std::str::FromStr>::Err;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.parse()?))
}
}
impl ::std::convert::TryFrom<&str> for Version {
type Error = <::std::num::NonZeroU64 as ::std::str::FromStr>::Err;
fn try_from(value: &str) -> ::std::result::Result<Self, Self::Error> {
value.parse()
}
}
impl ::std::convert::TryFrom<String> for Version {
type Error = <::std::num::NonZeroU64 as ::std::str::FromStr>::Err;
fn try_from(value: String) -> ::std::result::Result<Self, Self::Error> {
value.parse()
}
}
impl ::std::fmt::Display for Version {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
/// Types for composing complex structures.
pub mod builder {
#[derive(Clone, Debug)]
pub struct Payload {
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
profile_id: ::std::result::Result<super::Ulid, ::std::string::String>,
resolve: ::std::result::Result<bool, ::std::string::String>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
ext: Ok(Default::default()),
profile_id: Err("no value supplied for profile_id".to_string()),
resolve: Ok(Default::default()),
}
}
}
impl Payload {
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 profile_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Ulid>,
T::Error: ::std::fmt::Display,
{
self.profile_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for profile_id: {e}"));
self
}
pub fn resolve<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<bool>,
T::Error: ::std::fmt::Display,
{
self.resolve = value
.try_into()
.map_err(|e| format!("error converting supplied value for resolve: {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 {
ext: value.ext?,
profile_id: value.profile_id?,
resolve: value.resolve?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
ext: Ok(value.ext),
profile_id: Ok(value.profile_id),
resolve: Ok(value.resolve),
}
}
}
#[derive(Clone, Debug)]
pub struct Profile {
created_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
credential_refs: ::std::result::Result<
::std::vec::Vec<super::ProfileCredentialRefsItem>,
::std::string::String,
>,
entries: ::std::result::Result<::std::vec::Vec<super::ProfileEntry>, ::std::string::String>,
name: ::std::result::Result<super::ProfileName, ::std::string::String>,
profile_id: ::std::result::Result<super::Ulid, ::std::string::String>,
reach:
::std::result::Result<::std::option::Option<super::FaceReach>, ::std::string::String>,
retired_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
status: ::std::result::Result<super::ProfileStatus, ::std::string::String>,
updated_at:
::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
version: ::std::result::Result<super::Version, ::std::string::String>,
}
impl ::std::default::Default for Profile {
fn default() -> Self {
Self {
created_at: Ok(Default::default()),
credential_refs: Ok(Default::default()),
entries: Err("no value supplied for entries".to_string()),
name: Err("no value supplied for name".to_string()),
profile_id: Err("no value supplied for profile_id".to_string()),
reach: Ok(Default::default()),
retired_at: Ok(Default::default()),
status: Ok(super::defaults::profile_status()),
updated_at: Err("no value supplied for updated_at".to_string()),
version: Err("no value supplied for version".to_string()),
}
}
}
impl Profile {
pub fn created_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.created_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for created_at: {e}"));
self
}
pub fn credential_refs<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::ProfileCredentialRefsItem>>,
T::Error: ::std::fmt::Display,
{
self.credential_refs = value
.try_into()
.map_err(|e| format!("error converting supplied value for credential_refs: {e}"));
self
}
pub fn entries<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::ProfileEntry>>,
T::Error: ::std::fmt::Display,
{
self.entries = value
.try_into()
.map_err(|e| format!("error converting supplied value for entries: {e}"));
self
}
pub fn name<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ProfileName>,
T::Error: ::std::fmt::Display,
{
self.name = value
.try_into()
.map_err(|e| format!("error converting supplied value for name: {e}"));
self
}
pub fn profile_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Ulid>,
T::Error: ::std::fmt::Display,
{
self.profile_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for profile_id: {e}"));
self
}
pub fn reach<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::FaceReach>>,
T::Error: ::std::fmt::Display,
{
self.reach = value
.try_into()
.map_err(|e| format!("error converting supplied value for reach: {e}"));
self
}
pub fn retired_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.retired_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for retired_at: {e}"));
self
}
pub fn status<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ProfileStatus>,
T::Error: ::std::fmt::Display,
{
self.status = value
.try_into()
.map_err(|e| format!("error converting supplied value for status: {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 version<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Version>,
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<Profile> for super::Profile {
type Error = super::error::ConversionError;
fn try_from(value: Profile) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
created_at: value.created_at?,
credential_refs: value.credential_refs?,
entries: value.entries?,
name: value.name?,
profile_id: value.profile_id?,
reach: value.reach?,
retired_at: value.retired_at?,
status: value.status?,
updated_at: value.updated_at?,
version: value.version?,
})
}
}
impl ::std::convert::From<super::Profile> for Profile {
fn from(value: super::Profile) -> Self {
Self {
created_at: Ok(value.created_at),
credential_refs: Ok(value.credential_refs),
entries: Ok(value.entries),
name: Ok(value.name),
profile_id: Ok(value.profile_id),
reach: Ok(value.reach),
retired_at: Ok(value.retired_at),
status: Ok(value.status),
updated_at: Ok(value.updated_at),
version: Ok(value.version),
}
}
}
#[derive(Clone, Debug)]
pub struct ProfileEntryVariant2Override {
label: ::std::result::Result<
::std::option::Option<super::ProfileEntryVariant2OverrideLabel>,
::std::string::String,
>,
value: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for ProfileEntryVariant2Override {
fn default() -> Self {
Self {
label: Ok(Default::default()),
value: Err("no value supplied for value".to_string()),
}
}
}
impl ProfileEntryVariant2Override {
pub fn label<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<super::ProfileEntryVariant2OverrideLabel>,
>,
T::Error: ::std::fmt::Display,
{
self.label = value
.try_into()
.map_err(|e| format!("error converting supplied value for label: {e}"));
self
}
pub fn value<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.value = value
.try_into()
.map_err(|e| format!("error converting supplied value for value: {e}"));
self
}
}
impl ::std::convert::TryFrom<ProfileEntryVariant2Override> for super::ProfileEntryVariant2Override {
type Error = super::error::ConversionError;
fn try_from(
value: ProfileEntryVariant2Override,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
label: value.label?,
value: value.value?,
})
}
}
impl ::std::convert::From<super::ProfileEntryVariant2Override> for ProfileEntryVariant2Override {
fn from(value: super::ProfileEntryVariant2Override) -> Self {
Self {
label: Ok(value.label),
value: Ok(value.value),
}
}
}
#[derive(Clone, Debug)]
pub struct ProfileEntryVariant3Inline {
label: ::std::result::Result<
::std::option::Option<super::ProfileEntryVariant3InlineLabel>,
::std::string::String,
>,
provenance: ::std::result::Result<super::Provenance, ::std::string::String>,
type_: ::std::result::Result<super::ClaimType, ::std::string::String>,
value: ::std::result::Result<::serde_json::Value, ::std::string::String>,
value_type: ::std::result::Result<super::ValueType, ::std::string::String>,
}
impl ::std::default::Default for ProfileEntryVariant3Inline {
fn default() -> Self {
Self {
label: Ok(Default::default()),
provenance: Err("no value supplied for provenance".to_string()),
type_: Err("no value supplied for type_".to_string()),
value: Err("no value supplied for value".to_string()),
value_type: Err("no value supplied for value_type".to_string()),
}
}
}
impl ProfileEntryVariant3Inline {
pub fn label<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<super::ProfileEntryVariant3InlineLabel>,
>,
T::Error: ::std::fmt::Display,
{
self.label = value
.try_into()
.map_err(|e| format!("error converting supplied value for label: {e}"));
self
}
pub fn provenance<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Provenance>,
T::Error: ::std::fmt::Display,
{
self.provenance = value
.try_into()
.map_err(|e| format!("error converting supplied value for provenance: {e}"));
self
}
pub fn type_<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ClaimType>,
T::Error: ::std::fmt::Display,
{
self.type_ = value
.try_into()
.map_err(|e| format!("error converting supplied value for type_: {e}"));
self
}
pub fn value<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.value = value
.try_into()
.map_err(|e| format!("error converting supplied value for value: {e}"));
self
}
pub fn value_type<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ValueType>,
T::Error: ::std::fmt::Display,
{
self.value_type = value
.try_into()
.map_err(|e| format!("error converting supplied value for value_type: {e}"));
self
}
}
impl ::std::convert::TryFrom<ProfileEntryVariant3Inline> for super::ProfileEntryVariant3Inline {
type Error = super::error::ConversionError;
fn try_from(
value: ProfileEntryVariant3Inline,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
label: value.label?,
provenance: value.provenance?,
type_: value.type_?,
value: value.value?,
value_type: value.value_type?,
})
}
}
impl ::std::convert::From<super::ProfileEntryVariant3Inline> for ProfileEntryVariant3Inline {
fn from(value: super::ProfileEntryVariant3Inline) -> Self {
Self {
label: Ok(value.label),
provenance: Ok(value.provenance),
type_: Ok(value.type_),
value: Ok(value.value),
value_type: Ok(value.value_type),
}
}
}
#[derive(Clone, Debug)]
pub struct ResolvedClaim {
attribute_id:
::std::result::Result<::std::option::Option<super::Ulid>, ::std::string::String>,
label: ::std::result::Result<
::std::option::Option<super::ResolvedClaimLabel>,
::std::string::String,
>,
provenance: ::std::result::Result<super::Provenance, ::std::string::String>,
slot: ::std::result::Result<::std::option::Option<super::Slot>, ::std::string::String>,
stale: ::std::result::Result<::std::option::Option<bool>, ::std::string::String>,
stale_reason: ::std::result::Result<
::std::option::Option<super::ResolvedClaimStaleReason>,
::std::string::String,
>,
type_: ::std::result::Result<super::ClaimType, ::std::string::String>,
updated_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
value: ::std::result::Result<
::std::option::Option<::serde_json::Value>,
::std::string::String,
>,
value_type: ::std::result::Result<super::ValueType, ::std::string::String>,
version:
::std::result::Result<::std::option::Option<super::Version>, ::std::string::String>,
}
impl ::std::default::Default for ResolvedClaim {
fn default() -> Self {
Self {
attribute_id: Ok(Default::default()),
label: Ok(Default::default()),
provenance: Err("no value supplied for provenance".to_string()),
slot: Ok(Default::default()),
stale: Ok(Default::default()),
stale_reason: Ok(Default::default()),
type_: Err("no value supplied for type_".to_string()),
updated_at: Ok(Default::default()),
value: Ok(Default::default()),
value_type: Err("no value supplied for value_type".to_string()),
version: Ok(Default::default()),
}
}
}
impl ResolvedClaim {
pub fn attribute_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ulid>>,
T::Error: ::std::fmt::Display,
{
self.attribute_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for attribute_id: {e}"));
self
}
pub fn label<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ResolvedClaimLabel>>,
T::Error: ::std::fmt::Display,
{
self.label = value
.try_into()
.map_err(|e| format!("error converting supplied value for label: {e}"));
self
}
pub fn provenance<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Provenance>,
T::Error: ::std::fmt::Display,
{
self.provenance = value
.try_into()
.map_err(|e| format!("error converting supplied value for provenance: {e}"));
self
}
pub fn slot<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Slot>>,
T::Error: ::std::fmt::Display,
{
self.slot = value
.try_into()
.map_err(|e| format!("error converting supplied value for slot: {e}"));
self
}
pub fn stale<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<bool>>,
T::Error: ::std::fmt::Display,
{
self.stale = value
.try_into()
.map_err(|e| format!("error converting supplied value for stale: {e}"));
self
}
pub fn stale_reason<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ResolvedClaimStaleReason>>,
T::Error: ::std::fmt::Display,
{
self.stale_reason = value
.try_into()
.map_err(|e| format!("error converting supplied value for stale_reason: {e}"));
self
}
pub fn type_<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ClaimType>,
T::Error: ::std::fmt::Display,
{
self.type_ = value
.try_into()
.map_err(|e| format!("error converting supplied value for type_: {e}"));
self
}
pub fn updated_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.updated_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for updated_at: {e}"));
self
}
pub fn value<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::serde_json::Value>>,
T::Error: ::std::fmt::Display,
{
self.value = value
.try_into()
.map_err(|e| format!("error converting supplied value for value: {e}"));
self
}
pub fn value_type<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ValueType>,
T::Error: ::std::fmt::Display,
{
self.value_type = value
.try_into()
.map_err(|e| format!("error converting supplied value for value_type: {e}"));
self
}
pub fn version<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Version>>,
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<ResolvedClaim> for super::ResolvedClaim {
type Error = super::error::ConversionError;
fn try_from(
value: ResolvedClaim,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
attribute_id: value.attribute_id?,
label: value.label?,
provenance: value.provenance?,
slot: value.slot?,
stale: value.stale?,
stale_reason: value.stale_reason?,
type_: value.type_?,
updated_at: value.updated_at?,
value: value.value?,
value_type: value.value_type?,
version: value.version?,
})
}
}
impl ::std::convert::From<super::ResolvedClaim> for ResolvedClaim {
fn from(value: super::ResolvedClaim) -> Self {
Self {
attribute_id: Ok(value.attribute_id),
label: Ok(value.label),
provenance: Ok(value.provenance),
slot: Ok(value.slot),
stale: Ok(value.stale),
stale_reason: Ok(value.stale_reason),
type_: Ok(value.type_),
updated_at: Ok(value.updated_at),
value: Ok(value.value),
value_type: Ok(value.value_type),
version: Ok(value.version),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
disclosed_to: ::std::result::Result<
::std::option::Option<super::ResponseDisclosedTo>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
profile: ::std::result::Result<super::Profile, ::std::string::String>,
resolved:
::std::result::Result<::std::vec::Vec<super::ResolvedClaim>, ::std::string::String>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
disclosed_to: Ok(Default::default()),
ext: Ok(Default::default()),
profile: Err("no value supplied for profile".to_string()),
resolved: Ok(Default::default()),
}
}
}
impl Response {
pub fn disclosed_to<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ResponseDisclosedTo>>,
T::Error: ::std::fmt::Display,
{
self.disclosed_to = value
.try_into()
.map_err(|e| format!("error converting supplied value for disclosed_to: {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 profile<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Profile>,
T::Error: ::std::fmt::Display,
{
self.profile = value
.try_into()
.map_err(|e| format!("error converting supplied value for profile: {e}"));
self
}
pub fn resolved<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::ResolvedClaim>>,
T::Error: ::std::fmt::Display,
{
self.resolved = value
.try_into()
.map_err(|e| format!("error converting supplied value for resolved: {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 {
disclosed_to: value.disclosed_to?,
ext: value.ext?,
profile: value.profile?,
resolved: value.resolved?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
disclosed_to: Ok(value.disclosed_to),
ext: Ok(value.ext),
profile: Ok(value.profile),
resolved: Ok(value.resolved),
}
}
}
#[derive(Clone, Debug)]
pub struct ResponseDisclosedTo {
context_count: ::std::result::Result<u64, ::std::string::String>,
party_count: ::std::result::Result<u64, ::std::string::String>,
}
impl ::std::default::Default for ResponseDisclosedTo {
fn default() -> Self {
Self {
context_count: Err("no value supplied for context_count".to_string()),
party_count: Err("no value supplied for party_count".to_string()),
}
}
}
impl ResponseDisclosedTo {
pub fn context_count<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<u64>,
T::Error: ::std::fmt::Display,
{
self.context_count = value
.try_into()
.map_err(|e| format!("error converting supplied value for context_count: {e}"));
self
}
pub fn party_count<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<u64>,
T::Error: ::std::fmt::Display,
{
self.party_count = value
.try_into()
.map_err(|e| format!("error converting supplied value for party_count: {e}"));
self
}
}
impl ::std::convert::TryFrom<ResponseDisclosedTo> for super::ResponseDisclosedTo {
type Error = super::error::ConversionError;
fn try_from(
value: ResponseDisclosedTo,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
context_count: value.context_count?,
party_count: value.party_count?,
})
}
}
impl ::std::convert::From<super::ResponseDisclosedTo> for ResponseDisclosedTo {
fn from(value: super::ResponseDisclosedTo) -> Self {
Self {
context_count: Ok(value.context_count),
party_count: Ok(value.party_count),
}
}
}
}
/// Generation of default values for serde.
pub mod defaults {
pub(super) fn default_bool<const V: bool>() -> bool {
V
}
pub(super) fn profile_status() -> super::ProfileStatus {
super::ProfileStatus::Active
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/persona/profile/get/1.0";
const IS_PROOF_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"ClaimType\": {\n \"description\": \"The vocabulary token naming what a value IS — `name.legal`, `phone.mobile`, `address.postal`, `person.birthDate`. Dotted, most-general segment first, so that a consumer with no knowledge of the specific token can still group by its prefix.\\n\\nThe token is the maintainer's own; no external vocabulary is primary. External vocabularies (vCard/jCard, OIDC standard claims, schema.org) are mappings applied at PRESENTATION by a renderer, not at rest, so that a query written in any of them can be matched without the store having to live inside any one of them.\\n\\nThe `x:` prefix is an open extension namespace and is not decoration. The closest prior art — Windows CardSpace's self-issued card — supported exactly fifteen predefined claim types with no extensibility, and that is the specific way it failed the requirement a holder actually has. An `x:` attribute stores, composes, binds and discloses exactly like a known one; it renders generically and matches only an explicit query.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"pattern\": \"^(x:)?[a-z][a-zA-Z0-9]*(\\\\.[a-z][a-zA-Z0-9]*)*$\",\n \"title\": \"ClaimType\",\n \"type\": \"string\"\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 \"FaceReach\": {\n \"description\": \"Where a pool face may be worn. `anywhere` is the default and what an absent member means. `only` names the contexts it may be worn in, and a maintainer MUST refuse to wear it in any other (persona/binding/set `outsideReach`).\\n\\nA tagged object rather than a bare list of contexts, deliberately: an empty list has been read as both 'unrestricted' and 'nowhere' in this family's neighbours, and a shape where the two cannot be confused is worth more than one where they must be remembered. So `only` requires at least one context, and 'nowhere' is not a reach — it is a retired face.\\n\\nA context-local face has no reach: it lives in its context and is worn there by construction.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"anywhere\"\n }\n },\n \"required\": [\n \"kind\"\n ],\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"contextIds\": {\n \"items\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"maxItems\": 256,\n \"minItems\": 1,\n \"type\": \"array\",\n \"uniqueItems\": true\n },\n \"kind\": {\n \"const\": \"only\"\n }\n },\n \"required\": [\n \"kind\",\n \"contextIds\"\n ],\n \"type\": \"object\"\n }\n ],\n \"title\": \"FaceReach\"\n },\n \"Profile\": {\n \"additionalProperties\": false,\n \"description\": \"A named projection over the pool. Agent-scoped, like the pool it draws from. `entries` is ordered and the order is display order.\",\n \"properties\": {\n \"createdAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"credentialRefs\": {\n \"description\": \"Vault identifiers of credentials associated with this profile as INVENTORY, distinct from the evidence relationship a `credentialBacked` attribute expresses. The two answer different questions — what can this persona prove, versus what backs this specific claim — and a consumer MUST NOT read one as the other.\",\n \"items\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"maxItems\": 256,\n \"type\": \"array\"\n },\n \"entries\": {\n \"items\": {\n \"$ref\": \"#/$defs/ProfileEntry\"\n },\n \"maxItems\": 256,\n \"type\": \"array\"\n },\n \"name\": {\n \"description\": \"The holder's name for this profile — \\\"Work\\\", \\\"Gaming\\\". Not disclosed.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"profileId\": {\n \"$ref\": \"#/$defs/Ulid\"\n },\n \"reach\": {\n \"$ref\": \"#/$defs/FaceReach\"\n },\n \"retiredAt\": {\n \"description\": \"When the face was retired. Present exactly when `status` is `retired`.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"status\": {\n \"default\": \"active\",\n \"description\": \"`retired`: the face is worn nowhere, is left out of pickers and default listings, and cannot be worn until reinstated (persona/profile/retire, persona/profile/reinstate). Its disclosure history and every value it carries are kept — retiring is 'stop being this', not 'forget this'. Absent reads as `active`.\",\n \"enum\": [\n \"active\",\n \"retired\"\n ],\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"version\": {\n \"$ref\": \"#/$defs/Version\"\n }\n },\n \"required\": [\n \"profileId\",\n \"name\",\n \"entries\",\n \"version\",\n \"updatedAt\"\n ],\n \"title\": \"Profile\",\n \"type\": \"object\"\n },\n \"ProfileEntry\": {\n \"description\": \"One line of a profile, in exactly one of four forms. Together they are the whole of a profile's flexibility, and each exists for a case the others handle badly.\\n\\n`{ref}` — use the pool attribute, live. Editing the pool updates every profile that references it, which is the point.\\n\\n`{ref, pinVersion}` — use the value as it was at that version. For a profile that must keep presenting the value a counterparty already verified.\\n\\n`{ref, override}` — the same fact, a different value here. (\\\"In the gaming profile my display name is different.\\\")\\n\\n`{inline}` — a value that never enters the pool, and so never leaks into another profile.\\n\\nOmission is exclusion; there is no removal marker.\\n\\nAny form MAY carry a `slot` naming the role the entry plays in the profile — see `Slot`. A maintainer MUST refuse a profile in which two entries carry the same slot: a slot exists to answer one question with one entry.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"ref\": {\n \"$ref\": \"#/$defs/Ulid\"\n },\n \"slot\": {\n \"$ref\": \"#/$defs/Slot\"\n }\n },\n \"required\": [\n \"ref\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"pinVersion\": {\n \"$ref\": \"#/$defs/Version\"\n },\n \"ref\": {\n \"$ref\": \"#/$defs/Ulid\"\n },\n \"slot\": {\n \"$ref\": \"#/$defs/Slot\"\n }\n },\n \"required\": [\n \"ref\",\n \"pinVersion\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"override\": {\n \"additionalProperties\": false,\n \"description\": \"Replaces the pool attribute's value for this profile only. `type`, `valueType` and `provenance` are inherited from the referenced attribute and MUST NOT be overridden — an override that changed provenance would let a self-asserted value present as attested.\",\n \"properties\": {\n \"label\": {\n \"maxLength\": 128,\n \"type\": \"string\"\n },\n \"value\": {}\n },\n \"required\": [\n \"value\"\n ],\n \"type\": \"object\"\n },\n \"ref\": {\n \"$ref\": \"#/$defs/Ulid\"\n },\n \"slot\": {\n \"$ref\": \"#/$defs/Slot\"\n }\n },\n \"required\": [\n \"ref\",\n \"override\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"inline\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"label\": {\n \"maxLength\": 128,\n \"type\": \"string\"\n },\n \"provenance\": {\n \"$ref\": \"#/$defs/Provenance\"\n },\n \"type\": {\n \"$ref\": \"#/$defs/ClaimType\"\n },\n \"value\": {},\n \"valueType\": {\n \"$ref\": \"#/$defs/ValueType\"\n }\n },\n \"required\": [\n \"type\",\n \"valueType\",\n \"value\",\n \"provenance\"\n ],\n \"type\": \"object\"\n },\n \"slot\": {\n \"$ref\": \"#/$defs/Slot\"\n }\n },\n \"required\": [\n \"inline\"\n ]\n }\n ],\n \"title\": \"ProfileEntry\",\n \"type\": \"object\"\n },\n \"ProofRung\": {\n \"description\": \"How strongly a credential-backed claim is hidden when presented, ordered most private first. `predicate` proves a statement over a claim without disclosing the claim. `derived` discloses exactly the claims needed via an unlinkable derived proof, so two presentations cannot be joined. `selectiveDisclosure` discloses exactly the claims needed but carries the issuer's signature unchanged, so two presentations ARE linkable. `whole` discloses the entire credential.\\n\\nThe distinction between the first two and the last two is of kind, not degree: only `predicate` and `derived` avoid handing two verifiers a join key. A maintainer MUST default to the highest rung the credential's format supports, and MUST NOT silently fall to a lower one — a request that cannot be satisfied at the rung a producer asked for is refused, because a silent privacy downgrade discloses material the holder believed was hidden.\",\n \"enum\": [\n \"predicate\",\n \"derived\",\n \"selectiveDisclosure\",\n \"whole\"\n ],\n \"title\": \"ProofRung\",\n \"type\": \"string\"\n },\n \"Provenance\": {\n \"description\": \"Where a value comes from, and the member that makes this family worth building on a trust stack rather than in an address book. It survives to the verifier, so a recipient can tell — per field — what the holder typed from what an issuer attested.\\n\\n`selfAsserted` — the holder supplied it.\\n\\n`credentialBacked` — the value is derived from a credential in the vault at `claimPath`. The stored value is a CACHE FOR DISPLAY; the credential is the truth. A maintainer MUST re-derive it on read and MUST fail closed (never presenting a stale value) when the credential has been revoked, has expired, or has been archived or deleted.\\n\\n`generated` — the value is minted per verifier at disclosure time and recorded against that verifier, so every relying party receives a different one that routes back to the holder. This is the shape of the most widely adopted consumer privacy feature in this space; a maintainer need not operate a relay to conform, but the shape must exist, because retrofitting per-verifier values into a pool-of-values model is a migration rather than an addition.\\n\\n`derived` — the value was taken from a source the holder connected or supplied — a code-hosting profile, an uploaded CV — rather than typed by them or attested by an issuer. Nobody signed it: it is the holder's claim that the source said so, and a consumer MUST NOT present it as attested. It exists as its own kind because a derived value is neither of the others — the holder did not author it, and no one vouches for it — and a holder deciding whether to disclose deserves to know which of their values they typed.\\n\\nFor how strongly a disclosed value identifies the holder, the kinds rank `credentialBacked` above `derived` above `selfAsserted`; `generated` values are per-verifier and do not correlate.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"selfAsserted\"\n }\n },\n \"required\": [\n \"kind\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"claimPath\": {\n \"description\": \"RFC 6901 JSON Pointer to the claim within the credential, e.g. `/credentialSubject/familyName`.\",\n \"pattern\": \"^(/[^/~]*(~[01][^/~]*)*)*$\",\n \"type\": \"string\"\n },\n \"credentialId\": {\n \"description\": \"Vault identifier of the backing credential.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"issuerDid\": {\n \"description\": \"Issuer of the backing credential. Advisory: a consumer MUST verify the credential rather than trusting this member.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"credentialBacked\"\n },\n \"proof\": {\n \"$ref\": \"#/$defs/ProofRung\",\n \"description\": \"The disclosure rung this claim was, or will be, presented at.\"\n }\n },\n \"required\": [\n \"kind\",\n \"credentialId\",\n \"claimPath\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"generator\": {\n \"description\": \"Names the minting scheme, e.g. `relayEmail`. Maintainer-defined.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"generated\"\n },\n \"perVerifier\": {\n \"default\": true,\n \"description\": \"When true (the default and the only useful setting), a distinct value is minted for each verifier.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"kind\",\n \"generator\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"derivedAt\": {\n \"description\": \"When the value was taken from the source. A derived value is a snapshot: the source may have changed since, and nothing re-derives it.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"derived\"\n },\n \"source\": {\n \"description\": \"The KIND of source the value was taken from — `github`, `cvUpload`, `linkedIn` — never an account, handle or URL. Provenance survives to the verifier, so this member is disclosed with the claim; a handle here would disclose an identifier the holder never chose to share.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"pattern\": \"^[a-z][A-Za-z0-9.-]*$\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"source\",\n \"derivedAt\"\n ]\n }\n ],\n \"required\": [\n \"kind\"\n ],\n \"title\": \"Provenance\",\n \"type\": \"object\"\n },\n \"ResolvedClaim\": {\n \"additionalProperties\": false,\n \"description\": \"One line of a profile AFTER resolution: what the profile would present at this entry, rather than how the entry is written.\\n\\nDistinct from `Attribute` because a profile is a PROJECTION and may contain values that have no pool record behind them. An `inline` entry is a value the holder keeps in one profile and nowhere else — it has no `attributeId`, no `version` and no `updatedAt`, because there is no pool attribute to have them. Describing a resolved profile with the pool record's shape therefore cannot represent one at all, which leaves a maintainer choosing between synthesising an `attributeId` — a false claim about where a value lives — and omitting the entry, which returns a profile that appears to present less than it does. Neither is acceptable, so the projection gets its own shape.\\n\\nThe three pool members are consequently OPTIONAL and their absence is meaningful: it says this value is inline. Their PRESENCE is equally informative — `version` alongside a pinned entry is what lets a holder see that a profile is frozen at v3 while the pool has moved on.\",\n \"properties\": {\n \"attributeId\": {\n \"$ref\": \"#/$defs/Ulid\",\n \"description\": \"The pool attribute this entry resolves against. ABSENT for an `inline` entry, which is the whole distinction this member draws.\"\n },\n \"label\": {\n \"description\": \"The holder's own words, from the override where one is given and from the pool attribute otherwise. Never disclosed to a verifier.\",\n \"maxLength\": 128,\n \"type\": \"string\"\n },\n \"provenance\": {\n \"$ref\": \"#/$defs/Provenance\"\n },\n \"slot\": {\n \"$ref\": \"#/$defs/Slot\",\n \"description\": \"The slot of the entry this claim resolved from, where it has one.\"\n },\n \"stale\": {\n \"description\": \"Present and true when this entry cannot be presented — a credential-backed value that could not be re-derived, or a pin naming a version the maintainer no longer holds. Surfaced rather than omitted so a holder learns why a disclosure would be short.\",\n \"type\": \"boolean\"\n },\n \"staleReason\": {\n \"description\": \"Why the entry cannot be presented. Present only alongside `stale`.\",\n \"enum\": [\n \"revoked\",\n \"expired\",\n \"archived\",\n \"deleted\",\n \"notFound\"\n ],\n \"type\": \"string\"\n },\n \"type\": {\n \"$ref\": \"#/$defs/ClaimType\"\n },\n \"updatedAt\": {\n \"description\": \"When the pool attribute behind this entry was last written. ABSENT for an `inline` entry.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"value\": {\n \"description\": \"What this entry would present, with any override applied. Absent when `stale`, because a claim that could not be re-derived MUST NOT be disclosed and MUST NOT be shown as though it would be.\"\n },\n \"valueType\": {\n \"$ref\": \"#/$defs/ValueType\"\n },\n \"version\": {\n \"$ref\": \"#/$defs/Version\",\n \"description\": \"The pool attribute's version this entry resolved to — the pinned one for a pinned entry, the current one otherwise. ABSENT for an `inline` entry.\"\n }\n },\n \"required\": [\n \"type\",\n \"valueType\",\n \"provenance\"\n ],\n \"title\": \"ResolvedClaim\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"Success response to persona/profile/get. Type https://trusttasks.org/spec/persona/profile/get/1.0#response.\",\n \"properties\": {\n \"disclosedTo\": {\n \"additionalProperties\": false,\n \"description\": \"How many distinct parties this face has disclosed to, across how many contexts, from the holder's disclosure history. Counts, not identifiers; persona/disclosure/history names them. A producer shows this before a delete: deleting a face does not un-tell anyone what it told them.\",\n \"properties\": {\n \"contextCount\": {\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"partyCount\": {\n \"minimum\": 0,\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"partyCount\",\n \"contextCount\"\n ],\n \"type\": \"object\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"profile\": {\n \"$ref\": \"#/$defs/Profile\"\n },\n \"resolved\": {\n \"description\": \"Present only when `resolve` was true: the claims this profile would present, in entry order, with overrides applied and pinned versions honoured. A credential-backed claim whose backing could not be re-derived appears carrying `stale`, because a holder inspecting a profile needs to see that it has stopped being fully presentable.\\n\\nTyped as `ResolvedClaim` rather than `Attribute`: a profile is a projection and may contain `inline` values, which have no pool record and therefore no `attributeId`, `version` or `updatedAt`. The pool record's shape requires all three, so it cannot describe such an entry at all.\",\n \"items\": {\n \"$ref\": \"#/$defs/ResolvedClaim\"\n },\n \"maxItems\": 256,\n \"type\": \"array\"\n }\n },\n \"required\": [\n \"profile\"\n ],\n \"title\": \"Persona Profile Get — response payload\",\n \"type\": \"object\"\n },\n \"Slot\": {\n \"description\": \"A role a profile entry plays within its profile, so a consumer can find it without guessing from its claim type. A profile MAY hold several entries of one type — a legal name and a display name, two phone numbers — and only a slot says which answers a given question. Unique within a profile.\\n\\nWell-known slots:\\n\\n- `displayName` — what this face calls itself. The entry a consumer renders as the face's name to anyone it is shown to. Distinct from the profile's own `name`, which is the holder's private label and never disclosed.\\n- `primaryEmail`, `primaryPhone`, `primaryAddress` — the entry to use where a counterparty asks for one of a kind and the profile holds several.\\n- `avatar` — the image this face presents.\\n\\nOther values are the holder's or the producer's own and carry no meaning a maintainer interprets.\",\n \"pattern\": \"^[a-z][A-Za-z0-9]{0,31}$\",\n \"title\": \"Slot\",\n \"type\": \"string\"\n },\n \"Ulid\": {\n \"description\": \"A ULID in Crockford base32, uppercase. Used for `attributeId` and `profileId`. Chosen over a UUID because the leading 48 bits are a timestamp, so a key-ordered scan of the store is also creation-ordered and a `list` needs no secondary sort. Server-assigned on create; a producer MAY supply one to make a create idempotent, and a maintainer MUST reject a supplied value that already exists rather than silently overwriting.\",\n \"pattern\": \"^[0-9A-HJKMNP-TV-Z]{26}$\",\n \"title\": \"Ulid\",\n \"type\": \"string\"\n },\n \"ValueType\": {\n \"description\": \"The JSON shape of `value`, declared so that a consumer can render and compare without guessing. The maintainer validates that `value` agrees with this member and does nothing further: it does NOT validate a phone number against a phone-number grammar. That is a producer's affordance, and a store that grows opinions about the contents of its records eventually blocks its consumer's release.\",\n \"enum\": [\n \"string\",\n \"number\",\n \"boolean\",\n \"date\",\n \"object\"\n ],\n \"title\": \"ValueType\",\n \"type\": \"string\"\n },\n \"Version\": {\n \"description\": \"A value of the store's monotonic write counter. Server-assigned; a producer never chooses one.\",\n \"minimum\": 1,\n \"title\": \"Version\",\n \"type\": \"integer\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/persona/profile/get/1.0\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"Read one profile, either as composed (the entries the holder wrote) or as resolved (the claims it would actually present).\",\n \"properties\": {\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"profileId\": {\n \"$ref\": \"#/$defs/Ulid\"\n },\n \"resolve\": {\n \"default\": false,\n \"description\": \"When false (the default) the profile is returned as composed — entries as written, references unresolved. When true the maintainer resolves every entry against the pool and returns the claims the profile would present, which is what a preview renders and what a holder is really asking when they ask what a profile says. The default is the cheap, non-disclosing one.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"profileId\"\n ],\n \"title\": \"Persona Profile Get — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/persona/profile/get/1.0#response";
const IS_PROOF_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"ClaimType\": {\n \"description\": \"The vocabulary token naming what a value IS — `name.legal`, `phone.mobile`, `address.postal`, `person.birthDate`. Dotted, most-general segment first, so that a consumer with no knowledge of the specific token can still group by its prefix.\\n\\nThe token is the maintainer's own; no external vocabulary is primary. External vocabularies (vCard/jCard, OIDC standard claims, schema.org) are mappings applied at PRESENTATION by a renderer, not at rest, so that a query written in any of them can be matched without the store having to live inside any one of them.\\n\\nThe `x:` prefix is an open extension namespace and is not decoration. The closest prior art — Windows CardSpace's self-issued card — supported exactly fifteen predefined claim types with no extensibility, and that is the specific way it failed the requirement a holder actually has. An `x:` attribute stores, composes, binds and discloses exactly like a known one; it renders generically and matches only an explicit query.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"pattern\": \"^(x:)?[a-z][a-zA-Z0-9]*(\\\\.[a-z][a-zA-Z0-9]*)*$\",\n \"title\": \"ClaimType\",\n \"type\": \"string\"\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 \"FaceReach\": {\n \"description\": \"Where a pool face may be worn. `anywhere` is the default and what an absent member means. `only` names the contexts it may be worn in, and a maintainer MUST refuse to wear it in any other (persona/binding/set `outsideReach`).\\n\\nA tagged object rather than a bare list of contexts, deliberately: an empty list has been read as both 'unrestricted' and 'nowhere' in this family's neighbours, and a shape where the two cannot be confused is worth more than one where they must be remembered. So `only` requires at least one context, and 'nowhere' is not a reach — it is a retired face.\\n\\nA context-local face has no reach: it lives in its context and is worn there by construction.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"anywhere\"\n }\n },\n \"required\": [\n \"kind\"\n ],\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"contextIds\": {\n \"items\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"maxItems\": 256,\n \"minItems\": 1,\n \"type\": \"array\",\n \"uniqueItems\": true\n },\n \"kind\": {\n \"const\": \"only\"\n }\n },\n \"required\": [\n \"kind\",\n \"contextIds\"\n ],\n \"type\": \"object\"\n }\n ],\n \"title\": \"FaceReach\"\n },\n \"Profile\": {\n \"additionalProperties\": false,\n \"description\": \"A named projection over the pool. Agent-scoped, like the pool it draws from. `entries` is ordered and the order is display order.\",\n \"properties\": {\n \"createdAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"credentialRefs\": {\n \"description\": \"Vault identifiers of credentials associated with this profile as INVENTORY, distinct from the evidence relationship a `credentialBacked` attribute expresses. The two answer different questions — what can this persona prove, versus what backs this specific claim — and a consumer MUST NOT read one as the other.\",\n \"items\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"maxItems\": 256,\n \"type\": \"array\"\n },\n \"entries\": {\n \"items\": {\n \"$ref\": \"#/$defs/ProfileEntry\"\n },\n \"maxItems\": 256,\n \"type\": \"array\"\n },\n \"name\": {\n \"description\": \"The holder's name for this profile — \\\"Work\\\", \\\"Gaming\\\". Not disclosed.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"profileId\": {\n \"$ref\": \"#/$defs/Ulid\"\n },\n \"reach\": {\n \"$ref\": \"#/$defs/FaceReach\"\n },\n \"retiredAt\": {\n \"description\": \"When the face was retired. Present exactly when `status` is `retired`.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"status\": {\n \"default\": \"active\",\n \"description\": \"`retired`: the face is worn nowhere, is left out of pickers and default listings, and cannot be worn until reinstated (persona/profile/retire, persona/profile/reinstate). Its disclosure history and every value it carries are kept — retiring is 'stop being this', not 'forget this'. Absent reads as `active`.\",\n \"enum\": [\n \"active\",\n \"retired\"\n ],\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"version\": {\n \"$ref\": \"#/$defs/Version\"\n }\n },\n \"required\": [\n \"profileId\",\n \"name\",\n \"entries\",\n \"version\",\n \"updatedAt\"\n ],\n \"title\": \"Profile\",\n \"type\": \"object\"\n },\n \"ProfileEntry\": {\n \"description\": \"One line of a profile, in exactly one of four forms. Together they are the whole of a profile's flexibility, and each exists for a case the others handle badly.\\n\\n`{ref}` — use the pool attribute, live. Editing the pool updates every profile that references it, which is the point.\\n\\n`{ref, pinVersion}` — use the value as it was at that version. For a profile that must keep presenting the value a counterparty already verified.\\n\\n`{ref, override}` — the same fact, a different value here. (\\\"In the gaming profile my display name is different.\\\")\\n\\n`{inline}` — a value that never enters the pool, and so never leaks into another profile.\\n\\nOmission is exclusion; there is no removal marker.\\n\\nAny form MAY carry a `slot` naming the role the entry plays in the profile — see `Slot`. A maintainer MUST refuse a profile in which two entries carry the same slot: a slot exists to answer one question with one entry.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"ref\": {\n \"$ref\": \"#/$defs/Ulid\"\n },\n \"slot\": {\n \"$ref\": \"#/$defs/Slot\"\n }\n },\n \"required\": [\n \"ref\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"pinVersion\": {\n \"$ref\": \"#/$defs/Version\"\n },\n \"ref\": {\n \"$ref\": \"#/$defs/Ulid\"\n },\n \"slot\": {\n \"$ref\": \"#/$defs/Slot\"\n }\n },\n \"required\": [\n \"ref\",\n \"pinVersion\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"override\": {\n \"additionalProperties\": false,\n \"description\": \"Replaces the pool attribute's value for this profile only. `type`, `valueType` and `provenance` are inherited from the referenced attribute and MUST NOT be overridden — an override that changed provenance would let a self-asserted value present as attested.\",\n \"properties\": {\n \"label\": {\n \"maxLength\": 128,\n \"type\": \"string\"\n },\n \"value\": {}\n },\n \"required\": [\n \"value\"\n ],\n \"type\": \"object\"\n },\n \"ref\": {\n \"$ref\": \"#/$defs/Ulid\"\n },\n \"slot\": {\n \"$ref\": \"#/$defs/Slot\"\n }\n },\n \"required\": [\n \"ref\",\n \"override\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"inline\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"label\": {\n \"maxLength\": 128,\n \"type\": \"string\"\n },\n \"provenance\": {\n \"$ref\": \"#/$defs/Provenance\"\n },\n \"type\": {\n \"$ref\": \"#/$defs/ClaimType\"\n },\n \"value\": {},\n \"valueType\": {\n \"$ref\": \"#/$defs/ValueType\"\n }\n },\n \"required\": [\n \"type\",\n \"valueType\",\n \"value\",\n \"provenance\"\n ],\n \"type\": \"object\"\n },\n \"slot\": {\n \"$ref\": \"#/$defs/Slot\"\n }\n },\n \"required\": [\n \"inline\"\n ]\n }\n ],\n \"title\": \"ProfileEntry\",\n \"type\": \"object\"\n },\n \"ProofRung\": {\n \"description\": \"How strongly a credential-backed claim is hidden when presented, ordered most private first. `predicate` proves a statement over a claim without disclosing the claim. `derived` discloses exactly the claims needed via an unlinkable derived proof, so two presentations cannot be joined. `selectiveDisclosure` discloses exactly the claims needed but carries the issuer's signature unchanged, so two presentations ARE linkable. `whole` discloses the entire credential.\\n\\nThe distinction between the first two and the last two is of kind, not degree: only `predicate` and `derived` avoid handing two verifiers a join key. A maintainer MUST default to the highest rung the credential's format supports, and MUST NOT silently fall to a lower one — a request that cannot be satisfied at the rung a producer asked for is refused, because a silent privacy downgrade discloses material the holder believed was hidden.\",\n \"enum\": [\n \"predicate\",\n \"derived\",\n \"selectiveDisclosure\",\n \"whole\"\n ],\n \"title\": \"ProofRung\",\n \"type\": \"string\"\n },\n \"Provenance\": {\n \"description\": \"Where a value comes from, and the member that makes this family worth building on a trust stack rather than in an address book. It survives to the verifier, so a recipient can tell — per field — what the holder typed from what an issuer attested.\\n\\n`selfAsserted` — the holder supplied it.\\n\\n`credentialBacked` — the value is derived from a credential in the vault at `claimPath`. The stored value is a CACHE FOR DISPLAY; the credential is the truth. A maintainer MUST re-derive it on read and MUST fail closed (never presenting a stale value) when the credential has been revoked, has expired, or has been archived or deleted.\\n\\n`generated` — the value is minted per verifier at disclosure time and recorded against that verifier, so every relying party receives a different one that routes back to the holder. This is the shape of the most widely adopted consumer privacy feature in this space; a maintainer need not operate a relay to conform, but the shape must exist, because retrofitting per-verifier values into a pool-of-values model is a migration rather than an addition.\\n\\n`derived` — the value was taken from a source the holder connected or supplied — a code-hosting profile, an uploaded CV — rather than typed by them or attested by an issuer. Nobody signed it: it is the holder's claim that the source said so, and a consumer MUST NOT present it as attested. It exists as its own kind because a derived value is neither of the others — the holder did not author it, and no one vouches for it — and a holder deciding whether to disclose deserves to know which of their values they typed.\\n\\nFor how strongly a disclosed value identifies the holder, the kinds rank `credentialBacked` above `derived` above `selfAsserted`; `generated` values are per-verifier and do not correlate.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"selfAsserted\"\n }\n },\n \"required\": [\n \"kind\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"claimPath\": {\n \"description\": \"RFC 6901 JSON Pointer to the claim within the credential, e.g. `/credentialSubject/familyName`.\",\n \"pattern\": \"^(/[^/~]*(~[01][^/~]*)*)*$\",\n \"type\": \"string\"\n },\n \"credentialId\": {\n \"description\": \"Vault identifier of the backing credential.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"issuerDid\": {\n \"description\": \"Issuer of the backing credential. Advisory: a consumer MUST verify the credential rather than trusting this member.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"credentialBacked\"\n },\n \"proof\": {\n \"$ref\": \"#/$defs/ProofRung\",\n \"description\": \"The disclosure rung this claim was, or will be, presented at.\"\n }\n },\n \"required\": [\n \"kind\",\n \"credentialId\",\n \"claimPath\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"generator\": {\n \"description\": \"Names the minting scheme, e.g. `relayEmail`. Maintainer-defined.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"generated\"\n },\n \"perVerifier\": {\n \"default\": true,\n \"description\": \"When true (the default and the only useful setting), a distinct value is minted for each verifier.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"kind\",\n \"generator\"\n ]\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"derivedAt\": {\n \"description\": \"When the value was taken from the source. A derived value is a snapshot: the source may have changed since, and nothing re-derives it.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"derived\"\n },\n \"source\": {\n \"description\": \"The KIND of source the value was taken from — `github`, `cvUpload`, `linkedIn` — never an account, handle or URL. Provenance survives to the verifier, so this member is disclosed with the claim; a handle here would disclose an identifier the holder never chose to share.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"pattern\": \"^[a-z][A-Za-z0-9.-]*$\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"source\",\n \"derivedAt\"\n ]\n }\n ],\n \"required\": [\n \"kind\"\n ],\n \"title\": \"Provenance\",\n \"type\": \"object\"\n },\n \"ResolvedClaim\": {\n \"additionalProperties\": false,\n \"description\": \"One line of a profile AFTER resolution: what the profile would present at this entry, rather than how the entry is written.\\n\\nDistinct from `Attribute` because a profile is a PROJECTION and may contain values that have no pool record behind them. An `inline` entry is a value the holder keeps in one profile and nowhere else — it has no `attributeId`, no `version` and no `updatedAt`, because there is no pool attribute to have them. Describing a resolved profile with the pool record's shape therefore cannot represent one at all, which leaves a maintainer choosing between synthesising an `attributeId` — a false claim about where a value lives — and omitting the entry, which returns a profile that appears to present less than it does. Neither is acceptable, so the projection gets its own shape.\\n\\nThe three pool members are consequently OPTIONAL and their absence is meaningful: it says this value is inline. Their PRESENCE is equally informative — `version` alongside a pinned entry is what lets a holder see that a profile is frozen at v3 while the pool has moved on.\",\n \"properties\": {\n \"attributeId\": {\n \"$ref\": \"#/$defs/Ulid\",\n \"description\": \"The pool attribute this entry resolves against. ABSENT for an `inline` entry, which is the whole distinction this member draws.\"\n },\n \"label\": {\n \"description\": \"The holder's own words, from the override where one is given and from the pool attribute otherwise. Never disclosed to a verifier.\",\n \"maxLength\": 128,\n \"type\": \"string\"\n },\n \"provenance\": {\n \"$ref\": \"#/$defs/Provenance\"\n },\n \"slot\": {\n \"$ref\": \"#/$defs/Slot\",\n \"description\": \"The slot of the entry this claim resolved from, where it has one.\"\n },\n \"stale\": {\n \"description\": \"Present and true when this entry cannot be presented — a credential-backed value that could not be re-derived, or a pin naming a version the maintainer no longer holds. Surfaced rather than omitted so a holder learns why a disclosure would be short.\",\n \"type\": \"boolean\"\n },\n \"staleReason\": {\n \"description\": \"Why the entry cannot be presented. Present only alongside `stale`.\",\n \"enum\": [\n \"revoked\",\n \"expired\",\n \"archived\",\n \"deleted\",\n \"notFound\"\n ],\n \"type\": \"string\"\n },\n \"type\": {\n \"$ref\": \"#/$defs/ClaimType\"\n },\n \"updatedAt\": {\n \"description\": \"When the pool attribute behind this entry was last written. ABSENT for an `inline` entry.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"value\": {\n \"description\": \"What this entry would present, with any override applied. Absent when `stale`, because a claim that could not be re-derived MUST NOT be disclosed and MUST NOT be shown as though it would be.\"\n },\n \"valueType\": {\n \"$ref\": \"#/$defs/ValueType\"\n },\n \"version\": {\n \"$ref\": \"#/$defs/Version\",\n \"description\": \"The pool attribute's version this entry resolved to — the pinned one for a pinned entry, the current one otherwise. ABSENT for an `inline` entry.\"\n }\n },\n \"required\": [\n \"type\",\n \"valueType\",\n \"provenance\"\n ],\n \"title\": \"ResolvedClaim\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"Success response to persona/profile/get. Type https://trusttasks.org/spec/persona/profile/get/1.0#response.\",\n \"properties\": {\n \"disclosedTo\": {\n \"additionalProperties\": false,\n \"description\": \"How many distinct parties this face has disclosed to, across how many contexts, from the holder's disclosure history. Counts, not identifiers; persona/disclosure/history names them. A producer shows this before a delete: deleting a face does not un-tell anyone what it told them.\",\n \"properties\": {\n \"contextCount\": {\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"partyCount\": {\n \"minimum\": 0,\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"partyCount\",\n \"contextCount\"\n ],\n \"type\": \"object\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"profile\": {\n \"$ref\": \"#/$defs/Profile\"\n },\n \"resolved\": {\n \"description\": \"Present only when `resolve` was true: the claims this profile would present, in entry order, with overrides applied and pinned versions honoured. A credential-backed claim whose backing could not be re-derived appears carrying `stale`, because a holder inspecting a profile needs to see that it has stopped being fully presentable.\\n\\nTyped as `ResolvedClaim` rather than `Attribute`: a profile is a projection and may contain `inline` values, which have no pool record and therefore no `attributeId`, `version` or `updatedAt`. The pool record's shape requires all three, so it cannot describe such an entry at all.\",\n \"items\": {\n \"$ref\": \"#/$defs/ResolvedClaim\"\n },\n \"maxItems\": 256,\n \"type\": \"array\"\n }\n },\n \"required\": [\n \"profile\"\n ],\n \"title\": \"Persona Profile Get — response payload\",\n \"type\": \"object\"\n },\n \"Slot\": {\n \"description\": \"A role a profile entry plays within its profile, so a consumer can find it without guessing from its claim type. A profile MAY hold several entries of one type — a legal name and a display name, two phone numbers — and only a slot says which answers a given question. Unique within a profile.\\n\\nWell-known slots:\\n\\n- `displayName` — what this face calls itself. The entry a consumer renders as the face's name to anyone it is shown to. Distinct from the profile's own `name`, which is the holder's private label and never disclosed.\\n- `primaryEmail`, `primaryPhone`, `primaryAddress` — the entry to use where a counterparty asks for one of a kind and the profile holds several.\\n- `avatar` — the image this face presents.\\n\\nOther values are the holder's or the producer's own and carry no meaning a maintainer interprets.\",\n \"pattern\": \"^[a-z][A-Za-z0-9]{0,31}$\",\n \"title\": \"Slot\",\n \"type\": \"string\"\n },\n \"Ulid\": {\n \"description\": \"A ULID in Crockford base32, uppercase. Used for `attributeId` and `profileId`. Chosen over a UUID because the leading 48 bits are a timestamp, so a key-ordered scan of the store is also creation-ordered and a `list` needs no secondary sort. Server-assigned on create; a producer MAY supply one to make a create idempotent, and a maintainer MUST reject a supplied value that already exists rather than silently overwriting.\",\n \"pattern\": \"^[0-9A-HJKMNP-TV-Z]{26}$\",\n \"title\": \"Ulid\",\n \"type\": \"string\"\n },\n \"ValueType\": {\n \"description\": \"The JSON shape of `value`, declared so that a consumer can render and compare without guessing. The maintainer validates that `value` agrees with this member and does nothing further: it does NOT validate a phone number against a phone-number grammar. That is a producer's affordance, and a store that grows opinions about the contents of its records eventually blocks its consumer's release.\",\n \"enum\": [\n \"string\",\n \"number\",\n \"boolean\",\n \"date\",\n \"object\"\n ],\n \"title\": \"ValueType\",\n \"type\": \"string\"\n },\n \"Version\": {\n \"description\": \"A value of the store's monotonic write counter. Server-assigned; a producer never chooses one.\",\n \"minimum\": 1,\n \"title\": \"Version\",\n \"type\": \"integer\"\n }\n },\n \"$ref\": \"#/$defs/Response\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n}\n",
);
}
impl crate::RequestPayload for Payload {
type Response = Response;
}
/// 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::NOT_FOUND];
/// 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 {
/// `persona/profile/get:notFound`
///
/// No profile exists at the given identifier.
///
/// Declared `retryable: false`.
pub const NOT_FOUND: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "persona/profile/get:notFound",
retryable: false,
};
}