//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vtc/groups/requests/decide`. 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())
}
}
}
///A content-addressed image held in the community's blob store — an avatar or an `image` field. At most 256 KiB, images only, re-encoded by the community on upload (vtc/directory/images/upload: metadata stripped, dimensions capped) so its digest does not link the member across communities. A viewer reads the bytes with vtc/directory/images/get, which answers only where the same projection shows the value. `url` and `urlExpiresAt` MAY appear in a projection: a short-lived URL the community checks against the same projection, so a member-only image is never a public URL. A community that does not offer one leaves both out.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "CardBlobRef",
/// "description": "A content-addressed image held in the community's blob store — an avatar or an `image` field. At most 256 KiB, images only, re-encoded by the community on upload (vtc/directory/images/upload: metadata stripped, dimensions capped) so its digest does not link the member across communities. A viewer reads the bytes with vtc/directory/images/get, which answers only where the same projection shows the value. `url` and `urlExpiresAt` MAY appear in a projection: a short-lived URL the community checks against the same projection, so a member-only image is never a public URL. A community that does not offer one leaves both out.",
/// "type": "object",
/// "required": [
/// "mediaType",
/// "sha256"
/// ],
/// "properties": {
/// "mediaType": {
/// "description": "Media type of the stored bytes.",
/// "type": "string",
/// "enum": [
/// "image/png",
/// "image/jpeg",
/// "image/webp",
/// "image/avif"
/// ]
/// },
/// "sha256": {
/// "description": "Lowercase hex SHA-256 of the stored, re-encoded bytes.",
/// "type": "string",
/// "pattern": "^[0-9a-f]{64}$"
/// },
/// "size": {
/// "description": "Size in bytes of the stored bytes.",
/// "type": "integer",
/// "maximum": 262144.0,
/// "minimum": 1.0
/// },
/// "url": {
/// "description": "Projection only: a URL the viewer can fetch the image from until `urlExpiresAt`.",
/// "type": "string",
/// "format": "uri",
/// "maxLength": 2048
/// },
/// "urlExpiresAt": {
/// "description": "Projection only: when `url` stops working.",
/// "type": "string",
/// "format": "date-time"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CardBlobRef {
///Media type of the stored bytes.
#[serde(rename = "mediaType")]
pub media_type: CardBlobRefMediaType,
///Lowercase hex SHA-256 of the stored, re-encoded bytes.
pub sha256: CardBlobRefSha256,
///Size in bytes of the stored bytes.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub size: ::std::option::Option<::std::num::NonZeroU64>,
///Projection only: a URL the viewer can fetch the image from until `urlExpiresAt`.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub url: ::std::option::Option<::std::string::String>,
///Projection only: when `url` stops working.
#[serde(
rename = "urlExpiresAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub url_expires_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
}
impl CardBlobRef {
pub fn builder() -> builder::CardBlobRef {
Default::default()
}
}
///Media type of the stored bytes.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Media type of the stored bytes.",
/// "type": "string",
/// "enum": [
/// "image/png",
/// "image/jpeg",
/// "image/webp",
/// "image/avif"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum CardBlobRefMediaType {
#[serde(rename = "image/png")]
ImagePng,
#[serde(rename = "image/jpeg")]
ImageJpeg,
#[serde(rename = "image/webp")]
ImageWebp,
#[serde(rename = "image/avif")]
ImageAvif,
}
impl ::std::fmt::Display for CardBlobRefMediaType {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::ImagePng => f.write_str("image/png"),
Self::ImageJpeg => f.write_str("image/jpeg"),
Self::ImageWebp => f.write_str("image/webp"),
Self::ImageAvif => f.write_str("image/avif"),
}
}
}
impl ::std::str::FromStr for CardBlobRefMediaType {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"image/png" => Ok(Self::ImagePng),
"image/jpeg" => Ok(Self::ImageJpeg),
"image/webp" => Ok(Self::ImageWebp),
"image/avif" => Ok(Self::ImageAvif),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for CardBlobRefMediaType {
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 CardBlobRefMediaType {
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 CardBlobRefMediaType {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Lowercase hex SHA-256 of the stored, re-encoded bytes.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Lowercase hex SHA-256 of the stored, re-encoded bytes.",
/// "type": "string",
/// "pattern": "^[0-9a-f]{64}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct CardBlobRefSha256(::std::string::String);
impl ::std::ops::Deref for CardBlobRefSha256 {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<CardBlobRefSha256> for ::std::string::String {
fn from(value: CardBlobRefSha256) -> Self {
value.0
}
}
impl ::std::str::FromStr for CardBlobRefSha256 {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[0-9a-f]{64}$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[0-9a-f]{64}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for CardBlobRefSha256 {
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 CardBlobRefSha256 {
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 CardBlobRefSha256 {
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 CardBlobRefSha256 {
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 fields of one entry that a particular viewer may see, keyed by field: the intersection of the member's visibility, the community's ceiling and policy, plus any derived fields that intersection admits. A withheld field is ABSENT, never null.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "EntryFields",
/// "description": "The fields of one entry that a particular viewer may see, keyed by field: the intersection of the member's visibility, the community's ceiling and policy, plus any derived fields that intersection admits. A withheld field is ABSENT, never null.",
/// "type": "object",
/// "maxProperties": 64,
/// "additionalProperties": {
/// "$ref": "#/definitions/FieldValue"
/// },
/// "propertyNames": {
/// "$ref": "#/definitions/FieldKey"
/// }
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct EntryFields(pub ::std::collections::HashMap<FieldKey, FieldValue>);
impl ::std::ops::Deref for EntryFields {
type Target = ::std::collections::HashMap<FieldKey, FieldValue>;
fn deref(&self) -> &::std::collections::HashMap<FieldKey, FieldValue> {
&self.0
}
}
impl ::std::convert::From<EntryFields> for ::std::collections::HashMap<FieldKey, FieldValue> {
fn from(value: EntryFields) -> Self {
value.0
}
}
impl ::std::convert::From<::std::collections::HashMap<FieldKey, FieldValue>> for EntryFields {
fn from(value: ::std::collections::HashMap<FieldKey, FieldValue>) -> Self {
Self(value)
}
}
///Opaque identifier of one directory entry: `dir_` followed by 16 to 64 base64url characters. Random, scoped to one community, and stable for the life of the membership — it survives a rotation of the member's DID, which is why groups, notes and cards are keyed by it. It MUST NOT be derived from, and MUST NOT reveal, any DID of the member, and the same person's entries in two communities MUST NOT share one. Compared by exact string equality.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "EntryId",
/// "description": "Opaque identifier of one directory entry: `dir_` followed by 16 to 64 base64url characters. Random, scoped to one community, and stable for the life of the membership — it survives a rotation of the member's DID, which is why groups, notes and cards are keyed by it. It MUST NOT be derived from, and MUST NOT reveal, any DID of the member, and the same person's entries in two communities MUST NOT share one. Compared by exact string equality.",
/// "type": "string",
/// "pattern": "^dir_[A-Za-z0-9_-]{16,64}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct EntryId(::std::string::String);
impl ::std::ops::Deref for EntryId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<EntryId> for ::std::string::String {
fn from(value: EntryId) -> Self {
value.0
}
}
impl ::std::str::FromStr for EntryId {
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("^dir_[A-Za-z0-9_-]{16,64}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^dir_[A-Za-z0-9_-]{16,64}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for EntryId {
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 EntryId {
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 EntryId {
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 EntryId {
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())
})
}
}
///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())
})
}
}
///The value of one field. Which shape a field takes is fixed by its definition's `type`: text-like types (`text`, `longText`, `url`, `email`, `phone`, `enum`, `date` as YYYY-MM-DD, `country` as ISO 3166-1 alpha-2, `did`) are strings; `multiEnum` and the base field `links` are arrays of strings; `image` and the base field `avatar` are a `CardBlobRef`; `claim` is a `VerifiedValue`; the derived base field `personhood` is a boolean.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "FieldValue",
/// "description": "The value of one field. Which shape a field takes is fixed by its definition's `type`: text-like types (`text`, `longText`, `url`, `email`, `phone`, `enum`, `date` as YYYY-MM-DD, `country` as ISO 3166-1 alpha-2, `did`) are strings; `multiEnum` and the base field `links` are arrays of strings; `image` and the base field `avatar` are a `CardBlobRef`; `claim` is a `VerifiedValue`; the derived base field `personhood` is a boolean.",
/// "anyOf": [
/// {
/// "type": "string",
/// "maxLength": 2000
/// },
/// {
/// "type": "boolean"
/// },
/// {
/// "type": "array",
/// "items": {
/// "type": "string",
/// "maxLength": 500
/// },
/// "maxItems": 32
/// },
/// {
/// "$ref": "#/definitions/CardBlobRef"
/// },
/// {
/// "$ref": "#/definitions/VerifiedValue"
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged)]
#[non_exhaustive]
pub enum FieldValue {
String(FieldValueString),
Boolean(bool),
Array(::std::vec::Vec<FieldValueArrayItem>),
CardBlobRef(CardBlobRef),
VerifiedValue(VerifiedValue),
}
impl ::std::convert::From<FieldValueString> for FieldValue {
fn from(value: FieldValueString) -> Self {
Self::String(value)
}
}
impl ::std::convert::From<bool> for FieldValue {
fn from(value: bool) -> Self {
Self::Boolean(value)
}
}
impl ::std::convert::From<::std::vec::Vec<FieldValueArrayItem>> for FieldValue {
fn from(value: ::std::vec::Vec<FieldValueArrayItem>) -> Self {
Self::Array(value)
}
}
impl ::std::convert::From<CardBlobRef> for FieldValue {
fn from(value: CardBlobRef) -> Self {
Self::CardBlobRef(value)
}
}
impl ::std::convert::From<VerifiedValue> for FieldValue {
fn from(value: VerifiedValue) -> Self {
Self::VerifiedValue(value)
}
}
///`FieldValueArrayItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 500
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct FieldValueArrayItem(::std::string::String);
impl ::std::ops::Deref for FieldValueArrayItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<FieldValueArrayItem> for ::std::string::String {
fn from(value: FieldValueArrayItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for FieldValueArrayItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 500usize {
return Err("longer than 500 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for FieldValueArrayItem {
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 FieldValueArrayItem {
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 FieldValueArrayItem {
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 FieldValueArrayItem {
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())
})
}
}
///`FieldValueString`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 2000
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct FieldValueString(::std::string::String);
impl ::std::ops::Deref for FieldValueString {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<FieldValueString> for ::std::string::String {
fn from(value: FieldValueString) -> Self {
value.0
}
}
impl ::std::str::FromStr for FieldValueString {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 2000usize {
return Err("longer than 2000 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for FieldValueString {
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 FieldValueString {
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 FieldValueString {
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 FieldValueString {
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 (`id`) of a group membership credential issued to a member. Each renewal issues a new credential with a new identifier. Validity is the community's setting; a community SHOULD default to 30 days, renewed when 10 days remain.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "GroupCredentialId",
/// "description": "Identifier (`id`) of a group membership credential issued to a member. Each renewal issues a new credential with a new identifier. Validity is the community's setting; a community SHOULD default to 30 days, renewed when 10 days remain.",
/// "type": "string",
/// "maxLength": 512,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct GroupCredentialId(::std::string::String);
impl ::std::ops::Deref for GroupCredentialId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<GroupCredentialId> for ::std::string::String {
fn from(value: GroupCredentialId) -> Self {
value.0
}
}
impl ::std::str::FromStr for GroupCredentialId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 512usize {
return Err("longer than 512 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for GroupCredentialId {
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 GroupCredentialId {
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 GroupCredentialId {
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 GroupCredentialId {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Opaque identifier of a community group: `grp_` followed by 16 to 64 base64url characters. Random and community-scoped; not the group's DID.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "GroupId",
/// "description": "Opaque identifier of a community group: `grp_` followed by 16 to 64 base64url characters. Random and community-scoped; not the group's DID.",
/// "type": "string",
/// "pattern": "^grp_[A-Za-z0-9_-]{16,64}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct GroupId(::std::string::String);
impl ::std::ops::Deref for GroupId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<GroupId> for ::std::string::String {
fn from(value: GroupId) -> Self {
value.0
}
}
impl ::std::str::FromStr for GroupId {
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("^grp_[A-Za-z0-9_-]{16,64}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^grp_[A-Za-z0-9_-]{16,64}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for GroupId {
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 GroupId {
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 GroupId {
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 GroupId {
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())
})
}
}
///`GroupJoinRequest`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "GroupJoinRequest",
/// "type": "object",
/// "required": [
/// "createdAt",
/// "entryId",
/// "groupId",
/// "requestId",
/// "state"
/// ],
/// "properties": {
/// "createdAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "decidedAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "decidedBy": {
/// "description": "The manager who decided. Shown to managers only.",
/// "type": "string",
/// "maxLength": 2048,
/// "pattern": "^did:"
/// },
/// "entryId": {
/// "$ref": "#/definitions/EntryId"
/// },
/// "groupId": {
/// "$ref": "#/definitions/GroupId"
/// },
/// "message": {
/// "$ref": "#/definitions/JoinRequestMessage"
/// },
/// "requestId": {
/// "$ref": "#/definitions/JoinRequestId"
/// },
/// "state": {
/// "type": "string",
/// "enum": [
/// "pending",
/// "approved",
/// "declined",
/// "withdrawn"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct GroupJoinRequest {
#[serde(rename = "createdAt")]
pub created_at: ::chrono::DateTime<::chrono::offset::Utc>,
#[serde(
rename = "decidedAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub decided_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///The manager who decided. Shown to managers only.
#[serde(
rename = "decidedBy",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub decided_by: ::std::option::Option<GroupJoinRequestDecidedBy>,
#[serde(rename = "entryId")]
pub entry_id: EntryId,
#[serde(rename = "groupId")]
pub group_id: GroupId,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub message: ::std::option::Option<JoinRequestMessage>,
#[serde(rename = "requestId")]
pub request_id: JoinRequestId,
pub state: GroupJoinRequestState,
}
impl GroupJoinRequest {
pub fn builder() -> builder::GroupJoinRequest {
Default::default()
}
}
///The manager who decided. Shown to managers only.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The manager who decided. Shown to managers only.",
/// "type": "string",
/// "maxLength": 2048,
/// "pattern": "^did:"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct GroupJoinRequestDecidedBy(::std::string::String);
impl ::std::ops::Deref for GroupJoinRequestDecidedBy {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<GroupJoinRequestDecidedBy> for ::std::string::String {
fn from(value: GroupJoinRequestDecidedBy) -> Self {
value.0
}
}
impl ::std::str::FromStr for GroupJoinRequestDecidedBy {
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 GroupJoinRequestDecidedBy {
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 GroupJoinRequestDecidedBy {
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 GroupJoinRequestDecidedBy {
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 GroupJoinRequestDecidedBy {
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())
})
}
}
///`GroupJoinRequestState`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "pending",
/// "approved",
/// "declined",
/// "withdrawn"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum GroupJoinRequestState {
#[serde(rename = "pending")]
Pending,
#[serde(rename = "approved")]
Approved,
#[serde(rename = "declined")]
Declined,
#[serde(rename = "withdrawn")]
Withdrawn,
}
impl ::std::fmt::Display for GroupJoinRequestState {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Pending => f.write_str("pending"),
Self::Approved => f.write_str("approved"),
Self::Declined => f.write_str("declined"),
Self::Withdrawn => f.write_str("withdrawn"),
}
}
}
impl ::std::str::FromStr for GroupJoinRequestState {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"pending" => Ok(Self::Pending),
"approved" => Ok(Self::Approved),
"declined" => Ok(Self::Declined),
"withdrawn" => Ok(Self::Withdrawn),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for GroupJoinRequestState {
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 GroupJoinRequestState {
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 GroupJoinRequestState {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`GroupMember`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "GroupMember",
/// "type": "object",
/// "required": [
/// "entryId",
/// "since",
/// "source",
/// "state"
/// ],
/// "properties": {
/// "credentialId": {
/// "description": "The member's current group membership credential, or null when the group issues none.",
/// "anyOf": [
/// {
/// "$ref": "#/definitions/GroupCredentialId"
/// },
/// {
/// "type": "null"
/// }
/// ]
/// },
/// "credentialValidUntil": {
/// "description": "When the member's current group credential expires. Shown to the member themselves and to managers only.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "entryId": {
/// "$ref": "#/definitions/EntryId"
/// },
/// "fields": {
/// "description": "The member's directory fields that the caller may see, projected exactly as vtc/directory/entries/show would project them. Absent when the caller may see none.",
/// "$ref": "#/definitions/EntryFields"
/// },
/// "since": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "source": {
/// "$ref": "#/definitions/MembershipSource"
/// },
/// "state": {
/// "description": "`active`: a member. `pending`: an addition to a group carrying authority that is waiting for the consent the community requires for a grant.",
/// "type": "string",
/// "enum": [
/// "active",
/// "pending"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct GroupMember {
///The member's current group membership credential, or null when the group issues none.
#[serde(
rename = "credentialId",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub credential_id: ::std::option::Option<GroupCredentialId>,
///When the member's current group credential expires. Shown to the member themselves and to managers only.
#[serde(
rename = "credentialValidUntil",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub credential_valid_until: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
#[serde(rename = "entryId")]
pub entry_id: EntryId,
///The member's directory fields that the caller may see, projected exactly as vtc/directory/entries/show would project them. Absent when the caller may see none.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub fields: ::std::option::Option<EntryFields>,
pub since: ::chrono::DateTime<::chrono::offset::Utc>,
pub source: MembershipSource,
///`active`: a member. `pending`: an addition to a group carrying authority that is waiting for the consent the community requires for a grant.
pub state: GroupMemberState,
}
impl GroupMember {
pub fn builder() -> builder::GroupMember {
Default::default()
}
}
///`active`: a member. `pending`: an addition to a group carrying authority that is waiting for the consent the community requires for a grant.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "`active`: a member. `pending`: an addition to a group carrying authority that is waiting for the consent the community requires for a grant.",
/// "type": "string",
/// "enum": [
/// "active",
/// "pending"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum GroupMemberState {
#[serde(rename = "active")]
Active,
#[serde(rename = "pending")]
Pending,
}
impl ::std::fmt::Display for GroupMemberState {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Active => f.write_str("active"),
Self::Pending => f.write_str("pending"),
}
}
}
impl ::std::str::FromStr for GroupMemberState {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"active" => Ok(Self::Active),
"pending" => Ok(Self::Pending),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for GroupMemberState {
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 GroupMemberState {
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 GroupMemberState {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`JoinRequestId`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "JoinRequestId",
/// "type": "string",
/// "pattern": "^greq_[A-Za-z0-9_-]{16,64}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct JoinRequestId(::std::string::String);
impl ::std::ops::Deref for JoinRequestId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<JoinRequestId> for ::std::string::String {
fn from(value: JoinRequestId) -> Self {
value.0
}
}
impl ::std::str::FromStr for JoinRequestId {
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("^greq_[A-Za-z0-9_-]{16,64}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^greq_[A-Za-z0-9_-]{16,64}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for JoinRequestId {
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 JoinRequestId {
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 JoinRequestId {
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 JoinRequestId {
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())
})
}
}
///An optional note from the member to the group's managers. Plain text.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "JoinRequestMessage",
/// "description": "An optional note from the member to the group's managers. Plain text.",
/// "type": "string",
/// "maxLength": 280,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct JoinRequestMessage(::std::string::String);
impl ::std::ops::Deref for JoinRequestMessage {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<JoinRequestMessage> for ::std::string::String {
fn from(value: JoinRequestMessage) -> Self {
value.0
}
}
impl ::std::str::FromStr for JoinRequestMessage {
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 JoinRequestMessage {
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 JoinRequestMessage {
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 JoinRequestMessage {
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 JoinRequestMessage {
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())
})
}
}
///How the member came to be in the group. `added`: by a manager. `joined`: they joined an open group. `requestApproved`: a manager approved their request. `rule`: a dynamic group's rule admits them.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "MembershipSource",
/// "description": "How the member came to be in the group. `added`: by a manager. `joined`: they joined an open group. `requestApproved`: a manager approved their request. `rule`: a dynamic group's rule admits them.",
/// "type": "string",
/// "enum": [
/// "added",
/// "joined",
/// "requestApproved",
/// "rule"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum MembershipSource {
#[serde(rename = "added")]
Added,
#[serde(rename = "joined")]
Joined,
#[serde(rename = "requestApproved")]
RequestApproved,
#[serde(rename = "rule")]
Rule,
}
impl ::std::fmt::Display for MembershipSource {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Added => f.write_str("added"),
Self::Joined => f.write_str("joined"),
Self::RequestApproved => f.write_str("requestApproved"),
Self::Rule => f.write_str("rule"),
}
}
}
impl ::std::str::FromStr for MembershipSource {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"added" => Ok(Self::Added),
"joined" => Ok(Self::Joined),
"requestApproved" => Ok(Self::RequestApproved),
"rule" => Ok(Self::Rule),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for MembershipSource {
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 MembershipSource {
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 MembershipSource {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///A group manager approves or declines a request to join; an approval admits the member, with a membership credential issued by the group's DID where the group issues credentials. The outer document members are owned by the framework — SPEC §6.3.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/vtc/groups/requests/decide/0.1",
/// "title": "Payload",
/// "description": "A group manager approves or declines a request to join; an approval admits the member, with a membership credential issued by the group's DID where the group issues credentials. The outer document members are owned by the framework — SPEC §6.3.",
/// "type": "object",
/// "required": [
/// "decision",
/// "requestId"
/// ],
/// "properties": {
/// "decision": {
/// "type": "string",
/// "enum": [
/// "approve",
/// "decline"
/// ]
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "reason": {
/// "description": "Optional; recorded with the decision and shown to managers. Not sent to the requester.",
/// "type": "string",
/// "maxLength": 500,
/// "minLength": 1
/// },
/// "requestId": {
/// "$ref": "#/definitions/JoinRequestId"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Payload {
pub decision: PayloadDecision,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///Optional; recorded with the decision and shown to managers. Not sent to the requester.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reason: ::std::option::Option<PayloadReason>,
#[serde(rename = "requestId")]
pub request_id: JoinRequestId,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///`PayloadDecision`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "approve",
/// "decline"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum PayloadDecision {
#[serde(rename = "approve")]
Approve,
#[serde(rename = "decline")]
Decline,
}
impl ::std::fmt::Display for PayloadDecision {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Approve => f.write_str("approve"),
Self::Decline => f.write_str("decline"),
}
}
}
impl ::std::str::FromStr for PayloadDecision {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"approve" => Ok(Self::Approve),
"decline" => Ok(Self::Decline),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PayloadDecision {
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 PayloadDecision {
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 PayloadDecision {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Optional; recorded with the decision and shown to managers. Not sent to the requester.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Optional; recorded with the decision and shown to managers. Not sent to the requester.",
/// "type": "string",
/// "maxLength": 500,
/// "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() > 500usize {
return Err("longer than 500 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/groups/requests/decide/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/groups/requests/decide/0.1#response.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "The success response to a vtc/groups/requests/decide/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/groups/requests/decide/0.1#response.",
/// "type": "object",
/// "required": [
/// "credentialId",
/// "request"
/// ],
/// "properties": {
/// "credentialId": {
/// "description": "The membership credential offered, or null on a decline or where the group issues none.",
/// "anyOf": [
/// {
/// "$ref": "#/definitions/GroupCredentialId"
/// },
/// {
/// "type": "null"
/// }
/// ]
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "member": {
/// "description": "Present on approval.",
/// "$ref": "#/definitions/GroupMember"
/// },
/// "request": {
/// "$ref": "#/definitions/GroupJoinRequest"
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Response {
///The membership credential offered, or null on a decline or where the group issues none.
#[serde(rename = "credentialId")]
pub credential_id: ::std::option::Option<GroupCredentialId>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///Present on approval.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub member: ::std::option::Option<GroupMember>,
pub request: GroupJoinRequest,
}
impl Response {
pub fn builder() -> builder::Response {
Default::default()
}
}
///The value of a `credential`-sourced field: a claim the member disclosed from a credential they presented, with the issuer that attests it. A verified value always names its issuer, and a self-asserted value is never shaped as one. The community keeps only the disclosed claim and these facts about it — never the presentation.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "VerifiedValue",
/// "description": "The value of a `credential`-sourced field: a claim the member disclosed from a credential they presented, with the issuer that attests it. A verified value always names its issuer, and a self-asserted value is never shaped as one. The community keeps only the disclosed claim and these facts about it — never the presentation.",
/// "type": "object",
/// "required": [
/// "issuer",
/// "value",
/// "verifiedAt"
/// ],
/// "properties": {
/// "credentialType": {
/// "description": "The most specific `type` of the credential the claim came from.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1
/// },
/// "issuer": {
/// "description": "DID of the credential's issuer, shown as the field's verification badge.",
/// "type": "string",
/// "maxLength": 2048,
/// "pattern": "^did:"
/// },
/// "validUntil": {
/// "description": "When the credential expires, where it does. The community withdraws the value once it passes.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "value": {
/// "description": "The disclosed claim value.",
/// "anyOf": [
/// {
/// "type": "string",
/// "maxLength": 2000
/// },
/// {
/// "type": "boolean"
/// },
/// {
/// "type": "number"
/// }
/// ]
/// },
/// "verifiedAt": {
/// "description": "When the community verified the presentation.",
/// "type": "string",
/// "format": "date-time"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct VerifiedValue {
///The most specific `type` of the credential the claim came from.
#[serde(
rename = "credentialType",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub credential_type: ::std::option::Option<VerifiedValueCredentialType>,
///DID of the credential's issuer, shown as the field's verification badge.
pub issuer: VerifiedValueIssuer,
///When the credential expires, where it does. The community withdraws the value once it passes.
#[serde(
rename = "validUntil",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub valid_until: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///The disclosed claim value.
pub value: VerifiedValueValue,
///When the community verified the presentation.
#[serde(rename = "verifiedAt")]
pub verified_at: ::chrono::DateTime<::chrono::offset::Utc>,
}
impl VerifiedValue {
pub fn builder() -> builder::VerifiedValue {
Default::default()
}
}
///The most specific `type` of the credential the claim came from.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The most specific `type` of the credential the claim came from.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VerifiedValueCredentialType(::std::string::String);
impl ::std::ops::Deref for VerifiedValueCredentialType {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VerifiedValueCredentialType> for ::std::string::String {
fn from(value: VerifiedValueCredentialType) -> Self {
value.0
}
}
impl ::std::str::FromStr for VerifiedValueCredentialType {
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 VerifiedValueCredentialType {
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 VerifiedValueCredentialType {
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 VerifiedValueCredentialType {
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 VerifiedValueCredentialType {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///DID of the credential's issuer, shown as the field's verification badge.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "DID of the credential's issuer, shown as the field's verification badge.",
/// "type": "string",
/// "maxLength": 2048,
/// "pattern": "^did:"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VerifiedValueIssuer(::std::string::String);
impl ::std::ops::Deref for VerifiedValueIssuer {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VerifiedValueIssuer> for ::std::string::String {
fn from(value: VerifiedValueIssuer) -> Self {
value.0
}
}
impl ::std::str::FromStr for VerifiedValueIssuer {
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 VerifiedValueIssuer {
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 VerifiedValueIssuer {
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 VerifiedValueIssuer {
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 VerifiedValueIssuer {
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 disclosed claim value.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The disclosed claim value.",
/// "anyOf": [
/// {
/// "type": "string",
/// "maxLength": 2000
/// },
/// {
/// "type": "boolean"
/// },
/// {
/// "type": "number"
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged)]
#[non_exhaustive]
pub enum VerifiedValueValue {
String(VerifiedValueValueString),
Boolean(bool),
Number(f64),
}
impl ::std::str::FromStr for VerifiedValueValue {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if let Ok(v) = value.parse() {
Ok(Self::String(v))
} else if let Ok(v) = value.parse() {
Ok(Self::Boolean(v))
} else if let Ok(v) = value.parse() {
Ok(Self::Number(v))
} else {
Err("string conversion failed for all variants".into())
}
}
}
impl ::std::convert::TryFrom<&str> for VerifiedValueValue {
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 VerifiedValueValue {
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 VerifiedValueValue {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::fmt::Display for VerifiedValueValue {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match self {
Self::String(x) => x.fmt(f),
Self::Boolean(x) => x.fmt(f),
Self::Number(x) => x.fmt(f),
}
}
}
impl ::std::convert::From<VerifiedValueValueString> for VerifiedValueValue {
fn from(value: VerifiedValueValueString) -> Self {
Self::String(value)
}
}
impl ::std::convert::From<bool> for VerifiedValueValue {
fn from(value: bool) -> Self {
Self::Boolean(value)
}
}
impl ::std::convert::From<f64> for VerifiedValueValue {
fn from(value: f64) -> Self {
Self::Number(value)
}
}
///`VerifiedValueValueString`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 2000
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VerifiedValueValueString(::std::string::String);
impl ::std::ops::Deref for VerifiedValueValueString {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VerifiedValueValueString> for ::std::string::String {
fn from(value: VerifiedValueValueString) -> Self {
value.0
}
}
impl ::std::str::FromStr for VerifiedValueValueString {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 2000usize {
return Err("longer than 2000 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for VerifiedValueValueString {
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 VerifiedValueValueString {
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 VerifiedValueValueString {
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 VerifiedValueValueString {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
/// Types for composing complex structures.
pub mod builder {
#[derive(Clone, Debug)]
pub struct CardBlobRef {
media_type: ::std::result::Result<super::CardBlobRefMediaType, ::std::string::String>,
sha256: ::std::result::Result<super::CardBlobRefSha256, ::std::string::String>,
size: ::std::result::Result<
::std::option::Option<::std::num::NonZeroU64>,
::std::string::String,
>,
url: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
url_expires_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
}
impl ::std::default::Default for CardBlobRef {
fn default() -> Self {
Self {
media_type: Err("no value supplied for media_type".to_string()),
sha256: Err("no value supplied for sha256".to_string()),
size: Ok(Default::default()),
url: Ok(Default::default()),
url_expires_at: Ok(Default::default()),
}
}
}
impl CardBlobRef {
pub fn media_type<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::CardBlobRefMediaType>,
T::Error: ::std::fmt::Display,
{
self.media_type = value
.try_into()
.map_err(|e| format!("error converting supplied value for media_type: {e}"));
self
}
pub fn sha256<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::CardBlobRefSha256>,
T::Error: ::std::fmt::Display,
{
self.sha256 = value
.try_into()
.map_err(|e| format!("error converting supplied value for sha256: {e}"));
self
}
pub fn size<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::num::NonZeroU64>>,
T::Error: ::std::fmt::Display,
{
self.size = value
.try_into()
.map_err(|e| format!("error converting supplied value for size: {e}"));
self
}
pub fn url<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.url = value
.try_into()
.map_err(|e| format!("error converting supplied value for url: {e}"));
self
}
pub fn url_expires_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.url_expires_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for url_expires_at: {e}"));
self
}
}
impl ::std::convert::TryFrom<CardBlobRef> for super::CardBlobRef {
type Error = super::error::ConversionError;
fn try_from(
value: CardBlobRef,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
media_type: value.media_type?,
sha256: value.sha256?,
size: value.size?,
url: value.url?,
url_expires_at: value.url_expires_at?,
})
}
}
impl ::std::convert::From<super::CardBlobRef> for CardBlobRef {
fn from(value: super::CardBlobRef) -> Self {
Self {
media_type: Ok(value.media_type),
sha256: Ok(value.sha256),
size: Ok(value.size),
url: Ok(value.url),
url_expires_at: Ok(value.url_expires_at),
}
}
}
#[derive(Clone, Debug)]
pub struct GroupJoinRequest {
created_at:
::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
decided_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
decided_by: ::std::result::Result<
::std::option::Option<super::GroupJoinRequestDecidedBy>,
::std::string::String,
>,
entry_id: ::std::result::Result<super::EntryId, ::std::string::String>,
group_id: ::std::result::Result<super::GroupId, ::std::string::String>,
message: ::std::result::Result<
::std::option::Option<super::JoinRequestMessage>,
::std::string::String,
>,
request_id: ::std::result::Result<super::JoinRequestId, ::std::string::String>,
state: ::std::result::Result<super::GroupJoinRequestState, ::std::string::String>,
}
impl ::std::default::Default for GroupJoinRequest {
fn default() -> Self {
Self {
created_at: Err("no value supplied for created_at".to_string()),
decided_at: Ok(Default::default()),
decided_by: Ok(Default::default()),
entry_id: Err("no value supplied for entry_id".to_string()),
group_id: Err("no value supplied for group_id".to_string()),
message: Ok(Default::default()),
request_id: Err("no value supplied for request_id".to_string()),
state: Err("no value supplied for state".to_string()),
}
}
}
impl GroupJoinRequest {
pub fn created_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::chrono::DateTime<::chrono::offset::Utc>>,
T::Error: ::std::fmt::Display,
{
self.created_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for created_at: {e}"));
self
}
pub fn decided_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.decided_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for decided_at: {e}"));
self
}
pub fn decided_by<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::GroupJoinRequestDecidedBy>>,
T::Error: ::std::fmt::Display,
{
self.decided_by = value
.try_into()
.map_err(|e| format!("error converting supplied value for decided_by: {e}"));
self
}
pub fn entry_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::EntryId>,
T::Error: ::std::fmt::Display,
{
self.entry_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for entry_id: {e}"));
self
}
pub fn group_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::GroupId>,
T::Error: ::std::fmt::Display,
{
self.group_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for group_id: {e}"));
self
}
pub fn message<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::JoinRequestMessage>>,
T::Error: ::std::fmt::Display,
{
self.message = value
.try_into()
.map_err(|e| format!("error converting supplied value for message: {e}"));
self
}
pub fn request_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::JoinRequestId>,
T::Error: ::std::fmt::Display,
{
self.request_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for request_id: {e}"));
self
}
pub fn state<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::GroupJoinRequestState>,
T::Error: ::std::fmt::Display,
{
self.state = value
.try_into()
.map_err(|e| format!("error converting supplied value for state: {e}"));
self
}
}
impl ::std::convert::TryFrom<GroupJoinRequest> for super::GroupJoinRequest {
type Error = super::error::ConversionError;
fn try_from(
value: GroupJoinRequest,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
created_at: value.created_at?,
decided_at: value.decided_at?,
decided_by: value.decided_by?,
entry_id: value.entry_id?,
group_id: value.group_id?,
message: value.message?,
request_id: value.request_id?,
state: value.state?,
})
}
}
impl ::std::convert::From<super::GroupJoinRequest> for GroupJoinRequest {
fn from(value: super::GroupJoinRequest) -> Self {
Self {
created_at: Ok(value.created_at),
decided_at: Ok(value.decided_at),
decided_by: Ok(value.decided_by),
entry_id: Ok(value.entry_id),
group_id: Ok(value.group_id),
message: Ok(value.message),
request_id: Ok(value.request_id),
state: Ok(value.state),
}
}
}
#[derive(Clone, Debug)]
pub struct GroupMember {
credential_id: ::std::result::Result<
::std::option::Option<super::GroupCredentialId>,
::std::string::String,
>,
credential_valid_until: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
entry_id: ::std::result::Result<super::EntryId, ::std::string::String>,
fields:
::std::result::Result<::std::option::Option<super::EntryFields>, ::std::string::String>,
since:
::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
source: ::std::result::Result<super::MembershipSource, ::std::string::String>,
state: ::std::result::Result<super::GroupMemberState, ::std::string::String>,
}
impl ::std::default::Default for GroupMember {
fn default() -> Self {
Self {
credential_id: Ok(Default::default()),
credential_valid_until: Ok(Default::default()),
entry_id: Err("no value supplied for entry_id".to_string()),
fields: Ok(Default::default()),
since: Err("no value supplied for since".to_string()),
source: Err("no value supplied for source".to_string()),
state: Err("no value supplied for state".to_string()),
}
}
}
impl GroupMember {
pub fn credential_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::GroupCredentialId>>,
T::Error: ::std::fmt::Display,
{
self.credential_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for credential_id: {e}"));
self
}
pub fn credential_valid_until<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.credential_valid_until = value.try_into().map_err(|e| {
format!("error converting supplied value for credential_valid_until: {e}")
});
self
}
pub fn entry_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::EntryId>,
T::Error: ::std::fmt::Display,
{
self.entry_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for entry_id: {e}"));
self
}
pub fn fields<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::EntryFields>>,
T::Error: ::std::fmt::Display,
{
self.fields = value
.try_into()
.map_err(|e| format!("error converting supplied value for fields: {e}"));
self
}
pub fn since<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::chrono::DateTime<::chrono::offset::Utc>>,
T::Error: ::std::fmt::Display,
{
self.since = value
.try_into()
.map_err(|e| format!("error converting supplied value for since: {e}"));
self
}
pub fn source<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::MembershipSource>,
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::GroupMemberState>,
T::Error: ::std::fmt::Display,
{
self.state = value
.try_into()
.map_err(|e| format!("error converting supplied value for state: {e}"));
self
}
}
impl ::std::convert::TryFrom<GroupMember> for super::GroupMember {
type Error = super::error::ConversionError;
fn try_from(
value: GroupMember,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
credential_id: value.credential_id?,
credential_valid_until: value.credential_valid_until?,
entry_id: value.entry_id?,
fields: value.fields?,
since: value.since?,
source: value.source?,
state: value.state?,
})
}
}
impl ::std::convert::From<super::GroupMember> for GroupMember {
fn from(value: super::GroupMember) -> Self {
Self {
credential_id: Ok(value.credential_id),
credential_valid_until: Ok(value.credential_valid_until),
entry_id: Ok(value.entry_id),
fields: Ok(value.fields),
since: Ok(value.since),
source: Ok(value.source),
state: Ok(value.state),
}
}
}
#[derive(Clone, Debug)]
pub struct Payload {
decision: ::std::result::Result<super::PayloadDecision, ::std::string::String>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
reason: ::std::result::Result<
::std::option::Option<super::PayloadReason>,
::std::string::String,
>,
request_id: ::std::result::Result<super::JoinRequestId, ::std::string::String>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
decision: Err("no value supplied for decision".to_string()),
ext: Ok(Default::default()),
reason: Ok(Default::default()),
request_id: Err("no value supplied for request_id".to_string()),
}
}
}
impl Payload {
pub fn decision<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::PayloadDecision>,
T::Error: ::std::fmt::Display,
{
self.decision = value
.try_into()
.map_err(|e| format!("error converting supplied value for decision: {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 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 request_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::JoinRequestId>,
T::Error: ::std::fmt::Display,
{
self.request_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for request_id: {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 {
decision: value.decision?,
ext: value.ext?,
reason: value.reason?,
request_id: value.request_id?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
decision: Ok(value.decision),
ext: Ok(value.ext),
reason: Ok(value.reason),
request_id: Ok(value.request_id),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
credential_id: ::std::result::Result<
::std::option::Option<super::GroupCredentialId>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
member:
::std::result::Result<::std::option::Option<super::GroupMember>, ::std::string::String>,
request: ::std::result::Result<super::GroupJoinRequest, ::std::string::String>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
credential_id: Err("no value supplied for credential_id".to_string()),
ext: Ok(Default::default()),
member: Ok(Default::default()),
request: Err("no value supplied for request".to_string()),
}
}
}
impl Response {
pub fn credential_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::GroupCredentialId>>,
T::Error: ::std::fmt::Display,
{
self.credential_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for credential_id: {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 member<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::GroupMember>>,
T::Error: ::std::fmt::Display,
{
self.member = value
.try_into()
.map_err(|e| format!("error converting supplied value for member: {e}"));
self
}
pub fn request<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::GroupJoinRequest>,
T::Error: ::std::fmt::Display,
{
self.request = value
.try_into()
.map_err(|e| format!("error converting supplied value for request: {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 {
credential_id: value.credential_id?,
ext: value.ext?,
member: value.member?,
request: value.request?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
credential_id: Ok(value.credential_id),
ext: Ok(value.ext),
member: Ok(value.member),
request: Ok(value.request),
}
}
}
#[derive(Clone, Debug)]
pub struct VerifiedValue {
credential_type: ::std::result::Result<
::std::option::Option<super::VerifiedValueCredentialType>,
::std::string::String,
>,
issuer: ::std::result::Result<super::VerifiedValueIssuer, ::std::string::String>,
valid_until: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
value: ::std::result::Result<super::VerifiedValueValue, ::std::string::String>,
verified_at:
::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
}
impl ::std::default::Default for VerifiedValue {
fn default() -> Self {
Self {
credential_type: Ok(Default::default()),
issuer: Err("no value supplied for issuer".to_string()),
valid_until: Ok(Default::default()),
value: Err("no value supplied for value".to_string()),
verified_at: Err("no value supplied for verified_at".to_string()),
}
}
}
impl VerifiedValue {
pub fn credential_type<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::VerifiedValueCredentialType>>,
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 issuer<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::VerifiedValueIssuer>,
T::Error: ::std::fmt::Display,
{
self.issuer = value
.try_into()
.map_err(|e| format!("error converting supplied value for issuer: {e}"));
self
}
pub fn valid_until<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.valid_until = value
.try_into()
.map_err(|e| format!("error converting supplied value for valid_until: {e}"));
self
}
pub fn value<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::VerifiedValueValue>,
T::Error: ::std::fmt::Display,
{
self.value = value
.try_into()
.map_err(|e| format!("error converting supplied value for value: {e}"));
self
}
pub fn verified_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::chrono::DateTime<::chrono::offset::Utc>>,
T::Error: ::std::fmt::Display,
{
self.verified_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for verified_at: {e}"));
self
}
}
impl ::std::convert::TryFrom<VerifiedValue> for super::VerifiedValue {
type Error = super::error::ConversionError;
fn try_from(
value: VerifiedValue,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
credential_type: value.credential_type?,
issuer: value.issuer?,
valid_until: value.valid_until?,
value: value.value?,
verified_at: value.verified_at?,
})
}
}
impl ::std::convert::From<super::VerifiedValue> for VerifiedValue {
fn from(value: super::VerifiedValue) -> Self {
Self {
credential_type: Ok(value.credential_type),
issuer: Ok(value.issuer),
valid_until: Ok(value.valid_until),
value: Ok(value.value),
verified_at: Ok(value.verified_at),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vtc/groups/requests/decide/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 \"CardBlobRef\": {\n \"additionalProperties\": false,\n \"description\": \"A content-addressed image held in the community's blob store — an avatar or an `image` field. At most 256 KiB, images only, re-encoded by the community on upload (vtc/directory/images/upload: metadata stripped, dimensions capped) so its digest does not link the member across communities. A viewer reads the bytes with vtc/directory/images/get, which answers only where the same projection shows the value. `url` and `urlExpiresAt` MAY appear in a projection: a short-lived URL the community checks against the same projection, so a member-only image is never a public URL. A community that does not offer one leaves both out.\",\n \"properties\": {\n \"mediaType\": {\n \"description\": \"Media type of the stored bytes.\",\n \"enum\": [\n \"image/png\",\n \"image/jpeg\",\n \"image/webp\",\n \"image/avif\"\n ],\n \"type\": \"string\"\n },\n \"sha256\": {\n \"description\": \"Lowercase hex SHA-256 of the stored, re-encoded bytes.\",\n \"pattern\": \"^[0-9a-f]{64}$\",\n \"type\": \"string\"\n },\n \"size\": {\n \"description\": \"Size in bytes of the stored bytes.\",\n \"maximum\": 262144,\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"url\": {\n \"description\": \"Projection only: a URL the viewer can fetch the image from until `urlExpiresAt`.\",\n \"format\": \"uri\",\n \"maxLength\": 2048,\n \"type\": \"string\"\n },\n \"urlExpiresAt\": {\n \"description\": \"Projection only: when `url` stops working.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"sha256\",\n \"mediaType\"\n ],\n \"title\": \"CardBlobRef\",\n \"type\": \"object\"\n },\n \"EntryFields\": {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/FieldValue\"\n },\n \"description\": \"The fields of one entry that a particular viewer may see, keyed by field: the intersection of the member's visibility, the community's ceiling and policy, plus any derived fields that intersection admits. A withheld field is ABSENT, never null.\",\n \"maxProperties\": 64,\n \"propertyNames\": {\n \"$ref\": \"#/$defs/FieldKey\"\n },\n \"title\": \"EntryFields\",\n \"type\": \"object\"\n },\n \"EntryId\": {\n \"description\": \"Opaque identifier of one directory entry: `dir_` followed by 16 to 64 base64url characters. Random, scoped to one community, and stable for the life of the membership — it survives a rotation of the member's DID, which is why groups, notes and cards are keyed by it. It MUST NOT be derived from, and MUST NOT reveal, any DID of the member, and the same person's entries in two communities MUST NOT share one. Compared by exact string equality.\",\n \"pattern\": \"^dir_[A-Za-z0-9_-]{16,64}$\",\n \"title\": \"EntryId\",\n \"type\": \"string\"\n },\n \"Ext\": {\n \"additionalProperties\": true,\n \"description\": \"Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)+$\"\n },\n \"title\": \"Ext\",\n \"type\": \"object\"\n },\n \"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 \"FieldValue\": {\n \"anyOf\": [\n {\n \"maxLength\": 2000,\n \"type\": \"string\"\n },\n {\n \"type\": \"boolean\"\n },\n {\n \"items\": {\n \"maxLength\": 500,\n \"type\": \"string\"\n },\n \"maxItems\": 32,\n \"type\": \"array\"\n },\n {\n \"$ref\": \"#/$defs/CardBlobRef\"\n },\n {\n \"$ref\": \"#/$defs/VerifiedValue\"\n }\n ],\n \"description\": \"The value of one field. Which shape a field takes is fixed by its definition's `type`: text-like types (`text`, `longText`, `url`, `email`, `phone`, `enum`, `date` as YYYY-MM-DD, `country` as ISO 3166-1 alpha-2, `did`) are strings; `multiEnum` and the base field `links` are arrays of strings; `image` and the base field `avatar` are a `CardBlobRef`; `claim` is a `VerifiedValue`; the derived base field `personhood` is a boolean.\",\n \"title\": \"FieldValue\"\n },\n \"GroupCredentialId\": {\n \"description\": \"Identifier (`id`) of a group membership credential issued to a member. Each renewal issues a new credential with a new identifier. Validity is the community's setting; a community SHOULD default to 30 days, renewed when 10 days remain.\",\n \"maxLength\": 512,\n \"minLength\": 1,\n \"title\": \"GroupCredentialId\",\n \"type\": \"string\"\n },\n \"GroupId\": {\n \"description\": \"Opaque identifier of a community group: `grp_` followed by 16 to 64 base64url characters. Random and community-scoped; not the group's DID.\",\n \"pattern\": \"^grp_[A-Za-z0-9_-]{16,64}$\",\n \"title\": \"GroupId\",\n \"type\": \"string\"\n },\n \"GroupJoinRequest\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"createdAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"decidedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"decidedBy\": {\n \"description\": \"The manager who decided. Shown to managers only.\",\n \"maxLength\": 2048,\n \"pattern\": \"^did:\",\n \"type\": \"string\"\n },\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"groupId\": {\n \"$ref\": \"#/$defs/GroupId\"\n },\n \"message\": {\n \"$ref\": \"#/$defs/JoinRequestMessage\"\n },\n \"requestId\": {\n \"$ref\": \"#/$defs/JoinRequestId\"\n },\n \"state\": {\n \"enum\": [\n \"pending\",\n \"approved\",\n \"declined\",\n \"withdrawn\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"requestId\",\n \"groupId\",\n \"entryId\",\n \"createdAt\",\n \"state\"\n ],\n \"title\": \"GroupJoinRequest\",\n \"type\": \"object\"\n },\n \"GroupMember\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"credentialId\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/$defs/GroupCredentialId\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"The member's current group membership credential, or null when the group issues none.\"\n },\n \"credentialValidUntil\": {\n \"description\": \"When the member's current group credential expires. Shown to the member themselves and to managers only.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"fields\": {\n \"$ref\": \"#/$defs/EntryFields\",\n \"description\": \"The member's directory fields that the caller may see, projected exactly as vtc/directory/entries/show would project them. Absent when the caller may see none.\"\n },\n \"since\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"source\": {\n \"$ref\": \"#/$defs/MembershipSource\"\n },\n \"state\": {\n \"description\": \"`active`: a member. `pending`: an addition to a group carrying authority that is waiting for the consent the community requires for a grant.\",\n \"enum\": [\n \"active\",\n \"pending\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"entryId\",\n \"source\",\n \"since\",\n \"state\"\n ],\n \"title\": \"GroupMember\",\n \"type\": \"object\"\n },\n \"JoinRequestId\": {\n \"pattern\": \"^greq_[A-Za-z0-9_-]{16,64}$\",\n \"title\": \"JoinRequestId\",\n \"type\": \"string\"\n },\n \"JoinRequestMessage\": {\n \"description\": \"An optional note from the member to the group's managers. Plain text.\",\n \"maxLength\": 280,\n \"minLength\": 1,\n \"title\": \"JoinRequestMessage\",\n \"type\": \"string\"\n },\n \"MembershipSource\": {\n \"description\": \"How the member came to be in the group. `added`: by a manager. `joined`: they joined an open group. `requestApproved`: a manager approved their request. `rule`: a dynamic group's rule admits them.\",\n \"enum\": [\n \"added\",\n \"joined\",\n \"requestApproved\",\n \"rule\"\n ],\n \"title\": \"MembershipSource\",\n \"type\": \"string\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to a vtc/groups/requests/decide/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/groups/requests/decide/0.1#response.\",\n \"properties\": {\n \"credentialId\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/$defs/GroupCredentialId\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"The membership credential offered, or null on a decline or where the group issues none.\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"member\": {\n \"$ref\": \"#/$defs/GroupMember\",\n \"description\": \"Present on approval.\"\n },\n \"request\": {\n \"$ref\": \"#/$defs/GroupJoinRequest\"\n }\n },\n \"required\": [\n \"request\",\n \"credentialId\"\n ],\n \"title\": \"VTC Groups — Requests — Decide — response payload\",\n \"type\": \"object\"\n },\n \"VerifiedValue\": {\n \"additionalProperties\": false,\n \"description\": \"The value of a `credential`-sourced field: a claim the member disclosed from a credential they presented, with the issuer that attests it. A verified value always names its issuer, and a self-asserted value is never shaped as one. The community keeps only the disclosed claim and these facts about it — never the presentation.\",\n \"properties\": {\n \"credentialType\": {\n \"description\": \"The most specific `type` of the credential the claim came from.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"issuer\": {\n \"description\": \"DID of the credential's issuer, shown as the field's verification badge.\",\n \"maxLength\": 2048,\n \"pattern\": \"^did:\",\n \"type\": \"string\"\n },\n \"validUntil\": {\n \"description\": \"When the credential expires, where it does. The community withdraws the value once it passes.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"value\": {\n \"anyOf\": [\n {\n \"maxLength\": 2000,\n \"type\": \"string\"\n },\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"number\"\n }\n ],\n \"description\": \"The disclosed claim value.\"\n },\n \"verifiedAt\": {\n \"description\": \"When the community verified the presentation.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"value\",\n \"issuer\",\n \"verifiedAt\"\n ],\n \"title\": \"VerifiedValue\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/vtc/groups/requests/decide/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"A group manager approves or declines a request to join; an approval admits the member, with a membership credential issued by the group's DID where the group issues credentials. The outer document members are owned by the framework — SPEC §6.3.\",\n \"properties\": {\n \"decision\": {\n \"enum\": [\n \"approve\",\n \"decline\"\n ],\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"reason\": {\n \"description\": \"Optional; recorded with the decision and shown to managers. Not sent to the requester.\",\n \"maxLength\": 500,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"requestId\": {\n \"$ref\": \"#/$defs/JoinRequestId\"\n }\n },\n \"required\": [\n \"requestId\",\n \"decision\"\n ],\n \"title\": \"VTC Groups — Requests — Decide — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str =
"https://trusttasks.org/spec/vtc/groups/requests/decide/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 \"CardBlobRef\": {\n \"additionalProperties\": false,\n \"description\": \"A content-addressed image held in the community's blob store — an avatar or an `image` field. At most 256 KiB, images only, re-encoded by the community on upload (vtc/directory/images/upload: metadata stripped, dimensions capped) so its digest does not link the member across communities. A viewer reads the bytes with vtc/directory/images/get, which answers only where the same projection shows the value. `url` and `urlExpiresAt` MAY appear in a projection: a short-lived URL the community checks against the same projection, so a member-only image is never a public URL. A community that does not offer one leaves both out.\",\n \"properties\": {\n \"mediaType\": {\n \"description\": \"Media type of the stored bytes.\",\n \"enum\": [\n \"image/png\",\n \"image/jpeg\",\n \"image/webp\",\n \"image/avif\"\n ],\n \"type\": \"string\"\n },\n \"sha256\": {\n \"description\": \"Lowercase hex SHA-256 of the stored, re-encoded bytes.\",\n \"pattern\": \"^[0-9a-f]{64}$\",\n \"type\": \"string\"\n },\n \"size\": {\n \"description\": \"Size in bytes of the stored bytes.\",\n \"maximum\": 262144,\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"url\": {\n \"description\": \"Projection only: a URL the viewer can fetch the image from until `urlExpiresAt`.\",\n \"format\": \"uri\",\n \"maxLength\": 2048,\n \"type\": \"string\"\n },\n \"urlExpiresAt\": {\n \"description\": \"Projection only: when `url` stops working.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"sha256\",\n \"mediaType\"\n ],\n \"title\": \"CardBlobRef\",\n \"type\": \"object\"\n },\n \"EntryFields\": {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/FieldValue\"\n },\n \"description\": \"The fields of one entry that a particular viewer may see, keyed by field: the intersection of the member's visibility, the community's ceiling and policy, plus any derived fields that intersection admits. A withheld field is ABSENT, never null.\",\n \"maxProperties\": 64,\n \"propertyNames\": {\n \"$ref\": \"#/$defs/FieldKey\"\n },\n \"title\": \"EntryFields\",\n \"type\": \"object\"\n },\n \"EntryId\": {\n \"description\": \"Opaque identifier of one directory entry: `dir_` followed by 16 to 64 base64url characters. Random, scoped to one community, and stable for the life of the membership — it survives a rotation of the member's DID, which is why groups, notes and cards are keyed by it. It MUST NOT be derived from, and MUST NOT reveal, any DID of the member, and the same person's entries in two communities MUST NOT share one. Compared by exact string equality.\",\n \"pattern\": \"^dir_[A-Za-z0-9_-]{16,64}$\",\n \"title\": \"EntryId\",\n \"type\": \"string\"\n },\n \"Ext\": {\n \"additionalProperties\": true,\n \"description\": \"Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)+$\"\n },\n \"title\": \"Ext\",\n \"type\": \"object\"\n },\n \"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 \"FieldValue\": {\n \"anyOf\": [\n {\n \"maxLength\": 2000,\n \"type\": \"string\"\n },\n {\n \"type\": \"boolean\"\n },\n {\n \"items\": {\n \"maxLength\": 500,\n \"type\": \"string\"\n },\n \"maxItems\": 32,\n \"type\": \"array\"\n },\n {\n \"$ref\": \"#/$defs/CardBlobRef\"\n },\n {\n \"$ref\": \"#/$defs/VerifiedValue\"\n }\n ],\n \"description\": \"The value of one field. Which shape a field takes is fixed by its definition's `type`: text-like types (`text`, `longText`, `url`, `email`, `phone`, `enum`, `date` as YYYY-MM-DD, `country` as ISO 3166-1 alpha-2, `did`) are strings; `multiEnum` and the base field `links` are arrays of strings; `image` and the base field `avatar` are a `CardBlobRef`; `claim` is a `VerifiedValue`; the derived base field `personhood` is a boolean.\",\n \"title\": \"FieldValue\"\n },\n \"GroupCredentialId\": {\n \"description\": \"Identifier (`id`) of a group membership credential issued to a member. Each renewal issues a new credential with a new identifier. Validity is the community's setting; a community SHOULD default to 30 days, renewed when 10 days remain.\",\n \"maxLength\": 512,\n \"minLength\": 1,\n \"title\": \"GroupCredentialId\",\n \"type\": \"string\"\n },\n \"GroupId\": {\n \"description\": \"Opaque identifier of a community group: `grp_` followed by 16 to 64 base64url characters. Random and community-scoped; not the group's DID.\",\n \"pattern\": \"^grp_[A-Za-z0-9_-]{16,64}$\",\n \"title\": \"GroupId\",\n \"type\": \"string\"\n },\n \"GroupJoinRequest\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"createdAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"decidedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"decidedBy\": {\n \"description\": \"The manager who decided. Shown to managers only.\",\n \"maxLength\": 2048,\n \"pattern\": \"^did:\",\n \"type\": \"string\"\n },\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"groupId\": {\n \"$ref\": \"#/$defs/GroupId\"\n },\n \"message\": {\n \"$ref\": \"#/$defs/JoinRequestMessage\"\n },\n \"requestId\": {\n \"$ref\": \"#/$defs/JoinRequestId\"\n },\n \"state\": {\n \"enum\": [\n \"pending\",\n \"approved\",\n \"declined\",\n \"withdrawn\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"requestId\",\n \"groupId\",\n \"entryId\",\n \"createdAt\",\n \"state\"\n ],\n \"title\": \"GroupJoinRequest\",\n \"type\": \"object\"\n },\n \"GroupMember\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"credentialId\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/$defs/GroupCredentialId\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"The member's current group membership credential, or null when the group issues none.\"\n },\n \"credentialValidUntil\": {\n \"description\": \"When the member's current group credential expires. Shown to the member themselves and to managers only.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"fields\": {\n \"$ref\": \"#/$defs/EntryFields\",\n \"description\": \"The member's directory fields that the caller may see, projected exactly as vtc/directory/entries/show would project them. Absent when the caller may see none.\"\n },\n \"since\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"source\": {\n \"$ref\": \"#/$defs/MembershipSource\"\n },\n \"state\": {\n \"description\": \"`active`: a member. `pending`: an addition to a group carrying authority that is waiting for the consent the community requires for a grant.\",\n \"enum\": [\n \"active\",\n \"pending\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"entryId\",\n \"source\",\n \"since\",\n \"state\"\n ],\n \"title\": \"GroupMember\",\n \"type\": \"object\"\n },\n \"JoinRequestId\": {\n \"pattern\": \"^greq_[A-Za-z0-9_-]{16,64}$\",\n \"title\": \"JoinRequestId\",\n \"type\": \"string\"\n },\n \"JoinRequestMessage\": {\n \"description\": \"An optional note from the member to the group's managers. Plain text.\",\n \"maxLength\": 280,\n \"minLength\": 1,\n \"title\": \"JoinRequestMessage\",\n \"type\": \"string\"\n },\n \"MembershipSource\": {\n \"description\": \"How the member came to be in the group. `added`: by a manager. `joined`: they joined an open group. `requestApproved`: a manager approved their request. `rule`: a dynamic group's rule admits them.\",\n \"enum\": [\n \"added\",\n \"joined\",\n \"requestApproved\",\n \"rule\"\n ],\n \"title\": \"MembershipSource\",\n \"type\": \"string\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to a vtc/groups/requests/decide/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/groups/requests/decide/0.1#response.\",\n \"properties\": {\n \"credentialId\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/$defs/GroupCredentialId\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"The membership credential offered, or null on a decline or where the group issues none.\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"member\": {\n \"$ref\": \"#/$defs/GroupMember\",\n \"description\": \"Present on approval.\"\n },\n \"request\": {\n \"$ref\": \"#/$defs/GroupJoinRequest\"\n }\n },\n \"required\": [\n \"request\",\n \"credentialId\"\n ],\n \"title\": \"VTC Groups — Requests — Decide — response payload\",\n \"type\": \"object\"\n },\n \"VerifiedValue\": {\n \"additionalProperties\": false,\n \"description\": \"The value of a `credential`-sourced field: a claim the member disclosed from a credential they presented, with the issuer that attests it. A verified value always names its issuer, and a self-asserted value is never shaped as one. The community keeps only the disclosed claim and these facts about it — never the presentation.\",\n \"properties\": {\n \"credentialType\": {\n \"description\": \"The most specific `type` of the credential the claim came from.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"issuer\": {\n \"description\": \"DID of the credential's issuer, shown as the field's verification badge.\",\n \"maxLength\": 2048,\n \"pattern\": \"^did:\",\n \"type\": \"string\"\n },\n \"validUntil\": {\n \"description\": \"When the credential expires, where it does. The community withdraws the value once it passes.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"value\": {\n \"anyOf\": [\n {\n \"maxLength\": 2000,\n \"type\": \"string\"\n },\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"number\"\n }\n ],\n \"description\": \"The disclosed claim value.\"\n },\n \"verifiedAt\": {\n \"description\": \"When the community verified the presentation.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"value\",\n \"issuer\",\n \"verifiedAt\"\n ],\n \"title\": \"VerifiedValue\",\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::NOT_FOUND,
error_codes::ALREADY_DECIDED,
error_codes::SELF_DECISION,
error_codes::KEY_HOLDER_UNAVAILABLE,
error_codes::KEY_HOLDER_REFUSED,
];
/// 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/groups/requests/decide:notFound`
///
/// No request to a group the caller manages has this identifier.
///
/// Declared `retryable: false`.
pub const NOT_FOUND: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/groups/requests/decide:notFound",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/groups/requests/decide:alreadyDecided`
///
/// The request is no longer pending.
///
/// Declared `retryable: false`.
pub const ALREADY_DECIDED: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/groups/requests/decide:alreadyDecided",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/groups/requests/decide:selfDecision`
///
/// The caller made the request; nobody decides their own.
///
/// Declared `retryable: false`.
pub const SELF_DECISION: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/groups/requests/decide:selfDecision",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/groups/requests/decide:keyHolderUnavailable`
///
/// The community's VTA did not answer. The request is still pending.
///
/// Declared `retryable: true`.
pub const KEY_HOLDER_UNAVAILABLE: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/groups/requests/decide:keyHolderUnavailable",
retryable: true,
details_schema: ::core::option::Option::None,
};
/// `vtc/groups/requests/decide:keyHolderRefused`
///
/// The community's VTA refused a step. Its own code and message are carried in `details`. The request is still pending.
///
/// Declared `retryable: false`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const KEY_HOLDER_REFUSED: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/groups/requests/decide:keyHolderRefused",
retryable: false,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"code\":{\"maxLength\":128,\"type\":\"string\"},\"message\":{\"maxLength\":500,\"type\":\"string\"}},\"type\":\"object\"}",
),
};
}