//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vtc/admin/actions/acknowledge`. 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())
}
}
}
///One parked administrative operation, as the caller is entitled to see it. The same action reads differently to different callers only in `challenge` and `callerRole`, which are per-caller.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Action",
/// "description": "One parked administrative operation, as the caller is entitled to see it. The same action reads differently to different callers only in `challenge` and `callerRole`, which are per-caller.",
/// "type": "object",
/// "required": [
/// "actionId",
/// "approvals",
/// "callerRole",
/// "category",
/// "createdAt",
/// "kind",
/// "payload",
/// "payloadDigest",
/// "requester",
/// "status",
/// "summary",
/// "typeUri"
/// ],
/// "properties": {
/// "actionId": {
/// "$ref": "#/definitions/ActionId"
/// },
/// "approvals": {
/// "description": "The decisions in favour recorded so far — approvals for `approval` and `queue`, acknowledgements for `acknowledge` — one entry per distinct subject, in the order recorded. Empty while none has landed.",
/// "type": "array",
/// "items": {
/// "type": "object",
/// "required": [
/// "at",
/// "subject"
/// ],
/// "properties": {
/// "at": {
/// "description": "When the decision was recorded.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "subject": {
/// "description": "VID of the approver or acknowledger, as proven by the decision's own proof.",
/// "type": "string",
/// "maxLength": 2048,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
/// }
/// },
/// "approversRemaining": {
/// "description": "How many further distinct decisions the action needs while `open` — approvals for `approval`, acknowledgements for `acknowledge`. Lets a console say 'one more' without disclosing the eligible set.",
/// "type": "integer",
/// "minimum": 0.0
/// },
/// "callerRole": {
/// "description": "The caller's relation to this action. `approver` — an eligible approver (whether or not already decided). `requester` — the party whose operation was parked. `acknowledger` — an administrator expected to acknowledge it. `observer` — none of these; seen only through the audit-read capability on a `history` or `all` view.",
/// "type": "string",
/// "enum": [
/// "approver",
/// "requester",
/// "acknowledger",
/// "observer"
/// ]
/// },
/// "category": {
/// "description": "`approval` — eligible approvers approve or decline, N-of-M; the operation executes when the threshold is met. `acknowledge` — an operation that already happened (an operator's offline or break-glass write) which every remaining administrator must acknowledge; there is nothing to approve or decline. `queue` — an existing human decision (for example a join review) surfaced in the same list, with a threshold of one.",
/// "type": "string",
/// "enum": [
/// "approval",
/// "acknowledge",
/// "queue"
/// ]
/// },
/// "challenge": {
/// "description": "Present ONLY on an action the CALLER may decide now — an `approval` or `queue` action on which the caller is an eligible approver who has not yet decided. Per-approver: two approvers are shown different challenges for the same action. Echoed verbatim in `task-consent/decision`'s `challenge`, which binds that decision to this approver and this action. Absent for everyone else, including the requester.",
/// "type": "string",
/// "maxLength": 256,
/// "minLength": 16
/// },
/// "closedAt": {
/// "description": "When the action left `open`. Present exactly when `status` is not `open`.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "closedReason": {
/// "description": "Why the action closed. Present exactly when `status` is not `open`. `invalidated` — the community closed it because something it depended on stopped holding before the threshold (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met but the execution-time re-check refused.",
/// "type": "string",
/// "enum": [
/// "thresholdMet",
/// "declined",
/// "expired",
/// "cancelledByRequester",
/// "invalidated",
/// "failedRecheck",
/// "acknowledged"
/// ]
/// },
/// "createdAt": {
/// "description": "When the operation was parked.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "expiresAt": {
/// "description": "When an open action lapses. Absent for an `acknowledge` or `queue` action that does not expire; ALWAYS present for `approval`, whose open life is bounded (72 hours by default; the community configures it between 15 minutes and 14 days).",
/// "type": "string",
/// "format": "date-time"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "kind": {
/// "description": "The community's name for what kind of operation is parked, dotted and lowerCamelCase (`acl.grant.authority`, `member.join.review`). Selects the summary template. The set is OPEN: a renderer that does not recognise a kind still renders `summary` from its fields.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1,
/// "pattern": "^[a-z][a-zA-Z0-9.]*$"
/// },
/// "payload": {
/// "description": "The exact payload of the parked operation — the object `payloadDigest` is computed over and the one the community will execute. Carried so an approver can recompute the digest and re-derive every summary field from it rather than trusting the rendering (VTI-APV-013). Deliberately an open object: its shape is governed by the specification `typeUri` names, and a digest is checked over members exactly as received.",
/// "type": "object"
/// },
/// "payloadDigest": {
/// "description": "Digest of `payload`, taken over its RFC 8785 (JCS) canonicalization. The community re-derives it from the payload it is about to execute and refuses on mismatch. The digest an approver signs over is the challenge-salted one of `task-consent/decision`, not this value; this one lets the approver check that `payload` is what was parked.",
/// "$ref": "#/definitions/DigestMultibase"
/// },
/// "requester": {
/// "description": "VID of the party whose operation was parked. For `acknowledge`, the operator whose offline write is being acknowledged, where the community can attribute one.",
/// "type": "string",
/// "maxLength": 2048,
/// "minLength": 1
/// },
/// "requesterOpenActions": {
/// "description": "How many open actions the requester currently has at the community, this one included. For consent-fatigue display: an approver shown the twentieth request from one requester today should be able to see that it is the twentieth.",
/// "type": "integer",
/// "minimum": 0.0
/// },
/// "status": {
/// "description": "`open` — awaiting decisions. `completed` — the threshold was met and the operation executed (or, for `acknowledge`, every administrator acknowledged). `declined` — an eligible approver denied it. `expired` — it lapsed at `expiresAt`. `cancelled` — the requester withdrew it, or the community invalidated it (see `closedReason`). `failed` — the threshold was met but the re-check at execution refused it, or execution itself failed; the operation did not take effect.",
/// "type": "string",
/// "enum": [
/// "open",
/// "completed",
/// "declined",
/// "expired",
/// "cancelled",
/// "failed"
/// ]
/// },
/// "summary": {
/// "$ref": "#/definitions/Summary"
/// },
/// "threshold": {
/// "description": "The number of distinct approvals the operation needs. Present for `approval`; absent otherwise (a `queue` decision is one decision by construction, and `acknowledge` needs every remaining administrator).",
/// "type": "integer",
/// "minimum": 1.0
/// },
/// "typeUri": {
/// "description": "The Type URI of the parked operation — the Trust Task the community will execute when the action completes. Together with `payload` it is exactly what will run.",
/// "type": "string",
/// "format": "uri",
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Action {
#[serde(rename = "actionId")]
pub action_id: ActionId,
///The decisions in favour recorded so far — approvals for `approval` and `queue`, acknowledgements for `acknowledge` — one entry per distinct subject, in the order recorded. Empty while none has landed.
pub approvals: ::std::vec::Vec<ActionApprovalsItem>,
///How many further distinct decisions the action needs while `open` — approvals for `approval`, acknowledgements for `acknowledge`. Lets a console say 'one more' without disclosing the eligible set.
#[serde(
rename = "approversRemaining",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub approvers_remaining: ::std::option::Option<u64>,
///The caller's relation to this action. `approver` — an eligible approver (whether or not already decided). `requester` — the party whose operation was parked. `acknowledger` — an administrator expected to acknowledge it. `observer` — none of these; seen only through the audit-read capability on a `history` or `all` view.
#[serde(rename = "callerRole")]
pub caller_role: ActionCallerRole,
///`approval` — eligible approvers approve or decline, N-of-M; the operation executes when the threshold is met. `acknowledge` — an operation that already happened (an operator's offline or break-glass write) which every remaining administrator must acknowledge; there is nothing to approve or decline. `queue` — an existing human decision (for example a join review) surfaced in the same list, with a threshold of one.
pub category: ActionCategory,
///Present ONLY on an action the CALLER may decide now — an `approval` or `queue` action on which the caller is an eligible approver who has not yet decided. Per-approver: two approvers are shown different challenges for the same action. Echoed verbatim in `task-consent/decision`'s `challenge`, which binds that decision to this approver and this action. Absent for everyone else, including the requester.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub challenge: ::std::option::Option<ActionChallenge>,
///When the action left `open`. Present exactly when `status` is not `open`.
#[serde(
rename = "closedAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub closed_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///Why the action closed. Present exactly when `status` is not `open`. `invalidated` — the community closed it because something it depended on stopped holding before the threshold (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met but the execution-time re-check refused.
#[serde(
rename = "closedReason",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub closed_reason: ::std::option::Option<ActionClosedReason>,
///When the operation was parked.
#[serde(rename = "createdAt")]
pub created_at: ::chrono::DateTime<::chrono::offset::Utc>,
///When an open action lapses. Absent for an `acknowledge` or `queue` action that does not expire; ALWAYS present for `approval`, whose open life is bounded (72 hours by default; the community configures it between 15 minutes and 14 days).
#[serde(
rename = "expiresAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub expires_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///The community's name for what kind of operation is parked, dotted and lowerCamelCase (`acl.grant.authority`, `member.join.review`). Selects the summary template. The set is OPEN: a renderer that does not recognise a kind still renders `summary` from its fields.
pub kind: ActionKind,
///The exact payload of the parked operation — the object `payloadDigest` is computed over and the one the community will execute. Carried so an approver can recompute the digest and re-derive every summary field from it rather than trusting the rendering (VTI-APV-013). Deliberately an open object: its shape is governed by the specification `typeUri` names, and a digest is checked over members exactly as received.
pub payload: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
///Digest of `payload`, taken over its RFC 8785 (JCS) canonicalization. The community re-derives it from the payload it is about to execute and refuses on mismatch. The digest an approver signs over is the challenge-salted one of `task-consent/decision`, not this value; this one lets the approver check that `payload` is what was parked.
#[serde(rename = "payloadDigest")]
pub payload_digest: DigestMultibase,
///VID of the party whose operation was parked. For `acknowledge`, the operator whose offline write is being acknowledged, where the community can attribute one.
pub requester: ActionRequester,
///How many open actions the requester currently has at the community, this one included. For consent-fatigue display: an approver shown the twentieth request from one requester today should be able to see that it is the twentieth.
#[serde(
rename = "requesterOpenActions",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub requester_open_actions: ::std::option::Option<u64>,
///`open` — awaiting decisions. `completed` — the threshold was met and the operation executed (or, for `acknowledge`, every administrator acknowledged). `declined` — an eligible approver denied it. `expired` — it lapsed at `expiresAt`. `cancelled` — the requester withdrew it, or the community invalidated it (see `closedReason`). `failed` — the threshold was met but the re-check at execution refused it, or execution itself failed; the operation did not take effect.
pub status: ActionStatus,
pub summary: Summary,
///The number of distinct approvals the operation needs. Present for `approval`; absent otherwise (a `queue` decision is one decision by construction, and `acknowledge` needs every remaining administrator).
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub threshold: ::std::option::Option<::std::num::NonZeroU64>,
///The Type URI of the parked operation — the Trust Task the community will execute when the action completes. Together with `payload` it is exactly what will run.
#[serde(rename = "typeUri")]
pub type_uri: ::std::string::String,
}
impl Action {
pub fn builder() -> builder::Action {
Default::default()
}
}
///`ActionApprovalsItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "at",
/// "subject"
/// ],
/// "properties": {
/// "at": {
/// "description": "When the decision was recorded.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "subject": {
/// "description": "VID of the approver or acknowledger, as proven by the decision's own proof.",
/// "type": "string",
/// "maxLength": 2048,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct ActionApprovalsItem {
///When the decision was recorded.
pub at: ::chrono::DateTime<::chrono::offset::Utc>,
///VID of the approver or acknowledger, as proven by the decision's own proof.
pub subject: ActionApprovalsItemSubject,
}
impl ActionApprovalsItem {
pub fn builder() -> builder::ActionApprovalsItem {
Default::default()
}
}
///VID of the approver or acknowledger, as proven by the decision's own proof.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "VID of the approver or acknowledger, as proven by the decision's own proof.",
/// "type": "string",
/// "maxLength": 2048,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ActionApprovalsItemSubject(::std::string::String);
impl ::std::ops::Deref for ActionApprovalsItemSubject {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ActionApprovalsItemSubject> for ::std::string::String {
fn from(value: ActionApprovalsItemSubject) -> Self {
value.0
}
}
impl ::std::str::FromStr for ActionApprovalsItemSubject {
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());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ActionApprovalsItemSubject {
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 ActionApprovalsItemSubject {
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 ActionApprovalsItemSubject {
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 ActionApprovalsItemSubject {
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 caller's relation to this action. `approver` — an eligible approver (whether or not already decided). `requester` — the party whose operation was parked. `acknowledger` — an administrator expected to acknowledge it. `observer` — none of these; seen only through the audit-read capability on a `history` or `all` view.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The caller's relation to this action. `approver` — an eligible approver (whether or not already decided). `requester` — the party whose operation was parked. `acknowledger` — an administrator expected to acknowledge it. `observer` — none of these; seen only through the audit-read capability on a `history` or `all` view.",
/// "type": "string",
/// "enum": [
/// "approver",
/// "requester",
/// "acknowledger",
/// "observer"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ActionCallerRole {
#[serde(rename = "approver")]
Approver,
#[serde(rename = "requester")]
Requester,
#[serde(rename = "acknowledger")]
Acknowledger,
#[serde(rename = "observer")]
Observer,
}
impl ::std::fmt::Display for ActionCallerRole {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Approver => f.write_str("approver"),
Self::Requester => f.write_str("requester"),
Self::Acknowledger => f.write_str("acknowledger"),
Self::Observer => f.write_str("observer"),
}
}
}
impl ::std::str::FromStr for ActionCallerRole {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"approver" => Ok(Self::Approver),
"requester" => Ok(Self::Requester),
"acknowledger" => Ok(Self::Acknowledger),
"observer" => Ok(Self::Observer),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ActionCallerRole {
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 ActionCallerRole {
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 ActionCallerRole {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`approval` — eligible approvers approve or decline, N-of-M; the operation executes when the threshold is met. `acknowledge` — an operation that already happened (an operator's offline or break-glass write) which every remaining administrator must acknowledge; there is nothing to approve or decline. `queue` — an existing human decision (for example a join review) surfaced in the same list, with a threshold of one.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "`approval` — eligible approvers approve or decline, N-of-M; the operation executes when the threshold is met. `acknowledge` — an operation that already happened (an operator's offline or break-glass write) which every remaining administrator must acknowledge; there is nothing to approve or decline. `queue` — an existing human decision (for example a join review) surfaced in the same list, with a threshold of one.",
/// "type": "string",
/// "enum": [
/// "approval",
/// "acknowledge",
/// "queue"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ActionCategory {
#[serde(rename = "approval")]
Approval,
#[serde(rename = "acknowledge")]
Acknowledge,
#[serde(rename = "queue")]
Queue,
}
impl ::std::fmt::Display for ActionCategory {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Approval => f.write_str("approval"),
Self::Acknowledge => f.write_str("acknowledge"),
Self::Queue => f.write_str("queue"),
}
}
}
impl ::std::str::FromStr for ActionCategory {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"approval" => Ok(Self::Approval),
"acknowledge" => Ok(Self::Acknowledge),
"queue" => Ok(Self::Queue),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ActionCategory {
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 ActionCategory {
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 ActionCategory {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Present ONLY on an action the CALLER may decide now — an `approval` or `queue` action on which the caller is an eligible approver who has not yet decided. Per-approver: two approvers are shown different challenges for the same action. Echoed verbatim in `task-consent/decision`'s `challenge`, which binds that decision to this approver and this action. Absent for everyone else, including the requester.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Present ONLY on an action the CALLER may decide now — an `approval` or `queue` action on which the caller is an eligible approver who has not yet decided. Per-approver: two approvers are shown different challenges for the same action. Echoed verbatim in `task-consent/decision`'s `challenge`, which binds that decision to this approver and this action. Absent for everyone else, including the requester.",
/// "type": "string",
/// "maxLength": 256,
/// "minLength": 16
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ActionChallenge(::std::string::String);
impl ::std::ops::Deref for ActionChallenge {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ActionChallenge> for ::std::string::String {
fn from(value: ActionChallenge) -> Self {
value.0
}
}
impl ::std::str::FromStr for ActionChallenge {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 256usize {
return Err("longer than 256 characters".into());
}
if value.chars().count() < 16usize {
return Err("shorter than 16 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ActionChallenge {
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 ActionChallenge {
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 ActionChallenge {
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 ActionChallenge {
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())
})
}
}
///Why the action closed. Present exactly when `status` is not `open`. `invalidated` — the community closed it because something it depended on stopped holding before the threshold (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met but the execution-time re-check refused.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Why the action closed. Present exactly when `status` is not `open`. `invalidated` — the community closed it because something it depended on stopped holding before the threshold (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met but the execution-time re-check refused.",
/// "type": "string",
/// "enum": [
/// "thresholdMet",
/// "declined",
/// "expired",
/// "cancelledByRequester",
/// "invalidated",
/// "failedRecheck",
/// "acknowledged"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ActionClosedReason {
#[serde(rename = "thresholdMet")]
ThresholdMet,
#[serde(rename = "declined")]
Declined,
#[serde(rename = "expired")]
Expired,
#[serde(rename = "cancelledByRequester")]
CancelledByRequester,
#[serde(rename = "invalidated")]
Invalidated,
#[serde(rename = "failedRecheck")]
FailedRecheck,
#[serde(rename = "acknowledged")]
Acknowledged,
}
impl ::std::fmt::Display for ActionClosedReason {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::ThresholdMet => f.write_str("thresholdMet"),
Self::Declined => f.write_str("declined"),
Self::Expired => f.write_str("expired"),
Self::CancelledByRequester => f.write_str("cancelledByRequester"),
Self::Invalidated => f.write_str("invalidated"),
Self::FailedRecheck => f.write_str("failedRecheck"),
Self::Acknowledged => f.write_str("acknowledged"),
}
}
}
impl ::std::str::FromStr for ActionClosedReason {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"thresholdMet" => Ok(Self::ThresholdMet),
"declined" => Ok(Self::Declined),
"expired" => Ok(Self::Expired),
"cancelledByRequester" => Ok(Self::CancelledByRequester),
"invalidated" => Ok(Self::Invalidated),
"failedRecheck" => Ok(Self::FailedRecheck),
"acknowledged" => Ok(Self::Acknowledged),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ActionClosedReason {
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 ActionClosedReason {
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 ActionClosedReason {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Opaque, community-minted identifier of one action. A consumer MUST NOT parse or order it; it is compared for equality only. Long enough to be unguessable, because a show of an id the caller may not see is answered `notFound` and an enumerable id would turn that answer into an oracle.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ActionId",
/// "description": "Opaque, community-minted identifier of one action. A consumer MUST NOT parse or order it; it is compared for equality only. Long enough to be unguessable, because a show of an id the caller may not see is answered `notFound` and an enumerable id would turn that answer into an oracle.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 16,
/// "pattern": "^[A-Za-z0-9._~:-]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ActionId(::std::string::String);
impl ::std::ops::Deref for ActionId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ActionId> for ::std::string::String {
fn from(value: ActionId) -> Self {
value.0
}
}
impl ::std::str::FromStr for ActionId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 128usize {
return Err("longer than 128 characters".into());
}
if value.chars().count() < 16usize {
return Err("shorter than 16 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[A-Za-z0-9._~:-]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[A-Za-z0-9._~:-]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ActionId {
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 ActionId {
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 ActionId {
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 ActionId {
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 community's name for what kind of operation is parked, dotted and lowerCamelCase (`acl.grant.authority`, `member.join.review`). Selects the summary template. The set is OPEN: a renderer that does not recognise a kind still renders `summary` from its fields.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The community's name for what kind of operation is parked, dotted and lowerCamelCase (`acl.grant.authority`, `member.join.review`). Selects the summary template. The set is OPEN: a renderer that does not recognise a kind still renders `summary` from its fields.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1,
/// "pattern": "^[a-z][a-zA-Z0-9.]*$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ActionKind(::std::string::String);
impl ::std::ops::Deref for ActionKind {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ActionKind> for ::std::string::String {
fn from(value: ActionKind) -> Self {
value.0
}
}
impl ::std::str::FromStr for ActionKind {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 128usize {
return Err("longer than 128 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[a-z][a-zA-Z0-9.]*$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z][a-zA-Z0-9.]*$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ActionKind {
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 ActionKind {
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 ActionKind {
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 ActionKind {
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())
})
}
}
///VID of the party whose operation was parked. For `acknowledge`, the operator whose offline write is being acknowledged, where the community can attribute one.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "VID of the party whose operation was parked. For `acknowledge`, the operator whose offline write is being acknowledged, where the community can attribute one.",
/// "type": "string",
/// "maxLength": 2048,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ActionRequester(::std::string::String);
impl ::std::ops::Deref for ActionRequester {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ActionRequester> for ::std::string::String {
fn from(value: ActionRequester) -> Self {
value.0
}
}
impl ::std::str::FromStr for ActionRequester {
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());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ActionRequester {
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 ActionRequester {
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 ActionRequester {
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 ActionRequester {
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())
})
}
}
///`open` — awaiting decisions. `completed` — the threshold was met and the operation executed (or, for `acknowledge`, every administrator acknowledged). `declined` — an eligible approver denied it. `expired` — it lapsed at `expiresAt`. `cancelled` — the requester withdrew it, or the community invalidated it (see `closedReason`). `failed` — the threshold was met but the re-check at execution refused it, or execution itself failed; the operation did not take effect.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "`open` — awaiting decisions. `completed` — the threshold was met and the operation executed (or, for `acknowledge`, every administrator acknowledged). `declined` — an eligible approver denied it. `expired` — it lapsed at `expiresAt`. `cancelled` — the requester withdrew it, or the community invalidated it (see `closedReason`). `failed` — the threshold was met but the re-check at execution refused it, or execution itself failed; the operation did not take effect.",
/// "type": "string",
/// "enum": [
/// "open",
/// "completed",
/// "declined",
/// "expired",
/// "cancelled",
/// "failed"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ActionStatus {
#[serde(rename = "open")]
Open,
#[serde(rename = "completed")]
Completed,
#[serde(rename = "declined")]
Declined,
#[serde(rename = "expired")]
Expired,
#[serde(rename = "cancelled")]
Cancelled,
#[serde(rename = "failed")]
Failed,
}
impl ::std::fmt::Display for ActionStatus {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Open => f.write_str("open"),
Self::Completed => f.write_str("completed"),
Self::Declined => f.write_str("declined"),
Self::Expired => f.write_str("expired"),
Self::Cancelled => f.write_str("cancelled"),
Self::Failed => f.write_str("failed"),
}
}
}
impl ::std::str::FromStr for ActionStatus {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"open" => Ok(Self::Open),
"completed" => Ok(Self::Completed),
"declined" => Ok(Self::Declined),
"expired" => Ok(Self::Expired),
"cancelled" => Ok(Self::Cancelled),
"failed" => Ok(Self::Failed),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ActionStatus {
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 ActionStatus {
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 ActionStatus {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
/**
A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.
Multihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.
This definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.
Restricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that "interoperability is not guaranteed between implementations using such values", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "DigestMultibase",
/// "description": "A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\n\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\n\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\n\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \"interoperability is not guaranteed between implementations using such values\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.",
/// "examples": [
/// "zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"
/// ],
/// "type": "string",
/// "minLength": 16,
/// "pattern": "^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct DigestMultibase(::std::string::String);
impl ::std::ops::Deref for DigestMultibase {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DigestMultibase> for ::std::string::String {
fn from(value: DigestMultibase) -> Self {
value.0
}
}
impl ::std::str::FromStr for DigestMultibase {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 16usize {
return Err("shorter than 16 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err(
"doesn't match pattern \"^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$\"".into(),
);
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for DigestMultibase {
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 DigestMultibase {
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 DigestMultibase {
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 DigestMultibase {
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())
})
}
}
///One displayed value, with where it comes from and how to render it.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Field",
/// "description": "One displayed value, with where it comes from and how to render it.",
/// "type": "object",
/// "required": [
/// "format",
/// "pointer",
/// "value"
/// ],
/// "properties": {
/// "format": {
/// "description": "How to render the value. `did` — a DID, shown in full or with a verified display name, never truncated to a prefix that two DIDs share. `capabilityList` — an array of capability names. `duration` — an ISO 8601 duration. `datetime` — an RFC 3339 date-time. `text` — anything else, rendered as literal text.",
/// "type": "string",
/// "enum": [
/// "did",
/// "capabilityList",
/// "duration",
/// "datetime",
/// "text"
/// ]
/// },
/// "pointer": {
/// "description": "RFC 6901 JSON Pointer into the action's `payload`. The empty string addresses the whole payload.",
/// "type": "string",
/// "maxLength": 512,
/// "pattern": "^(/([^~/]|~[01])*)*$"
/// },
/// "value": {
/// "description": "The value found at `pointer` when the community rendered the summary. A renderer re-derives it from `payload` and refuses to render the action on any mismatch; it is carried so that a mismatch is detectable, not so that it can be trusted."
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Field {
///How to render the value. `did` — a DID, shown in full or with a verified display name, never truncated to a prefix that two DIDs share. `capabilityList` — an array of capability names. `duration` — an ISO 8601 duration. `datetime` — an RFC 3339 date-time. `text` — anything else, rendered as literal text.
pub format: FieldFormat,
///RFC 6901 JSON Pointer into the action's `payload`. The empty string addresses the whole payload.
pub pointer: FieldPointer,
///The value found at `pointer` when the community rendered the summary. A renderer re-derives it from `payload` and refuses to render the action on any mismatch; it is carried so that a mismatch is detectable, not so that it can be trusted.
pub value: ::serde_json::Value,
}
impl Field {
pub fn builder() -> builder::Field {
Default::default()
}
}
///How to render the value. `did` — a DID, shown in full or with a verified display name, never truncated to a prefix that two DIDs share. `capabilityList` — an array of capability names. `duration` — an ISO 8601 duration. `datetime` — an RFC 3339 date-time. `text` — anything else, rendered as literal text.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "How to render the value. `did` — a DID, shown in full or with a verified display name, never truncated to a prefix that two DIDs share. `capabilityList` — an array of capability names. `duration` — an ISO 8601 duration. `datetime` — an RFC 3339 date-time. `text` — anything else, rendered as literal text.",
/// "type": "string",
/// "enum": [
/// "did",
/// "capabilityList",
/// "duration",
/// "datetime",
/// "text"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum FieldFormat {
#[serde(rename = "did")]
Did,
#[serde(rename = "capabilityList")]
CapabilityList,
#[serde(rename = "duration")]
Duration,
#[serde(rename = "datetime")]
Datetime,
#[serde(rename = "text")]
Text,
}
impl ::std::fmt::Display for FieldFormat {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Did => f.write_str("did"),
Self::CapabilityList => f.write_str("capabilityList"),
Self::Duration => f.write_str("duration"),
Self::Datetime => f.write_str("datetime"),
Self::Text => f.write_str("text"),
}
}
}
impl ::std::str::FromStr for FieldFormat {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"did" => Ok(Self::Did),
"capabilityList" => Ok(Self::CapabilityList),
"duration" => Ok(Self::Duration),
"datetime" => Ok(Self::Datetime),
"text" => Ok(Self::Text),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for FieldFormat {
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 FieldFormat {
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 FieldFormat {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///RFC 6901 JSON Pointer into the action's `payload`. The empty string addresses the whole payload.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "RFC 6901 JSON Pointer into the action's `payload`. The empty string addresses the whole payload.",
/// "type": "string",
/// "maxLength": 512,
/// "pattern": "^(/([^~/]|~[01])*)*$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct FieldPointer(::std::string::String);
impl ::std::ops::Deref for FieldPointer {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<FieldPointer> for ::std::string::String {
fn from(value: FieldPointer) -> Self {
value.0
}
}
impl ::std::str::FromStr for FieldPointer {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 512usize {
return Err("longer than 512 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^(/([^~/]|~[01])*)*$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^(/([^~/]|~[01])*)*$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for FieldPointer {
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 FieldPointer {
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 FieldPointer {
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 FieldPointer {
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 acknowledges an `acknowledge`-category action — an operation that already took effect outside the approval path, such as an operator's offline or break-glass write — recording that they have seen it. There is nothing to approve or decline. The outer document members (id, type, issuer, recipient, issuedAt, expiresAt, proof) are owned by the framework — SPEC §6.3.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/vtc/admin/actions/acknowledge/0.1",
/// "title": "Payload",
/// "description": "An administrator acknowledges an `acknowledge`-category action — an operation that already took effect outside the approval path, such as an operator's offline or break-glass write — recording that they have seen it. There is nothing to approve or decline. The outer document members (id, type, issuer, recipient, issuedAt, expiresAt, proof) are owned by the framework — SPEC §6.3.",
/// "type": "object",
/// "required": [
/// "actionId"
/// ],
/// "properties": {
/// "actionId": {
/// "description": "The open `acknowledge` action being acknowledged.",
/// "$ref": "#/definitions/ActionId"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Payload {
///The open `acknowledge` action being acknowledged.
#[serde(rename = "actionId")]
pub action_id: ActionId,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///The action with the caller's acknowledgement recorded in `approvals`. When the caller was the last administrator expected to acknowledge it, `status` is `completed` and `closedReason` is `acknowledged`. Failures use trust-task-error, not this shape.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "The action with the caller's acknowledgement recorded in `approvals`. When the caller was the last administrator expected to acknowledge it, `status` is `completed` and `closedReason` is `acknowledged`. Failures use trust-task-error, not this shape.",
/// "type": "object",
/// "required": [
/// "action"
/// ],
/// "properties": {
/// "action": {
/// "$ref": "#/definitions/Action"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Response {
pub action: Action,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
}
impl Response {
pub fn builder() -> builder::Response {
Default::default()
}
}
///What an approver is shown, rendered from the summary template for the action's `kind`. Title and effect are the template's prose; the fields are the payload values that prose is about, each located by pointer so a renderer can verify it.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Summary",
/// "description": "What an approver is shown, rendered from the summary template for the action's `kind`. Title and effect are the template's prose; the fields are the payload values that prose is about, each located by pointer so a renderer can verify it.",
/// "type": "object",
/// "required": [
/// "fields",
/// "templateDigest",
/// "title"
/// ],
/// "properties": {
/// "effect": {
/// "description": "One or two sentences from the template saying what executing the operation will do.",
/// "type": "string",
/// "maxLength": 1024
/// },
/// "fields": {
/// "description": "Named values the template displays, keyed by a lowerCamelCase field name. Each locates its value in `payload` by JSON Pointer.",
/// "type": "object",
/// "additionalProperties": {
/// "$ref": "#/definitions/Field"
/// },
/// "propertyNames": {
/// "maxLength": 64,
/// "pattern": "^[a-z][a-zA-Z0-9]*$"
/// }
/// },
/// "templateDigest": {
/// "description": "Digest of the summary template this summary was rendered from, over its RFC 8785 (JCS) canonicalization. Pinned per `kind`: a renderer that holds the template for a kind refuses a summary naming a different digest, so the community cannot change what approvers are shown for a kind without that change being visible.",
/// "$ref": "#/definitions/DigestMultibase"
/// },
/// "title": {
/// "description": "One-line heading from the template. Prose only: a renderer MUST NOT present the action from this text without the fields.",
/// "type": "string",
/// "maxLength": 256,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Summary {
///One or two sentences from the template saying what executing the operation will do.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub effect: ::std::option::Option<SummaryEffect>,
///Named values the template displays, keyed by a lowerCamelCase field name. Each locates its value in `payload` by JSON Pointer.
pub fields: ::std::collections::HashMap<SummaryFieldsKey, Field>,
///Digest of the summary template this summary was rendered from, over its RFC 8785 (JCS) canonicalization. Pinned per `kind`: a renderer that holds the template for a kind refuses a summary naming a different digest, so the community cannot change what approvers are shown for a kind without that change being visible.
#[serde(rename = "templateDigest")]
pub template_digest: DigestMultibase,
///One-line heading from the template. Prose only: a renderer MUST NOT present the action from this text without the fields.
pub title: SummaryTitle,
}
impl Summary {
pub fn builder() -> builder::Summary {
Default::default()
}
}
///One or two sentences from the template saying what executing the operation will do.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "One or two sentences from the template saying what executing the operation will do.",
/// "type": "string",
/// "maxLength": 1024
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SummaryEffect(::std::string::String);
impl ::std::ops::Deref for SummaryEffect {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SummaryEffect> for ::std::string::String {
fn from(value: SummaryEffect) -> Self {
value.0
}
}
impl ::std::str::FromStr for SummaryEffect {
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());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SummaryEffect {
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 SummaryEffect {
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 SummaryEffect {
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 SummaryEffect {
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())
})
}
}
///`SummaryFieldsKey`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 64,
/// "pattern": "^[a-z][a-zA-Z0-9]*$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SummaryFieldsKey(::std::string::String);
impl ::std::ops::Deref for SummaryFieldsKey {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SummaryFieldsKey> for ::std::string::String {
fn from(value: SummaryFieldsKey) -> Self {
value.0
}
}
impl ::std::str::FromStr for SummaryFieldsKey {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 64usize {
return Err("longer than 64 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[a-z][a-zA-Z0-9]*$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z][a-zA-Z0-9]*$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SummaryFieldsKey {
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 SummaryFieldsKey {
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 SummaryFieldsKey {
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 SummaryFieldsKey {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///One-line heading from the template. Prose only: a renderer MUST NOT present the action from this text without the fields.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "One-line heading from the template. Prose only: a renderer MUST NOT present the action from this text without the fields.",
/// "type": "string",
/// "maxLength": 256,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SummaryTitle(::std::string::String);
impl ::std::ops::Deref for SummaryTitle {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SummaryTitle> for ::std::string::String {
fn from(value: SummaryTitle) -> Self {
value.0
}
}
impl ::std::str::FromStr for SummaryTitle {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 256usize {
return Err("longer than 256 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SummaryTitle {
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 SummaryTitle {
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 SummaryTitle {
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 SummaryTitle {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
/// Types for composing complex structures.
pub mod builder {
#[derive(Clone, Debug)]
pub struct Action {
action_id: ::std::result::Result<super::ActionId, ::std::string::String>,
approvals: ::std::result::Result<
::std::vec::Vec<super::ActionApprovalsItem>,
::std::string::String,
>,
approvers_remaining:
::std::result::Result<::std::option::Option<u64>, ::std::string::String>,
caller_role: ::std::result::Result<super::ActionCallerRole, ::std::string::String>,
category: ::std::result::Result<super::ActionCategory, ::std::string::String>,
challenge: ::std::result::Result<
::std::option::Option<super::ActionChallenge>,
::std::string::String,
>,
closed_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
closed_reason: ::std::result::Result<
::std::option::Option<super::ActionClosedReason>,
::std::string::String,
>,
created_at:
::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
expires_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
kind: ::std::result::Result<super::ActionKind, ::std::string::String>,
payload: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
payload_digest: ::std::result::Result<super::DigestMultibase, ::std::string::String>,
requester: ::std::result::Result<super::ActionRequester, ::std::string::String>,
requester_open_actions:
::std::result::Result<::std::option::Option<u64>, ::std::string::String>,
status: ::std::result::Result<super::ActionStatus, ::std::string::String>,
summary: ::std::result::Result<super::Summary, ::std::string::String>,
threshold: ::std::result::Result<
::std::option::Option<::std::num::NonZeroU64>,
::std::string::String,
>,
type_uri: ::std::result::Result<::std::string::String, ::std::string::String>,
}
impl ::std::default::Default for Action {
fn default() -> Self {
Self {
action_id: Err("no value supplied for action_id".to_string()),
approvals: Err("no value supplied for approvals".to_string()),
approvers_remaining: Ok(Default::default()),
caller_role: Err("no value supplied for caller_role".to_string()),
category: Err("no value supplied for category".to_string()),
challenge: Ok(Default::default()),
closed_at: Ok(Default::default()),
closed_reason: Ok(Default::default()),
created_at: Err("no value supplied for created_at".to_string()),
expires_at: Ok(Default::default()),
ext: Ok(Default::default()),
kind: Err("no value supplied for kind".to_string()),
payload: Err("no value supplied for payload".to_string()),
payload_digest: Err("no value supplied for payload_digest".to_string()),
requester: Err("no value supplied for requester".to_string()),
requester_open_actions: Ok(Default::default()),
status: Err("no value supplied for status".to_string()),
summary: Err("no value supplied for summary".to_string()),
threshold: Ok(Default::default()),
type_uri: Err("no value supplied for type_uri".to_string()),
}
}
}
impl Action {
pub fn action_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ActionId>,
T::Error: ::std::fmt::Display,
{
self.action_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for action_id: {e}"));
self
}
pub fn approvals<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::ActionApprovalsItem>>,
T::Error: ::std::fmt::Display,
{
self.approvals = value
.try_into()
.map_err(|e| format!("error converting supplied value for approvals: {e}"));
self
}
pub fn approvers_remaining<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<u64>>,
T::Error: ::std::fmt::Display,
{
self.approvers_remaining = value.try_into().map_err(|e| {
format!("error converting supplied value for approvers_remaining: {e}")
});
self
}
pub fn caller_role<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ActionCallerRole>,
T::Error: ::std::fmt::Display,
{
self.caller_role = value
.try_into()
.map_err(|e| format!("error converting supplied value for caller_role: {e}"));
self
}
pub fn category<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ActionCategory>,
T::Error: ::std::fmt::Display,
{
self.category = value
.try_into()
.map_err(|e| format!("error converting supplied value for category: {e}"));
self
}
pub fn challenge<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ActionChallenge>>,
T::Error: ::std::fmt::Display,
{
self.challenge = value
.try_into()
.map_err(|e| format!("error converting supplied value for challenge: {e}"));
self
}
pub fn closed_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.closed_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for closed_at: {e}"));
self
}
pub fn closed_reason<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ActionClosedReason>>,
T::Error: ::std::fmt::Display,
{
self.closed_reason = value
.try_into()
.map_err(|e| format!("error converting supplied value for closed_reason: {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 expires_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.expires_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for expires_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 kind<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ActionKind>,
T::Error: ::std::fmt::Display,
{
self.kind = value
.try_into()
.map_err(|e| format!("error converting supplied value for kind: {e}"));
self
}
pub fn payload<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
>,
T::Error: ::std::fmt::Display,
{
self.payload = value
.try_into()
.map_err(|e| format!("error converting supplied value for payload: {e}"));
self
}
pub fn payload_digest<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DigestMultibase>,
T::Error: ::std::fmt::Display,
{
self.payload_digest = value
.try_into()
.map_err(|e| format!("error converting supplied value for payload_digest: {e}"));
self
}
pub fn requester<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ActionRequester>,
T::Error: ::std::fmt::Display,
{
self.requester = value
.try_into()
.map_err(|e| format!("error converting supplied value for requester: {e}"));
self
}
pub fn requester_open_actions<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<u64>>,
T::Error: ::std::fmt::Display,
{
self.requester_open_actions = value.try_into().map_err(|e| {
format!("error converting supplied value for requester_open_actions: {e}")
});
self
}
pub fn status<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ActionStatus>,
T::Error: ::std::fmt::Display,
{
self.status = value
.try_into()
.map_err(|e| format!("error converting supplied value for status: {e}"));
self
}
pub fn summary<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Summary>,
T::Error: ::std::fmt::Display,
{
self.summary = value
.try_into()
.map_err(|e| format!("error converting supplied value for summary: {e}"));
self
}
pub fn threshold<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::num::NonZeroU64>>,
T::Error: ::std::fmt::Display,
{
self.threshold = value
.try_into()
.map_err(|e| format!("error converting supplied value for threshold: {e}"));
self
}
pub fn type_uri<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::string::String>,
T::Error: ::std::fmt::Display,
{
self.type_uri = value
.try_into()
.map_err(|e| format!("error converting supplied value for type_uri: {e}"));
self
}
}
impl ::std::convert::TryFrom<Action> for super::Action {
type Error = super::error::ConversionError;
fn try_from(value: Action) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
action_id: value.action_id?,
approvals: value.approvals?,
approvers_remaining: value.approvers_remaining?,
caller_role: value.caller_role?,
category: value.category?,
challenge: value.challenge?,
closed_at: value.closed_at?,
closed_reason: value.closed_reason?,
created_at: value.created_at?,
expires_at: value.expires_at?,
ext: value.ext?,
kind: value.kind?,
payload: value.payload?,
payload_digest: value.payload_digest?,
requester: value.requester?,
requester_open_actions: value.requester_open_actions?,
status: value.status?,
summary: value.summary?,
threshold: value.threshold?,
type_uri: value.type_uri?,
})
}
}
impl ::std::convert::From<super::Action> for Action {
fn from(value: super::Action) -> Self {
Self {
action_id: Ok(value.action_id),
approvals: Ok(value.approvals),
approvers_remaining: Ok(value.approvers_remaining),
caller_role: Ok(value.caller_role),
category: Ok(value.category),
challenge: Ok(value.challenge),
closed_at: Ok(value.closed_at),
closed_reason: Ok(value.closed_reason),
created_at: Ok(value.created_at),
expires_at: Ok(value.expires_at),
ext: Ok(value.ext),
kind: Ok(value.kind),
payload: Ok(value.payload),
payload_digest: Ok(value.payload_digest),
requester: Ok(value.requester),
requester_open_actions: Ok(value.requester_open_actions),
status: Ok(value.status),
summary: Ok(value.summary),
threshold: Ok(value.threshold),
type_uri: Ok(value.type_uri),
}
}
}
#[derive(Clone, Debug)]
pub struct ActionApprovalsItem {
at: ::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
subject: ::std::result::Result<super::ActionApprovalsItemSubject, ::std::string::String>,
}
impl ::std::default::Default for ActionApprovalsItem {
fn default() -> Self {
Self {
at: Err("no value supplied for at".to_string()),
subject: Err("no value supplied for subject".to_string()),
}
}
}
impl ActionApprovalsItem {
pub fn at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::chrono::DateTime<::chrono::offset::Utc>>,
T::Error: ::std::fmt::Display,
{
self.at = value
.try_into()
.map_err(|e| format!("error converting supplied value for at: {e}"));
self
}
pub fn subject<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ActionApprovalsItemSubject>,
T::Error: ::std::fmt::Display,
{
self.subject = value
.try_into()
.map_err(|e| format!("error converting supplied value for subject: {e}"));
self
}
}
impl ::std::convert::TryFrom<ActionApprovalsItem> for super::ActionApprovalsItem {
type Error = super::error::ConversionError;
fn try_from(
value: ActionApprovalsItem,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
at: value.at?,
subject: value.subject?,
})
}
}
impl ::std::convert::From<super::ActionApprovalsItem> for ActionApprovalsItem {
fn from(value: super::ActionApprovalsItem) -> Self {
Self {
at: Ok(value.at),
subject: Ok(value.subject),
}
}
}
#[derive(Clone, Debug)]
pub struct Field {
format: ::std::result::Result<super::FieldFormat, ::std::string::String>,
pointer: ::std::result::Result<super::FieldPointer, ::std::string::String>,
value: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for Field {
fn default() -> Self {
Self {
format: Err("no value supplied for format".to_string()),
pointer: Err("no value supplied for pointer".to_string()),
value: Err("no value supplied for value".to_string()),
}
}
}
impl Field {
pub fn format<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::FieldFormat>,
T::Error: ::std::fmt::Display,
{
self.format = value
.try_into()
.map_err(|e| format!("error converting supplied value for format: {e}"));
self
}
pub fn pointer<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::FieldPointer>,
T::Error: ::std::fmt::Display,
{
self.pointer = value
.try_into()
.map_err(|e| format!("error converting supplied value for pointer: {e}"));
self
}
pub fn value<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.value = value
.try_into()
.map_err(|e| format!("error converting supplied value for value: {e}"));
self
}
}
impl ::std::convert::TryFrom<Field> for super::Field {
type Error = super::error::ConversionError;
fn try_from(value: Field) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
format: value.format?,
pointer: value.pointer?,
value: value.value?,
})
}
}
impl ::std::convert::From<super::Field> for Field {
fn from(value: super::Field) -> Self {
Self {
format: Ok(value.format),
pointer: Ok(value.pointer),
value: Ok(value.value),
}
}
}
#[derive(Clone, Debug)]
pub struct Payload {
action_id: ::std::result::Result<super::ActionId, ::std::string::String>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
action_id: Err("no value supplied for action_id".to_string()),
ext: Ok(Default::default()),
}
}
}
impl Payload {
pub fn action_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ActionId>,
T::Error: ::std::fmt::Display,
{
self.action_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for action_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
}
}
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 {
action_id: value.action_id?,
ext: value.ext?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
action_id: Ok(value.action_id),
ext: Ok(value.ext),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
action: ::std::result::Result<super::Action, ::std::string::String>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
action: Err("no value supplied for action".to_string()),
ext: Ok(Default::default()),
}
}
}
impl Response {
pub fn action<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Action>,
T::Error: ::std::fmt::Display,
{
self.action = value
.try_into()
.map_err(|e| format!("error converting supplied value for action: {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
}
}
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 {
action: value.action?,
ext: value.ext?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
action: Ok(value.action),
ext: Ok(value.ext),
}
}
}
#[derive(Clone, Debug)]
pub struct Summary {
effect: ::std::result::Result<
::std::option::Option<super::SummaryEffect>,
::std::string::String,
>,
fields: ::std::result::Result<
::std::collections::HashMap<super::SummaryFieldsKey, super::Field>,
::std::string::String,
>,
template_digest: ::std::result::Result<super::DigestMultibase, ::std::string::String>,
title: ::std::result::Result<super::SummaryTitle, ::std::string::String>,
}
impl ::std::default::Default for Summary {
fn default() -> Self {
Self {
effect: Ok(Default::default()),
fields: Err("no value supplied for fields".to_string()),
template_digest: Err("no value supplied for template_digest".to_string()),
title: Err("no value supplied for title".to_string()),
}
}
}
impl Summary {
pub fn effect<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::SummaryEffect>>,
T::Error: ::std::fmt::Display,
{
self.effect = value
.try_into()
.map_err(|e| format!("error converting supplied value for effect: {e}"));
self
}
pub fn fields<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::collections::HashMap<super::SummaryFieldsKey, super::Field>,
>,
T::Error: ::std::fmt::Display,
{
self.fields = value
.try_into()
.map_err(|e| format!("error converting supplied value for fields: {e}"));
self
}
pub fn template_digest<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::DigestMultibase>,
T::Error: ::std::fmt::Display,
{
self.template_digest = value
.try_into()
.map_err(|e| format!("error converting supplied value for template_digest: {e}"));
self
}
pub fn title<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::SummaryTitle>,
T::Error: ::std::fmt::Display,
{
self.title = value
.try_into()
.map_err(|e| format!("error converting supplied value for title: {e}"));
self
}
}
impl ::std::convert::TryFrom<Summary> for super::Summary {
type Error = super::error::ConversionError;
fn try_from(value: Summary) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
effect: value.effect?,
fields: value.fields?,
template_digest: value.template_digest?,
title: value.title?,
})
}
}
impl ::std::convert::From<super::Summary> for Summary {
fn from(value: super::Summary) -> Self {
Self {
effect: Ok(value.effect),
fields: Ok(value.fields),
template_digest: Ok(value.template_digest),
title: Ok(value.title),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/vtc/admin/actions/acknowledge/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 \"Action\": {\n \"additionalProperties\": false,\n \"description\": \"One parked administrative operation, as the caller is entitled to see it. The same action reads differently to different callers only in `challenge` and `callerRole`, which are per-caller.\",\n \"properties\": {\n \"actionId\": {\n \"$ref\": \"#/$defs/ActionId\"\n },\n \"approvals\": {\n \"description\": \"The decisions in favour recorded so far — approvals for `approval` and `queue`, acknowledgements for `acknowledge` — one entry per distinct subject, in the order recorded. Empty while none has landed.\",\n \"items\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"at\": {\n \"description\": \"When the decision was recorded.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"subject\": {\n \"description\": \"VID of the approver or acknowledger, as proven by the decision's own proof.\",\n \"maxLength\": 2048,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"subject\",\n \"at\"\n ],\n \"type\": \"object\"\n },\n \"type\": \"array\"\n },\n \"approversRemaining\": {\n \"description\": \"How many further distinct decisions the action needs while `open` — approvals for `approval`, acknowledgements for `acknowledge`. Lets a console say 'one more' without disclosing the eligible set.\",\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"callerRole\": {\n \"description\": \"The caller's relation to this action. `approver` — an eligible approver (whether or not already decided). `requester` — the party whose operation was parked. `acknowledger` — an administrator expected to acknowledge it. `observer` — none of these; seen only through the audit-read capability on a `history` or `all` view.\",\n \"enum\": [\n \"approver\",\n \"requester\",\n \"acknowledger\",\n \"observer\"\n ],\n \"type\": \"string\"\n },\n \"category\": {\n \"description\": \"`approval` — eligible approvers approve or decline, N-of-M; the operation executes when the threshold is met. `acknowledge` — an operation that already happened (an operator's offline or break-glass write) which every remaining administrator must acknowledge; there is nothing to approve or decline. `queue` — an existing human decision (for example a join review) surfaced in the same list, with a threshold of one.\",\n \"enum\": [\n \"approval\",\n \"acknowledge\",\n \"queue\"\n ],\n \"type\": \"string\"\n },\n \"challenge\": {\n \"description\": \"Present ONLY on an action the CALLER may decide now — an `approval` or `queue` action on which the caller is an eligible approver who has not yet decided. Per-approver: two approvers are shown different challenges for the same action. Echoed verbatim in `task-consent/decision`'s `challenge`, which binds that decision to this approver and this action. Absent for everyone else, including the requester.\",\n \"maxLength\": 256,\n \"minLength\": 16,\n \"type\": \"string\"\n },\n \"closedAt\": {\n \"description\": \"When the action left `open`. Present exactly when `status` is not `open`.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"closedReason\": {\n \"description\": \"Why the action closed. Present exactly when `status` is not `open`. `invalidated` — the community closed it because something it depended on stopped holding before the threshold (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met but the execution-time re-check refused.\",\n \"enum\": [\n \"thresholdMet\",\n \"declined\",\n \"expired\",\n \"cancelledByRequester\",\n \"invalidated\",\n \"failedRecheck\",\n \"acknowledged\"\n ],\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"description\": \"When the operation was parked.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"expiresAt\": {\n \"description\": \"When an open action lapses. Absent for an `acknowledge` or `queue` action that does not expire; ALWAYS present for `approval`, whose open life is bounded (72 hours by default; the community configures it between 15 minutes and 14 days).\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"kind\": {\n \"description\": \"The community's name for what kind of operation is parked, dotted and lowerCamelCase (`acl.grant.authority`, `member.join.review`). Selects the summary template. The set is OPEN: a renderer that does not recognise a kind still renders `summary` from its fields.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"pattern\": \"^[a-z][a-zA-Z0-9.]*$\",\n \"type\": \"string\"\n },\n \"payload\": {\n \"description\": \"The exact payload of the parked operation — the object `payloadDigest` is computed over and the one the community will execute. Carried so an approver can recompute the digest and re-derive every summary field from it rather than trusting the rendering (VTI-APV-013). Deliberately an open object: its shape is governed by the specification `typeUri` names, and a digest is checked over members exactly as received.\",\n \"type\": \"object\"\n },\n \"payloadDigest\": {\n \"$ref\": \"#/$defs/DigestMultibase\",\n \"description\": \"Digest of `payload`, taken over its RFC 8785 (JCS) canonicalization. The community re-derives it from the payload it is about to execute and refuses on mismatch. The digest an approver signs over is the challenge-salted one of `task-consent/decision`, not this value; this one lets the approver check that `payload` is what was parked.\"\n },\n \"requester\": {\n \"description\": \"VID of the party whose operation was parked. For `acknowledge`, the operator whose offline write is being acknowledged, where the community can attribute one.\",\n \"maxLength\": 2048,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"requesterOpenActions\": {\n \"description\": \"How many open actions the requester currently has at the community, this one included. For consent-fatigue display: an approver shown the twentieth request from one requester today should be able to see that it is the twentieth.\",\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"status\": {\n \"description\": \"`open` — awaiting decisions. `completed` — the threshold was met and the operation executed (or, for `acknowledge`, every administrator acknowledged). `declined` — an eligible approver denied it. `expired` — it lapsed at `expiresAt`. `cancelled` — the requester withdrew it, or the community invalidated it (see `closedReason`). `failed` — the threshold was met but the re-check at execution refused it, or execution itself failed; the operation did not take effect.\",\n \"enum\": [\n \"open\",\n \"completed\",\n \"declined\",\n \"expired\",\n \"cancelled\",\n \"failed\"\n ],\n \"type\": \"string\"\n },\n \"summary\": {\n \"$ref\": \"#/$defs/Summary\"\n },\n \"threshold\": {\n \"description\": \"The number of distinct approvals the operation needs. Present for `approval`; absent otherwise (a `queue` decision is one decision by construction, and `acknowledge` needs every remaining administrator).\",\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"typeUri\": {\n \"description\": \"The Type URI of the parked operation — the Trust Task the community will execute when the action completes. Together with `payload` it is exactly what will run.\",\n \"format\": \"uri\",\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"actionId\",\n \"category\",\n \"kind\",\n \"typeUri\",\n \"requester\",\n \"status\",\n \"createdAt\",\n \"approvals\",\n \"summary\",\n \"payload\",\n \"payloadDigest\",\n \"callerRole\"\n ],\n \"title\": \"Action\",\n \"type\": \"object\"\n },\n \"ActionId\": {\n \"description\": \"Opaque, community-minted identifier of one action. A consumer MUST NOT parse or order it; it is compared for equality only. Long enough to be unguessable, because a show of an id the caller may not see is answered `notFound` and an enumerable id would turn that answer into an oracle.\",\n \"maxLength\": 128,\n \"minLength\": 16,\n \"pattern\": \"^[A-Za-z0-9._~:-]+$\",\n \"title\": \"ActionId\",\n \"type\": \"string\"\n },\n \"DigestMultibase\": {\n \"description\": \"A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\\n\\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\\n\\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\\n\\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \\\"interoperability is not guaranteed between implementations using such values\\\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.\",\n \"examples\": [\n \"zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR\"\n ],\n \"minLength\": 16,\n \"pattern\": \"^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$\",\n \"title\": \"DigestMultibase\",\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 \"Field\": {\n \"additionalProperties\": false,\n \"description\": \"One displayed value, with where it comes from and how to render it.\",\n \"properties\": {\n \"format\": {\n \"description\": \"How to render the value. `did` — a DID, shown in full or with a verified display name, never truncated to a prefix that two DIDs share. `capabilityList` — an array of capability names. `duration` — an ISO 8601 duration. `datetime` — an RFC 3339 date-time. `text` — anything else, rendered as literal text.\",\n \"enum\": [\n \"did\",\n \"capabilityList\",\n \"duration\",\n \"datetime\",\n \"text\"\n ],\n \"type\": \"string\"\n },\n \"pointer\": {\n \"description\": \"RFC 6901 JSON Pointer into the action's `payload`. The empty string addresses the whole payload.\",\n \"maxLength\": 512,\n \"pattern\": \"^(/([^~/]|~[01])*)*$\",\n \"type\": \"string\"\n },\n \"value\": {\n \"description\": \"The value found at `pointer` when the community rendered the summary. A renderer re-derives it from `payload` and refuses to render the action on any mismatch; it is carried so that a mismatch is detectable, not so that it can be trusted.\"\n }\n },\n \"required\": [\n \"pointer\",\n \"format\",\n \"value\"\n ],\n \"title\": \"Field\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The action with the caller's acknowledgement recorded in `approvals`. When the caller was the last administrator expected to acknowledge it, `status` is `completed` and `closedReason` is `acknowledged`. Failures use trust-task-error, not this shape.\",\n \"properties\": {\n \"action\": {\n \"$ref\": \"#/$defs/Action\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n }\n },\n \"required\": [\n \"action\"\n ],\n \"title\": \"VTC Admin Actions — Acknowledge — response payload\",\n \"type\": \"object\"\n },\n \"Summary\": {\n \"additionalProperties\": false,\n \"description\": \"What an approver is shown, rendered from the summary template for the action's `kind`. Title and effect are the template's prose; the fields are the payload values that prose is about, each located by pointer so a renderer can verify it.\",\n \"properties\": {\n \"effect\": {\n \"description\": \"One or two sentences from the template saying what executing the operation will do.\",\n \"maxLength\": 1024,\n \"type\": \"string\"\n },\n \"fields\": {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/Field\"\n },\n \"description\": \"Named values the template displays, keyed by a lowerCamelCase field name. Each locates its value in `payload` by JSON Pointer.\",\n \"propertyNames\": {\n \"maxLength\": 64,\n \"pattern\": \"^[a-z][a-zA-Z0-9]*$\"\n },\n \"type\": \"object\"\n },\n \"templateDigest\": {\n \"$ref\": \"#/$defs/DigestMultibase\",\n \"description\": \"Digest of the summary template this summary was rendered from, over its RFC 8785 (JCS) canonicalization. Pinned per `kind`: a renderer that holds the template for a kind refuses a summary naming a different digest, so the community cannot change what approvers are shown for a kind without that change being visible.\"\n },\n \"title\": {\n \"description\": \"One-line heading from the template. Prose only: a renderer MUST NOT present the action from this text without the fields.\",\n \"maxLength\": 256,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"title\",\n \"fields\",\n \"templateDigest\"\n ],\n \"title\": \"Summary\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/vtc/admin/actions/acknowledge/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"An administrator acknowledges an `acknowledge`-category action — an operation that already took effect outside the approval path, such as an operator's offline or break-glass write — recording that they have seen it. There is nothing to approve or decline. The outer document members (id, type, issuer, recipient, issuedAt, expiresAt, proof) are owned by the framework — SPEC §6.3.\",\n \"properties\": {\n \"actionId\": {\n \"$ref\": \"#/$defs/ActionId\",\n \"description\": \"The open `acknowledge` action being acknowledged.\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n }\n },\n \"required\": [\n \"actionId\"\n ],\n \"title\": \"VTC Admin Actions — Acknowledge — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str =
"https://trusttasks.org/spec/vtc/admin/actions/acknowledge/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 \"Action\": {\n \"additionalProperties\": false,\n \"description\": \"One parked administrative operation, as the caller is entitled to see it. The same action reads differently to different callers only in `challenge` and `callerRole`, which are per-caller.\",\n \"properties\": {\n \"actionId\": {\n \"$ref\": \"#/$defs/ActionId\"\n },\n \"approvals\": {\n \"description\": \"The decisions in favour recorded so far — approvals for `approval` and `queue`, acknowledgements for `acknowledge` — one entry per distinct subject, in the order recorded. Empty while none has landed.\",\n \"items\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"at\": {\n \"description\": \"When the decision was recorded.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"subject\": {\n \"description\": \"VID of the approver or acknowledger, as proven by the decision's own proof.\",\n \"maxLength\": 2048,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"subject\",\n \"at\"\n ],\n \"type\": \"object\"\n },\n \"type\": \"array\"\n },\n \"approversRemaining\": {\n \"description\": \"How many further distinct decisions the action needs while `open` — approvals for `approval`, acknowledgements for `acknowledge`. Lets a console say 'one more' without disclosing the eligible set.\",\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"callerRole\": {\n \"description\": \"The caller's relation to this action. `approver` — an eligible approver (whether or not already decided). `requester` — the party whose operation was parked. `acknowledger` — an administrator expected to acknowledge it. `observer` — none of these; seen only through the audit-read capability on a `history` or `all` view.\",\n \"enum\": [\n \"approver\",\n \"requester\",\n \"acknowledger\",\n \"observer\"\n ],\n \"type\": \"string\"\n },\n \"category\": {\n \"description\": \"`approval` — eligible approvers approve or decline, N-of-M; the operation executes when the threshold is met. `acknowledge` — an operation that already happened (an operator's offline or break-glass write) which every remaining administrator must acknowledge; there is nothing to approve or decline. `queue` — an existing human decision (for example a join review) surfaced in the same list, with a threshold of one.\",\n \"enum\": [\n \"approval\",\n \"acknowledge\",\n \"queue\"\n ],\n \"type\": \"string\"\n },\n \"challenge\": {\n \"description\": \"Present ONLY on an action the CALLER may decide now — an `approval` or `queue` action on which the caller is an eligible approver who has not yet decided. Per-approver: two approvers are shown different challenges for the same action. Echoed verbatim in `task-consent/decision`'s `challenge`, which binds that decision to this approver and this action. Absent for everyone else, including the requester.\",\n \"maxLength\": 256,\n \"minLength\": 16,\n \"type\": \"string\"\n },\n \"closedAt\": {\n \"description\": \"When the action left `open`. Present exactly when `status` is not `open`.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"closedReason\": {\n \"description\": \"Why the action closed. Present exactly when `status` is not `open`. `invalidated` — the community closed it because something it depended on stopped holding before the threshold (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met but the execution-time re-check refused.\",\n \"enum\": [\n \"thresholdMet\",\n \"declined\",\n \"expired\",\n \"cancelledByRequester\",\n \"invalidated\",\n \"failedRecheck\",\n \"acknowledged\"\n ],\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"description\": \"When the operation was parked.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"expiresAt\": {\n \"description\": \"When an open action lapses. Absent for an `acknowledge` or `queue` action that does not expire; ALWAYS present for `approval`, whose open life is bounded (72 hours by default; the community configures it between 15 minutes and 14 days).\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"kind\": {\n \"description\": \"The community's name for what kind of operation is parked, dotted and lowerCamelCase (`acl.grant.authority`, `member.join.review`). Selects the summary template. The set is OPEN: a renderer that does not recognise a kind still renders `summary` from its fields.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"pattern\": \"^[a-z][a-zA-Z0-9.]*$\",\n \"type\": \"string\"\n },\n \"payload\": {\n \"description\": \"The exact payload of the parked operation — the object `payloadDigest` is computed over and the one the community will execute. Carried so an approver can recompute the digest and re-derive every summary field from it rather than trusting the rendering (VTI-APV-013). Deliberately an open object: its shape is governed by the specification `typeUri` names, and a digest is checked over members exactly as received.\",\n \"type\": \"object\"\n },\n \"payloadDigest\": {\n \"$ref\": \"#/$defs/DigestMultibase\",\n \"description\": \"Digest of `payload`, taken over its RFC 8785 (JCS) canonicalization. The community re-derives it from the payload it is about to execute and refuses on mismatch. The digest an approver signs over is the challenge-salted one of `task-consent/decision`, not this value; this one lets the approver check that `payload` is what was parked.\"\n },\n \"requester\": {\n \"description\": \"VID of the party whose operation was parked. For `acknowledge`, the operator whose offline write is being acknowledged, where the community can attribute one.\",\n \"maxLength\": 2048,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"requesterOpenActions\": {\n \"description\": \"How many open actions the requester currently has at the community, this one included. For consent-fatigue display: an approver shown the twentieth request from one requester today should be able to see that it is the twentieth.\",\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"status\": {\n \"description\": \"`open` — awaiting decisions. `completed` — the threshold was met and the operation executed (or, for `acknowledge`, every administrator acknowledged). `declined` — an eligible approver denied it. `expired` — it lapsed at `expiresAt`. `cancelled` — the requester withdrew it, or the community invalidated it (see `closedReason`). `failed` — the threshold was met but the re-check at execution refused it, or execution itself failed; the operation did not take effect.\",\n \"enum\": [\n \"open\",\n \"completed\",\n \"declined\",\n \"expired\",\n \"cancelled\",\n \"failed\"\n ],\n \"type\": \"string\"\n },\n \"summary\": {\n \"$ref\": \"#/$defs/Summary\"\n },\n \"threshold\": {\n \"description\": \"The number of distinct approvals the operation needs. Present for `approval`; absent otherwise (a `queue` decision is one decision by construction, and `acknowledge` needs every remaining administrator).\",\n \"minimum\": 1,\n \"type\": \"integer\"\n },\n \"typeUri\": {\n \"description\": \"The Type URI of the parked operation — the Trust Task the community will execute when the action completes. Together with `payload` it is exactly what will run.\",\n \"format\": \"uri\",\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"actionId\",\n \"category\",\n \"kind\",\n \"typeUri\",\n \"requester\",\n \"status\",\n \"createdAt\",\n \"approvals\",\n \"summary\",\n \"payload\",\n \"payloadDigest\",\n \"callerRole\"\n ],\n \"title\": \"Action\",\n \"type\": \"object\"\n },\n \"ActionId\": {\n \"description\": \"Opaque, community-minted identifier of one action. A consumer MUST NOT parse or order it; it is compared for equality only. Long enough to be unguessable, because a show of an id the caller may not see is answered `notFound` and an enumerable id would turn that answer into an oracle.\",\n \"maxLength\": 128,\n \"minLength\": 16,\n \"pattern\": \"^[A-Za-z0-9._~:-]+$\",\n \"title\": \"ActionId\",\n \"type\": \"string\"\n },\n \"DigestMultibase\": {\n \"description\": \"A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\\n\\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\\n\\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\\n\\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \\\"interoperability is not guaranteed between implementations using such values\\\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.\",\n \"examples\": [\n \"zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR\"\n ],\n \"minLength\": 16,\n \"pattern\": \"^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$\",\n \"title\": \"DigestMultibase\",\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 \"Field\": {\n \"additionalProperties\": false,\n \"description\": \"One displayed value, with where it comes from and how to render it.\",\n \"properties\": {\n \"format\": {\n \"description\": \"How to render the value. `did` — a DID, shown in full or with a verified display name, never truncated to a prefix that two DIDs share. `capabilityList` — an array of capability names. `duration` — an ISO 8601 duration. `datetime` — an RFC 3339 date-time. `text` — anything else, rendered as literal text.\",\n \"enum\": [\n \"did\",\n \"capabilityList\",\n \"duration\",\n \"datetime\",\n \"text\"\n ],\n \"type\": \"string\"\n },\n \"pointer\": {\n \"description\": \"RFC 6901 JSON Pointer into the action's `payload`. The empty string addresses the whole payload.\",\n \"maxLength\": 512,\n \"pattern\": \"^(/([^~/]|~[01])*)*$\",\n \"type\": \"string\"\n },\n \"value\": {\n \"description\": \"The value found at `pointer` when the community rendered the summary. A renderer re-derives it from `payload` and refuses to render the action on any mismatch; it is carried so that a mismatch is detectable, not so that it can be trusted.\"\n }\n },\n \"required\": [\n \"pointer\",\n \"format\",\n \"value\"\n ],\n \"title\": \"Field\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The action with the caller's acknowledgement recorded in `approvals`. When the caller was the last administrator expected to acknowledge it, `status` is `completed` and `closedReason` is `acknowledged`. Failures use trust-task-error, not this shape.\",\n \"properties\": {\n \"action\": {\n \"$ref\": \"#/$defs/Action\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n }\n },\n \"required\": [\n \"action\"\n ],\n \"title\": \"VTC Admin Actions — Acknowledge — response payload\",\n \"type\": \"object\"\n },\n \"Summary\": {\n \"additionalProperties\": false,\n \"description\": \"What an approver is shown, rendered from the summary template for the action's `kind`. Title and effect are the template's prose; the fields are the payload values that prose is about, each located by pointer so a renderer can verify it.\",\n \"properties\": {\n \"effect\": {\n \"description\": \"One or two sentences from the template saying what executing the operation will do.\",\n \"maxLength\": 1024,\n \"type\": \"string\"\n },\n \"fields\": {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/Field\"\n },\n \"description\": \"Named values the template displays, keyed by a lowerCamelCase field name. Each locates its value in `payload` by JSON Pointer.\",\n \"propertyNames\": {\n \"maxLength\": 64,\n \"pattern\": \"^[a-z][a-zA-Z0-9]*$\"\n },\n \"type\": \"object\"\n },\n \"templateDigest\": {\n \"$ref\": \"#/$defs/DigestMultibase\",\n \"description\": \"Digest of the summary template this summary was rendered from, over its RFC 8785 (JCS) canonicalization. Pinned per `kind`: a renderer that holds the template for a kind refuses a summary naming a different digest, so the community cannot change what approvers are shown for a kind without that change being visible.\"\n },\n \"title\": {\n \"description\": \"One-line heading from the template. Prose only: a renderer MUST NOT present the action from this text without the fields.\",\n \"maxLength\": 256,\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"title\",\n \"fields\",\n \"templateDigest\"\n ],\n \"title\": \"Summary\",\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_ACKNOWLEDGEABLE,
error_codes::ALREADY_ACKNOWLEDGED,
];
/// 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/admin/actions/acknowledge:notFound`
///
/// No action with this `actionId` exists that the caller may see. Answered identically for both cases.
///
/// Declared `retryable: false`.
pub const NOT_FOUND: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/admin/actions/acknowledge:notFound",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/admin/actions/acknowledge:notAcknowledgeable`
///
/// The action cannot be acknowledged by this caller — it is not of category `acknowledge`, it is no longer `open`, or the caller is not among the administrators expected to acknowledge it (for example, its requester).
///
/// Declared `retryable: false`.
pub const NOT_ACKNOWLEDGEABLE: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/admin/actions/acknowledge:notAcknowledgeable",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/admin/actions/acknowledge:alreadyAcknowledged`
///
/// The caller has already acknowledged this action. The earlier acknowledgement stands; the state the caller wanted is already true.
///
/// Declared `retryable: false`.
pub const ALREADY_ACKNOWLEDGED: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/admin/actions/acknowledge:alreadyAcknowledged",
retryable: false,
details_schema: ::core::option::Option::None,
};
}