//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vtc/groups/members/remove`. 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())
}
}
}
///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())
})
}
}
///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())
})
}
}
///A group manager removes a member from a static group: renewal of their group credential stops, and room admissions and grants that only this group provided are withdrawn. 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/members/remove/0.1",
/// "title": "Payload",
/// "description": "A group manager removes a member from a static group: renewal of their group credential stops, and room admissions and grants that only this group provided are withdrawn. The outer document members are owned by the framework — SPEC §6.3.",
/// "type": "object",
/// "required": [
/// "entryId",
/// "groupId"
/// ],
/// "properties": {
/// "entryId": {
/// "$ref": "#/definitions/EntryId"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "groupId": {
/// "$ref": "#/definitions/GroupId"
/// },
/// "reason": {
/// "description": "Why, recorded with the change and shown to anyone who must approve it.",
/// "type": "string",
/// "maxLength": 1024,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Payload {
#[serde(rename = "entryId")]
pub entry_id: EntryId,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
#[serde(rename = "groupId")]
pub group_id: GroupId,
///Why, recorded with the change and shown to anyone who must approve it.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reason: ::std::option::Option<PayloadReason>,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///Why, recorded with the change and shown to anyone who must approve it.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Why, recorded with the change and shown to anyone who must approve it.",
/// "type": "string",
/// "maxLength": 1024,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadReason(::std::string::String);
impl ::std::ops::Deref for PayloadReason {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadReason> for ::std::string::String {
fn from(value: PayloadReason) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadReason {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 1024usize {
return Err("longer than 1024 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PayloadReason {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PayloadReason {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PayloadReason {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for PayloadReason {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///The success response to a vtc/groups/members/remove/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/groups/members/remove/0.1#response.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "The success response to a vtc/groups/members/remove/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/groups/members/remove/0.1#response.",
/// "type": "object",
/// "required": [
/// "entryId",
/// "groupId",
/// "state"
/// ],
/// "properties": {
/// "credentialValidUntil": {
/// "description": "When the member's last group credential lapses; renewal has stopped. Null when they held none.",
/// "type": [
/// "string",
/// "null"
/// ],
/// "format": "date-time"
/// },
/// "entryId": {
/// "$ref": "#/definitions/EntryId"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "groupId": {
/// "$ref": "#/definitions/GroupId"
/// },
/// "state": {
/// "description": "`removed`: done. `pending`: a reduction of authority the community is holding for its cooling-off or consent.",
/// "type": "string",
/// "enum": [
/// "removed",
/// "pending"
/// ]
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Response {
///When the member's last group credential lapses; renewal has stopped. Null when they held none.
#[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,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
#[serde(rename = "groupId")]
pub group_id: GroupId,
///`removed`: done. `pending`: a reduction of authority the community is holding for its cooling-off or consent.
pub state: ResponseState,
}
impl Response {
pub fn builder() -> builder::Response {
Default::default()
}
}
///`removed`: done. `pending`: a reduction of authority the community is holding for its cooling-off or consent.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "`removed`: done. `pending`: a reduction of authority the community is holding for its cooling-off or consent.",
/// "type": "string",
/// "enum": [
/// "removed",
/// "pending"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ResponseState {
#[serde(rename = "removed")]
Removed,
#[serde(rename = "pending")]
Pending,
}
impl ::std::fmt::Display for ResponseState {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Removed => f.write_str("removed"),
Self::Pending => f.write_str("pending"),
}
}
}
impl ::std::str::FromStr for ResponseState {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"removed" => Ok(Self::Removed),
"pending" => Ok(Self::Pending),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ResponseState {
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 ResponseState {
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 ResponseState {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
/// Types for composing complex structures.
pub mod builder {
#[derive(Clone, Debug)]
pub struct Payload {
entry_id: ::std::result::Result<super::EntryId, ::std::string::String>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
group_id: ::std::result::Result<super::GroupId, ::std::string::String>,
reason: ::std::result::Result<
::std::option::Option<super::PayloadReason>,
::std::string::String,
>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
entry_id: Err("no value supplied for entry_id".to_string()),
ext: Ok(Default::default()),
group_id: Err("no value supplied for group_id".to_string()),
reason: Ok(Default::default()),
}
}
}
impl Payload {
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 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 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 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
}
}
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 {
entry_id: value.entry_id?,
ext: value.ext?,
group_id: value.group_id?,
reason: value.reason?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
entry_id: Ok(value.entry_id),
ext: Ok(value.ext),
group_id: Ok(value.group_id),
reason: Ok(value.reason),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
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>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
group_id: ::std::result::Result<super::GroupId, ::std::string::String>,
state: ::std::result::Result<super::ResponseState, ::std::string::String>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
credential_valid_until: Ok(Default::default()),
entry_id: Err("no value supplied for entry_id".to_string()),
ext: Ok(Default::default()),
group_id: Err("no value supplied for group_id".to_string()),
state: Err("no value supplied for state".to_string()),
}
}
}
impl Response {
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 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 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 state<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ResponseState>,
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<Response> for super::Response {
type Error = super::error::ConversionError;
fn try_from(value: Response) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
credential_valid_until: value.credential_valid_until?,
entry_id: value.entry_id?,
ext: value.ext?,
group_id: value.group_id?,
state: value.state?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
credential_valid_until: Ok(value.credential_valid_until),
entry_id: Ok(value.entry_id),
ext: Ok(value.ext),
group_id: Ok(value.group_id),
state: Ok(value.state),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vtc/groups/members/remove/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 \"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 \"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 \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to a vtc/groups/members/remove/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/groups/members/remove/0.1#response.\",\n \"properties\": {\n \"credentialValidUntil\": {\n \"description\": \"When the member's last group credential lapses; renewal has stopped. Null when they held none.\",\n \"format\": \"date-time\",\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"groupId\": {\n \"$ref\": \"#/$defs/GroupId\"\n },\n \"state\": {\n \"description\": \"`removed`: done. `pending`: a reduction of authority the community is holding for its cooling-off or consent.\",\n \"enum\": [\n \"removed\",\n \"pending\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"groupId\",\n \"entryId\",\n \"state\"\n ],\n \"title\": \"VTC Groups — Members — Remove — response payload\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/vtc/groups/members/remove/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"A group manager removes a member from a static group: renewal of their group credential stops, and room admissions and grants that only this group provided are withdrawn. The outer document members are owned by the framework — SPEC §6.3.\",\n \"properties\": {\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"groupId\": {\n \"$ref\": \"#/$defs/GroupId\"\n },\n \"reason\": {\n \"description\": \"Why, recorded with the change and shown to anyone who must approve it.\",\n \"maxLength\": 1024,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"groupId\",\n \"entryId\"\n ],\n \"title\": \"VTC Groups — Members — Remove — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str =
"https://trusttasks.org/spec/vtc/groups/members/remove/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 \"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 \"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 \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to a vtc/groups/members/remove/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/groups/members/remove/0.1#response.\",\n \"properties\": {\n \"credentialValidUntil\": {\n \"description\": \"When the member's last group credential lapses; renewal has stopped. Null when they held none.\",\n \"format\": \"date-time\",\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"groupId\": {\n \"$ref\": \"#/$defs/GroupId\"\n },\n \"state\": {\n \"description\": \"`removed`: done. `pending`: a reduction of authority the community is holding for its cooling-off or consent.\",\n \"enum\": [\n \"removed\",\n \"pending\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"groupId\",\n \"entryId\",\n \"state\"\n ],\n \"title\": \"VTC Groups — Members — Remove — response payload\",\n \"type\": \"object\"\n }\n },\n \"$ref\": \"#/$defs/Response\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n}\n",
);
}
impl crate::RequestPayload for Payload {
type Response = Response;
}
/// The extended error codes this specification declares (SPEC §7.3 item 9,
/// §8.5), in declaration order. Empty when it declares none.
pub const ERROR_CODES: &[crate::DeclaredErrorCode] = &[
error_codes::NOT_FOUND,
error_codes::NOT_IN_GROUP,
error_codes::DYNAMIC_GROUP,
];
/// 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/members/remove:notFound`
///
/// No group the caller may manage has this identifier.
///
/// Declared `retryable: false`.
pub const NOT_FOUND: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/groups/members/remove:notFound",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/groups/members/remove:notInGroup`
///
/// The entry does not belong to the group.
///
/// Declared `retryable: false`.
pub const NOT_IN_GROUP: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/groups/members/remove:notInGroup",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/groups/members/remove:dynamicGroup`
///
/// The group is dynamic; its membership is computed from its rule.
///
/// Declared `retryable: false`.
pub const DYNAMIC_GROUP: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/groups/members/remove:dynamicGroup",
retryable: false,
details_schema: ::core::option::Option::None,
};
}