//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `keys/sign-document`. 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())
}
}
}
///A DID (W3C DID Core §3.1) — never a DID URL: no path, query or fragment.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "A DID (W3C DID Core §3.1) — never a DID URL: no path, query or fragment.",
/// "type": "string",
/// "maxLength": 2048,
/// "minLength": 7,
/// "pattern": "^did:[a-z0-9]+:[A-Za-z0-9._:%-]*[A-Za-z0-9._%-]$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct Did(::std::string::String);
impl ::std::ops::Deref for Did {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<Did> for ::std::string::String {
fn from(value: Did) -> Self {
value.0
}
}
impl ::std::str::FromStr for Did {
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() < 7usize {
return Err("shorter than 7 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^did:[a-z0-9]+:[A-Za-z0-9._:%-]*[A-Za-z0-9._%-]$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err(
"doesn't match pattern \"^did:[a-z0-9]+:[A-Za-z0-9._:%-]*[A-Za-z0-9._%-]$\"".into(),
);
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for Did {
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 Did {
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 Did {
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 Did {
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())
})
}
}
///A request for a W3C Data Integrity proof (`eddsa-jcs-2022`) over a JSON document, made with a key the custodian already holds, named by `keyId`. The document names its own signer — an `issuer` or a `controller` — and the custodian signs only as that DID, only with a key that DID's document lists under the requested proof purpose. The custodian canonicalises the document (RFC 8785), builds the proof configuration and the signing input itself; the producer never supplies bytes to sign. 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/keys/sign-document/0.1",
/// "title": "Payload",
/// "description": "A request for a W3C Data Integrity proof (`eddsa-jcs-2022`) over a JSON document, made with a key the custodian already holds, named by `keyId`. The document names its own signer — an `issuer` or a `controller` — and the custodian signs only as that DID, only with a key that DID's document lists under the requested proof purpose. The custodian canonicalises the document (RFC 8785), builds the proof configuration and the signing input itself; the producer never supplies bytes to sign. The outer document members (id, type, issuer, recipient, issuedAt, expiresAt, proof) are owned by the framework — SPEC §6.3.",
/// "type": "object",
/// "required": [
/// "document",
/// "keyId"
/// ],
/// "properties": {
/// "challenge": {
/// "description": "A challenge the proof's verifier issued, copied into the proof's `challenge` member verbatim (W3C Data Integrity). Absent means the proof carries none. The custodian does not interpret it.",
/// "type": "string",
/// "maxLength": 1024,
/// "minLength": 1
/// },
/// "created": {
/// "description": "The proof's `created` value (an XML Schema dateTimeStamp, as Data Integrity requires). Absent means the custodian's own clock at signing. When present, the custodian refuses a value outside its acceptance window around its own clock with `keys:invalidArgument`: the key's signature dates the proof, so the producer cannot back- or forward-date it.",
/// "type": "string",
/// "format": "date-time",
/// "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$"
/// },
/// "document": {
/// "description": "The JSON document to secure — a verifiable credential, a Trust Task document, or another document that names its own signer. It MUST NOT carry `proof`, and MUST carry `issuer` (a DID, or an object whose `id` is a DID) or `controller` (a DID, or an array holding exactly one DID), every one present naming the DID the key belongs to. The custodian checks these rules itself (`proofPresent`, `documentInvalid`, `issuerMismatch`) rather than the schema, because the document is carried whole and every member is signed as given: a typed document would drop the members it does not name. The custodian serialises the whole object with RFC 8785.",
/// "type": "object"
/// },
/// "domain": {
/// "description": "The security domain the proof is restricted to, copied into the proof's `domain` member verbatim (W3C Data Integrity). Absent means the proof carries none. The custodian does not interpret it.",
/// "type": "string",
/// "maxLength": 1024,
/// "minLength": 1
/// },
/// "ext": {
/// "description": "Ecosystem-defined extension members per SPEC.md §4.5.1.",
/// "$ref": "#/definitions/Ext"
/// },
/// "keyId": {
/// "description": "Identifier of the key to sign with, as `keys/show` describes it. The key MUST be `active`, `ed25519`, and a verification method of the DID the document names as its issuer or controller.",
/// "type": "string",
/// "minLength": 1
/// },
/// "proofPurpose": {
/// "description": "The verification relationship the proof is made under, carried verbatim into the proof (W3C Data Integrity). The key MUST be listed under this relationship in the signer DID's document. Absent means `assertionMethod`, which is what a credential's issuer signs under; `authentication` is for a document the DID presents as itself, such as a Trust Task document. Externally owned, carried verbatim.",
/// "type": "string",
/// "enum": [
/// "assertionMethod",
/// "authentication"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Payload {
///A challenge the proof's verifier issued, copied into the proof's `challenge` member verbatim (W3C Data Integrity). Absent means the proof carries none. The custodian does not interpret it.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub challenge: ::std::option::Option<PayloadChallenge>,
///The proof's `created` value (an XML Schema dateTimeStamp, as Data Integrity requires). Absent means the custodian's own clock at signing. When present, the custodian refuses a value outside its acceptance window around its own clock with `keys:invalidArgument`: the key's signature dates the proof, so the producer cannot back- or forward-date it.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub created: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///The JSON document to secure — a verifiable credential, a Trust Task document, or another document that names its own signer. It MUST NOT carry `proof`, and MUST carry `issuer` (a DID, or an object whose `id` is a DID) or `controller` (a DID, or an array holding exactly one DID), every one present naming the DID the key belongs to. The custodian checks these rules itself (`proofPresent`, `documentInvalid`, `issuerMismatch`) rather than the schema, because the document is carried whole and every member is signed as given: a typed document would drop the members it does not name. The custodian serialises the whole object with RFC 8785.
pub document: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
///The security domain the proof is restricted to, copied into the proof's `domain` member verbatim (W3C Data Integrity). Absent means the proof carries none. The custodian does not interpret it.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub domain: ::std::option::Option<PayloadDomain>,
///Ecosystem-defined extension members per SPEC.md §4.5.1.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///Identifier of the key to sign with, as `keys/show` describes it. The key MUST be `active`, `ed25519`, and a verification method of the DID the document names as its issuer or controller.
#[serde(rename = "keyId")]
pub key_id: PayloadKeyId,
///The verification relationship the proof is made under, carried verbatim into the proof (W3C Data Integrity). The key MUST be listed under this relationship in the signer DID's document. Absent means `assertionMethod`, which is what a credential's issuer signs under; `authentication` is for a document the DID presents as itself, such as a Trust Task document. Externally owned, carried verbatim.
#[serde(
rename = "proofPurpose",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub proof_purpose: ::std::option::Option<PayloadProofPurpose>,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///A challenge the proof's verifier issued, copied into the proof's `challenge` member verbatim (W3C Data Integrity). Absent means the proof carries none. The custodian does not interpret it.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "A challenge the proof's verifier issued, copied into the proof's `challenge` member verbatim (W3C Data Integrity). Absent means the proof carries none. The custodian does not interpret it.",
/// "type": "string",
/// "maxLength": 1024,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadChallenge(::std::string::String);
impl ::std::ops::Deref for PayloadChallenge {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadChallenge> for ::std::string::String {
fn from(value: PayloadChallenge) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadChallenge {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 1024usize {
return Err("longer than 1024 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PayloadChallenge {
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 PayloadChallenge {
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 PayloadChallenge {
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 PayloadChallenge {
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 security domain the proof is restricted to, copied into the proof's `domain` member verbatim (W3C Data Integrity). Absent means the proof carries none. The custodian does not interpret it.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The security domain the proof is restricted to, copied into the proof's `domain` member verbatim (W3C Data Integrity). Absent means the proof carries none. The custodian does not interpret it.",
/// "type": "string",
/// "maxLength": 1024,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadDomain(::std::string::String);
impl ::std::ops::Deref for PayloadDomain {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadDomain> for ::std::string::String {
fn from(value: PayloadDomain) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadDomain {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 1024usize {
return Err("longer than 1024 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PayloadDomain {
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 PayloadDomain {
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 PayloadDomain {
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 PayloadDomain {
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())
})
}
}
///Identifier of the key to sign with, as `keys/show` describes it. The key MUST be `active`, `ed25519`, and a verification method of the DID the document names as its issuer or controller.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Identifier of the key to sign with, as `keys/show` describes it. The key MUST be `active`, `ed25519`, and a verification method of the DID the document names as its issuer or controller.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadKeyId(::std::string::String);
impl ::std::ops::Deref for PayloadKeyId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadKeyId> for ::std::string::String {
fn from(value: PayloadKeyId) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadKeyId {
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 PayloadKeyId {
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 PayloadKeyId {
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 PayloadKeyId {
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 PayloadKeyId {
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 verification relationship the proof is made under, carried verbatim into the proof (W3C Data Integrity). The key MUST be listed under this relationship in the signer DID's document. Absent means `assertionMethod`, which is what a credential's issuer signs under; `authentication` is for a document the DID presents as itself, such as a Trust Task document. Externally owned, carried verbatim.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The verification relationship the proof is made under, carried verbatim into the proof (W3C Data Integrity). The key MUST be listed under this relationship in the signer DID's document. Absent means `assertionMethod`, which is what a credential's issuer signs under; `authentication` is for a document the DID presents as itself, such as a Trust Task document. Externally owned, carried verbatim.",
/// "type": "string",
/// "enum": [
/// "assertionMethod",
/// "authentication"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum PayloadProofPurpose {
#[serde(rename = "assertionMethod")]
AssertionMethod,
#[serde(rename = "authentication")]
Authentication,
}
impl ::std::fmt::Display for PayloadProofPurpose {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::AssertionMethod => f.write_str("assertionMethod"),
Self::Authentication => f.write_str("authentication"),
}
}
}
impl ::std::str::FromStr for PayloadProofPurpose {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"assertionMethod" => Ok(Self::AssertionMethod),
"authentication" => Ok(Self::Authentication),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PayloadProofPurpose {
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 PayloadProofPurpose {
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 PayloadProofPurpose {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///The proof the custodian made: a W3C `DataIntegrityProof` under the `eddsa-jcs-2022` cryptosuite. Member names and values are Data Integrity's, carried verbatim.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Data Integrity proof",
/// "description": "The proof the custodian made: a W3C `DataIntegrityProof` under the `eddsa-jcs-2022` cryptosuite. Member names and values are Data Integrity's, carried verbatim.",
/// "type": "object",
/// "required": [
/// "created",
/// "cryptosuite",
/// "proofPurpose",
/// "proofValue",
/// "type",
/// "verificationMethod"
/// ],
/// "properties": {
/// "@context": {
/// "description": "The document's own `@context`, copied into the proof configuration as `eddsa-jcs-2022` requires when the document has one; absent otherwise.",
/// "oneOf": [
/// {
/// "type": "string"
/// },
/// {
/// "type": "array",
/// "minItems": 1
/// }
/// ]
/// },
/// "challenge": {
/// "type": "string"
/// },
/// "created": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "cryptosuite": {
/// "description": "The only cryptosuite this version defines.",
/// "type": "string",
/// "enum": [
/// "eddsa-jcs-2022"
/// ]
/// },
/// "domain": {
/// "type": "string"
/// },
/// "proofPurpose": {
/// "type": "string",
/// "enum": [
/// "assertionMethod",
/// "authentication"
/// ]
/// },
/// "proofValue": {
/// "description": "The Ed25519 signature, base58btc multibase-encoded.",
/// "type": "string",
/// "pattern": "^z[1-9A-HJ-NP-Za-km-z]+$"
/// },
/// "type": {
/// "type": "string",
/// "const": "DataIntegrityProof"
/// },
/// "verificationMethod": {
/// "description": "The DID URL of the key's verification method in the signer DID's document, chosen by the custodian.",
/// "type": "string",
/// "pattern": "^did:[a-z0-9]+:[^#\\s]+#[^\\s]+$"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Proof {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub challenge: ::std::option::Option<::std::string::String>,
///The document's own `@context`, copied into the proof configuration as `eddsa-jcs-2022` requires when the document has one; absent otherwise.
#[serde(
rename = "@context",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub context: ::std::option::Option<ProofContext>,
pub created: ::chrono::DateTime<::chrono::offset::Utc>,
///The only cryptosuite this version defines.
pub cryptosuite: ProofCryptosuite,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub domain: ::std::option::Option<::std::string::String>,
#[serde(rename = "proofPurpose")]
pub proof_purpose: ProofProofPurpose,
///The Ed25519 signature, base58btc multibase-encoded.
#[serde(rename = "proofValue")]
pub proof_value: ProofProofValue,
#[serde(rename = "type")]
pub type_: ::std::string::String,
///The DID URL of the key's verification method in the signer DID's document, chosen by the custodian.
#[serde(rename = "verificationMethod")]
pub verification_method: ProofVerificationMethod,
}
impl Proof {
pub fn builder() -> builder::Proof {
Default::default()
}
}
///The document's own `@context`, copied into the proof configuration as `eddsa-jcs-2022` requires when the document has one; absent otherwise.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The document's own `@context`, copied into the proof configuration as `eddsa-jcs-2022` requires when the document has one; absent otherwise.",
/// "oneOf": [
/// {
/// "type": "string"
/// },
/// {
/// "type": "array",
/// "minItems": 1
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged)]
#[non_exhaustive]
pub enum ProofContext {
String(::std::string::String),
Array(::std::vec::Vec<::serde_json::Value>),
}
impl ::std::convert::From<::std::vec::Vec<::serde_json::Value>> for ProofContext {
fn from(value: ::std::vec::Vec<::serde_json::Value>) -> Self {
Self::Array(value)
}
}
///The only cryptosuite this version defines.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The only cryptosuite this version defines.",
/// "type": "string",
/// "enum": [
/// "eddsa-jcs-2022"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ProofCryptosuite {
#[serde(rename = "eddsa-jcs-2022")]
EddsaJcs2022,
}
impl ::std::fmt::Display for ProofCryptosuite {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::EddsaJcs2022 => f.write_str("eddsa-jcs-2022"),
}
}
}
impl ::std::str::FromStr for ProofCryptosuite {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"eddsa-jcs-2022" => Ok(Self::EddsaJcs2022),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ProofCryptosuite {
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 ProofCryptosuite {
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 ProofCryptosuite {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`ProofProofPurpose`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "assertionMethod",
/// "authentication"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum ProofProofPurpose {
#[serde(rename = "assertionMethod")]
AssertionMethod,
#[serde(rename = "authentication")]
Authentication,
}
impl ::std::fmt::Display for ProofProofPurpose {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::AssertionMethod => f.write_str("assertionMethod"),
Self::Authentication => f.write_str("authentication"),
}
}
}
impl ::std::str::FromStr for ProofProofPurpose {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"assertionMethod" => Ok(Self::AssertionMethod),
"authentication" => Ok(Self::Authentication),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ProofProofPurpose {
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 ProofProofPurpose {
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 ProofProofPurpose {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///The Ed25519 signature, base58btc multibase-encoded.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The Ed25519 signature, base58btc multibase-encoded.",
/// "type": "string",
/// "pattern": "^z[1-9A-HJ-NP-Za-km-z]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ProofProofValue(::std::string::String);
impl ::std::ops::Deref for ProofProofValue {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProofProofValue> for ::std::string::String {
fn from(value: ProofProofValue) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProofProofValue {
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("^z[1-9A-HJ-NP-Za-km-z]+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^z[1-9A-HJ-NP-Za-km-z]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ProofProofValue {
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 ProofProofValue {
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 ProofProofValue {
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 ProofProofValue {
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 DID URL of the key's verification method in the signer DID's document, chosen by the custodian.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The DID URL of the key's verification method in the signer DID's document, chosen by the custodian.",
/// "type": "string",
/// "pattern": "^did:[a-z0-9]+:[^#\\s]+#[^\\s]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ProofVerificationMethod(::std::string::String);
impl ::std::ops::Deref for ProofVerificationMethod {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ProofVerificationMethod> for ::std::string::String {
fn from(value: ProofVerificationMethod) -> Self {
value.0
}
}
impl ::std::str::FromStr for ProofVerificationMethod {
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("^did:[a-z0-9]+:[^#\\s]+#[^\\s]+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^did:[a-z0-9]+:[^#\\s]+#[^\\s]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ProofVerificationMethod {
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 ProofVerificationMethod {
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 ProofVerificationMethod {
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 ProofVerificationMethod {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///The success response to a keys/sign-document request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/keys/sign-document/0.1#response. Failures use trust-task-error, not this shape.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "The success response to a keys/sign-document request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/keys/sign-document/0.1#response. Failures use trust-task-error, not this shape.",
/// "type": "object",
/// "required": [
/// "document",
/// "keyId",
/// "proof",
/// "signerDid"
/// ],
/// "properties": {
/// "document": {
/// "description": "The request's document, unchanged, with `proof` added. Every other member is exactly as the producer sent it.",
/// "type": "object"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "keyId": {
/// "description": "The key that produced the proof. Echoed so a response separated from its request is still attributable.",
/// "type": "string"
/// },
/// "proof": {
/// "description": "The proof the custodian attached to `document`, returned on its own so a producer need not dig it out.",
/// "$ref": "#/definitions/Proof"
/// },
/// "signerDid": {
/// "description": "The DID the document was signed as — the one its `issuer` or `controller` names, and the DID a verifier resolves the proof's verification method against.",
/// "$ref": "#/definitions/Did"
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Response {
///The request's document, unchanged, with `proof` added. Every other member is exactly as the producer sent it.
pub document: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///The key that produced the proof. Echoed so a response separated from its request is still attributable.
#[serde(rename = "keyId")]
pub key_id: ::std::string::String,
///The proof the custodian attached to `document`, returned on its own so a producer need not dig it out.
pub proof: Proof,
///The DID the document was signed as — the one its `issuer` or `controller` names, and the DID a verifier resolves the proof's verification method against.
#[serde(rename = "signerDid")]
pub signer_did: Did,
}
impl Response {
pub fn builder() -> builder::Response {
Default::default()
}
}
/// Types for composing complex structures.
pub mod builder {
#[derive(Clone, Debug)]
pub struct Payload {
challenge: ::std::result::Result<
::std::option::Option<super::PayloadChallenge>,
::std::string::String,
>,
created: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
document: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
domain: ::std::result::Result<
::std::option::Option<super::PayloadDomain>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
key_id: ::std::result::Result<super::PayloadKeyId, ::std::string::String>,
proof_purpose: ::std::result::Result<
::std::option::Option<super::PayloadProofPurpose>,
::std::string::String,
>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
challenge: Ok(Default::default()),
created: Ok(Default::default()),
document: Err("no value supplied for document".to_string()),
domain: Ok(Default::default()),
ext: Ok(Default::default()),
key_id: Err("no value supplied for key_id".to_string()),
proof_purpose: Ok(Default::default()),
}
}
}
impl Payload {
pub fn challenge<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::PayloadChallenge>>,
T::Error: ::std::fmt::Display,
{
self.challenge = value
.try_into()
.map_err(|e| format!("error converting supplied value for challenge: {e}"));
self
}
pub fn created<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.created = value
.try_into()
.map_err(|e| format!("error converting supplied value for created: {e}"));
self
}
pub fn document<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.document = value
.try_into()
.map_err(|e| format!("error converting supplied value for document: {e}"));
self
}
pub fn domain<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::PayloadDomain>>,
T::Error: ::std::fmt::Display,
{
self.domain = value
.try_into()
.map_err(|e| format!("error converting supplied value for domain: {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 key_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::PayloadKeyId>,
T::Error: ::std::fmt::Display,
{
self.key_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for key_id: {e}"));
self
}
pub fn proof_purpose<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::PayloadProofPurpose>>,
T::Error: ::std::fmt::Display,
{
self.proof_purpose = value
.try_into()
.map_err(|e| format!("error converting supplied value for proof_purpose: {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 {
challenge: value.challenge?,
created: value.created?,
document: value.document?,
domain: value.domain?,
ext: value.ext?,
key_id: value.key_id?,
proof_purpose: value.proof_purpose?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
challenge: Ok(value.challenge),
created: Ok(value.created),
document: Ok(value.document),
domain: Ok(value.domain),
ext: Ok(value.ext),
key_id: Ok(value.key_id),
proof_purpose: Ok(value.proof_purpose),
}
}
}
#[derive(Clone, Debug)]
pub struct Proof {
challenge: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
context: ::std::result::Result<
::std::option::Option<super::ProofContext>,
::std::string::String,
>,
created:
::std::result::Result<::chrono::DateTime<::chrono::offset::Utc>, ::std::string::String>,
cryptosuite: ::std::result::Result<super::ProofCryptosuite, ::std::string::String>,
domain: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
proof_purpose: ::std::result::Result<super::ProofProofPurpose, ::std::string::String>,
proof_value: ::std::result::Result<super::ProofProofValue, ::std::string::String>,
type_: ::std::result::Result<::std::string::String, ::std::string::String>,
verification_method:
::std::result::Result<super::ProofVerificationMethod, ::std::string::String>,
}
impl ::std::default::Default for Proof {
fn default() -> Self {
Self {
challenge: Ok(Default::default()),
context: Ok(Default::default()),
created: Err("no value supplied for created".to_string()),
cryptosuite: Err("no value supplied for cryptosuite".to_string()),
domain: Ok(Default::default()),
proof_purpose: Err("no value supplied for proof_purpose".to_string()),
proof_value: Err("no value supplied for proof_value".to_string()),
type_: Err("no value supplied for type_".to_string()),
verification_method: Err("no value supplied for verification_method".to_string()),
}
}
}
impl Proof {
pub fn challenge<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.challenge = value
.try_into()
.map_err(|e| format!("error converting supplied value for challenge: {e}"));
self
}
pub fn context<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ProofContext>>,
T::Error: ::std::fmt::Display,
{
self.context = value
.try_into()
.map_err(|e| format!("error converting supplied value for context: {e}"));
self
}
pub fn created<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::chrono::DateTime<::chrono::offset::Utc>>,
T::Error: ::std::fmt::Display,
{
self.created = value
.try_into()
.map_err(|e| format!("error converting supplied value for created: {e}"));
self
}
pub fn cryptosuite<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ProofCryptosuite>,
T::Error: ::std::fmt::Display,
{
self.cryptosuite = value
.try_into()
.map_err(|e| format!("error converting supplied value for cryptosuite: {e}"));
self
}
pub fn domain<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.domain = value
.try_into()
.map_err(|e| format!("error converting supplied value for domain: {e}"));
self
}
pub fn proof_purpose<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ProofProofPurpose>,
T::Error: ::std::fmt::Display,
{
self.proof_purpose = value
.try_into()
.map_err(|e| format!("error converting supplied value for proof_purpose: {e}"));
self
}
pub fn proof_value<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ProofProofValue>,
T::Error: ::std::fmt::Display,
{
self.proof_value = value
.try_into()
.map_err(|e| format!("error converting supplied value for proof_value: {e}"));
self
}
pub fn type_<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::string::String>,
T::Error: ::std::fmt::Display,
{
self.type_ = value
.try_into()
.map_err(|e| format!("error converting supplied value for type_: {e}"));
self
}
pub fn verification_method<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::ProofVerificationMethod>,
T::Error: ::std::fmt::Display,
{
self.verification_method = value.try_into().map_err(|e| {
format!("error converting supplied value for verification_method: {e}")
});
self
}
}
impl ::std::convert::TryFrom<Proof> for super::Proof {
type Error = super::error::ConversionError;
fn try_from(value: Proof) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
challenge: value.challenge?,
context: value.context?,
created: value.created?,
cryptosuite: value.cryptosuite?,
domain: value.domain?,
proof_purpose: value.proof_purpose?,
proof_value: value.proof_value?,
type_: value.type_?,
verification_method: value.verification_method?,
})
}
}
impl ::std::convert::From<super::Proof> for Proof {
fn from(value: super::Proof) -> Self {
Self {
challenge: Ok(value.challenge),
context: Ok(value.context),
created: Ok(value.created),
cryptosuite: Ok(value.cryptosuite),
domain: Ok(value.domain),
proof_purpose: Ok(value.proof_purpose),
proof_value: Ok(value.proof_value),
type_: Ok(value.type_),
verification_method: Ok(value.verification_method),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
document: ::std::result::Result<
::serde_json::Map<::std::string::String, ::serde_json::Value>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
key_id: ::std::result::Result<::std::string::String, ::std::string::String>,
proof: ::std::result::Result<super::Proof, ::std::string::String>,
signer_did: ::std::result::Result<super::Did, ::std::string::String>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
document: Err("no value supplied for document".to_string()),
ext: Ok(Default::default()),
key_id: Err("no value supplied for key_id".to_string()),
proof: Err("no value supplied for proof".to_string()),
signer_did: Err("no value supplied for signer_did".to_string()),
}
}
}
impl Response {
pub fn document<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.document = value
.try_into()
.map_err(|e| format!("error converting supplied value for document: {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 key_id<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::string::String>,
T::Error: ::std::fmt::Display,
{
self.key_id = value
.try_into()
.map_err(|e| format!("error converting supplied value for key_id: {e}"));
self
}
pub fn proof<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Proof>,
T::Error: ::std::fmt::Display,
{
self.proof = value
.try_into()
.map_err(|e| format!("error converting supplied value for proof: {e}"));
self
}
pub fn signer_did<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Did>,
T::Error: ::std::fmt::Display,
{
self.signer_did = value
.try_into()
.map_err(|e| format!("error converting supplied value for signer_did: {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 {
document: value.document?,
ext: value.ext?,
key_id: value.key_id?,
proof: value.proof?,
signer_did: value.signer_did?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
document: Ok(value.document),
ext: Ok(value.ext),
key_id: Ok(value.key_id),
proof: Ok(value.proof),
signer_did: Ok(value.signer_did),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/keys/sign-document/0.1";
const IS_PROOF_REQUIRED: bool = true;
const IS_ISSUED_AT_REQUIRED: bool = true;
const MAX_DOCUMENT_BYTES: Option<usize> = Some(65536usize);
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"Did\": {\n \"description\": \"A DID (W3C DID Core §3.1) — never a DID URL: no path, query or fragment.\",\n \"maxLength\": 2048,\n \"minLength\": 7,\n \"pattern\": \"^did:[a-z0-9]+:[A-Za-z0-9._:%-]*[A-Za-z0-9._%-]$\",\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 \"Proof\": {\n \"additionalProperties\": false,\n \"description\": \"The proof the custodian made: a W3C `DataIntegrityProof` under the `eddsa-jcs-2022` cryptosuite. Member names and values are Data Integrity's, carried verbatim.\",\n \"properties\": {\n \"@context\": {\n \"description\": \"The document's own `@context`, copied into the proof configuration as `eddsa-jcs-2022` requires when the document has one; absent otherwise.\",\n \"oneOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"minItems\": 1,\n \"type\": \"array\"\n }\n ]\n },\n \"challenge\": {\n \"type\": \"string\"\n },\n \"created\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"cryptosuite\": {\n \"description\": \"The only cryptosuite this version defines.\",\n \"enum\": [\n \"eddsa-jcs-2022\"\n ],\n \"type\": \"string\"\n },\n \"domain\": {\n \"type\": \"string\"\n },\n \"proofPurpose\": {\n \"enum\": [\n \"assertionMethod\",\n \"authentication\"\n ],\n \"type\": \"string\"\n },\n \"proofValue\": {\n \"description\": \"The Ed25519 signature, base58btc multibase-encoded.\",\n \"pattern\": \"^z[1-9A-HJ-NP-Za-km-z]+$\",\n \"type\": \"string\"\n },\n \"type\": {\n \"const\": \"DataIntegrityProof\",\n \"type\": \"string\"\n },\n \"verificationMethod\": {\n \"description\": \"The DID URL of the key's verification method in the signer DID's document, chosen by the custodian.\",\n \"pattern\": \"^did:[a-z0-9]+:[^#\\\\s]+#[^\\\\s]+$\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"type\",\n \"cryptosuite\",\n \"created\",\n \"verificationMethod\",\n \"proofPurpose\",\n \"proofValue\"\n ],\n \"title\": \"Data Integrity proof\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to a keys/sign-document request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/keys/sign-document/0.1#response. Failures use trust-task-error, not this shape.\",\n \"properties\": {\n \"document\": {\n \"description\": \"The request's document, unchanged, with `proof` added. Every other member is exactly as the producer sent it.\",\n \"type\": \"object\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"keyId\": {\n \"description\": \"The key that produced the proof. Echoed so a response separated from its request is still attributable.\",\n \"type\": \"string\"\n },\n \"proof\": {\n \"$ref\": \"#/$defs/Proof\",\n \"description\": \"The proof the custodian attached to `document`, returned on its own so a producer need not dig it out.\"\n },\n \"signerDid\": {\n \"$ref\": \"#/$defs/Did\",\n \"description\": \"The DID the document was signed as — the one its `issuer` or `controller` names, and the DID a verifier resolves the proof's verification method against.\"\n }\n },\n \"required\": [\n \"keyId\",\n \"signerDid\",\n \"document\",\n \"proof\"\n ],\n \"title\": \"Keys — Sign Document — response payload\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/keys/sign-document/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"A request for a W3C Data Integrity proof (`eddsa-jcs-2022`) over a JSON document, made with a key the custodian already holds, named by `keyId`. The document names its own signer — an `issuer` or a `controller` — and the custodian signs only as that DID, only with a key that DID's document lists under the requested proof purpose. The custodian canonicalises the document (RFC 8785), builds the proof configuration and the signing input itself; the producer never supplies bytes to sign. The outer document members (id, type, issuer, recipient, issuedAt, expiresAt, proof) are owned by the framework — SPEC §6.3.\",\n \"properties\": {\n \"challenge\": {\n \"description\": \"A challenge the proof's verifier issued, copied into the proof's `challenge` member verbatim (W3C Data Integrity). Absent means the proof carries none. The custodian does not interpret it.\",\n \"maxLength\": 1024,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"created\": {\n \"description\": \"The proof's `created` value (an XML Schema dateTimeStamp, as Data Integrity requires). Absent means the custodian's own clock at signing. When present, the custodian refuses a value outside its acceptance window around its own clock with `keys:invalidArgument`: the key's signature dates the proof, so the producer cannot back- or forward-date it.\",\n \"format\": \"date-time\",\n \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2}T\\\\d{2}:\\\\d{2}:\\\\d{2}(\\\\.\\\\d+)?(Z|[+-]\\\\d{2}:\\\\d{2})$\",\n \"type\": \"string\"\n },\n \"document\": {\n \"description\": \"The JSON document to secure — a verifiable credential, a Trust Task document, or another document that names its own signer. It MUST NOT carry `proof`, and MUST carry `issuer` (a DID, or an object whose `id` is a DID) or `controller` (a DID, or an array holding exactly one DID), every one present naming the DID the key belongs to. The custodian checks these rules itself (`proofPresent`, `documentInvalid`, `issuerMismatch`) rather than the schema, because the document is carried whole and every member is signed as given: a typed document would drop the members it does not name. The custodian serialises the whole object with RFC 8785.\",\n \"type\": \"object\"\n },\n \"domain\": {\n \"description\": \"The security domain the proof is restricted to, copied into the proof's `domain` member verbatim (W3C Data Integrity). Absent means the proof carries none. The custodian does not interpret it.\",\n \"maxLength\": 1024,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1.\"\n },\n \"keyId\": {\n \"description\": \"Identifier of the key to sign with, as `keys/show` describes it. The key MUST be `active`, `ed25519`, and a verification method of the DID the document names as its issuer or controller.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"proofPurpose\": {\n \"description\": \"The verification relationship the proof is made under, carried verbatim into the proof (W3C Data Integrity). The key MUST be listed under this relationship in the signer DID's document. Absent means `assertionMethod`, which is what a credential's issuer signs under; `authentication` is for a document the DID presents as itself, such as a Trust Task document. Externally owned, carried verbatim.\",\n \"enum\": [\n \"assertionMethod\",\n \"authentication\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"keyId\",\n \"document\"\n ],\n \"title\": \"Keys — Sign Document — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/keys/sign-document/0.1#response";
const IS_ISSUED_AT_REQUIRED: bool = true;
const MAX_DOCUMENT_BYTES: Option<usize> = Some(131072usize);
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"Did\": {\n \"description\": \"A DID (W3C DID Core §3.1) — never a DID URL: no path, query or fragment.\",\n \"maxLength\": 2048,\n \"minLength\": 7,\n \"pattern\": \"^did:[a-z0-9]+:[A-Za-z0-9._:%-]*[A-Za-z0-9._%-]$\",\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 \"Proof\": {\n \"additionalProperties\": false,\n \"description\": \"The proof the custodian made: a W3C `DataIntegrityProof` under the `eddsa-jcs-2022` cryptosuite. Member names and values are Data Integrity's, carried verbatim.\",\n \"properties\": {\n \"@context\": {\n \"description\": \"The document's own `@context`, copied into the proof configuration as `eddsa-jcs-2022` requires when the document has one; absent otherwise.\",\n \"oneOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"minItems\": 1,\n \"type\": \"array\"\n }\n ]\n },\n \"challenge\": {\n \"type\": \"string\"\n },\n \"created\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"cryptosuite\": {\n \"description\": \"The only cryptosuite this version defines.\",\n \"enum\": [\n \"eddsa-jcs-2022\"\n ],\n \"type\": \"string\"\n },\n \"domain\": {\n \"type\": \"string\"\n },\n \"proofPurpose\": {\n \"enum\": [\n \"assertionMethod\",\n \"authentication\"\n ],\n \"type\": \"string\"\n },\n \"proofValue\": {\n \"description\": \"The Ed25519 signature, base58btc multibase-encoded.\",\n \"pattern\": \"^z[1-9A-HJ-NP-Za-km-z]+$\",\n \"type\": \"string\"\n },\n \"type\": {\n \"const\": \"DataIntegrityProof\",\n \"type\": \"string\"\n },\n \"verificationMethod\": {\n \"description\": \"The DID URL of the key's verification method in the signer DID's document, chosen by the custodian.\",\n \"pattern\": \"^did:[a-z0-9]+:[^#\\\\s]+#[^\\\\s]+$\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"type\",\n \"cryptosuite\",\n \"created\",\n \"verificationMethod\",\n \"proofPurpose\",\n \"proofValue\"\n ],\n \"title\": \"Data Integrity proof\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to a keys/sign-document request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/keys/sign-document/0.1#response. Failures use trust-task-error, not this shape.\",\n \"properties\": {\n \"document\": {\n \"description\": \"The request's document, unchanged, with `proof` added. Every other member is exactly as the producer sent it.\",\n \"type\": \"object\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"keyId\": {\n \"description\": \"The key that produced the proof. Echoed so a response separated from its request is still attributable.\",\n \"type\": \"string\"\n },\n \"proof\": {\n \"$ref\": \"#/$defs/Proof\",\n \"description\": \"The proof the custodian attached to `document`, returned on its own so a producer need not dig it out.\"\n },\n \"signerDid\": {\n \"$ref\": \"#/$defs/Did\",\n \"description\": \"The DID the document was signed as — the one its `issuer` or `controller` names, and the DID a verifier resolves the proof's verification method against.\"\n }\n },\n \"required\": [\n \"keyId\",\n \"signerDid\",\n \"document\",\n \"proof\"\n ],\n \"title\": \"Keys — Sign Document — response payload\",\n \"type\": \"object\"\n }\n },\n \"$ref\": \"#/$defs/Response\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n}\n",
);
}
impl crate::RequestPayload for Payload {
type Response = Response;
}
/// The extended error codes this specification declares (SPEC §7.3 item 9,
/// §8.5), in declaration order. Empty when it declares none.
pub const ERROR_CODES: &[crate::DeclaredErrorCode] = &[
error_codes::NOT_FOUND,
error_codes::INVALID_ARGUMENT,
error_codes::FAILED_PRECONDITION,
error_codes::KEY_TYPE_UNSUPPORTED,
error_codes::PROOF_PRESENT,
error_codes::DOCUMENT_INVALID,
error_codes::ISSUER_MISMATCH,
error_codes::PURPOSE_NOT_AUTHORIZED,
];
/// 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 {
/// `keys:notFound`
///
/// No key record on this custodian carries the named `keyId` that the producer may name — whether the custodian holds no such key or holds it outside the producer's scope, which this code does not distinguish. See [category conventions](../../_shared/0.1/CONVENTIONS.md#1-family-error-codes).
///
/// Declared `retryable: false`.
pub const NOT_FOUND: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "keys:notFound",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `keys:invalidArgument`
///
/// A request member is well-formed against the schema but unusable — a `created` outside the custodian's acceptance window around its own clock. See [category conventions](../../_shared/0.1/CONVENTIONS.md#1-family-error-codes).
///
/// Declared `retryable: false`.
pub const INVALID_ARGUMENT: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "keys:invalidArgument",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `keys/sign-document:failedPrecondition`
///
/// The named key exists but cannot sign a document in its current state — its `status` is not `active`, the custodian has bound it to a protocol other than Data Integrity, or the custodian knows of no DID whose document lists it as a verification method.
///
/// Declared `retryable: false`.
pub const FAILED_PRECONDITION: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "keys/sign-document:failedPrecondition",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `keys/sign-document:keyTypeUnsupported`
///
/// The named key's `keyType` has no cryptosuite this specification defines — anything but `ed25519`.
///
/// Declared `retryable: false`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const KEY_TYPE_UNSUPPORTED: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "keys/sign-document:keyTypeUnsupported",
retryable: false,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"keyType\":{\"type\":\"string\"}},\"required\":[\"keyType\"],\"type\":\"object\"}",
),
};
/// `keys/sign-document:proofPresent`
///
/// The document already carries a `proof` member. This task makes a document's only proof; it neither strips an existing proof nor adds to a proof set or chain.
///
/// Declared `retryable: false`.
pub const PROOF_PRESENT: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "keys/sign-document:proofPresent",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `keys/sign-document:documentInvalid`
///
/// The document cannot be signed as given — it names its signer in neither `issuer` nor `controller` (`noSigner`), names it in a form this specification does not admit (`signerMalformed`), or holds a value RFC 8785 cannot serialise without changing it, such as a number outside IEEE 754 double precision or a lone surrogate (`notCanonicalizable`).
///
/// Declared `retryable: false`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const DOCUMENT_INVALID: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "keys/sign-document:documentInvalid",
retryable: false,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"reason\":{\"enum\":[\"noSigner\",\"signerMalformed\",\"notCanonicalizable\"],\"type\":\"string\"}},\"required\":[\"reason\"],\"type\":\"object\"}",
),
};
/// `keys/sign-document:issuerMismatch`
///
/// The document's `issuer` (or `issuer.id`), or its `controller`, names a DID of which the named key is not a verification method. The custodian signs only as the DID the document names, and only with that DID's own key.
///
/// Declared `retryable: false`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const ISSUER_MISMATCH: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "keys/sign-document:issuerMismatch",
retryable: false,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"member\":{\"enum\":[\"issuer\",\"controller\"],\"type\":\"string\"}},\"required\":[\"member\"],\"type\":\"object\"}",
),
};
/// `keys/sign-document:purposeNotAuthorized`
///
/// The named key is a verification method of the signer DID, but that DID's document does not list it under the requested `proofPurpose`.
///
/// Declared `retryable: false`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const PURPOSE_NOT_AUTHORIZED: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "keys/sign-document:purposeNotAuthorized",
retryable: false,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"proofPurpose\":{\"enum\":[\"assertionMethod\",\"authentication\"],\"type\":\"string\"}},\"required\":[\"proofPurpose\"],\"type\":\"object\"}",
),
};
}