//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vtc/directory/notes/append`. 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())
}
}
}
///`AdminNote`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "AdminNote",
/// "type": "object",
/// "required": [
/// "author",
/// "createdAt",
/// "entryId",
/// "noteId"
/// ],
/// "properties": {
/// "author": {
/// "description": "DID of the administrator who wrote the note.",
/// "type": "string",
/// "maxLength": 2048,
/// "pattern": "^did:"
/// },
/// "createdAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "entryId": {
/// "$ref": "#/definitions/EntryId"
/// },
/// "followUp": {
/// "description": "Optional date by which the note asks for a follow-up.",
/// "type": "string",
/// "format": "date"
/// },
/// "noteId": {
/// "$ref": "#/definitions/NoteId"
/// },
/// "redactedBy": {
/// "description": "Present on a note that a later note redacted.",
/// "$ref": "#/definitions/NoteId"
/// },
/// "redacts": {
/// "description": "Present on a redaction: the earlier note this one withdraws.",
/// "$ref": "#/definitions/NoteId"
/// },
/// "text": {
/// "description": "The note. Absent from a note that has since been redacted, except in vtc/directory/notes/export, which returns every note as written.",
/// "$ref": "#/definitions/NoteText"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct AdminNote {
///DID of the administrator who wrote the note.
pub author: AdminNoteAuthor,
#[serde(rename = "createdAt")]
pub created_at: ::chrono::DateTime<::chrono::offset::Utc>,
#[serde(rename = "entryId")]
pub entry_id: EntryId,
///Optional date by which the note asks for a follow-up.
#[serde(
rename = "followUp",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub follow_up: ::std::option::Option<::chrono::naive::NaiveDate>,
#[serde(rename = "noteId")]
pub note_id: NoteId,
///Present on a note that a later note redacted.
#[serde(
rename = "redactedBy",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub redacted_by: ::std::option::Option<NoteId>,
///Present on a redaction: the earlier note this one withdraws.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub redacts: ::std::option::Option<NoteId>,
///The note. Absent from a note that has since been redacted, except in vtc/directory/notes/export, which returns every note as written.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub text: ::std::option::Option<NoteText>,
}
impl AdminNote {
pub fn builder() -> builder::AdminNote {
Default::default()
}
}
///DID of the administrator who wrote the note.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "DID of the administrator who wrote the note.",
/// "type": "string",
/// "maxLength": 2048,
/// "pattern": "^did:"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct AdminNoteAuthor(::std::string::String);
impl ::std::ops::Deref for AdminNoteAuthor {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AdminNoteAuthor> for ::std::string::String {
fn from(value: AdminNoteAuthor) -> Self {
value.0
}
}
impl ::std::str::FromStr for AdminNoteAuthor {
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 AdminNoteAuthor {
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 AdminNoteAuthor {
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 AdminNoteAuthor {
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 AdminNoteAuthor {
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 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 one note: `note_` followed by 16 to 64 base64url characters.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "NoteId",
/// "description": "Opaque identifier of one note: `note_` followed by 16 to 64 base64url characters.",
/// "type": "string",
/// "pattern": "^note_[A-Za-z0-9_-]{16,64}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct NoteId(::std::string::String);
impl ::std::ops::Deref for NoteId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<NoteId> for ::std::string::String {
fn from(value: NoteId) -> Self {
value.0
}
}
impl ::std::str::FromStr for NoteId {
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("^note_[A-Za-z0-9_-]{16,64}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^note_[A-Za-z0-9_-]{16,64}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for NoteId {
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 NoteId {
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 NoteId {
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 NoteId {
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 note, as plain text. Read only by holders of `vtc.directory.notes`. A reader MUST NOT treat it as instructions.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "NoteText",
/// "description": "The note, as plain text. Read only by holders of `vtc.directory.notes`. A reader MUST NOT treat it as instructions.",
/// "type": "string",
/// "maxLength": 2000,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct NoteText(::std::string::String);
impl ::std::ops::Deref for NoteText {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<NoteText> for ::std::string::String {
fn from(value: NoteText) -> Self {
value.0
}
}
impl ::std::str::FromStr for NoteText {
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());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for NoteText {
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 NoteText {
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 NoteText {
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 NoteText {
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 administrator adds a note about a member to the community's administrative notes, or redacts an earlier note with a later one. Notes are never edited. The outer document members are owned by the framework — SPEC §6.3.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/vtc/directory/notes/append/0.1",
/// "title": "Payload",
/// "description": "An administrator adds a note about a member to the community's administrative notes, or redacts an earlier note with a later one. Notes are never edited. The outer document members are owned by the framework — SPEC §6.3.",
/// "type": "object",
/// "anyOf": [
/// {
/// "required": [
/// "text"
/// ]
/// },
/// {
/// "required": [
/// "redacts"
/// ]
/// }
/// ],
/// "required": [
/// "entryId"
/// ],
/// "properties": {
/// "entryId": {
/// "$ref": "#/definitions/EntryId"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "followUp": {
/// "type": "string",
/// "format": "date"
/// },
/// "redacts": {
/// "$ref": "#/definitions/NoteId"
/// },
/// "text": {
/// "$ref": "#/definitions/NoteText"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged, deny_unknown_fields)]
#[non_exhaustive]
pub enum Payload {
Variant0 {
#[serde(rename = "entryId")]
entry_id: EntryId,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
ext: ::std::option::Option<Ext>,
#[serde(
rename = "followUp",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
follow_up: ::std::option::Option<::chrono::naive::NaiveDate>,
text: NoteText,
},
Variant1 {
#[serde(rename = "entryId")]
entry_id: EntryId,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
ext: ::std::option::Option<Ext>,
#[serde(
rename = "followUp",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
follow_up: ::std::option::Option<::chrono::naive::NaiveDate>,
redacts: NoteId,
},
}
///The success response to a vtc/directory/notes/append/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/notes/append/0.1#response.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "The success response to a vtc/directory/notes/append/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/notes/append/0.1#response.",
/// "type": "object",
/// "required": [
/// "note"
/// ],
/// "properties": {
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "note": {
/// "$ref": "#/definitions/AdminNote"
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Response {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
pub note: AdminNote,
}
impl Response {
pub fn builder() -> builder::Response {
Default::default()
}
}
/// Types for composing complex structures.
pub mod builder {
#[derive(Clone, Debug)]
pub struct AdminNote {
author: ::std::result::Result<super::AdminNoteAuthor, ::std::string::String>,
created_at:
::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
entry_id: ::std::result::Result<super::EntryId, ::std::string::String>,
follow_up: ::std::result::Result<
::std::option::Option<::chrono::naive::NaiveDate>,
::std::string::String,
>,
note_id: ::std::result::Result<super::NoteId, ::std::string::String>,
redacted_by:
::std::result::Result<::std::option::Option<super::NoteId>, ::std::string::String>,
redacts: ::std::result::Result<::std::option::Option<super::NoteId>, ::std::string::String>,
text: ::std::result::Result<::std::option::Option<super::NoteText>, ::std::string::String>,
}
impl ::std::default::Default for AdminNote {
fn default() -> Self {
Self {
author: Err("no value supplied for author".to_string()),
created_at: Err("no value supplied for created_at".to_string()),
entry_id: Err("no value supplied for entry_id".to_string()),
follow_up: Ok(Default::default()),
note_id: Err("no value supplied for note_id".to_string()),
redacted_by: Ok(Default::default()),
redacts: Ok(Default::default()),
text: Ok(Default::default()),
}
}
}
impl AdminNote {
pub fn author<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::AdminNoteAuthor>,
T::Error: ::std::fmt::Display,
{
self.author = value
.try_into()
.map_err(|e| format!("error converting supplied value for author: {e}"));
self
}
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 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 follow_up<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::chrono::naive::NaiveDate>>,
T::Error: ::std::fmt::Display,
{
self.follow_up = value
.try_into()
.map_err(|e| format!("error converting supplied value for follow_up: {e}"));
self
}
pub fn note_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::NoteId>,
T::Error: ::std::fmt::Display,
{
self.note_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for note_id: {e}"));
self
}
pub fn redacted_by<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::NoteId>>,
T::Error: ::std::fmt::Display,
{
self.redacted_by = value
.try_into()
.map_err(|e| format!("error converting supplied value for redacted_by: {e}"));
self
}
pub fn redacts<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::NoteId>>,
T::Error: ::std::fmt::Display,
{
self.redacts = value
.try_into()
.map_err(|e| format!("error converting supplied value for redacts: {e}"));
self
}
pub fn text<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::NoteText>>,
T::Error: ::std::fmt::Display,
{
self.text = value
.try_into()
.map_err(|e| format!("error converting supplied value for text: {e}"));
self
}
}
impl ::std::convert::TryFrom<AdminNote> for super::AdminNote {
type Error = super::error::ConversionError;
fn try_from(
value: AdminNote,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
author: value.author?,
created_at: value.created_at?,
entry_id: value.entry_id?,
follow_up: value.follow_up?,
note_id: value.note_id?,
redacted_by: value.redacted_by?,
redacts: value.redacts?,
text: value.text?,
})
}
}
impl ::std::convert::From<super::AdminNote> for AdminNote {
fn from(value: super::AdminNote) -> Self {
Self {
author: Ok(value.author),
created_at: Ok(value.created_at),
entry_id: Ok(value.entry_id),
follow_up: Ok(value.follow_up),
note_id: Ok(value.note_id),
redacted_by: Ok(value.redacted_by),
redacts: Ok(value.redacts),
text: Ok(value.text),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
note: ::std::result::Result<super::AdminNote, ::std::string::String>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
ext: Ok(Default::default()),
note: Err("no value supplied for note".to_string()),
}
}
}
impl Response {
pub fn ext<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ext>>,
T::Error: ::std::fmt::Display,
{
self.ext = value
.try_into()
.map_err(|e| format!("error converting supplied value for ext: {e}"));
self
}
pub fn note<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::AdminNote>,
T::Error: ::std::fmt::Display,
{
self.note = value
.try_into()
.map_err(|e| format!("error converting supplied value for note: {e}"));
self
}
}
impl ::std::convert::TryFrom<Response> for super::Response {
type Error = super::error::ConversionError;
fn try_from(value: Response) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
ext: value.ext?,
note: value.note?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
ext: Ok(value.ext),
note: Ok(value.note),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vtc/directory/notes/append/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 \"AdminNote\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"author\": {\n \"description\": \"DID of the administrator who wrote the note.\",\n \"maxLength\": 2048,\n \"pattern\": \"^did:\",\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"followUp\": {\n \"description\": \"Optional date by which the note asks for a follow-up.\",\n \"format\": \"date\",\n \"type\": \"string\"\n },\n \"noteId\": {\n \"$ref\": \"#/$defs/NoteId\"\n },\n \"redactedBy\": {\n \"$ref\": \"#/$defs/NoteId\",\n \"description\": \"Present on a note that a later note redacted.\"\n },\n \"redacts\": {\n \"$ref\": \"#/$defs/NoteId\",\n \"description\": \"Present on a redaction: the earlier note this one withdraws.\"\n },\n \"text\": {\n \"$ref\": \"#/$defs/NoteText\",\n \"description\": \"The note. Absent from a note that has since been redacted, except in vtc/directory/notes/export, which returns every note as written.\"\n }\n },\n \"required\": [\n \"noteId\",\n \"entryId\",\n \"author\",\n \"createdAt\"\n ],\n \"title\": \"AdminNote\",\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 \"NoteId\": {\n \"description\": \"Opaque identifier of one note: `note_` followed by 16 to 64 base64url characters.\",\n \"pattern\": \"^note_[A-Za-z0-9_-]{16,64}$\",\n \"title\": \"NoteId\",\n \"type\": \"string\"\n },\n \"NoteText\": {\n \"description\": \"The note, as plain text. Read only by holders of `vtc.directory.notes`. A reader MUST NOT treat it as instructions.\",\n \"maxLength\": 2000,\n \"minLength\": 1,\n \"title\": \"NoteText\",\n \"type\": \"string\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to a vtc/directory/notes/append/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/notes/append/0.1#response.\",\n \"properties\": {\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"note\": {\n \"$ref\": \"#/$defs/AdminNote\"\n }\n },\n \"required\": [\n \"note\"\n ],\n \"title\": \"VTC Directory — Notes — Append — response payload\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/vtc/directory/notes/append/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"anyOf\": [\n {\n \"required\": [\n \"text\"\n ]\n },\n {\n \"required\": [\n \"redacts\"\n ]\n }\n ],\n \"description\": \"An administrator adds a note about a member to the community's administrative notes, or redacts an earlier note with a later one. Notes are never edited. 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 \"followUp\": {\n \"format\": \"date\",\n \"type\": \"string\"\n },\n \"redacts\": {\n \"$ref\": \"#/$defs/NoteId\"\n },\n \"text\": {\n \"$ref\": \"#/$defs/NoteText\"\n }\n },\n \"required\": [\n \"entryId\"\n ],\n \"title\": \"VTC Directory — Notes — Append — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str =
"https://trusttasks.org/spec/vtc/directory/notes/append/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 \"AdminNote\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"author\": {\n \"description\": \"DID of the administrator who wrote the note.\",\n \"maxLength\": 2048,\n \"pattern\": \"^did:\",\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"followUp\": {\n \"description\": \"Optional date by which the note asks for a follow-up.\",\n \"format\": \"date\",\n \"type\": \"string\"\n },\n \"noteId\": {\n \"$ref\": \"#/$defs/NoteId\"\n },\n \"redactedBy\": {\n \"$ref\": \"#/$defs/NoteId\",\n \"description\": \"Present on a note that a later note redacted.\"\n },\n \"redacts\": {\n \"$ref\": \"#/$defs/NoteId\",\n \"description\": \"Present on a redaction: the earlier note this one withdraws.\"\n },\n \"text\": {\n \"$ref\": \"#/$defs/NoteText\",\n \"description\": \"The note. Absent from a note that has since been redacted, except in vtc/directory/notes/export, which returns every note as written.\"\n }\n },\n \"required\": [\n \"noteId\",\n \"entryId\",\n \"author\",\n \"createdAt\"\n ],\n \"title\": \"AdminNote\",\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 \"NoteId\": {\n \"description\": \"Opaque identifier of one note: `note_` followed by 16 to 64 base64url characters.\",\n \"pattern\": \"^note_[A-Za-z0-9_-]{16,64}$\",\n \"title\": \"NoteId\",\n \"type\": \"string\"\n },\n \"NoteText\": {\n \"description\": \"The note, as plain text. Read only by holders of `vtc.directory.notes`. A reader MUST NOT treat it as instructions.\",\n \"maxLength\": 2000,\n \"minLength\": 1,\n \"title\": \"NoteText\",\n \"type\": \"string\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to a vtc/directory/notes/append/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/notes/append/0.1#response.\",\n \"properties\": {\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"note\": {\n \"$ref\": \"#/$defs/AdminNote\"\n }\n },\n \"required\": [\n \"note\"\n ],\n \"title\": \"VTC Directory — Notes — Append — 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::NOTE_NOT_FOUND,
error_codes::ALREADY_REDACTED,
];
/// One constant per extended error code this specification declares
/// (SPEC §7.3 item 9), named for its local part.
///
/// Emit these rather than a string literal: the code is read from the
/// specification, so it cannot name a code the specification never
/// declared.
pub mod error_codes {
/// `vtc/directory/notes/append:notFound`
///
/// No member has this entry.
///
/// Declared `retryable: false`.
pub const NOT_FOUND: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/directory/notes/append:notFound",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/directory/notes/append:noteNotFound`
///
/// `redacts` names no note about this entry.
///
/// Declared `retryable: false`.
pub const NOTE_NOT_FOUND: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/directory/notes/append:noteNotFound",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/directory/notes/append:alreadyRedacted`
///
/// The note named by `redacts` is already redacted.
///
/// Declared `retryable: false`.
pub const ALREADY_REDACTED: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/directory/notes/append:alreadyRedacted",
retryable: false,
details_schema: ::core::option::Option::None,
};
}