//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vtc/directory/fields/update`. Version: `0.1`.
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
/// Error types.
pub mod error {
/// Error from a `TryFrom` or `FromStr` implementation.
pub struct ConversionError(::std::borrow::Cow<'static, str>);
impl ::std::error::Error for ConversionError {}
impl ::std::fmt::Display for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Display::fmt(&self.0, f)
}
}
impl ::std::fmt::Debug for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Debug::fmt(&self.0, f)
}
}
impl From<&'static str> for ConversionError {
fn from(value: &'static str) -> Self {
Self(value.into())
}
}
impl From<String> for ConversionError {
fn from(value: String) -> Self {
Self(value.into())
}
}
}
/**
Who may see a directory field, ordered from narrowest to widest. `admins`: holders of `vtc.directory.admin` (and, for derived fields, `vtc.members.manage`). `groups`: members who share at least one community group with the subject (narrowed to the groups the subject names in `groupAudience`, where it names any). `connections`: members holding an attributed, in-force verified relationship with the subject at the community. `members`: every active member. `public`: anyone, and what the member's signed public card carries outside the community.
`groups` and `connections` are not a chain: a viewer sees a field when they satisfy the audience the subject chose for it or any wider audience. Every audience includes the administrators, and the subject always sees their own whole card. There is no `onlyMe`: a value nobody else should see is not directory data.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Audience",
/// "description": "Who may see a directory field, ordered from narrowest to widest. `admins`: holders of `vtc.directory.admin` (and, for derived fields, `vtc.members.manage`). `groups`: members who share at least one community group with the subject (narrowed to the groups the subject names in `groupAudience`, where it names any). `connections`: members holding an attributed, in-force verified relationship with the subject at the community. `members`: every active member. `public`: anyone, and what the member's signed public card carries outside the community.\n\n`groups` and `connections` are not a chain: a viewer sees a field when they satisfy the audience the subject chose for it or any wider audience. Every audience includes the administrators, and the subject always sees their own whole card. There is no `onlyMe`: a value nobody else should see is not directory data.",
/// "type": "string",
/// "enum": [
/// "admins",
/// "groups",
/// "connections",
/// "members",
/// "public"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum Audience {
#[serde(rename = "admins")]
Admins,
#[serde(rename = "groups")]
Groups,
#[serde(rename = "connections")]
Connections,
#[serde(rename = "members")]
Members,
#[serde(rename = "public")]
Public,
}
impl ::std::fmt::Display for Audience {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Admins => f.write_str("admins"),
Self::Groups => f.write_str("groups"),
Self::Connections => f.write_str("connections"),
Self::Members => f.write_str("members"),
Self::Public => f.write_str("public"),
}
}
}
impl ::std::str::FromStr for Audience {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"admins" => Ok(Self::Admins),
"groups" => Ok(Self::Groups),
"connections" => Ok(Self::Connections),
"members" => Ok(Self::Members),
"public" => Ok(Self::Public),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for Audience {
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 Audience {
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 Audience {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Which claim a `claim` field accepts, from which credentials and issuers.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ClaimSelector",
/// "description": "Which claim a `claim` field accepts, from which credentials and issuers.",
/// "type": "object",
/// "required": [
/// "claimPath",
/// "credentialType"
/// ],
/// "properties": {
/// "claimPath": {
/// "description": "JSON Pointer (RFC 6901) to the claim within `credentialSubject`.",
/// "type": "string",
/// "maxLength": 256,
/// "minLength": 1
/// },
/// "credentialType": {
/// "description": "A `type` the presented credential MUST carry.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1
/// },
/// "issuers": {
/// "description": "Issuers the community accepts for this field. Absent: the community's trusted issuers for the credential type, as its own policy decides.",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "maxLength": 2048,
/// "pattern": "^did:"
/// },
/// "maxItems": 32,
/// "uniqueItems": true
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct ClaimSelector {
///JSON Pointer (RFC 6901) to the claim within `credentialSubject`.
#[serde(rename = "claimPath")]
pub claim_path: ClaimSelectorClaimPath,
///A `type` the presented credential MUST carry.
#[serde(rename = "credentialType")]
pub credential_type: ClaimSelectorCredentialType,
///Issuers the community accepts for this field. Absent: the community's trusted issuers for the credential type, as its own policy decides.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub issuers: ::std::option::Option<Vec<ClaimSelectorIssuersItem>>,
}
impl ClaimSelector {
pub fn builder() -> builder::ClaimSelector {
Default::default()
}
}
///JSON Pointer (RFC 6901) to the claim within `credentialSubject`.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "JSON Pointer (RFC 6901) to the claim within `credentialSubject`.",
/// "type": "string",
/// "maxLength": 256,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ClaimSelectorClaimPath(::std::string::String);
impl ::std::ops::Deref for ClaimSelectorClaimPath {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ClaimSelectorClaimPath> for ::std::string::String {
fn from(value: ClaimSelectorClaimPath) -> Self {
value.0
}
}
impl ::std::str::FromStr for ClaimSelectorClaimPath {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 256usize {
return Err("longer than 256 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ClaimSelectorClaimPath {
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 ClaimSelectorClaimPath {
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 ClaimSelectorClaimPath {
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 ClaimSelectorClaimPath {
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 `type` the presented credential MUST carry.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "A `type` the presented credential MUST carry.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ClaimSelectorCredentialType(::std::string::String);
impl ::std::ops::Deref for ClaimSelectorCredentialType {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ClaimSelectorCredentialType> for ::std::string::String {
fn from(value: ClaimSelectorCredentialType) -> Self {
value.0
}
}
impl ::std::str::FromStr for ClaimSelectorCredentialType {
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 ClaimSelectorCredentialType {
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 ClaimSelectorCredentialType {
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 ClaimSelectorCredentialType {
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 ClaimSelectorCredentialType {
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())
})
}
}
///`ClaimSelectorIssuersItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 2048,
/// "pattern": "^did:"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ClaimSelectorIssuersItem(::std::string::String);
impl ::std::ops::Deref for ClaimSelectorIssuersItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ClaimSelectorIssuersItem> for ::std::string::String {
fn from(value: ClaimSelectorIssuersItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for ClaimSelectorIssuersItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 2048usize {
return Err("longer than 2048 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^did:").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^did:\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ClaimSelectorIssuersItem {
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 ClaimSelectorIssuersItem {
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 ClaimSelectorIssuersItem {
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 ClaimSelectorIssuersItem {
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())
})
}
}
///`EnumOption`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "EnumOption",
/// "type": "object",
/// "required": [
/// "label",
/// "value"
/// ],
/// "properties": {
/// "label": {
/// "description": "What a reader is shown for it.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
/// },
/// "value": {
/// "description": "The stored value.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1,
/// "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct EnumOption {
///What a reader is shown for it.
pub label: EnumOptionLabel,
///The stored value.
pub value: EnumOptionValue,
}
impl EnumOption {
pub fn builder() -> builder::EnumOption {
Default::default()
}
}
///What a reader is shown for it.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "What a reader is shown for it.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct EnumOptionLabel(::std::string::String);
impl ::std::ops::Deref for EnumOptionLabel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<EnumOptionLabel> for ::std::string::String {
fn from(value: EnumOptionLabel) -> Self {
value.0
}
}
impl ::std::str::FromStr for EnumOptionLabel {
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 EnumOptionLabel {
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 EnumOptionLabel {
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 EnumOptionLabel {
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 EnumOptionLabel {
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 stored value.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The stored value.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1,
/// "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct EnumOptionValue(::std::string::String);
impl ::std::ops::Deref for EnumOptionValue {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<EnumOptionValue> for ::std::string::String {
fn from(value: EnumOptionValue) -> Self {
value.0
}
}
impl ::std::str::FromStr for EnumOptionValue {
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-zA-Z0-9][a-zA-Z0-9._-]{0,63}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for EnumOptionValue {
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 EnumOptionValue {
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 EnumOptionValue {
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 EnumOptionValue {
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())
})
}
}
///Per-type constraints. A member that does not apply to the field's type is refused by the community with `valueInvalid` when the definition is written.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "FieldConstraints",
/// "description": "Per-type constraints. A member that does not apply to the field's type is refused by the community with `valueInvalid` when the definition is written.",
/// "type": "object",
/// "properties": {
/// "claim": {
/// "$ref": "#/definitions/ClaimSelector"
/// },
/// "maxDate": {
/// "type": "string",
/// "format": "date"
/// },
/// "maxItems": {
/// "type": "integer",
/// "maximum": 32.0,
/// "minimum": 1.0
/// },
/// "maxLength": {
/// "type": "integer",
/// "maximum": 2000.0,
/// "minimum": 1.0
/// },
/// "minDate": {
/// "type": "string",
/// "format": "date"
/// },
/// "minLength": {
/// "type": "integer",
/// "maximum": 2000.0,
/// "minimum": 0.0
/// },
/// "options": {
/// "description": "The permitted values of an `enum` or `multiEnum` field.",
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/EnumOption"
/// },
/// "maxItems": 128,
/// "minItems": 1
/// },
/// "pattern": {
/// "description": "ECMA-262 regular expression a text value MUST match.",
/// "type": "string",
/// "maxLength": 256,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct FieldConstraints {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub claim: ::std::option::Option<ClaimSelector>,
#[serde(
rename = "maxDate",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub max_date: ::std::option::Option<::chrono::naive::NaiveDate>,
#[serde(
rename = "maxItems",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub max_items: ::std::option::Option<::std::num::NonZeroU64>,
#[serde(
rename = "maxLength",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub max_length: ::std::option::Option<::std::num::NonZeroU64>,
#[serde(
rename = "minDate",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub min_date: ::std::option::Option<::chrono::naive::NaiveDate>,
#[serde(
rename = "minLength",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub min_length: ::std::option::Option<i64>,
///The permitted values of an `enum` or `multiEnum` field.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub options: ::std::vec::Vec<EnumOption>,
///ECMA-262 regular expression a text value MUST match.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub pattern: ::std::option::Option<FieldConstraintsPattern>,
}
impl ::std::default::Default for FieldConstraints {
fn default() -> Self {
Self {
claim: Default::default(),
max_date: Default::default(),
max_items: Default::default(),
max_length: Default::default(),
min_date: Default::default(),
min_length: Default::default(),
options: Default::default(),
pattern: Default::default(),
}
}
}
impl FieldConstraints {
pub fn builder() -> builder::FieldConstraints {
Default::default()
}
}
///ECMA-262 regular expression a text value MUST match.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "ECMA-262 regular expression a text value MUST match.",
/// "type": "string",
/// "maxLength": 256,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct FieldConstraintsPattern(::std::string::String);
impl ::std::ops::Deref for FieldConstraintsPattern {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<FieldConstraintsPattern> for ::std::string::String {
fn from(value: FieldConstraintsPattern) -> Self {
value.0
}
}
impl ::std::str::FromStr for FieldConstraintsPattern {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 256usize {
return Err("longer than 256 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for FieldConstraintsPattern {
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 FieldConstraintsPattern {
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 FieldConstraintsPattern {
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 FieldConstraintsPattern {
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 field of the community's directory schema, as the community holds it. The audience order `admins` < `groups`/`connections` < `members` < `public` applies to `ceiling` and `defaultVisibility`; `defaultVisibility` is never wider than `ceiling`.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "FieldDefinition",
/// "description": "One field of the community's directory schema, as the community holds it. The audience order `admins` < `groups`/`connections` < `members` < `public` applies to `ceiling` and `defaultVisibility`; `defaultVisibility` is never wider than `ceiling`.",
/// "type": "object",
/// "required": [
/// "base",
/// "ceiling",
/// "defaultVisibility",
/// "facet",
/// "key",
/// "label",
/// "order",
/// "required",
/// "searchable",
/// "source",
/// "state",
/// "type"
/// ],
/// "properties": {
/// "base": {
/// "description": "`true` for a base field, present in every community; `false` for a field this community defined.",
/// "type": "boolean"
/// },
/// "ceiling": {
/// "$ref": "#/definitions/Audience"
/// },
/// "constraints": {
/// "$ref": "#/definitions/FieldConstraints"
/// },
/// "defaultVisibility": {
/// "$ref": "#/definitions/Audience"
/// },
/// "description": {
/// "$ref": "#/definitions/FieldDescription"
/// },
/// "ext": {
/// "description": "Ecosystem-defined extension members per SPEC.md §4.5.1. An extension member MUST NOT widen a ceiling.",
/// "$ref": "#/definitions/Ext"
/// },
/// "facet": {
/// "type": "boolean"
/// },
/// "jsContactPath": {
/// "description": "Where the field lands when an entry is exported as a JSContact Card (RFC 9553), e.g. `name.full`, `nicknames`, `speakToAs.pronouns`. Absent: a vendor-specific property named by the key.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1
/// },
/// "key": {
/// "$ref": "#/definitions/FieldKey"
/// },
/// "label": {
/// "$ref": "#/definitions/FieldLabel"
/// },
/// "order": {
/// "type": "integer",
/// "maximum": 10000.0,
/// "minimum": 0.0
/// },
/// "purgeAfter": {
/// "description": "When the values of a retired field are purged. Present only on a retired field.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "required": {
/// "type": "boolean"
/// },
/// "retiredAt": {
/// "description": "When the field was retired. Present only on a retired field.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "searchable": {
/// "type": "boolean"
/// },
/// "source": {
/// "$ref": "#/definitions/FieldSource"
/// },
/// "state": {
/// "$ref": "#/definitions/FieldState"
/// },
/// "type": {
/// "$ref": "#/definitions/FieldType"
/// },
/// "updatedAt": {
/// "type": "string",
/// "format": "date-time"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct FieldDefinition {
///`true` for a base field, present in every community; `false` for a field this community defined.
pub base: bool,
pub ceiling: Audience,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub constraints: ::std::option::Option<FieldConstraints>,
#[serde(rename = "defaultVisibility")]
pub default_visibility: Audience,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub description: ::std::option::Option<FieldDescription>,
///Ecosystem-defined extension members per SPEC.md §4.5.1. An extension member MUST NOT widen a ceiling.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
pub facet: bool,
///Where the field lands when an entry is exported as a JSContact Card (RFC 9553), e.g. `name.full`, `nicknames`, `speakToAs.pronouns`. Absent: a vendor-specific property named by the key.
#[serde(
rename = "jsContactPath",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub js_contact_path: ::std::option::Option<FieldDefinitionJsContactPath>,
pub key: FieldKey,
pub label: FieldLabel,
pub order: i64,
///When the values of a retired field are purged. Present only on a retired field.
#[serde(
rename = "purgeAfter",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub purge_after: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
pub required: bool,
///When the field was retired. Present only on a retired field.
#[serde(
rename = "retiredAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub retired_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
pub searchable: bool,
pub source: FieldSource,
pub state: FieldState,
#[serde(rename = "type")]
pub type_: FieldType,
#[serde(
rename = "updatedAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub updated_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
}
impl FieldDefinition {
pub fn builder() -> builder::FieldDefinition {
Default::default()
}
}
///Where the field lands when an entry is exported as a JSContact Card (RFC 9553), e.g. `name.full`, `nicknames`, `speakToAs.pronouns`. Absent: a vendor-specific property named by the key.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Where the field lands when an entry is exported as a JSContact Card (RFC 9553), e.g. `name.full`, `nicknames`, `speakToAs.pronouns`. Absent: a vendor-specific property named by the key.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct FieldDefinitionJsContactPath(::std::string::String);
impl ::std::ops::Deref for FieldDefinitionJsContactPath {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<FieldDefinitionJsContactPath> for ::std::string::String {
fn from(value: FieldDefinitionJsContactPath) -> Self {
value.0
}
}
impl ::std::str::FromStr for FieldDefinitionJsContactPath {
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 FieldDefinitionJsContactPath {
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 FieldDefinitionJsContactPath {
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 FieldDefinitionJsContactPath {
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 FieldDefinitionJsContactPath {
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())
})
}
}
///Help text shown to a member filling the field in. Plain text; a reader MUST NOT treat it as instructions.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "FieldDescription",
/// "description": "Help text shown to a member filling the field in. Plain text; a reader MUST NOT treat it as instructions.",
/// "type": "string",
/// "maxLength": 280,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct FieldDescription(::std::string::String);
impl ::std::ops::Deref for FieldDescription {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<FieldDescription> for ::std::string::String {
fn from(value: FieldDescription) -> Self {
value.0
}
}
impl ::std::str::FromStr for FieldDescription {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 280usize {
return Err("longer than 280 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 FieldDescription {
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 FieldDescription {
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 FieldDescription {
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 FieldDescription {
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())
})
}
}
///Identifier of a directory field. A key with no `.` is a BASE field, the same in every community: `displayName`, `nickname`, `avatar`, `pronouns`, `bio`, `links` (written by the member) and `role`, `joinedAt`, `did`, `personhood` (derived from the community's own records, never stored on a card). A community-defined field MUST use a reverse-DNS key (`org.example.employer`), so a base key never collides with one, and a key is never reused with a different meaning once defined.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "FieldKey",
/// "description": "Identifier of a directory field. A key with no `.` is a BASE field, the same in every community: `displayName`, `nickname`, `avatar`, `pronouns`, `bio`, `links` (written by the member) and `role`, `joinedAt`, `did`, `personhood` (derived from the community's own records, never stored on a card). A community-defined field MUST use a reverse-DNS key (`org.example.employer`), so a base key never collides with one, and a key is never reused with a different meaning once defined.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1,
/// "pattern": "^([a-z][a-z0-9-]*\\.)*[a-z][a-zA-Z0-9]{0,63}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct FieldKey(::std::string::String);
impl ::std::ops::Deref for FieldKey {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<FieldKey> for ::std::string::String {
fn from(value: FieldKey) -> Self {
value.0
}
}
impl ::std::str::FromStr for FieldKey {
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("^([a-z][a-z0-9-]*\\.)*[a-z][a-zA-Z0-9]{0,63}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err(
"doesn't match pattern \"^([a-z][a-z0-9-]*\\.)*[a-z][a-zA-Z0-9]{0,63}$\"".into(),
);
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for FieldKey {
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 FieldKey {
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 FieldKey {
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 FieldKey {
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())
})
}
}
///What readers see as the field's name. Plain text.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "FieldLabel",
/// "description": "What readers see as the field's name. Plain text.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct FieldLabel(::std::string::String);
impl ::std::ops::Deref for FieldLabel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<FieldLabel> for ::std::string::String {
fn from(value: FieldLabel) -> Self {
value.0
}
}
impl ::std::str::FromStr for FieldLabel {
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 FieldLabel {
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 FieldLabel {
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 FieldLabel {
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 FieldLabel {
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())
})
}
}
///Who writes the value. `member`: self-asserted, through vtc/directory/card/update. `admin`: asserted by the community through vtc/directory/card/assert; the member reads it and cannot change it. `credential`: a claim the member discloses from a credential through vtc/directory/card/present, badged with its issuer. `derived`: a base field read from the community's own records (`role`, `joinedAt`, `did`, `personhood`) and never stored on a card. Each source is written only through its own path.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "FieldSource",
/// "description": "Who writes the value. `member`: self-asserted, through vtc/directory/card/update. `admin`: asserted by the community through vtc/directory/card/assert; the member reads it and cannot change it. `credential`: a claim the member discloses from a credential through vtc/directory/card/present, badged with its issuer. `derived`: a base field read from the community's own records (`role`, `joinedAt`, `did`, `personhood`) and never stored on a card. Each source is written only through its own path.",
/// "type": "string",
/// "enum": [
/// "member",
/// "admin",
/// "credential",
/// "derived"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum FieldSource {
#[serde(rename = "member")]
Member,
#[serde(rename = "admin")]
Admin,
#[serde(rename = "credential")]
Credential,
#[serde(rename = "derived")]
Derived,
}
impl ::std::fmt::Display for FieldSource {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Member => f.write_str("member"),
Self::Admin => f.write_str("admin"),
Self::Credential => f.write_str("credential"),
Self::Derived => f.write_str("derived"),
}
}
}
impl ::std::str::FromStr for FieldSource {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"member" => Ok(Self::Member),
"admin" => Ok(Self::Admin),
"credential" => Ok(Self::Credential),
"derived" => Ok(Self::Derived),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for FieldSource {
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 FieldSource {
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 FieldSource {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`active`: in use. `disabled`: a base field the community has switched off; hidden from every projection and re-enablable. `retired`: a community field withdrawn for good; hidden at once, its values purged after the community's retention period, and its key never reused.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "FieldState",
/// "description": "`active`: in use. `disabled`: a base field the community has switched off; hidden from every projection and re-enablable. `retired`: a community field withdrawn for good; hidden at once, its values purged after the community's retention period, and its key never reused.",
/// "type": "string",
/// "enum": [
/// "active",
/// "disabled",
/// "retired"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum FieldState {
#[serde(rename = "active")]
Active,
#[serde(rename = "disabled")]
Disabled,
#[serde(rename = "retired")]
Retired,
}
impl ::std::fmt::Display for FieldState {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Active => f.write_str("active"),
Self::Disabled => f.write_str("disabled"),
Self::Retired => f.write_str("retired"),
}
}
}
impl ::std::str::FromStr for FieldState {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"active" => Ok(Self::Active),
"disabled" => Ok(Self::Disabled),
"retired" => Ok(Self::Retired),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for FieldState {
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 FieldState {
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 FieldState {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///The kind of value a field holds, which fixes its `FieldValue` shape. `did` holds a DID the member chooses to show (never their membership DID, which is the derived base field `did`). `claim` holds a `VerifiedValue` and requires `source: credential`.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "FieldType",
/// "description": "The kind of value a field holds, which fixes its `FieldValue` shape. `did` holds a DID the member chooses to show (never their membership DID, which is the derived base field `did`). `claim` holds a `VerifiedValue` and requires `source: credential`.",
/// "type": "string",
/// "enum": [
/// "text",
/// "longText",
/// "url",
/// "email",
/// "phone",
/// "enum",
/// "multiEnum",
/// "date",
/// "country",
/// "image",
/// "did",
/// "claim"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum FieldType {
#[serde(rename = "text")]
Text,
#[serde(rename = "longText")]
LongText,
#[serde(rename = "url")]
Url,
#[serde(rename = "email")]
Email,
#[serde(rename = "phone")]
Phone,
#[serde(rename = "enum")]
Enum,
#[serde(rename = "multiEnum")]
MultiEnum,
#[serde(rename = "date")]
Date,
#[serde(rename = "country")]
Country,
#[serde(rename = "image")]
Image,
#[serde(rename = "did")]
Did,
#[serde(rename = "claim")]
Claim,
}
impl ::std::fmt::Display for FieldType {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Text => f.write_str("text"),
Self::LongText => f.write_str("longText"),
Self::Url => f.write_str("url"),
Self::Email => f.write_str("email"),
Self::Phone => f.write_str("phone"),
Self::Enum => f.write_str("enum"),
Self::MultiEnum => f.write_str("multiEnum"),
Self::Date => f.write_str("date"),
Self::Country => f.write_str("country"),
Self::Image => f.write_str("image"),
Self::Did => f.write_str("did"),
Self::Claim => f.write_str("claim"),
}
}
}
impl ::std::str::FromStr for FieldType {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"text" => Ok(Self::Text),
"longText" => Ok(Self::LongText),
"url" => Ok(Self::Url),
"email" => Ok(Self::Email),
"phone" => Ok(Self::Phone),
"enum" => Ok(Self::Enum),
"multiEnum" => Ok(Self::MultiEnum),
"date" => Ok(Self::Date),
"country" => Ok(Self::Country),
"image" => Ok(Self::Image),
"did" => Ok(Self::Did),
"claim" => Ok(Self::Claim),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for FieldType {
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 FieldType {
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 FieldType {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///An administrator changes a directory field's label, help text, constraints, order, ceiling or default visibility, or disables or re-enables a base field. The outer document members are owned by the framework — SPEC §6.3.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/vtc/directory/fields/update/0.1",
/// "title": "Payload",
/// "description": "An administrator changes a directory field's label, help text, constraints, order, ceiling or default visibility, or disables or re-enables a base field. The outer document members are owned by the framework — SPEC §6.3.",
/// "type": "object",
/// "required": [
/// "key"
/// ],
/// "properties": {
/// "ceiling": {
/// "$ref": "#/definitions/Audience"
/// },
/// "constraints": {
/// "description": "Replaces the constraints whole. Values already stored that no longer satisfy them stay until their writer next changes them; projections show them unchanged.",
/// "$ref": "#/definitions/FieldConstraints"
/// },
/// "defaultVisibility": {
/// "$ref": "#/definitions/Audience"
/// },
/// "description": {
/// "$ref": "#/definitions/FieldDescription"
/// },
/// "enabled": {
/// "description": "Base fields only: `false` disables the field (hidden from every projection, values kept), `true` re-enables it.",
/// "type": "boolean"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "facet": {
/// "type": "boolean"
/// },
/// "key": {
/// "$ref": "#/definitions/FieldKey"
/// },
/// "label": {
/// "$ref": "#/definitions/FieldLabel"
/// },
/// "order": {
/// "type": "integer",
/// "maximum": 10000.0,
/// "minimum": 0.0
/// },
/// "reason": {
/// "description": "Why, recorded with the change and shown to anyone who must approve it.",
/// "type": "string",
/// "maxLength": 1024,
/// "minLength": 1
/// },
/// "required": {
/// "type": "boolean"
/// },
/// "searchable": {
/// "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 ceiling: ::std::option::Option<Audience>,
///Replaces the constraints whole. Values already stored that no longer satisfy them stay until their writer next changes them; projections show them unchanged.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub constraints: ::std::option::Option<FieldConstraints>,
#[serde(
rename = "defaultVisibility",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub default_visibility: ::std::option::Option<Audience>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub description: ::std::option::Option<FieldDescription>,
///Base fields only: `false` disables the field (hidden from every projection, values kept), `true` re-enables it.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub enabled: ::std::option::Option<bool>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub facet: ::std::option::Option<bool>,
pub key: FieldKey,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub label: ::std::option::Option<FieldLabel>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub order: ::std::option::Option<i64>,
///Why, recorded with the change and shown to anyone who must approve it.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reason: ::std::option::Option<PayloadReason>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub required: ::std::option::Option<bool>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub searchable: ::std::option::Option<bool>,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///Why, recorded with the change and shown to anyone who must approve it.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Why, recorded with the change and shown to anyone who must approve it.",
/// "type": "string",
/// "maxLength": 1024,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadReason(::std::string::String);
impl ::std::ops::Deref for PayloadReason {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadReason> for ::std::string::String {
fn from(value: PayloadReason) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadReason {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 1024usize {
return Err("longer than 1024 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 PayloadReason {
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 PayloadReason {
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 PayloadReason {
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 PayloadReason {
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 success response to a vtc/directory/fields/update/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/fields/update/0.1#response.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "The success response to a vtc/directory/fields/update/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/fields/update/0.1#response.",
/// "type": "object",
/// "required": [
/// "field"
/// ],
/// "properties": {
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "field": {
/// "$ref": "#/definitions/FieldDefinition"
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Response {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
pub field: FieldDefinition,
}
impl Response {
pub fn builder() -> builder::Response {
Default::default()
}
}
/// Types for composing complex structures.
pub mod builder {
#[derive(Clone, Debug)]
pub struct ClaimSelector {
claim_path: ::std::result::Result<super::ClaimSelectorClaimPath, ::std::string::String>,
credential_type:
::std::result::Result<super::ClaimSelectorCredentialType, ::std::string::String>,
issuers: ::std::result::Result<
::std::option::Option<Vec<super::ClaimSelectorIssuersItem>>,
::std::string::String,
>,
}
impl ::std::default::Default for ClaimSelector {
fn default() -> Self {
Self {
claim_path: Err("no value supplied for claim_path".to_string()),
credential_type: Err("no value supplied for credential_type".to_string()),
issuers: Ok(Default::default()),
}
}
}
impl ClaimSelector {
pub fn claim_path<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ClaimSelectorClaimPath>,
T::Error: ::std::fmt::Display,
{
self.claim_path = value
.try_into()
.map_err(|e| format!("error converting supplied value for claim_path: {e}"));
self
}
pub fn credential_type<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ClaimSelectorCredentialType>,
T::Error: ::std::fmt::Display,
{
self.credential_type = value
.try_into()
.map_err(|e| format!("error converting supplied value for credential_type: {e}"));
self
}
pub fn issuers<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<Vec<super::ClaimSelectorIssuersItem>>>,
T::Error: ::std::fmt::Display,
{
self.issuers = value
.try_into()
.map_err(|e| format!("error converting supplied value for issuers: {e}"));
self
}
}
impl ::std::convert::TryFrom<ClaimSelector> for super::ClaimSelector {
type Error = super::error::ConversionError;
fn try_from(
value: ClaimSelector,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
claim_path: value.claim_path?,
credential_type: value.credential_type?,
issuers: value.issuers?,
})
}
}
impl ::std::convert::From<super::ClaimSelector> for ClaimSelector {
fn from(value: super::ClaimSelector) -> Self {
Self {
claim_path: Ok(value.claim_path),
credential_type: Ok(value.credential_type),
issuers: Ok(value.issuers),
}
}
}
#[derive(Clone, Debug)]
pub struct EnumOption {
label: ::std::result::Result<super::EnumOptionLabel, ::std::string::String>,
value: ::std::result::Result<super::EnumOptionValue, ::std::string::String>,
}
impl ::std::default::Default for EnumOption {
fn default() -> Self {
Self {
label: Err("no value supplied for label".to_string()),
value: Err("no value supplied for value".to_string()),
}
}
}
impl EnumOption {
pub fn label<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::EnumOptionLabel>,
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<super::EnumOptionValue>,
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<EnumOption> for super::EnumOption {
type Error = super::error::ConversionError;
fn try_from(
value: EnumOption,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
label: value.label?,
value: value.value?,
})
}
}
impl ::std::convert::From<super::EnumOption> for EnumOption {
fn from(value: super::EnumOption) -> Self {
Self {
label: Ok(value.label),
value: Ok(value.value),
}
}
}
#[derive(Clone, Debug)]
pub struct FieldConstraints {
claim: ::std::result::Result<
::std::option::Option<super::ClaimSelector>,
::std::string::String,
>,
max_date: ::std::result::Result<
::std::option::Option<::chrono::naive::NaiveDate>,
::std::string::String,
>,
max_items: ::std::result::Result<
::std::option::Option<::std::num::NonZeroU64>,
::std::string::String,
>,
max_length: ::std::result::Result<
::std::option::Option<::std::num::NonZeroU64>,
::std::string::String,
>,
min_date: ::std::result::Result<
::std::option::Option<::chrono::naive::NaiveDate>,
::std::string::String,
>,
min_length: ::std::result::Result<::std::option::Option<i64>, ::std::string::String>,
options: ::std::result::Result<::std::vec::Vec<super::EnumOption>, ::std::string::String>,
pattern: ::std::result::Result<
::std::option::Option<super::FieldConstraintsPattern>,
::std::string::String,
>,
}
impl ::std::default::Default for FieldConstraints {
fn default() -> Self {
Self {
claim: Ok(Default::default()),
max_date: Ok(Default::default()),
max_items: Ok(Default::default()),
max_length: Ok(Default::default()),
min_date: Ok(Default::default()),
min_length: Ok(Default::default()),
options: Ok(Default::default()),
pattern: Ok(Default::default()),
}
}
}
impl FieldConstraints {
pub fn claim<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ClaimSelector>>,
T::Error: ::std::fmt::Display,
{
self.claim = value
.try_into()
.map_err(|e| format!("error converting supplied value for claim: {e}"));
self
}
pub fn max_date<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::chrono::naive::NaiveDate>>,
T::Error: ::std::fmt::Display,
{
self.max_date = value
.try_into()
.map_err(|e| format!("error converting supplied value for max_date: {e}"));
self
}
pub fn max_items<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::num::NonZeroU64>>,
T::Error: ::std::fmt::Display,
{
self.max_items = value
.try_into()
.map_err(|e| format!("error converting supplied value for max_items: {e}"));
self
}
pub fn max_length<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::num::NonZeroU64>>,
T::Error: ::std::fmt::Display,
{
self.max_length = value
.try_into()
.map_err(|e| format!("error converting supplied value for max_length: {e}"));
self
}
pub fn min_date<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::chrono::naive::NaiveDate>>,
T::Error: ::std::fmt::Display,
{
self.min_date = value
.try_into()
.map_err(|e| format!("error converting supplied value for min_date: {e}"));
self
}
pub fn min_length<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<i64>>,
T::Error: ::std::fmt::Display,
{
self.min_length = value
.try_into()
.map_err(|e| format!("error converting supplied value for min_length: {e}"));
self
}
pub fn options<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::EnumOption>>,
T::Error: ::std::fmt::Display,
{
self.options = value
.try_into()
.map_err(|e| format!("error converting supplied value for options: {e}"));
self
}
pub fn pattern<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::FieldConstraintsPattern>>,
T::Error: ::std::fmt::Display,
{
self.pattern = value
.try_into()
.map_err(|e| format!("error converting supplied value for pattern: {e}"));
self
}
}
impl ::std::convert::TryFrom<FieldConstraints> for super::FieldConstraints {
type Error = super::error::ConversionError;
fn try_from(
value: FieldConstraints,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
claim: value.claim?,
max_date: value.max_date?,
max_items: value.max_items?,
max_length: value.max_length?,
min_date: value.min_date?,
min_length: value.min_length?,
options: value.options?,
pattern: value.pattern?,
})
}
}
impl ::std::convert::From<super::FieldConstraints> for FieldConstraints {
fn from(value: super::FieldConstraints) -> Self {
Self {
claim: Ok(value.claim),
max_date: Ok(value.max_date),
max_items: Ok(value.max_items),
max_length: Ok(value.max_length),
min_date: Ok(value.min_date),
min_length: Ok(value.min_length),
options: Ok(value.options),
pattern: Ok(value.pattern),
}
}
}
#[derive(Clone, Debug)]
pub struct FieldDefinition {
base: ::std::result::Result<bool, ::std::string::String>,
ceiling: ::std::result::Result<super::Audience, ::std::string::String>,
constraints: ::std::result::Result<
::std::option::Option<super::FieldConstraints>,
::std::string::String,
>,
default_visibility: ::std::result::Result<super::Audience, ::std::string::String>,
description: ::std::result::Result<
::std::option::Option<super::FieldDescription>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
facet: ::std::result::Result<bool, ::std::string::String>,
js_contact_path: ::std::result::Result<
::std::option::Option<super::FieldDefinitionJsContactPath>,
::std::string::String,
>,
key: ::std::result::Result<super::FieldKey, ::std::string::String>,
label: ::std::result::Result<super::FieldLabel, ::std::string::String>,
order: ::std::result::Result<i64, ::std::string::String>,
purge_after: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
required: ::std::result::Result<bool, ::std::string::String>,
retired_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
searchable: ::std::result::Result<bool, ::std::string::String>,
source: ::std::result::Result<super::FieldSource, ::std::string::String>,
state: ::std::result::Result<super::FieldState, ::std::string::String>,
type_: ::std::result::Result<super::FieldType, ::std::string::String>,
updated_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
}
impl ::std::default::Default for FieldDefinition {
fn default() -> Self {
Self {
base: Err("no value supplied for base".to_string()),
ceiling: Err("no value supplied for ceiling".to_string()),
constraints: Ok(Default::default()),
default_visibility: Err("no value supplied for default_visibility".to_string()),
description: Ok(Default::default()),
ext: Ok(Default::default()),
facet: Err("no value supplied for facet".to_string()),
js_contact_path: Ok(Default::default()),
key: Err("no value supplied for key".to_string()),
label: Err("no value supplied for label".to_string()),
order: Err("no value supplied for order".to_string()),
purge_after: Ok(Default::default()),
required: Err("no value supplied for required".to_string()),
retired_at: Ok(Default::default()),
searchable: Err("no value supplied for searchable".to_string()),
source: Err("no value supplied for source".to_string()),
state: Err("no value supplied for state".to_string()),
type_: Err("no value supplied for type_".to_string()),
updated_at: Ok(Default::default()),
}
}
}
impl FieldDefinition {
pub fn base<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<bool>,
T::Error: ::std::fmt::Display,
{
self.base = value
.try_into()
.map_err(|e| format!("error converting supplied value for base: {e}"));
self
}
pub fn ceiling<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Audience>,
T::Error: ::std::fmt::Display,
{
self.ceiling = value
.try_into()
.map_err(|e| format!("error converting supplied value for ceiling: {e}"));
self
}
pub fn constraints<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::FieldConstraints>>,
T::Error: ::std::fmt::Display,
{
self.constraints = value
.try_into()
.map_err(|e| format!("error converting supplied value for constraints: {e}"));
self
}
pub fn default_visibility<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Audience>,
T::Error: ::std::fmt::Display,
{
self.default_visibility = value.try_into().map_err(|e| {
format!("error converting supplied value for default_visibility: {e}")
});
self
}
pub fn description<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::FieldDescription>>,
T::Error: ::std::fmt::Display,
{
self.description = value
.try_into()
.map_err(|e| format!("error converting supplied value for description: {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 facet<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<bool>,
T::Error: ::std::fmt::Display,
{
self.facet = value
.try_into()
.map_err(|e| format!("error converting supplied value for facet: {e}"));
self
}
pub fn js_contact_path<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::FieldDefinitionJsContactPath>>,
T::Error: ::std::fmt::Display,
{
self.js_contact_path = value
.try_into()
.map_err(|e| format!("error converting supplied value for js_contact_path: {e}"));
self
}
pub fn key<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::FieldKey>,
T::Error: ::std::fmt::Display,
{
self.key = value
.try_into()
.map_err(|e| format!("error converting supplied value for key: {e}"));
self
}
pub fn label<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::FieldLabel>,
T::Error: ::std::fmt::Display,
{
self.label = value
.try_into()
.map_err(|e| format!("error converting supplied value for label: {e}"));
self
}
pub fn order<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<i64>,
T::Error: ::std::fmt::Display,
{
self.order = value
.try_into()
.map_err(|e| format!("error converting supplied value for order: {e}"));
self
}
pub fn purge_after<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.purge_after = value
.try_into()
.map_err(|e| format!("error converting supplied value for purge_after: {e}"));
self
}
pub fn required<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<bool>,
T::Error: ::std::fmt::Display,
{
self.required = value
.try_into()
.map_err(|e| format!("error converting supplied value for required: {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 searchable<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<bool>,
T::Error: ::std::fmt::Display,
{
self.searchable = value
.try_into()
.map_err(|e| format!("error converting supplied value for searchable: {e}"));
self
}
pub fn source<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::FieldSource>,
T::Error: ::std::fmt::Display,
{
self.source = value
.try_into()
.map_err(|e| format!("error converting supplied value for source: {e}"));
self
}
pub fn state<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::FieldState>,
T::Error: ::std::fmt::Display,
{
self.state = value
.try_into()
.map_err(|e| format!("error converting supplied value for state: {e}"));
self
}
pub fn type_<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::FieldType>,
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
}
}
impl ::std::convert::TryFrom<FieldDefinition> for super::FieldDefinition {
type Error = super::error::ConversionError;
fn try_from(
value: FieldDefinition,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
base: value.base?,
ceiling: value.ceiling?,
constraints: value.constraints?,
default_visibility: value.default_visibility?,
description: value.description?,
ext: value.ext?,
facet: value.facet?,
js_contact_path: value.js_contact_path?,
key: value.key?,
label: value.label?,
order: value.order?,
purge_after: value.purge_after?,
required: value.required?,
retired_at: value.retired_at?,
searchable: value.searchable?,
source: value.source?,
state: value.state?,
type_: value.type_?,
updated_at: value.updated_at?,
})
}
}
impl ::std::convert::From<super::FieldDefinition> for FieldDefinition {
fn from(value: super::FieldDefinition) -> Self {
Self {
base: Ok(value.base),
ceiling: Ok(value.ceiling),
constraints: Ok(value.constraints),
default_visibility: Ok(value.default_visibility),
description: Ok(value.description),
ext: Ok(value.ext),
facet: Ok(value.facet),
js_contact_path: Ok(value.js_contact_path),
key: Ok(value.key),
label: Ok(value.label),
order: Ok(value.order),
purge_after: Ok(value.purge_after),
required: Ok(value.required),
retired_at: Ok(value.retired_at),
searchable: Ok(value.searchable),
source: Ok(value.source),
state: Ok(value.state),
type_: Ok(value.type_),
updated_at: Ok(value.updated_at),
}
}
}
#[derive(Clone, Debug)]
pub struct Payload {
ceiling:
::std::result::Result<::std::option::Option<super::Audience>, ::std::string::String>,
constraints: ::std::result::Result<
::std::option::Option<super::FieldConstraints>,
::std::string::String,
>,
default_visibility:
::std::result::Result<::std::option::Option<super::Audience>, ::std::string::String>,
description: ::std::result::Result<
::std::option::Option<super::FieldDescription>,
::std::string::String,
>,
enabled: ::std::result::Result<::std::option::Option<bool>, ::std::string::String>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
facet: ::std::result::Result<::std::option::Option<bool>, ::std::string::String>,
key: ::std::result::Result<super::FieldKey, ::std::string::String>,
label:
::std::result::Result<::std::option::Option<super::FieldLabel>, ::std::string::String>,
order: ::std::result::Result<::std::option::Option<i64>, ::std::string::String>,
reason: ::std::result::Result<
::std::option::Option<super::PayloadReason>,
::std::string::String,
>,
required: ::std::result::Result<::std::option::Option<bool>, ::std::string::String>,
searchable: ::std::result::Result<::std::option::Option<bool>, ::std::string::String>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
ceiling: Ok(Default::default()),
constraints: Ok(Default::default()),
default_visibility: Ok(Default::default()),
description: Ok(Default::default()),
enabled: Ok(Default::default()),
ext: Ok(Default::default()),
facet: Ok(Default::default()),
key: Err("no value supplied for key".to_string()),
label: Ok(Default::default()),
order: Ok(Default::default()),
reason: Ok(Default::default()),
required: Ok(Default::default()),
searchable: Ok(Default::default()),
}
}
}
impl Payload {
pub fn ceiling<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Audience>>,
T::Error: ::std::fmt::Display,
{
self.ceiling = value
.try_into()
.map_err(|e| format!("error converting supplied value for ceiling: {e}"));
self
}
pub fn constraints<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::FieldConstraints>>,
T::Error: ::std::fmt::Display,
{
self.constraints = value
.try_into()
.map_err(|e| format!("error converting supplied value for constraints: {e}"));
self
}
pub fn default_visibility<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Audience>>,
T::Error: ::std::fmt::Display,
{
self.default_visibility = value.try_into().map_err(|e| {
format!("error converting supplied value for default_visibility: {e}")
});
self
}
pub fn description<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::FieldDescription>>,
T::Error: ::std::fmt::Display,
{
self.description = value
.try_into()
.map_err(|e| format!("error converting supplied value for description: {e}"));
self
}
pub fn enabled<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<bool>>,
T::Error: ::std::fmt::Display,
{
self.enabled = value
.try_into()
.map_err(|e| format!("error converting supplied value for enabled: {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 facet<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<bool>>,
T::Error: ::std::fmt::Display,
{
self.facet = value
.try_into()
.map_err(|e| format!("error converting supplied value for facet: {e}"));
self
}
pub fn key<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::FieldKey>,
T::Error: ::std::fmt::Display,
{
self.key = value
.try_into()
.map_err(|e| format!("error converting supplied value for key: {e}"));
self
}
pub fn label<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::FieldLabel>>,
T::Error: ::std::fmt::Display,
{
self.label = value
.try_into()
.map_err(|e| format!("error converting supplied value for label: {e}"));
self
}
pub fn order<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<i64>>,
T::Error: ::std::fmt::Display,
{
self.order = value
.try_into()
.map_err(|e| format!("error converting supplied value for order: {e}"));
self
}
pub fn reason<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::PayloadReason>>,
T::Error: ::std::fmt::Display,
{
self.reason = value
.try_into()
.map_err(|e| format!("error converting supplied value for reason: {e}"));
self
}
pub fn required<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<bool>>,
T::Error: ::std::fmt::Display,
{
self.required = value
.try_into()
.map_err(|e| format!("error converting supplied value for required: {e}"));
self
}
pub fn searchable<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<bool>>,
T::Error: ::std::fmt::Display,
{
self.searchable = value
.try_into()
.map_err(|e| format!("error converting supplied value for searchable: {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 {
ceiling: value.ceiling?,
constraints: value.constraints?,
default_visibility: value.default_visibility?,
description: value.description?,
enabled: value.enabled?,
ext: value.ext?,
facet: value.facet?,
key: value.key?,
label: value.label?,
order: value.order?,
reason: value.reason?,
required: value.required?,
searchable: value.searchable?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
ceiling: Ok(value.ceiling),
constraints: Ok(value.constraints),
default_visibility: Ok(value.default_visibility),
description: Ok(value.description),
enabled: Ok(value.enabled),
ext: Ok(value.ext),
facet: Ok(value.facet),
key: Ok(value.key),
label: Ok(value.label),
order: Ok(value.order),
reason: Ok(value.reason),
required: Ok(value.required),
searchable: Ok(value.searchable),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
field: ::std::result::Result<super::FieldDefinition, ::std::string::String>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
ext: Ok(Default::default()),
field: Err("no value supplied for field".to_string()),
}
}
}
impl Response {
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 field<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::FieldDefinition>,
T::Error: ::std::fmt::Display,
{
self.field = value
.try_into()
.map_err(|e| format!("error converting supplied value for field: {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 {
ext: value.ext?,
field: value.field?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
ext: Ok(value.ext),
field: Ok(value.field),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vtc/directory/fields/update/0.1";
const IS_PROOF_REQUIRED: bool = true;
const IS_ISSUED_AT_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"Audience\": {\n \"description\": \"Who may see a directory field, ordered from narrowest to widest. `admins`: holders of `vtc.directory.admin` (and, for derived fields, `vtc.members.manage`). `groups`: members who share at least one community group with the subject (narrowed to the groups the subject names in `groupAudience`, where it names any). `connections`: members holding an attributed, in-force verified relationship with the subject at the community. `members`: every active member. `public`: anyone, and what the member's signed public card carries outside the community.\\n\\n`groups` and `connections` are not a chain: a viewer sees a field when they satisfy the audience the subject chose for it or any wider audience. Every audience includes the administrators, and the subject always sees their own whole card. There is no `onlyMe`: a value nobody else should see is not directory data.\",\n \"enum\": [\n \"admins\",\n \"groups\",\n \"connections\",\n \"members\",\n \"public\"\n ],\n \"title\": \"Audience\",\n \"type\": \"string\"\n },\n \"ClaimSelector\": {\n \"additionalProperties\": false,\n \"description\": \"Which claim a `claim` field accepts, from which credentials and issuers.\",\n \"properties\": {\n \"claimPath\": {\n \"description\": \"JSON Pointer (RFC 6901) to the claim within `credentialSubject`.\",\n \"maxLength\": 256,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"credentialType\": {\n \"description\": \"A `type` the presented credential MUST carry.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"issuers\": {\n \"description\": \"Issuers the community accepts for this field. Absent: the community's trusted issuers for the credential type, as its own policy decides.\",\n \"items\": {\n \"maxLength\": 2048,\n \"pattern\": \"^did:\",\n \"type\": \"string\"\n },\n \"maxItems\": 32,\n \"type\": \"array\",\n \"uniqueItems\": true\n }\n },\n \"required\": [\n \"credentialType\",\n \"claimPath\"\n ],\n \"title\": \"ClaimSelector\",\n \"type\": \"object\"\n },\n \"EnumOption\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"label\": {\n \"description\": \"What a reader is shown for it.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"value\": {\n \"description\": \"The stored value.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"pattern\": \"^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"value\",\n \"label\"\n ],\n \"title\": \"EnumOption\",\n \"type\": \"object\"\n },\n \"Ext\": {\n \"additionalProperties\": true,\n \"description\": \"Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)+$\"\n },\n \"title\": \"Ext\",\n \"type\": \"object\"\n },\n \"FieldConstraints\": {\n \"additionalProperties\": false,\n \"description\": \"Per-type constraints. A member that does not apply to the field's type is refused by the community with `valueInvalid` when the definition is written.\",\n \"properties\": {\n \"claim\": {\n \"$ref\": \"#/$defs/ClaimSelector\"\n },\n \"maxDate\": {\n \"format\": \"date\",\n \"type\": \"string\"\n },\n \"maxItems\": {\n \"maximum\": 32,\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"maxLength\": {\n \"maximum\": 2000,\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"minDate\": {\n \"format\": \"date\",\n \"type\": \"string\"\n },\n \"minLength\": {\n \"maximum\": 2000,\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"options\": {\n \"description\": \"The permitted values of an `enum` or `multiEnum` field.\",\n \"items\": {\n \"$ref\": \"#/$defs/EnumOption\"\n },\n \"maxItems\": 128,\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"pattern\": {\n \"description\": \"ECMA-262 regular expression a text value MUST match.\",\n \"maxLength\": 256,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"title\": \"FieldConstraints\",\n \"type\": \"object\"\n },\n \"FieldDefinition\": {\n \"additionalProperties\": false,\n \"description\": \"One field of the community's directory schema, as the community holds it. The audience order `admins` < `groups`/`connections` < `members` < `public` applies to `ceiling` and `defaultVisibility`; `defaultVisibility` is never wider than `ceiling`.\",\n \"properties\": {\n \"base\": {\n \"description\": \"`true` for a base field, present in every community; `false` for a field this community defined.\",\n \"type\": \"boolean\"\n },\n \"ceiling\": {\n \"$ref\": \"#/$defs/Audience\"\n },\n \"constraints\": {\n \"$ref\": \"#/$defs/FieldConstraints\"\n },\n \"defaultVisibility\": {\n \"$ref\": \"#/$defs/Audience\"\n },\n \"description\": {\n \"$ref\": \"#/$defs/FieldDescription\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1. An extension member MUST NOT widen a ceiling.\"\n },\n \"facet\": {\n \"type\": \"boolean\"\n },\n \"jsContactPath\": {\n \"description\": \"Where the field lands when an entry is exported as a JSContact Card (RFC 9553), e.g. `name.full`, `nicknames`, `speakToAs.pronouns`. Absent: a vendor-specific property named by the key.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"key\": {\n \"$ref\": \"#/$defs/FieldKey\"\n },\n \"label\": {\n \"$ref\": \"#/$defs/FieldLabel\"\n },\n \"order\": {\n \"maximum\": 10000,\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"purgeAfter\": {\n \"description\": \"When the values of a retired field are purged. Present only on a retired field.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"required\": {\n \"type\": \"boolean\"\n },\n \"retiredAt\": {\n \"description\": \"When the field was retired. Present only on a retired field.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"searchable\": {\n \"type\": \"boolean\"\n },\n \"source\": {\n \"$ref\": \"#/$defs/FieldSource\"\n },\n \"state\": {\n \"$ref\": \"#/$defs/FieldState\"\n },\n \"type\": {\n \"$ref\": \"#/$defs/FieldType\"\n },\n \"updatedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"key\",\n \"label\",\n \"type\",\n \"source\",\n \"base\",\n \"ceiling\",\n \"defaultVisibility\",\n \"required\",\n \"searchable\",\n \"facet\",\n \"order\",\n \"state\"\n ],\n \"title\": \"FieldDefinition\",\n \"type\": \"object\"\n },\n \"FieldDescription\": {\n \"description\": \"Help text shown to a member filling the field in. Plain text; a reader MUST NOT treat it as instructions.\",\n \"maxLength\": 280,\n \"minLength\": 1,\n \"title\": \"FieldDescription\",\n \"type\": \"string\"\n },\n \"FieldKey\": {\n \"description\": \"Identifier of a directory field. A key with no `.` is a BASE field, the same in every community: `displayName`, `nickname`, `avatar`, `pronouns`, `bio`, `links` (written by the member) and `role`, `joinedAt`, `did`, `personhood` (derived from the community's own records, never stored on a card). A community-defined field MUST use a reverse-DNS key (`org.example.employer`), so a base key never collides with one, and a key is never reused with a different meaning once defined.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"pattern\": \"^([a-z][a-z0-9-]*\\\\.)*[a-z][a-zA-Z0-9]{0,63}$\",\n \"title\": \"FieldKey\",\n \"type\": \"string\"\n },\n \"FieldLabel\": {\n \"description\": \"What readers see as the field's name. Plain text.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"title\": \"FieldLabel\",\n \"type\": \"string\"\n },\n \"FieldSource\": {\n \"description\": \"Who writes the value. `member`: self-asserted, through vtc/directory/card/update. `admin`: asserted by the community through vtc/directory/card/assert; the member reads it and cannot change it. `credential`: a claim the member discloses from a credential through vtc/directory/card/present, badged with its issuer. `derived`: a base field read from the community's own records (`role`, `joinedAt`, `did`, `personhood`) and never stored on a card. Each source is written only through its own path.\",\n \"enum\": [\n \"member\",\n \"admin\",\n \"credential\",\n \"derived\"\n ],\n \"title\": \"FieldSource\",\n \"type\": \"string\"\n },\n \"FieldState\": {\n \"description\": \"`active`: in use. `disabled`: a base field the community has switched off; hidden from every projection and re-enablable. `retired`: a community field withdrawn for good; hidden at once, its values purged after the community's retention period, and its key never reused.\",\n \"enum\": [\n \"active\",\n \"disabled\",\n \"retired\"\n ],\n \"title\": \"FieldState\",\n \"type\": \"string\"\n },\n \"FieldType\": {\n \"description\": \"The kind of value a field holds, which fixes its `FieldValue` shape. `did` holds a DID the member chooses to show (never their membership DID, which is the derived base field `did`). `claim` holds a `VerifiedValue` and requires `source: credential`.\",\n \"enum\": [\n \"text\",\n \"longText\",\n \"url\",\n \"email\",\n \"phone\",\n \"enum\",\n \"multiEnum\",\n \"date\",\n \"country\",\n \"image\",\n \"did\",\n \"claim\"\n ],\n \"title\": \"FieldType\",\n \"type\": \"string\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to a vtc/directory/fields/update/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/fields/update/0.1#response.\",\n \"properties\": {\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"field\": {\n \"$ref\": \"#/$defs/FieldDefinition\"\n }\n },\n \"required\": [\n \"field\"\n ],\n \"title\": \"VTC Directory — Fields — Update — response payload\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/vtc/directory/fields/update/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"An administrator changes a directory field's label, help text, constraints, order, ceiling or default visibility, or disables or re-enables a base field. The outer document members are owned by the framework — SPEC §6.3.\",\n \"properties\": {\n \"ceiling\": {\n \"$ref\": \"#/$defs/Audience\"\n },\n \"constraints\": {\n \"$ref\": \"#/$defs/FieldConstraints\",\n \"description\": \"Replaces the constraints whole. Values already stored that no longer satisfy them stay until their writer next changes them; projections show them unchanged.\"\n },\n \"defaultVisibility\": {\n \"$ref\": \"#/$defs/Audience\"\n },\n \"description\": {\n \"$ref\": \"#/$defs/FieldDescription\"\n },\n \"enabled\": {\n \"description\": \"Base fields only: `false` disables the field (hidden from every projection, values kept), `true` re-enables it.\",\n \"type\": \"boolean\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"facet\": {\n \"type\": \"boolean\"\n },\n \"key\": {\n \"$ref\": \"#/$defs/FieldKey\"\n },\n \"label\": {\n \"$ref\": \"#/$defs/FieldLabel\"\n },\n \"order\": {\n \"maximum\": 10000,\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"reason\": {\n \"description\": \"Why, recorded with the change and shown to anyone who must approve it.\",\n \"maxLength\": 1024,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"required\": {\n \"type\": \"boolean\"\n },\n \"searchable\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"key\"\n ],\n \"title\": \"VTC Directory — Fields — Update — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str =
"https://trusttasks.org/spec/vtc/directory/fields/update/0.1#response";
const IS_PROOF_REQUIRED: bool = true;
const IS_ISSUED_AT_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"Audience\": {\n \"description\": \"Who may see a directory field, ordered from narrowest to widest. `admins`: holders of `vtc.directory.admin` (and, for derived fields, `vtc.members.manage`). `groups`: members who share at least one community group with the subject (narrowed to the groups the subject names in `groupAudience`, where it names any). `connections`: members holding an attributed, in-force verified relationship with the subject at the community. `members`: every active member. `public`: anyone, and what the member's signed public card carries outside the community.\\n\\n`groups` and `connections` are not a chain: a viewer sees a field when they satisfy the audience the subject chose for it or any wider audience. Every audience includes the administrators, and the subject always sees their own whole card. There is no `onlyMe`: a value nobody else should see is not directory data.\",\n \"enum\": [\n \"admins\",\n \"groups\",\n \"connections\",\n \"members\",\n \"public\"\n ],\n \"title\": \"Audience\",\n \"type\": \"string\"\n },\n \"ClaimSelector\": {\n \"additionalProperties\": false,\n \"description\": \"Which claim a `claim` field accepts, from which credentials and issuers.\",\n \"properties\": {\n \"claimPath\": {\n \"description\": \"JSON Pointer (RFC 6901) to the claim within `credentialSubject`.\",\n \"maxLength\": 256,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"credentialType\": {\n \"description\": \"A `type` the presented credential MUST carry.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"issuers\": {\n \"description\": \"Issuers the community accepts for this field. Absent: the community's trusted issuers for the credential type, as its own policy decides.\",\n \"items\": {\n \"maxLength\": 2048,\n \"pattern\": \"^did:\",\n \"type\": \"string\"\n },\n \"maxItems\": 32,\n \"type\": \"array\",\n \"uniqueItems\": true\n }\n },\n \"required\": [\n \"credentialType\",\n \"claimPath\"\n ],\n \"title\": \"ClaimSelector\",\n \"type\": \"object\"\n },\n \"EnumOption\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"label\": {\n \"description\": \"What a reader is shown for it.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"value\": {\n \"description\": \"The stored value.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"pattern\": \"^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"value\",\n \"label\"\n ],\n \"title\": \"EnumOption\",\n \"type\": \"object\"\n },\n \"Ext\": {\n \"additionalProperties\": true,\n \"description\": \"Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)+$\"\n },\n \"title\": \"Ext\",\n \"type\": \"object\"\n },\n \"FieldConstraints\": {\n \"additionalProperties\": false,\n \"description\": \"Per-type constraints. A member that does not apply to the field's type is refused by the community with `valueInvalid` when the definition is written.\",\n \"properties\": {\n \"claim\": {\n \"$ref\": \"#/$defs/ClaimSelector\"\n },\n \"maxDate\": {\n \"format\": \"date\",\n \"type\": \"string\"\n },\n \"maxItems\": {\n \"maximum\": 32,\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"maxLength\": {\n \"maximum\": 2000,\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"minDate\": {\n \"format\": \"date\",\n \"type\": \"string\"\n },\n \"minLength\": {\n \"maximum\": 2000,\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"options\": {\n \"description\": \"The permitted values of an `enum` or `multiEnum` field.\",\n \"items\": {\n \"$ref\": \"#/$defs/EnumOption\"\n },\n \"maxItems\": 128,\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"pattern\": {\n \"description\": \"ECMA-262 regular expression a text value MUST match.\",\n \"maxLength\": 256,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"title\": \"FieldConstraints\",\n \"type\": \"object\"\n },\n \"FieldDefinition\": {\n \"additionalProperties\": false,\n \"description\": \"One field of the community's directory schema, as the community holds it. The audience order `admins` < `groups`/`connections` < `members` < `public` applies to `ceiling` and `defaultVisibility`; `defaultVisibility` is never wider than `ceiling`.\",\n \"properties\": {\n \"base\": {\n \"description\": \"`true` for a base field, present in every community; `false` for a field this community defined.\",\n \"type\": \"boolean\"\n },\n \"ceiling\": {\n \"$ref\": \"#/$defs/Audience\"\n },\n \"constraints\": {\n \"$ref\": \"#/$defs/FieldConstraints\"\n },\n \"defaultVisibility\": {\n \"$ref\": \"#/$defs/Audience\"\n },\n \"description\": {\n \"$ref\": \"#/$defs/FieldDescription\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1. An extension member MUST NOT widen a ceiling.\"\n },\n \"facet\": {\n \"type\": \"boolean\"\n },\n \"jsContactPath\": {\n \"description\": \"Where the field lands when an entry is exported as a JSContact Card (RFC 9553), e.g. `name.full`, `nicknames`, `speakToAs.pronouns`. Absent: a vendor-specific property named by the key.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"key\": {\n \"$ref\": \"#/$defs/FieldKey\"\n },\n \"label\": {\n \"$ref\": \"#/$defs/FieldLabel\"\n },\n \"order\": {\n \"maximum\": 10000,\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"purgeAfter\": {\n \"description\": \"When the values of a retired field are purged. Present only on a retired field.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"required\": {\n \"type\": \"boolean\"\n },\n \"retiredAt\": {\n \"description\": \"When the field was retired. Present only on a retired field.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"searchable\": {\n \"type\": \"boolean\"\n },\n \"source\": {\n \"$ref\": \"#/$defs/FieldSource\"\n },\n \"state\": {\n \"$ref\": \"#/$defs/FieldState\"\n },\n \"type\": {\n \"$ref\": \"#/$defs/FieldType\"\n },\n \"updatedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"key\",\n \"label\",\n \"type\",\n \"source\",\n \"base\",\n \"ceiling\",\n \"defaultVisibility\",\n \"required\",\n \"searchable\",\n \"facet\",\n \"order\",\n \"state\"\n ],\n \"title\": \"FieldDefinition\",\n \"type\": \"object\"\n },\n \"FieldDescription\": {\n \"description\": \"Help text shown to a member filling the field in. Plain text; a reader MUST NOT treat it as instructions.\",\n \"maxLength\": 280,\n \"minLength\": 1,\n \"title\": \"FieldDescription\",\n \"type\": \"string\"\n },\n \"FieldKey\": {\n \"description\": \"Identifier of a directory field. A key with no `.` is a BASE field, the same in every community: `displayName`, `nickname`, `avatar`, `pronouns`, `bio`, `links` (written by the member) and `role`, `joinedAt`, `did`, `personhood` (derived from the community's own records, never stored on a card). A community-defined field MUST use a reverse-DNS key (`org.example.employer`), so a base key never collides with one, and a key is never reused with a different meaning once defined.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"pattern\": \"^([a-z][a-z0-9-]*\\\\.)*[a-z][a-zA-Z0-9]{0,63}$\",\n \"title\": \"FieldKey\",\n \"type\": \"string\"\n },\n \"FieldLabel\": {\n \"description\": \"What readers see as the field's name. Plain text.\",\n \"maxLength\": 64,\n \"minLength\": 1,\n \"title\": \"FieldLabel\",\n \"type\": \"string\"\n },\n \"FieldSource\": {\n \"description\": \"Who writes the value. `member`: self-asserted, through vtc/directory/card/update. `admin`: asserted by the community through vtc/directory/card/assert; the member reads it and cannot change it. `credential`: a claim the member discloses from a credential through vtc/directory/card/present, badged with its issuer. `derived`: a base field read from the community's own records (`role`, `joinedAt`, `did`, `personhood`) and never stored on a card. Each source is written only through its own path.\",\n \"enum\": [\n \"member\",\n \"admin\",\n \"credential\",\n \"derived\"\n ],\n \"title\": \"FieldSource\",\n \"type\": \"string\"\n },\n \"FieldState\": {\n \"description\": \"`active`: in use. `disabled`: a base field the community has switched off; hidden from every projection and re-enablable. `retired`: a community field withdrawn for good; hidden at once, its values purged after the community's retention period, and its key never reused.\",\n \"enum\": [\n \"active\",\n \"disabled\",\n \"retired\"\n ],\n \"title\": \"FieldState\",\n \"type\": \"string\"\n },\n \"FieldType\": {\n \"description\": \"The kind of value a field holds, which fixes its `FieldValue` shape. `did` holds a DID the member chooses to show (never their membership DID, which is the derived base field `did`). `claim` holds a `VerifiedValue` and requires `source: credential`.\",\n \"enum\": [\n \"text\",\n \"longText\",\n \"url\",\n \"email\",\n \"phone\",\n \"enum\",\n \"multiEnum\",\n \"date\",\n \"country\",\n \"image\",\n \"did\",\n \"claim\"\n ],\n \"title\": \"FieldType\",\n \"type\": \"string\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to a vtc/directory/fields/update/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/fields/update/0.1#response.\",\n \"properties\": {\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"field\": {\n \"$ref\": \"#/$defs/FieldDefinition\"\n }\n },\n \"required\": [\n \"field\"\n ],\n \"title\": \"VTC Directory — Fields — Update — response payload\",\n \"type\": \"object\"\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::FIELD_UNKNOWN,
error_codes::FIELD_RETIRED,
error_codes::ABOVE_CEILING,
error_codes::VALUE_INVALID,
];
/// 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 {
/// `vtc/directory/fields/update:fieldUnknown`
///
/// No field has this key.
///
/// Declared `retryable: false`.
pub const FIELD_UNKNOWN: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/directory/fields/update:fieldUnknown",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/directory/fields/update:fieldRetired`
///
/// The field is retired and cannot be changed.
///
/// Declared `retryable: false`.
pub const FIELD_RETIRED: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/directory/fields/update:fieldRetired",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/directory/fields/update:aboveCeiling`
///
/// The resulting `defaultVisibility` would be wider than the resulting `ceiling`.
///
/// Declared `retryable: false`.
pub const ABOVE_CEILING: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/directory/fields/update:aboveCeiling",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/directory/fields/update:valueInvalid`
///
/// The constraints do not fit the field's type, or `enabled` was sent for a community field.
///
/// Declared `retryable: false`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const VALUE_INVALID: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/directory/fields/update:valueInvalid",
retryable: false,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"field\":{\"maxLength\":128,\"type\":\"string\"},\"reason\":{\"maxLength\":500,\"type\":\"string\"}},\"required\":[\"field\"],\"type\":\"object\"}",
),
};
}