//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vtc/directory/notes/export`. 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 exports every administrative note about one member, redacted ones included, to answer that member's subject-access request. 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/export/0.1",
/// "title": "Payload",
/// "description": "An administrator exports every administrative note about one member, redacted ones included, to answer that member's subject-access request. The outer document members are owned by the framework — SPEC §6.3.",
/// "type": "object",
/// "required": [
/// "entryId",
/// "reason"
/// ],
/// "properties": {
/// "entryId": {
/// "$ref": "#/definitions/EntryId"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "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>,
///Why, recorded with the change and shown to anyone who must approve it.
pub reason: 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/directory/notes/export/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/notes/export/0.1#response.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "The success response to a vtc/directory/notes/export/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/notes/export/0.1#response.",
/// "type": "object",
/// "required": [
/// "entryId",
/// "exportedAt",
/// "notes"
/// ],
/// "properties": {
/// "entryId": {
/// "$ref": "#/definitions/EntryId"
/// },
/// "exportedAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "notes": {
/// "description": "Every note about the entry, oldest first, with the text of redacted notes included.",
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/AdminNote"
/// },
/// "maxItems": 10000
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Response {
#[serde(rename = "entryId")]
pub entry_id: EntryId,
#[serde(rename = "exportedAt")]
pub exported_at: ::chrono::DateTime<::chrono::offset::Utc>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///Every note about the entry, oldest first, with the text of redacted notes included.
pub notes: ::std::vec::Vec<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 Payload {
entry_id: ::std::result::Result<super::EntryId, ::std::string::String>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
reason: ::std::result::Result<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()),
reason: Err("no value supplied for reason".to_string()),
}
}
}
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 reason<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<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?,
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),
reason: Ok(value.reason),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
entry_id: ::std::result::Result<super::EntryId, ::std::string::String>,
exported_at:
::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
notes: ::std::result::Result<::std::vec::Vec<super::AdminNote>, ::std::string::String>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
entry_id: Err("no value supplied for entry_id".to_string()),
exported_at: Err("no value supplied for exported_at".to_string()),
ext: Ok(Default::default()),
notes: Err("no value supplied for notes".to_string()),
}
}
}
impl Response {
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 exported_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::chrono::DateTime<::chrono::offset::Utc>>,
T::Error: ::std::fmt::Display,
{
self.exported_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for exported_at: {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 notes<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::AdminNote>>,
T::Error: ::std::fmt::Display,
{
self.notes = value
.try_into()
.map_err(|e| format!("error converting supplied value for notes: {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 {
entry_id: value.entry_id?,
exported_at: value.exported_at?,
ext: value.ext?,
notes: value.notes?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
entry_id: Ok(value.entry_id),
exported_at: Ok(value.exported_at),
ext: Ok(value.ext),
notes: Ok(value.notes),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vtc/directory/notes/export/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/export/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/notes/export/0.1#response.\",\n \"properties\": {\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"exportedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"notes\": {\n \"description\": \"Every note about the entry, oldest first, with the text of redacted notes included.\",\n \"items\": {\n \"$ref\": \"#/$defs/AdminNote\"\n },\n \"maxItems\": 10000,\n \"type\": \"array\"\n }\n },\n \"required\": [\n \"entryId\",\n \"notes\",\n \"exportedAt\"\n ],\n \"title\": \"VTC Directory — Notes — Export — response payload\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/vtc/directory/notes/export/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"An administrator exports every administrative note about one member, redacted ones included, to answer that member's subject-access request. 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 \"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 \"entryId\",\n \"reason\"\n ],\n \"title\": \"VTC Directory — Notes — Export — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str =
"https://trusttasks.org/spec/vtc/directory/notes/export/0.1#response";
const IS_PROOF_REQUIRED: bool = true;
const IS_ISSUED_AT_REQUIRED: bool = true;
const MAX_DOCUMENT_BYTES: Option<usize> = Some(4194304usize);
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/export/0.1 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/vtc/directory/notes/export/0.1#response.\",\n \"properties\": {\n \"entryId\": {\n \"$ref\": \"#/$defs/EntryId\"\n },\n \"exportedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"notes\": {\n \"description\": \"Every note about the entry, oldest first, with the text of redacted notes included.\",\n \"items\": {\n \"$ref\": \"#/$defs/AdminNote\"\n },\n \"maxItems\": 10000,\n \"type\": \"array\"\n }\n },\n \"required\": [\n \"entryId\",\n \"notes\",\n \"exportedAt\"\n ],\n \"title\": \"VTC Directory — Notes — Export — 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];
/// 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/export:notFound`
///
/// No member, past or present, has this entry, or its notes have been purged.
///
/// Declared `retryable: false`.
pub const NOT_FOUND: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/directory/notes/export:notFound",
retryable: false,
details_schema: ::core::option::Option::None,
};
}