//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `trust-task-control`. Version: `0.1`.
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
/// Error types.
pub mod error {
/// Error from a `TryFrom` or `FromStr` implementation.
pub struct ConversionError(::std::borrow::Cow<'static, str>);
impl ::std::error::Error for ConversionError {}
impl ::std::fmt::Display for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Display::fmt(&self.0, f)
}
}
impl ::std::fmt::Debug for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Debug::fmt(&self.0, f)
}
}
impl From<&'static str> for ConversionError {
fn from(value: &'static str) -> Self {
Self(value.into())
}
}
impl From<String> for ConversionError {
fn from(value: String) -> Self {
Self(value.into())
}
}
}
/**
The task-control request defined at SPEC.md §12: a producer withdrawing, pausing, or resuming work a consumer has already accepted.
This is a REQUEST, not a response. A consumer that stops work on its own initiative does not send one of these — it returns a trust-task-error carrying `cancelled`, so that a withdrawal and a refusal remain distinguishable to every party and to any auditor reading the retained documents afterwards.
The operation takes effect through SPEC.md §7.2 item 12: a valid, authorized control operation is one of the conditions a consumer re-evaluates immediately before each irreversible or externally visible effect. There is no separate race protocol.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/trust-task-control/0.1",
/// "title": "Payload",
/// "description": "\nThe task-control request defined at SPEC.md §12: a producer withdrawing, pausing, or resuming work a consumer has already accepted.\n\nThis is a REQUEST, not a response. A consumer that stops work on its own initiative does not send one of these — it returns a trust-task-error carrying `cancelled`, so that a withdrawal and a refusal remain distinguishable to every party and to any auditor reading the retained documents afterwards.\n\nThe operation takes effect through SPEC.md §7.2 item 12: a valid, authorized control operation is one of the conditions a consumer re-evaluates immediately before each irreversible or externally visible effect. There is no separate race protocol.",
/// "type": "object",
/// "required": [
/// "operation",
/// "target"
/// ],
/// "properties": {
/// "ext": {
/// "description": "Vendor-namespaced extension data per SPEC.md §4.5.1. Every immediate child key MUST be a reverse-DNS prefix the producer controls.",
/// "type": "object"
/// },
/// "operation": {
/// "description": "\nThe control operation requested.\n\n`cancel` stops the task permanently: it is terminal, and a cancelled task MUST NOT be resumed, retried, or cancelled again (SPEC.md §12.3). `suspend` halts further effects while preserving the consumer's current execution state — it does not undo work already performed. `resume` continues a suspended task from the state the consumer holds; a consumer MUST NOT resume after the target document's `expiresAt` (SPEC.md §12.5).\n\nThis is a discriminating field. A consumer that does not recognize a value MUST reject the document rather than apply a default — silently downgrading an unrecognized operation to a known one would let a producer's intent be replaced by the consumer's guess.",
/// "enum": [
/// "cancel",
/// "suspend",
/// "resume"
/// ]
/// },
/// "reason": {
/// "description": "Human-readable explanation of why the operation was requested. Non-normative; intended for operator UI and audit records. A consumer MUST NOT condition its handling of the operation on this value.",
/// "type": "string"
/// },
/// "target": {
/// "description": "The specific Trust Task document this operation applies to. Per SPEC.md §12.2, `threadId`, `parentThreadId` and ceremony membership MUST NOT identify the target on their own: more than one document can occur in a single exchange or enactment.",
/// "type": "object",
/// "required": [
/// "id"
/// ],
/// "properties": {
/// "id": {
/// "description": "The `id` of the target Trust Task document. The sole identifying member.",
/// "type": "string",
/// "minLength": 1
/// },
/// "typeUri": {
/// "description": "The target document's `type`, including any `#request` fragment. RECOMMENDED. A consumer that holds the named `id` under a different specification can then detect the mismatch rather than acting on a coincidence of identifiers.",
/// "type": "string",
/// "format": "uri",
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct Payload {
///Vendor-namespaced extension data per SPEC.md §4.5.1. Every immediate child key MUST be a reverse-DNS prefix the producer controls.
#[serde(default, skip_serializing_if = "::serde_json::Map::is_empty")]
pub ext: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
/**
The control operation requested.
`cancel` stops the task permanently: it is terminal, and a cancelled task MUST NOT be resumed, retried, or cancelled again (SPEC.md §12.3). `suspend` halts further effects while preserving the consumer's current execution state — it does not undo work already performed. `resume` continues a suspended task from the state the consumer holds; a consumer MUST NOT resume after the target document's `expiresAt` (SPEC.md §12.5).
This is a discriminating field. A consumer that does not recognize a value MUST reject the document rather than apply a default — silently downgrading an unrecognized operation to a known one would let a producer's intent be replaced by the consumer's guess.*/
pub operation: PayloadOperation,
///Human-readable explanation of why the operation was requested. Non-normative; intended for operator UI and audit records. A consumer MUST NOT condition its handling of the operation on this value.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reason: ::std::option::Option<::std::string::String>,
pub target: PayloadTarget,
}
/**
The control operation requested.
`cancel` stops the task permanently: it is terminal, and a cancelled task MUST NOT be resumed, retried, or cancelled again (SPEC.md §12.3). `suspend` halts further effects while preserving the consumer's current execution state — it does not undo work already performed. `resume` continues a suspended task from the state the consumer holds; a consumer MUST NOT resume after the target document's `expiresAt` (SPEC.md §12.5).
This is a discriminating field. A consumer that does not recognize a value MUST reject the document rather than apply a default — silently downgrading an unrecognized operation to a known one would let a producer's intent be replaced by the consumer's guess.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "\nThe control operation requested.\n\n`cancel` stops the task permanently: it is terminal, and a cancelled task MUST NOT be resumed, retried, or cancelled again (SPEC.md §12.3). `suspend` halts further effects while preserving the consumer's current execution state — it does not undo work already performed. `resume` continues a suspended task from the state the consumer holds; a consumer MUST NOT resume after the target document's `expiresAt` (SPEC.md §12.5).\n\nThis is a discriminating field. A consumer that does not recognize a value MUST reject the document rather than apply a default — silently downgrading an unrecognized operation to a known one would let a producer's intent be replaced by the consumer's guess.",
/// "enum": [
/// "cancel",
/// "suspend",
/// "resume"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum PayloadOperation {
#[serde(rename = "cancel")]
Cancel,
#[serde(rename = "suspend")]
Suspend,
#[serde(rename = "resume")]
Resume,
}
impl ::std::fmt::Display for PayloadOperation {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Cancel => f.write_str("cancel"),
Self::Suspend => f.write_str("suspend"),
Self::Resume => f.write_str("resume"),
}
}
}
impl ::std::str::FromStr for PayloadOperation {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"cancel" => Ok(Self::Cancel),
"suspend" => Ok(Self::Suspend),
"resume" => Ok(Self::Resume),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PayloadOperation {
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 PayloadOperation {
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 PayloadOperation {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///The specific Trust Task document this operation applies to. Per SPEC.md §12.2, `threadId`, `parentThreadId` and ceremony membership MUST NOT identify the target on their own: more than one document can occur in a single exchange or enactment.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The specific Trust Task document this operation applies to. Per SPEC.md §12.2, `threadId`, `parentThreadId` and ceremony membership MUST NOT identify the target on their own: more than one document can occur in a single exchange or enactment.",
/// "type": "object",
/// "required": [
/// "id"
/// ],
/// "properties": {
/// "id": {
/// "description": "The `id` of the target Trust Task document. The sole identifying member.",
/// "type": "string",
/// "minLength": 1
/// },
/// "typeUri": {
/// "description": "The target document's `type`, including any `#request` fragment. RECOMMENDED. A consumer that holds the named `id` under a different specification can then detect the mismatch rather than acting on a coincidence of identifiers.",
/// "type": "string",
/// "format": "uri",
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct PayloadTarget {
///The `id` of the target Trust Task document. The sole identifying member.
pub id: PayloadTargetId,
///The target document's `type`, including any `#request` fragment. RECOMMENDED. A consumer that holds the named `id` under a different specification can then detect the mismatch rather than acting on a coincidence of identifiers.
#[serde(
rename = "typeUri",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub type_uri: ::std::option::Option<::std::string::String>,
}
///The `id` of the target Trust Task document. The sole identifying member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The `id` of the target Trust Task document. The sole identifying member.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadTargetId(::std::string::String);
impl ::std::ops::Deref for PayloadTargetId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadTargetId> for ::std::string::String {
fn from(value: PayloadTargetId) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadTargetId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PayloadTargetId {
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 PayloadTargetId {
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 PayloadTargetId {
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 PayloadTargetId {
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())
})
}
}
///What the consumer did. The `outcome` is the load-bearing member: it is what tells the producer whether a compensating action is required, since SPEC.md §12.4 declines to require rollback.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "What the consumer did. The `outcome` is the load-bearing member: it is what tells the producer whether a compensating action is required, since SPEC.md §12.4 declines to require rollback.",
/// "type": "object",
/// "required": [
/// "operation",
/// "outcome",
/// "target"
/// ],
/// "properties": {
/// "effects": {
/// "description": "What was created, changed, disclosed, or exercised before the operation took hold. A consumer MUST populate this where `outcome` is `appliedWithEffects` or `alreadyCompleted` — a producer cannot decide whether to compensate without it — and the specification's Conformance section carries that requirement normatively. It is not expressed as a conditional schema because the registry's Rust code generator does not support if/then/else. The framework does not constrain how a task describes its own effects.",
/// "type": "array",
/// "items": {
/// "type": "object",
/// "required": [
/// "description"
/// ],
/// "properties": {
/// "description": {
/// "description": "Human-readable statement of the effect that occurred.",
/// "type": "string",
/// "minLength": 1
/// },
/// "ref": {
/// "description": "An identifier for the effect where one exists — a credential id, a record identifier, a transaction reference — so a compensating task can name it.",
/// "type": "string"
/// },
/// "reversible": {
/// "description": "Whether the consumer believes this effect can be compensated by a further Trust Task. Advisory. Absent means unknown, which a producer SHOULD treat as no weaker than `false`.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": false
/// }
/// },
/// "ext": {
/// "description": "Vendor-namespaced extension data per SPEC.md §4.5.1.",
/// "type": "object"
/// },
/// "operation": {
/// "description": "Echoed from the request, so the response is self-describing when retained apart from it.",
/// "enum": [
/// "cancel",
/// "suspend",
/// "resume"
/// ]
/// },
/// "outcome": {
/// "description": "\n`applied` — the operation took effect and NO irreversible or externally visible effect had occurred. The only outcome that means the task left no trace.\n\n`appliedWithEffects` — the operation took effect, but effects had already occurred before it did. `effects` describes them. A consumer MUST NOT report `applied` in this case (SPEC.md §12.3).\n\n`alreadyCompleted` — the task finished before the control document was processed. Not a cancellation; whether to compensate is the producer's own decision.\n\n`unknownTask` — the consumer holds no record of the target `id`, either because it never received it or because its acceptance window has lapsed. A consumer that records the operation as a tombstone against a not-yet-arrived document reports `applied`, not this.",
/// "enum": [
/// "applied",
/// "appliedWithEffects",
/// "alreadyCompleted",
/// "unknownTask"
/// ]
/// },
/// "target": {
/// "description": "Echoed from the request.",
/// "type": "object",
/// "required": [
/// "id"
/// ],
/// "properties": {
/// "id": {
/// "type": "string",
/// "minLength": 1
/// },
/// "typeUri": {
/// "type": "string",
/// "format": "uri",
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct Response {
///What was created, changed, disclosed, or exercised before the operation took hold. A consumer MUST populate this where `outcome` is `appliedWithEffects` or `alreadyCompleted` — a producer cannot decide whether to compensate without it — and the specification's Conformance section carries that requirement normatively. It is not expressed as a conditional schema because the registry's Rust code generator does not support if/then/else. The framework does not constrain how a task describes its own effects.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub effects: ::std::vec::Vec<ResponseEffectsItem>,
///Vendor-namespaced extension data per SPEC.md §4.5.1.
#[serde(default, skip_serializing_if = "::serde_json::Map::is_empty")]
pub ext: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
///Echoed from the request, so the response is self-describing when retained apart from it.
pub operation: ResponseOperation,
/**
`applied` — the operation took effect and NO irreversible or externally visible effect had occurred. The only outcome that means the task left no trace.
`appliedWithEffects` — the operation took effect, but effects had already occurred before it did. `effects` describes them. A consumer MUST NOT report `applied` in this case (SPEC.md §12.3).
`alreadyCompleted` — the task finished before the control document was processed. Not a cancellation; whether to compensate is the producer's own decision.
`unknownTask` — the consumer holds no record of the target `id`, either because it never received it or because its acceptance window has lapsed. A consumer that records the operation as a tombstone against a not-yet-arrived document reports `applied`, not this.*/
pub outcome: ResponseOutcome,
pub target: ResponseTarget,
}
///`ResponseEffectsItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "description"
/// ],
/// "properties": {
/// "description": {
/// "description": "Human-readable statement of the effect that occurred.",
/// "type": "string",
/// "minLength": 1
/// },
/// "ref": {
/// "description": "An identifier for the effect where one exists — a credential id, a record identifier, a transaction reference — so a compensating task can name it.",
/// "type": "string"
/// },
/// "reversible": {
/// "description": "Whether the consumer believes this effect can be compensated by a further Trust Task. Advisory. Absent means unknown, which a producer SHOULD treat as no weaker than `false`.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct ResponseEffectsItem {
///Human-readable statement of the effect that occurred.
pub description: ResponseEffectsItemDescription,
///An identifier for the effect where one exists — a credential id, a record identifier, a transaction reference — so a compensating task can name it.
#[serde(
rename = "ref",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub ref_: ::std::option::Option<::std::string::String>,
///Whether the consumer believes this effect can be compensated by a further Trust Task. Advisory. Absent means unknown, which a producer SHOULD treat as no weaker than `false`.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reversible: ::std::option::Option<bool>,
}
///Human-readable statement of the effect that occurred.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Human-readable statement of the effect that occurred.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ResponseEffectsItemDescription(::std::string::String);
impl ::std::ops::Deref for ResponseEffectsItemDescription {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ResponseEffectsItemDescription> for ::std::string::String {
fn from(value: ResponseEffectsItemDescription) -> Self {
value.0
}
}
impl ::std::str::FromStr for ResponseEffectsItemDescription {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ResponseEffectsItemDescription {
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 ResponseEffectsItemDescription {
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 ResponseEffectsItemDescription {
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 ResponseEffectsItemDescription {
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())
})
}
}
///Echoed from the request, so the response is self-describing when retained apart from it.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Echoed from the request, so the response is self-describing when retained apart from it.",
/// "enum": [
/// "cancel",
/// "suspend",
/// "resume"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum ResponseOperation {
#[serde(rename = "cancel")]
Cancel,
#[serde(rename = "suspend")]
Suspend,
#[serde(rename = "resume")]
Resume,
}
impl ::std::fmt::Display for ResponseOperation {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Cancel => f.write_str("cancel"),
Self::Suspend => f.write_str("suspend"),
Self::Resume => f.write_str("resume"),
}
}
}
impl ::std::str::FromStr for ResponseOperation {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"cancel" => Ok(Self::Cancel),
"suspend" => Ok(Self::Suspend),
"resume" => Ok(Self::Resume),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ResponseOperation {
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 ResponseOperation {
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 ResponseOperation {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
/**
`applied` — the operation took effect and NO irreversible or externally visible effect had occurred. The only outcome that means the task left no trace.
`appliedWithEffects` — the operation took effect, but effects had already occurred before it did. `effects` describes them. A consumer MUST NOT report `applied` in this case (SPEC.md §12.3).
`alreadyCompleted` — the task finished before the control document was processed. Not a cancellation; whether to compensate is the producer's own decision.
`unknownTask` — the consumer holds no record of the target `id`, either because it never received it or because its acceptance window has lapsed. A consumer that records the operation as a tombstone against a not-yet-arrived document reports `applied`, not this.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "\n`applied` — the operation took effect and NO irreversible or externally visible effect had occurred. The only outcome that means the task left no trace.\n\n`appliedWithEffects` — the operation took effect, but effects had already occurred before it did. `effects` describes them. A consumer MUST NOT report `applied` in this case (SPEC.md §12.3).\n\n`alreadyCompleted` — the task finished before the control document was processed. Not a cancellation; whether to compensate is the producer's own decision.\n\n`unknownTask` — the consumer holds no record of the target `id`, either because it never received it or because its acceptance window has lapsed. A consumer that records the operation as a tombstone against a not-yet-arrived document reports `applied`, not this.",
/// "enum": [
/// "applied",
/// "appliedWithEffects",
/// "alreadyCompleted",
/// "unknownTask"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum ResponseOutcome {
#[serde(rename = "applied")]
Applied,
#[serde(rename = "appliedWithEffects")]
AppliedWithEffects,
#[serde(rename = "alreadyCompleted")]
AlreadyCompleted,
#[serde(rename = "unknownTask")]
UnknownTask,
}
impl ::std::fmt::Display for ResponseOutcome {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Applied => f.write_str("applied"),
Self::AppliedWithEffects => f.write_str("appliedWithEffects"),
Self::AlreadyCompleted => f.write_str("alreadyCompleted"),
Self::UnknownTask => f.write_str("unknownTask"),
}
}
}
impl ::std::str::FromStr for ResponseOutcome {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"applied" => Ok(Self::Applied),
"appliedWithEffects" => Ok(Self::AppliedWithEffects),
"alreadyCompleted" => Ok(Self::AlreadyCompleted),
"unknownTask" => Ok(Self::UnknownTask),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ResponseOutcome {
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 ResponseOutcome {
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 ResponseOutcome {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Echoed from the request.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Echoed from the request.",
/// "type": "object",
/// "required": [
/// "id"
/// ],
/// "properties": {
/// "id": {
/// "type": "string",
/// "minLength": 1
/// },
/// "typeUri": {
/// "type": "string",
/// "format": "uri",
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct ResponseTarget {
pub id: ResponseTargetId,
#[serde(
rename = "typeUri",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub type_uri: ::std::option::Option<::std::string::String>,
}
///`ResponseTargetId`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ResponseTargetId(::std::string::String);
impl ::std::ops::Deref for ResponseTargetId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ResponseTargetId> for ::std::string::String {
fn from(value: ResponseTargetId) -> Self {
value.0
}
}
impl ::std::str::FromStr for ResponseTargetId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ResponseTargetId {
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 ResponseTargetId {
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 ResponseTargetId {
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 ResponseTargetId {
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())
})
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/trust-task-control/0.1";
const IS_PROOF_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
}
impl crate::Payload for Response {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/trust-task-control/0.1#response";
const IS_PROOF_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
}
#[cfg(feature = "validate")]
impl crate::validate::ValidatedPayload for Payload {
const SCHEMA_JSON: &'static str = "{\n \"$defs\": {\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"What the consumer did. The `outcome` is the load-bearing member: it is what tells the producer whether a compensating action is required, since SPEC.md §12.4 declines to require rollback.\",\n \"properties\": {\n \"effects\": {\n \"description\": \"What was created, changed, disclosed, or exercised before the operation took hold. A consumer MUST populate this where `outcome` is `appliedWithEffects` or `alreadyCompleted` — a producer cannot decide whether to compensate without it — and the specification's Conformance section carries that requirement normatively. It is not expressed as a conditional schema because the registry's Rust code generator does not support if/then/else. The framework does not constrain how a task describes its own effects.\",\n \"items\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"description\": {\n \"description\": \"Human-readable statement of the effect that occurred.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"ref\": {\n \"description\": \"An identifier for the effect where one exists — a credential id, a record identifier, a transaction reference — so a compensating task can name it.\",\n \"type\": \"string\"\n },\n \"reversible\": {\n \"description\": \"Whether the consumer believes this effect can be compensated by a further Trust Task. Advisory. Absent means unknown, which a producer SHOULD treat as no weaker than `false`.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"description\"\n ],\n \"type\": \"object\"\n },\n \"type\": \"array\"\n },\n \"ext\": {\n \"description\": \"Vendor-namespaced extension data per SPEC.md §4.5.1.\",\n \"type\": \"object\"\n },\n \"operation\": {\n \"description\": \"Echoed from the request, so the response is self-describing when retained apart from it.\",\n \"enum\": [\n \"cancel\",\n \"suspend\",\n \"resume\"\n ]\n },\n \"outcome\": {\n \"description\": \"`applied` — the operation took effect and NO irreversible or externally visible effect had occurred. The only outcome that means the task left no trace.\\n\\n`appliedWithEffects` — the operation took effect, but effects had already occurred before it did. `effects` describes them. A consumer MUST NOT report `applied` in this case (SPEC.md §12.3).\\n\\n`alreadyCompleted` — the task finished before the control document was processed. Not a cancellation; whether to compensate is the producer's own decision.\\n\\n`unknownTask` — the consumer holds no record of the target `id`, either because it never received it or because its acceptance window has lapsed. A consumer that records the operation as a tombstone against a not-yet-arrived document reports `applied`, not this.\",\n \"enum\": [\n \"applied\",\n \"appliedWithEffects\",\n \"alreadyCompleted\",\n \"unknownTask\"\n ]\n },\n \"target\": {\n \"additionalProperties\": false,\n \"description\": \"Echoed from the request.\",\n \"properties\": {\n \"id\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"typeUri\": {\n \"format\": \"uri\",\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\"\n ],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"operation\",\n \"target\",\n \"outcome\"\n ],\n \"title\": \"Trust Task Control — response payload\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/trust-task-control/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"The task-control request defined at SPEC.md §12: a producer withdrawing, pausing, or resuming work a consumer has already accepted.\\n\\nThis is a REQUEST, not a response. A consumer that stops work on its own initiative does not send one of these — it returns a trust-task-error carrying `cancelled`, so that a withdrawal and a refusal remain distinguishable to every party and to any auditor reading the retained documents afterwards.\\n\\nThe operation takes effect through SPEC.md §7.2 item 12: a valid, authorized control operation is one of the conditions a consumer re-evaluates immediately before each irreversible or externally visible effect. There is no separate race protocol.\",\n \"properties\": {\n \"ext\": {\n \"description\": \"Vendor-namespaced extension data per SPEC.md §4.5.1. Every immediate child key MUST be a reverse-DNS prefix the producer controls.\",\n \"type\": \"object\"\n },\n \"operation\": {\n \"description\": \"The control operation requested.\\n\\n`cancel` stops the task permanently: it is terminal, and a cancelled task MUST NOT be resumed, retried, or cancelled again (SPEC.md §12.3). `suspend` halts further effects while preserving the consumer's current execution state — it does not undo work already performed. `resume` continues a suspended task from the state the consumer holds; a consumer MUST NOT resume after the target document's `expiresAt` (SPEC.md §12.5).\\n\\nThis is a discriminating field. A consumer that does not recognize a value MUST reject the document rather than apply a default — silently downgrading an unrecognized operation to a known one would let a producer's intent be replaced by the consumer's guess.\",\n \"enum\": [\n \"cancel\",\n \"suspend\",\n \"resume\"\n ]\n },\n \"reason\": {\n \"description\": \"Human-readable explanation of why the operation was requested. Non-normative; intended for operator UI and audit records. A consumer MUST NOT condition its handling of the operation on this value.\",\n \"type\": \"string\"\n },\n \"target\": {\n \"additionalProperties\": false,\n \"description\": \"The specific Trust Task document this operation applies to. Per SPEC.md §12.2, `threadId`, `parentThreadId` and ceremony membership MUST NOT identify the target on their own: more than one document can occur in a single exchange or enactment.\",\n \"properties\": {\n \"id\": {\n \"description\": \"The `id` of the target Trust Task document. The sole identifying member.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"typeUri\": {\n \"description\": \"The target document's `type`, including any `#request` fragment. RECOMMENDED. A consumer that holds the named `id` under a different specification can then detect the mismatch rather than acting on a coincidence of identifiers.\",\n \"format\": \"uri\",\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\"\n ],\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"operation\",\n \"target\"\n ],\n \"title\": \"Trust Task Control — payload\",\n \"type\": \"object\"\n}\n";
}