//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `vtc/admin/actions/cancel`. Version: `0.2`.
#[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, and always empty for `coolingOff`, which takes no decisions.",
/// "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. Absent for `coolingOff`, which waits on time, not on decisions.",
/// "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. `subject` — the party a `coolingOff` operation acts on, shown it so that they learn of it before it lands; a subject can neither decide nor cancel it. `observer` — none of these; seen only through the audit-read capability on a `history` or `all` view.",
/// "type": "string",
/// "enum": [
/// "approver",
/// "requester",
/// "acknowledger",
/// "subject",
/// "observer"
/// ]
/// },
/// "cancellableBy": {
/// "description": "Who may withdraw the action with `vtc/admin/actions/cancel` while it is `open`. Present on every open `coolingOff` action, where it is `requester`: the operation lands unless its requester stops it, and nobody else — the subject included — can. A closed set so that a console can offer a cancel control without inferring it; future values would widen who may cancel and need a new version.",
/// "type": "string",
/// "enum": [
/// "requester"
/// ]
/// },
/// "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. `coolingOff` — an operation with no eligible third party to consent, which lands by itself at `landsAt` unless its requester cancels it first; nobody approves, declines or acknowledges it.",
/// "type": "string",
/// "enum": [
/// "approval",
/// "acknowledge",
/// "queue",
/// "coolingOff"
/// ]
/// },
/// "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. Never present on `acknowledge` or `coolingOff`. 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 or `landsAt` (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met or `landsAt` reached but the execution-time re-check refused; `landedAfterCoolingOff` — a `coolingOff` action reached `landsAt` uncancelled and its operation executed (`status: completed`).",
/// "type": "string",
/// "enum": [
/// "thresholdMet",
/// "declined",
/// "expired",
/// "cancelledByRequester",
/// "invalidated",
/// "failedRecheck",
/// "acknowledged",
/// "landedAfterCoolingOff"
/// ]
/// },
/// "createdAt": {
/// "description": "When the operation was parked.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "expiresAt": {
/// "description": "When an open action lapses. ALWAYS present for `approval`, whose open life is bounded (72 hours by default; the community configures it between 15 minutes and 14 days). Absent for an `acknowledge` or `queue` action that does not expire, and ALWAYS absent for `coolingOff`, which does not lapse but lands — see `landsAt`.",
/// "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.]*$"
/// },
/// "landsAt": {
/// "description": "When a `coolingOff` action lands: the instant from which the community executes the parked operation, after its execution-time re-check, unless the requester cancelled first. Present exactly when `category` is `coolingOff`. It is a deadline for the requester's cancellation, not for anyone's approval, and it is fixed when the action is parked: neither the requester nor the subject can move it.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "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. For `coolingOff`, the administrator whose operation will land — the only party who may cancel it.",
/// "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, or for `coolingOff` awaiting `landsAt`. `completed` — the threshold was met and the operation executed, a `coolingOff` operation landed, 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 or `landsAt` reached 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, `acknowledge` needs every remaining administrator, and `coolingOff` needs no approval at all).",
/// "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 (for `coolingOff`, when it lands). Together with `payload` it is exactly what will run. For `acknowledge`, the Type URI of the operation that already took effect; an operator's offline write, which is a command on the community's host and has no Trust Task of its own, is named by the record type `https://trusttasks.org/spec/vtc/operator/offline-write/0.1`, and `payload` is then that record.",
/// "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, and always empty for `coolingOff`, which takes no decisions.
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. Absent for `coolingOff`, which waits on time, not on decisions.
#[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. `subject` — the party a `coolingOff` operation acts on, shown it so that they learn of it before it lands; a subject can neither decide nor cancel 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,
///Who may withdraw the action with `vtc/admin/actions/cancel` while it is `open`. Present on every open `coolingOff` action, where it is `requester`: the operation lands unless its requester stops it, and nobody else — the subject included — can. A closed set so that a console can offer a cancel control without inferring it; future values would widen who may cancel and need a new version.
#[serde(
rename = "cancellableBy",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub cancellable_by: ::std::option::Option<ActionCancellableBy>,
///`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. `coolingOff` — an operation with no eligible third party to consent, which lands by itself at `landsAt` unless its requester cancels it first; nobody approves, declines or acknowledges it.
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. Never present on `acknowledge` or `coolingOff`. 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 or `landsAt` (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met or `landsAt` reached but the execution-time re-check refused; `landedAfterCoolingOff` — a `coolingOff` action reached `landsAt` uncancelled and its operation executed (`status: completed`).
#[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. ALWAYS present for `approval`, whose open life is bounded (72 hours by default; the community configures it between 15 minutes and 14 days). Absent for an `acknowledge` or `queue` action that does not expire, and ALWAYS absent for `coolingOff`, which does not lapse but lands — see `landsAt`.
#[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,
///When a `coolingOff` action lands: the instant from which the community executes the parked operation, after its execution-time re-check, unless the requester cancelled first. Present exactly when `category` is `coolingOff`. It is a deadline for the requester's cancellation, not for anyone's approval, and it is fixed when the action is parked: neither the requester nor the subject can move it.
#[serde(
rename = "landsAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub lands_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///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. For `coolingOff`, the administrator whose operation will land — the only party who may cancel it.
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, or for `coolingOff` awaiting `landsAt`. `completed` — the threshold was met and the operation executed, a `coolingOff` operation landed, 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 or `landsAt` reached 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, `acknowledge` needs every remaining administrator, and `coolingOff` needs no approval at all).
#[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 (for `coolingOff`, when it lands). Together with `payload` it is exactly what will run. For `acknowledge`, the Type URI of the operation that already took effect; an operator's offline write, which is a command on the community's host and has no Trust Task of its own, is named by the record type `https://trusttasks.org/spec/vtc/operator/offline-write/0.1`, and `payload` is then that record.
#[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. `subject` — the party a `coolingOff` operation acts on, shown it so that they learn of it before it lands; a subject can neither decide nor cancel 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. `subject` — the party a `coolingOff` operation acts on, shown it so that they learn of it before it lands; a subject can neither decide nor cancel it. `observer` — none of these; seen only through the audit-read capability on a `history` or `all` view.",
/// "type": "string",
/// "enum": [
/// "approver",
/// "requester",
/// "acknowledger",
/// "subject",
/// "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 = "subject")]
Subject,
#[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::Subject => f.write_str("subject"),
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),
"subject" => Ok(Self::Subject),
"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()
}
}
///Who may withdraw the action with `vtc/admin/actions/cancel` while it is `open`. Present on every open `coolingOff` action, where it is `requester`: the operation lands unless its requester stops it, and nobody else — the subject included — can. A closed set so that a console can offer a cancel control without inferring it; future values would widen who may cancel and need a new version.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Who may withdraw the action with `vtc/admin/actions/cancel` while it is `open`. Present on every open `coolingOff` action, where it is `requester`: the operation lands unless its requester stops it, and nobody else — the subject included — can. A closed set so that a console can offer a cancel control without inferring it; future values would widen who may cancel and need a new version.",
/// "type": "string",
/// "enum": [
/// "requester"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ActionCancellableBy {
#[serde(rename = "requester")]
Requester,
}
impl ::std::fmt::Display for ActionCancellableBy {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Requester => f.write_str("requester"),
}
}
}
impl ::std::str::FromStr for ActionCancellableBy {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"requester" => Ok(Self::Requester),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ActionCancellableBy {
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 ActionCancellableBy {
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 ActionCancellableBy {
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. `coolingOff` — an operation with no eligible third party to consent, which lands by itself at `landsAt` unless its requester cancels it first; nobody approves, declines or acknowledges it.
///
/// <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. `coolingOff` — an operation with no eligible third party to consent, which lands by itself at `landsAt` unless its requester cancels it first; nobody approves, declines or acknowledges it.",
/// "type": "string",
/// "enum": [
/// "approval",
/// "acknowledge",
/// "queue",
/// "coolingOff"
/// ]
///}
/// ```
/// </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,
#[serde(rename = "coolingOff")]
CoolingOff,
}
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"),
Self::CoolingOff => f.write_str("coolingOff"),
}
}
}
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),
"coolingOff" => Ok(Self::CoolingOff),
_ => 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. Never present on `acknowledge` or `coolingOff`. 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. Never present on `acknowledge` or `coolingOff`. 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 or `landsAt` (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met or `landsAt` reached but the execution-time re-check refused; `landedAfterCoolingOff` — a `coolingOff` action reached `landsAt` uncancelled and its operation executed (`status: completed`).
///
/// <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 or `landsAt` (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met or `landsAt` reached but the execution-time re-check refused; `landedAfterCoolingOff` — a `coolingOff` action reached `landsAt` uncancelled and its operation executed (`status: completed`).",
/// "type": "string",
/// "enum": [
/// "thresholdMet",
/// "declined",
/// "expired",
/// "cancelledByRequester",
/// "invalidated",
/// "failedRecheck",
/// "acknowledged",
/// "landedAfterCoolingOff"
/// ]
///}
/// ```
/// </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,
#[serde(rename = "landedAfterCoolingOff")]
LandedAfterCoolingOff,
}
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"),
Self::LandedAfterCoolingOff => f.write_str("landedAfterCoolingOff"),
}
}
}
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),
"landedAfterCoolingOff" => Ok(Self::LandedAfterCoolingOff),
_ => 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. For `coolingOff`, the administrator whose operation will land — the only party who may cancel it.
///
/// <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. For `coolingOff`, the administrator whose operation will land — the only party who may cancel it.",
/// "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, or for `coolingOff` awaiting `landsAt`. `completed` — the threshold was met and the operation executed, a `coolingOff` operation landed, 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 or `landsAt` reached 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, or for `coolingOff` awaiting `landsAt`. `completed` — the threshold was met and the operation executed, a `coolingOff` operation landed, 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 or `landsAt` reached 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())
})
}
}
///The requester of an open administrative action withdraws it, so the parked operation never executes and the action leaves every administrator's list. 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/cancel/0.2",
/// "title": "Payload",
/// "description": "The requester of an open administrative action withdraws it, so the parked operation never executes and the action leaves every administrator's list. 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 action to withdraw.",
/// "$ref": "#/definitions/ActionId"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "reason": {
/// "description": "OPTIONAL note shown to the action's approvers and kept in the audit record. Read by every administrator who can see the action.",
/// "type": "string",
/// "maxLength": 500
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Payload {
///The open action to withdraw.
#[serde(rename = "actionId")]
pub action_id: ActionId,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///OPTIONAL note shown to the action's approvers and kept in the audit record. Read by every administrator who can see the action.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reason: ::std::option::Option<PayloadReason>,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///OPTIONAL note shown to the action's approvers and kept in the audit record. Read by every administrator who can see the action.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "OPTIONAL note shown to the action's approvers and kept in the audit record. Read by every administrator who can see the action.",
/// "type": "string",
/// "maxLength": 500
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadReason(::std::string::String);
impl ::std::ops::Deref for PayloadReason {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadReason> for ::std::string::String {
fn from(value: PayloadReason) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadReason {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 500usize {
return Err("longer than 500 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PayloadReason {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PayloadReason {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PayloadReason {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for PayloadReason {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///The action as it now stands — `status: cancelled`, `closedReason: cancelledByRequester`. Failures use trust-task-error, not this shape.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "The action as it now stands — `status: cancelled`, `closedReason: cancelledByRequester`. 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>,
cancellable_by: ::std::result::Result<
::std::option::Option<super::ActionCancellableBy>,
::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>,
lands_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::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()),
cancellable_by: Ok(Default::default()),
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()),
lands_at: Ok(Default::default()),
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 cancellable_by<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ActionCancellableBy>>,
T::Error: ::std::fmt::Display,
{
self.cancellable_by = value
.try_into()
.map_err(|e| format!("error converting supplied value for cancellable_by: {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 lands_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.lands_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for lands_at: {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?,
cancellable_by: value.cancellable_by?,
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?,
lands_at: value.lands_at?,
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),
cancellable_by: Ok(value.cancellable_by),
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),
lands_at: Ok(value.lands_at),
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>,
reason: ::std::result::Result<
::std::option::Option<super::PayloadReason>,
::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()),
reason: 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
}
pub fn reason<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::PayloadReason>>,
T::Error: ::std::fmt::Display,
{
self.reason = value
.try_into()
.map_err(|e| format!("error converting supplied value for reason: {e}"));
self
}
}
impl ::std::convert::TryFrom<Payload> for super::Payload {
type Error = super::error::ConversionError;
fn try_from(value: Payload) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
action_id: value.action_id?,
ext: value.ext?,
reason: value.reason?,
})
}
}
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),
reason: Ok(value.reason),
}
}
}
#[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/cancel/0.2";
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, and always empty for `coolingOff`, which takes no decisions.\",\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. Absent for `coolingOff`, which waits on time, not on decisions.\",\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. `subject` — the party a `coolingOff` operation acts on, shown it so that they learn of it before it lands; a subject can neither decide nor cancel 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 \"subject\",\n \"observer\"\n ],\n \"type\": \"string\"\n },\n \"cancellableBy\": {\n \"description\": \"Who may withdraw the action with `vtc/admin/actions/cancel` while it is `open`. Present on every open `coolingOff` action, where it is `requester`: the operation lands unless its requester stops it, and nobody else — the subject included — can. A closed set so that a console can offer a cancel control without inferring it; future values would widen who may cancel and need a new version.\",\n \"enum\": [\n \"requester\"\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. `coolingOff` — an operation with no eligible third party to consent, which lands by itself at `landsAt` unless its requester cancels it first; nobody approves, declines or acknowledges it.\",\n \"enum\": [\n \"approval\",\n \"acknowledge\",\n \"queue\",\n \"coolingOff\"\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. Never present on `acknowledge` or `coolingOff`. 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 or `landsAt` (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met or `landsAt` reached but the execution-time re-check refused; `landedAfterCoolingOff` — a `coolingOff` action reached `landsAt` uncancelled and its operation executed (`status: completed`).\",\n \"enum\": [\n \"thresholdMet\",\n \"declined\",\n \"expired\",\n \"cancelledByRequester\",\n \"invalidated\",\n \"failedRecheck\",\n \"acknowledged\",\n \"landedAfterCoolingOff\"\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. ALWAYS present for `approval`, whose open life is bounded (72 hours by default; the community configures it between 15 minutes and 14 days). Absent for an `acknowledge` or `queue` action that does not expire, and ALWAYS absent for `coolingOff`, which does not lapse but lands — see `landsAt`.\",\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 \"landsAt\": {\n \"description\": \"When a `coolingOff` action lands: the instant from which the community executes the parked operation, after its execution-time re-check, unless the requester cancelled first. Present exactly when `category` is `coolingOff`. It is a deadline for the requester's cancellation, not for anyone's approval, and it is fixed when the action is parked: neither the requester nor the subject can move it.\",\n \"format\": \"date-time\",\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. For `coolingOff`, the administrator whose operation will land — the only party who may cancel it.\",\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, or for `coolingOff` awaiting `landsAt`. `completed` — the threshold was met and the operation executed, a `coolingOff` operation landed, 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 or `landsAt` reached 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, `acknowledge` needs every remaining administrator, and `coolingOff` needs no approval at all).\",\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 (for `coolingOff`, when it lands). Together with `payload` it is exactly what will run. For `acknowledge`, the Type URI of the operation that already took effect; an operator's offline write, which is a command on the community's host and has no Trust Task of its own, is named by the record type `https://trusttasks.org/spec/vtc/operator/offline-write/0.1`, and `payload` is then that record.\",\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 as it now stands — `status: cancelled`, `closedReason: cancelledByRequester`. 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 — Cancel — 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/cancel/0.2\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"The requester of an open administrative action withdraws it, so the parked operation never executes and the action leaves every administrator's list. 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 action to withdraw.\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"reason\": {\n \"description\": \"OPTIONAL note shown to the action's approvers and kept in the audit record. Read by every administrator who can see the action.\",\n \"maxLength\": 500,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"actionId\"\n ],\n \"title\": \"VTC Admin Actions — Cancel — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str =
"https://trusttasks.org/spec/vtc/admin/actions/cancel/0.2#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, and always empty for `coolingOff`, which takes no decisions.\",\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. Absent for `coolingOff`, which waits on time, not on decisions.\",\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. `subject` — the party a `coolingOff` operation acts on, shown it so that they learn of it before it lands; a subject can neither decide nor cancel 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 \"subject\",\n \"observer\"\n ],\n \"type\": \"string\"\n },\n \"cancellableBy\": {\n \"description\": \"Who may withdraw the action with `vtc/admin/actions/cancel` while it is `open`. Present on every open `coolingOff` action, where it is `requester`: the operation lands unless its requester stops it, and nobody else — the subject included — can. A closed set so that a console can offer a cancel control without inferring it; future values would widen who may cancel and need a new version.\",\n \"enum\": [\n \"requester\"\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. `coolingOff` — an operation with no eligible third party to consent, which lands by itself at `landsAt` unless its requester cancels it first; nobody approves, declines or acknowledges it.\",\n \"enum\": [\n \"approval\",\n \"acknowledge\",\n \"queue\",\n \"coolingOff\"\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. Never present on `acknowledge` or `coolingOff`. 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 or `landsAt` (an approver or the requester lost standing, the target state moved); `failedRecheck` — the threshold was met or `landsAt` reached but the execution-time re-check refused; `landedAfterCoolingOff` — a `coolingOff` action reached `landsAt` uncancelled and its operation executed (`status: completed`).\",\n \"enum\": [\n \"thresholdMet\",\n \"declined\",\n \"expired\",\n \"cancelledByRequester\",\n \"invalidated\",\n \"failedRecheck\",\n \"acknowledged\",\n \"landedAfterCoolingOff\"\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. ALWAYS present for `approval`, whose open life is bounded (72 hours by default; the community configures it between 15 minutes and 14 days). Absent for an `acknowledge` or `queue` action that does not expire, and ALWAYS absent for `coolingOff`, which does not lapse but lands — see `landsAt`.\",\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 \"landsAt\": {\n \"description\": \"When a `coolingOff` action lands: the instant from which the community executes the parked operation, after its execution-time re-check, unless the requester cancelled first. Present exactly when `category` is `coolingOff`. It is a deadline for the requester's cancellation, not for anyone's approval, and it is fixed when the action is parked: neither the requester nor the subject can move it.\",\n \"format\": \"date-time\",\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. For `coolingOff`, the administrator whose operation will land — the only party who may cancel it.\",\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, or for `coolingOff` awaiting `landsAt`. `completed` — the threshold was met and the operation executed, a `coolingOff` operation landed, 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 or `landsAt` reached 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, `acknowledge` needs every remaining administrator, and `coolingOff` needs no approval at all).\",\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 (for `coolingOff`, when it lands). Together with `payload` it is exactly what will run. For `acknowledge`, the Type URI of the operation that already took effect; an operator's offline write, which is a command on the community's host and has no Trust Task of its own, is named by the record type `https://trusttasks.org/spec/vtc/operator/offline-write/0.1`, and `payload` is then that record.\",\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 as it now stands — `status: cancelled`, `closedReason: cancelledByRequester`. 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 — Cancel — 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_REQUESTER,
error_codes::NOT_OPEN,
];
/// 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/cancel: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/cancel:notFound",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/admin/actions/cancel:notRequester`
///
/// The caller can see the action but is not its requester.
///
/// Declared `retryable: false`.
pub const NOT_REQUESTER: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/admin/actions/cancel:notRequester",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `vtc/admin/actions/cancel:notOpen`
///
/// The action is no longer `open` — it completed, was declined, expired, failed, or was already cancelled.
///
/// Declared `retryable: false`.
pub const NOT_OPEN: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "vtc/admin/actions/cancel:notOpen",
retryable: false,
details_schema: ::core::option::Option::None,
};
}